@rocicorp/zero 1.10.0-canary.24 → 1.10.0-canary.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (568) hide show
  1. package/out/analyze-query/src/bin-analyze.js +8 -9
  2. package/out/analyze-query/src/bin-analyze.js.map +1 -1
  3. package/out/replicache/src/btree/node.d.ts.map +1 -1
  4. package/out/replicache/src/btree/node.js +6 -3
  5. package/out/replicache/src/btree/node.js.map +1 -1
  6. package/out/replicache/src/btree/read.d.ts +1 -12
  7. package/out/replicache/src/btree/read.d.ts.map +1 -1
  8. package/out/replicache/src/btree/read.js +12 -24
  9. package/out/replicache/src/btree/read.js.map +1 -1
  10. package/out/replicache/src/dag/gc.d.ts.map +1 -1
  11. package/out/replicache/src/dag/gc.js +11 -8
  12. package/out/replicache/src/dag/gc.js.map +1 -1
  13. package/out/replicache/src/dag/store-impl.d.ts +2 -12
  14. package/out/replicache/src/dag/store-impl.d.ts.map +1 -1
  15. package/out/replicache/src/dag/store-impl.js +8 -22
  16. package/out/replicache/src/dag/store-impl.js.map +1 -1
  17. package/out/replicache/src/db/rebase.d.ts +2 -14
  18. package/out/replicache/src/db/rebase.d.ts.map +1 -1
  19. package/out/replicache/src/db/rebase.js +5 -27
  20. package/out/replicache/src/db/rebase.js.map +1 -1
  21. package/out/replicache/src/db/write.js.map +1 -1
  22. package/out/replicache/src/kv/expo-sqlite/store.d.ts.map +1 -1
  23. package/out/replicache/src/kv/expo-sqlite/store.js +5 -28
  24. package/out/replicache/src/kv/expo-sqlite/store.js.map +1 -1
  25. package/out/replicache/src/kv/idb-store-with-mem-fallback.d.ts +5 -15
  26. package/out/replicache/src/kv/idb-store-with-mem-fallback.d.ts.map +1 -1
  27. package/out/replicache/src/kv/idb-store-with-mem-fallback.js +25 -25
  28. package/out/replicache/src/kv/idb-store-with-mem-fallback.js.map +1 -1
  29. package/out/replicache/src/kv/idb-store.d.ts +0 -9
  30. package/out/replicache/src/kv/idb-store.d.ts.map +1 -1
  31. package/out/replicache/src/kv/idb-store.js +2 -14
  32. package/out/replicache/src/kv/idb-store.js.map +1 -1
  33. package/out/replicache/src/kv/mem-store.d.ts +0 -1
  34. package/out/replicache/src/kv/mem-store.d.ts.map +1 -1
  35. package/out/replicache/src/kv/mem-store.js +0 -3
  36. package/out/replicache/src/kv/mem-store.js.map +1 -1
  37. package/out/replicache/src/kv/op-sqlite/store.d.ts.map +1 -1
  38. package/out/replicache/src/kv/op-sqlite/store.js +1 -1
  39. package/out/replicache/src/kv/op-sqlite/store.js.map +1 -1
  40. package/out/replicache/src/kv/sqlite-store.d.ts +1 -13
  41. package/out/replicache/src/kv/sqlite-store.d.ts.map +1 -1
  42. package/out/replicache/src/kv/sqlite-store.js +6 -73
  43. package/out/replicache/src/kv/sqlite-store.js.map +1 -1
  44. package/out/replicache/src/kv/store.d.ts +0 -6
  45. package/out/replicache/src/kv/store.d.ts.map +1 -1
  46. package/out/replicache/src/persist/collect-idb-databases.d.ts +5 -10
  47. package/out/replicache/src/persist/collect-idb-databases.d.ts.map +1 -1
  48. package/out/replicache/src/persist/collect-idb-databases.js +9 -16
  49. package/out/replicache/src/persist/collect-idb-databases.js.map +1 -1
  50. package/out/replicache/src/persist/persist.d.ts.map +1 -1
  51. package/out/replicache/src/persist/persist.js +6 -13
  52. package/out/replicache/src/persist/persist.js.map +1 -1
  53. package/out/replicache/src/persist/refresh.js +2 -6
  54. package/out/replicache/src/persist/refresh.js.map +1 -1
  55. package/out/replicache/src/replicache-impl.d.ts +3 -14
  56. package/out/replicache/src/replicache-impl.d.ts.map +1 -1
  57. package/out/replicache/src/replicache-impl.js +11 -118
  58. package/out/replicache/src/replicache-impl.js.map +1 -1
  59. package/out/replicache/src/replicache-options.d.ts +0 -9
  60. package/out/replicache/src/replicache-options.d.ts.map +1 -1
  61. package/out/replicache/src/transactions.d.ts.map +1 -1
  62. package/out/replicache/src/transactions.js +1 -1
  63. package/out/replicache/src/transactions.js.map +1 -1
  64. package/out/shared/src/arrays.d.ts +0 -5
  65. package/out/shared/src/arrays.d.ts.map +1 -1
  66. package/out/shared/src/arrays.js +24 -8
  67. package/out/shared/src/arrays.js.map +1 -1
  68. package/out/shared/src/base64.d.ts +19 -0
  69. package/out/shared/src/base64.d.ts.map +1 -0
  70. package/out/shared/src/base64.js +40 -0
  71. package/out/shared/src/base64.js.map +1 -0
  72. package/out/shared/src/error.d.ts +0 -11
  73. package/out/shared/src/error.d.ts.map +1 -1
  74. package/out/shared/src/error.js +1 -35
  75. package/out/shared/src/error.js.map +1 -1
  76. package/out/shared/src/hash.d.ts +0 -1
  77. package/out/shared/src/hash.d.ts.map +1 -1
  78. package/out/shared/src/hash.js +10 -87
  79. package/out/shared/src/hash.js.map +1 -1
  80. package/out/shared/src/iterables.d.ts +0 -2
  81. package/out/shared/src/iterables.d.ts.map +1 -1
  82. package/out/shared/src/iterables.js +1 -18
  83. package/out/shared/src/iterables.js.map +1 -1
  84. package/out/shared/src/json.d.ts.map +1 -1
  85. package/out/shared/src/json.js +2 -2
  86. package/out/shared/src/json.js.map +1 -1
  87. package/out/shared/src/map.d.ts +2 -24
  88. package/out/shared/src/map.d.ts.map +1 -1
  89. package/out/shared/src/map.js +4 -18
  90. package/out/shared/src/map.js.map +1 -1
  91. package/out/shared/src/ring-buffer.d.ts +0 -8
  92. package/out/shared/src/ring-buffer.d.ts.map +1 -1
  93. package/out/shared/src/ring-buffer.js +1 -22
  94. package/out/shared/src/ring-buffer.js.map +1 -1
  95. package/out/z2s/src/sql.d.ts.map +1 -1
  96. package/out/z2s/src/sql.js +2 -2
  97. package/out/z2s/src/sql.js.map +1 -1
  98. package/out/zero/package.js +3 -2
  99. package/out/zero/package.js.map +1 -1
  100. package/out/zero-cache/src/auth/read-authorizer.js +1 -1
  101. package/out/zero-cache/src/auth/write-authorizer.d.ts.map +1 -1
  102. package/out/zero-cache/src/auth/write-authorizer.js +0 -1
  103. package/out/zero-cache/src/auth/write-authorizer.js.map +1 -1
  104. package/out/zero-cache/src/config/zero-config.d.ts +2 -42
  105. package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
  106. package/out/zero-cache/src/config/zero-config.js +28 -149
  107. package/out/zero-cache/src/config/zero-config.js.map +1 -1
  108. package/out/zero-cache/src/custom-queries/transform-query.js +1 -1
  109. package/out/zero-cache/src/db/create.d.ts.map +1 -1
  110. package/out/zero-cache/src/db/create.js +1 -4
  111. package/out/zero-cache/src/db/create.js.map +1 -1
  112. package/out/zero-cache/src/db/lite-tables.d.ts +2 -10
  113. package/out/zero-cache/src/db/lite-tables.d.ts.map +1 -1
  114. package/out/zero-cache/src/db/lite-tables.js +6 -10
  115. package/out/zero-cache/src/db/lite-tables.js.map +1 -1
  116. package/out/zero-cache/src/db/specs.d.ts +0 -41
  117. package/out/zero-cache/src/db/specs.d.ts.map +1 -1
  118. package/out/zero-cache/src/db/specs.js +3 -30
  119. package/out/zero-cache/src/db/specs.js.map +1 -1
  120. package/out/zero-cache/src/observability/metrics.d.ts.map +1 -1
  121. package/out/zero-cache/src/observability/metrics.js +7 -2
  122. package/out/zero-cache/src/observability/metrics.js.map +1 -1
  123. package/out/zero-cache/src/server/change-streamer.d.ts.map +1 -1
  124. package/out/zero-cache/src/server/change-streamer.js +4 -13
  125. package/out/zero-cache/src/server/change-streamer.js.map +1 -1
  126. package/out/zero-cache/src/server/inspector-delegate.d.ts +2 -18
  127. package/out/zero-cache/src/server/inspector-delegate.d.ts.map +1 -1
  128. package/out/zero-cache/src/server/inspector-delegate.js +17 -25
  129. package/out/zero-cache/src/server/inspector-delegate.js.map +1 -1
  130. package/out/zero-cache/src/server/main.d.ts.map +1 -1
  131. package/out/zero-cache/src/server/main.js +1 -8
  132. package/out/zero-cache/src/server/main.js.map +1 -1
  133. package/out/zero-cache/src/server/mutator.js +0 -2
  134. package/out/zero-cache/src/server/mutator.js.map +1 -1
  135. package/out/zero-cache/src/server/reaper.d.ts.map +1 -1
  136. package/out/zero-cache/src/server/reaper.js +0 -2
  137. package/out/zero-cache/src/server/reaper.js.map +1 -1
  138. package/out/zero-cache/src/server/replicator.d.ts.map +1 -1
  139. package/out/zero-cache/src/server/replicator.js +2 -8
  140. package/out/zero-cache/src/server/replicator.js.map +1 -1
  141. package/out/zero-cache/src/server/runner/zero-dispatcher.d.ts.map +1 -1
  142. package/out/zero-cache/src/server/runner/zero-dispatcher.js +0 -3
  143. package/out/zero-cache/src/server/runner/zero-dispatcher.js.map +1 -1
  144. package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
  145. package/out/zero-cache/src/server/syncer.js +1 -5
  146. package/out/zero-cache/src/server/syncer.js.map +1 -1
  147. package/out/zero-cache/src/services/analyze.d.ts.map +1 -1
  148. package/out/zero-cache/src/services/analyze.js +9 -11
  149. package/out/zero-cache/src/services/analyze.js.map +1 -1
  150. package/out/zero-cache/src/services/change-source/common/backfill-manager.d.ts.map +1 -1
  151. package/out/zero-cache/src/services/change-source/common/backfill-manager.js +1 -14
  152. package/out/zero-cache/src/services/change-source/common/backfill-manager.js.map +1 -1
  153. package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.d.ts.map +1 -1
  154. package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.js +3 -15
  155. package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.js.map +1 -1
  156. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts +1 -11
  157. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts.map +1 -1
  158. package/out/zero-cache/src/services/change-source/pg/change-source.js +2 -21
  159. package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
  160. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts +0 -1
  161. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts.map +1 -1
  162. package/out/zero-cache/src/services/change-source/pg/initial-sync.js +7 -8
  163. package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
  164. package/out/zero-cache/src/services/change-source/pg/schema/ddl.d.ts +229 -1513
  165. package/out/zero-cache/src/services/change-source/pg/schema/ddl.d.ts.map +1 -1
  166. package/out/zero-cache/src/services/change-source/pg/schema/ddl.js +2 -2
  167. package/out/zero-cache/src/services/change-source/pg/schema/ddl.js.map +1 -1
  168. package/out/zero-cache/src/services/change-source/pg/schema/init.d.ts +1 -1
  169. package/out/zero-cache/src/services/change-source/pg/schema/init.d.ts.map +1 -1
  170. package/out/zero-cache/src/services/change-source/pg/schema/init.js +6 -15
  171. package/out/zero-cache/src/services/change-source/pg/schema/init.js.map +1 -1
  172. package/out/zero-cache/src/services/change-source/pg/schema/published.d.ts +20 -137
  173. package/out/zero-cache/src/services/change-source/pg/schema/published.d.ts.map +1 -1
  174. package/out/zero-cache/src/services/change-source/pg/schema/published.js +13 -82
  175. package/out/zero-cache/src/services/change-source/pg/schema/published.js.map +1 -1
  176. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts +21 -128
  177. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts.map +1 -1
  178. package/out/zero-cache/src/services/change-source/pg/schema/shard.js +5 -5
  179. package/out/zero-cache/src/services/change-source/pg/schema/shard.js.map +1 -1
  180. package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts +0 -2
  181. package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts.map +1 -1
  182. package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts +0 -3
  183. package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts.map +1 -1
  184. package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts +0 -3
  185. package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts.map +1 -1
  186. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +1 -3
  187. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
  188. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts +0 -1
  189. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts.map +1 -1
  190. package/out/zero-cache/src/services/litestream/commands.d.ts.map +1 -1
  191. package/out/zero-cache/src/services/litestream/commands.js +3 -8
  192. package/out/zero-cache/src/services/litestream/commands.js.map +1 -1
  193. package/out/zero-cache/src/services/litestream/config-v5.yml +1 -15
  194. package/out/zero-cache/src/services/mutagen/mutagen.d.ts +0 -5
  195. package/out/zero-cache/src/services/mutagen/mutagen.d.ts.map +1 -1
  196. package/out/zero-cache/src/services/mutagen/mutagen.js +1 -7
  197. package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -1
  198. package/out/zero-cache/src/services/mutagen/pusher.d.ts +119 -119
  199. package/out/zero-cache/src/services/mutagen/pusher.d.ts.map +1 -1
  200. package/out/zero-cache/src/services/mutagen/pusher.js +6 -5
  201. package/out/zero-cache/src/services/mutagen/pusher.js.map +1 -1
  202. package/out/zero-cache/src/services/replicator/change-processor.d.ts.map +1 -1
  203. package/out/zero-cache/src/services/replicator/change-processor.js +16 -16
  204. package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
  205. package/out/zero-cache/src/services/replicator/incremental-sync.d.ts.map +1 -1
  206. package/out/zero-cache/src/services/replicator/incremental-sync.js +0 -1
  207. package/out/zero-cache/src/services/replicator/incremental-sync.js.map +1 -1
  208. package/out/zero-cache/src/services/replicator/write-worker-client.d.ts +2 -27
  209. package/out/zero-cache/src/services/replicator/write-worker-client.d.ts.map +1 -1
  210. package/out/zero-cache/src/services/replicator/write-worker-client.js +2 -3
  211. package/out/zero-cache/src/services/replicator/write-worker-client.js.map +1 -1
  212. package/out/zero-cache/src/services/replicator/write-worker.js +5 -24
  213. package/out/zero-cache/src/services/replicator/write-worker.js.map +1 -1
  214. package/out/zero-cache/src/services/run-ast.d.ts +0 -12
  215. package/out/zero-cache/src/services/run-ast.d.ts.map +1 -1
  216. package/out/zero-cache/src/services/run-ast.js +15 -27
  217. package/out/zero-cache/src/services/run-ast.js.map +1 -1
  218. package/out/zero-cache/src/services/runner.d.ts.map +1 -1
  219. package/out/zero-cache/src/services/runner.js +1 -1
  220. package/out/zero-cache/src/services/runner.js.map +1 -1
  221. package/out/zero-cache/src/services/view-syncer/cvr.d.ts +0 -45
  222. package/out/zero-cache/src/services/view-syncer/cvr.d.ts.map +1 -1
  223. package/out/zero-cache/src/services/view-syncer/cvr.js +1 -133
  224. package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
  225. package/out/zero-cache/src/services/view-syncer/drain-coordinator.d.ts +1 -14
  226. package/out/zero-cache/src/services/view-syncer/drain-coordinator.d.ts.map +1 -1
  227. package/out/zero-cache/src/services/view-syncer/drain-coordinator.js +4 -30
  228. package/out/zero-cache/src/services/view-syncer/drain-coordinator.js.map +1 -1
  229. package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts +1 -1
  230. package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts.map +1 -1
  231. package/out/zero-cache/src/services/view-syncer/inspect-handler.js +2 -2
  232. package/out/zero-cache/src/services/view-syncer/inspect-handler.js.map +1 -1
  233. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts +1 -2
  234. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
  235. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +27 -48
  236. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
  237. package/out/zero-cache/src/services/view-syncer/query-covering.d.ts.map +1 -1
  238. package/out/zero-cache/src/services/view-syncer/query-covering.js +6 -2
  239. package/out/zero-cache/src/services/view-syncer/query-covering.js.map +1 -1
  240. package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts +4 -42
  241. package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts.map +1 -1
  242. package/out/zero-cache/src/services/view-syncer/snapshotter.js +28 -117
  243. package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
  244. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts +1 -11
  245. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
  246. package/out/zero-cache/src/services/view-syncer/view-syncer.js +95 -466
  247. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  248. package/out/zero-cache/src/types/processes.d.ts +0 -32
  249. package/out/zero-cache/src/types/processes.d.ts.map +1 -1
  250. package/out/zero-cache/src/types/processes.js +4 -43
  251. package/out/zero-cache/src/types/processes.js.map +1 -1
  252. package/out/zero-cache/src/types/profiler.d.ts +0 -12
  253. package/out/zero-cache/src/types/profiler.d.ts.map +1 -1
  254. package/out/zero-cache/src/types/profiler.js +1 -46
  255. package/out/zero-cache/src/types/profiler.js.map +1 -1
  256. package/out/zero-cache/src/types/row-key.d.ts.map +1 -1
  257. package/out/zero-cache/src/types/row-key.js +5 -5
  258. package/out/zero-cache/src/types/row-key.js.map +1 -1
  259. package/out/zero-cache/src/workers/connect-params.d.ts +7 -0
  260. package/out/zero-cache/src/workers/connect-params.d.ts.map +1 -1
  261. package/out/zero-cache/src/workers/connect-params.js +20 -1
  262. package/out/zero-cache/src/workers/connect-params.js.map +1 -1
  263. package/out/zero-cache/src/workers/connection.d.ts +4 -4
  264. package/out/zero-cache/src/workers/connection.d.ts.map +1 -1
  265. package/out/zero-cache/src/workers/connection.js +8 -8
  266. package/out/zero-cache/src/workers/connection.js.map +1 -1
  267. package/out/zero-cache/src/workers/replicator.d.ts +0 -1
  268. package/out/zero-cache/src/workers/replicator.d.ts.map +1 -1
  269. package/out/zero-cache/src/workers/replicator.js +2 -4
  270. package/out/zero-cache/src/workers/replicator.js.map +1 -1
  271. package/out/zero-cache/src/workers/syncer-ws-message-handler.d.ts.map +1 -1
  272. package/out/zero-cache/src/workers/syncer-ws-message-handler.js +16 -21
  273. package/out/zero-cache/src/workers/syncer-ws-message-handler.js.map +1 -1
  274. package/out/zero-cache/src/workers/syncer.d.ts.map +1 -1
  275. package/out/zero-cache/src/workers/syncer.js +1 -10
  276. package/out/zero-cache/src/workers/syncer.js.map +1 -1
  277. package/out/zero-client/src/client/connection-manager.d.ts +0 -20
  278. package/out/zero-client/src/client/connection-manager.d.ts.map +1 -1
  279. package/out/zero-client/src/client/connection-manager.js +13 -77
  280. package/out/zero-client/src/client/connection-manager.js.map +1 -1
  281. package/out/zero-client/src/client/connection-status-enum.d.ts +0 -2
  282. package/out/zero-client/src/client/connection-status-enum.d.ts.map +1 -1
  283. package/out/zero-client/src/client/connection-status-enum.js +1 -3
  284. package/out/zero-client/src/client/connection-status-enum.js.map +1 -1
  285. package/out/zero-client/src/client/connection.d.ts +0 -6
  286. package/out/zero-client/src/client/connection.d.ts.map +1 -1
  287. package/out/zero-client/src/client/connection.js +1 -2
  288. package/out/zero-client/src/client/connection.js.map +1 -1
  289. package/out/zero-client/src/client/context.d.ts +2 -27
  290. package/out/zero-client/src/client/context.d.ts.map +1 -1
  291. package/out/zero-client/src/client/context.js +1 -112
  292. package/out/zero-client/src/client/context.js.map +1 -1
  293. package/out/zero-client/src/client/custom.js +2 -2
  294. package/out/zero-client/src/client/custom.js.map +1 -1
  295. package/out/zero-client/src/client/error.js +1 -1
  296. package/out/zero-client/src/client/inspector/lazy-inspector.js +2 -2
  297. package/out/zero-client/src/client/inspector/lazy-inspector.js.map +1 -1
  298. package/out/zero-client/src/client/ivm-branch.d.ts.map +1 -1
  299. package/out/zero-client/src/client/ivm-branch.js +3 -20
  300. package/out/zero-client/src/client/ivm-branch.js.map +1 -1
  301. package/out/zero-client/src/client/mutation-tracker.d.ts.map +1 -1
  302. package/out/zero-client/src/client/mutation-tracker.js +1 -1
  303. package/out/zero-client/src/client/mutation-tracker.js.map +1 -1
  304. package/out/zero-client/src/client/mutator-proxy.d.ts.map +1 -1
  305. package/out/zero-client/src/client/mutator-proxy.js +1 -2
  306. package/out/zero-client/src/client/mutator-proxy.js.map +1 -1
  307. package/out/zero-client/src/client/options.d.ts +0 -3
  308. package/out/zero-client/src/client/options.d.ts.map +1 -1
  309. package/out/zero-client/src/client/options.js.map +1 -1
  310. package/out/zero-client/src/client/query-manager.d.ts +0 -2
  311. package/out/zero-client/src/client/query-manager.d.ts.map +1 -1
  312. package/out/zero-client/src/client/query-manager.js +14 -50
  313. package/out/zero-client/src/client/query-manager.js.map +1 -1
  314. package/out/zero-client/src/client/version.js +1 -1
  315. package/out/zero-client/src/client/zero-rep.d.ts +0 -1
  316. package/out/zero-client/src/client/zero-rep.d.ts.map +1 -1
  317. package/out/zero-client/src/client/zero-rep.js +6 -9
  318. package/out/zero-client/src/client/zero-rep.js.map +1 -1
  319. package/out/zero-client/src/client/zero.d.ts +3 -18
  320. package/out/zero-client/src/client/zero.d.ts.map +1 -1
  321. package/out/zero-client/src/client/zero.js +36 -123
  322. package/out/zero-client/src/client/zero.js.map +1 -1
  323. package/out/zero-client/src/types/query-result.d.ts +0 -2
  324. package/out/zero-client/src/types/query-result.d.ts.map +1 -1
  325. package/out/zero-protocol/src/analyze-query-result.d.ts +5 -5
  326. package/out/zero-protocol/src/analyze-query-result.d.ts.map +1 -1
  327. package/out/zero-protocol/src/analyze-query-result.js +1 -1
  328. package/out/zero-protocol/src/analyze-query-result.js.map +1 -1
  329. package/out/zero-protocol/src/ast.d.ts +1 -64
  330. package/out/zero-protocol/src/ast.d.ts.map +1 -1
  331. package/out/zero-protocol/src/ast.js +54 -225
  332. package/out/zero-protocol/src/ast.js.map +1 -1
  333. package/out/zero-protocol/src/connect.d.ts +13 -0
  334. package/out/zero-protocol/src/connect.d.ts.map +1 -1
  335. package/out/zero-protocol/src/connect.js +30 -1
  336. package/out/zero-protocol/src/connect.js.map +1 -1
  337. package/out/zero-protocol/src/down.d.ts +2 -2
  338. package/out/zero-protocol/src/error.d.ts +1 -1
  339. package/out/zero-protocol/src/inspect-down.d.ts +6 -6
  340. package/out/zero-protocol/src/poke.d.ts +11 -4
  341. package/out/zero-protocol/src/poke.d.ts.map +1 -1
  342. package/out/zero-protocol/src/poke.js +3 -2
  343. package/out/zero-protocol/src/poke.js.map +1 -1
  344. package/out/zero-protocol/src/protocol-flag-enum.d.ts +7 -0
  345. package/out/zero-protocol/src/protocol-flag-enum.d.ts.map +1 -0
  346. package/out/zero-protocol/src/protocol-flag-enum.js +7 -0
  347. package/out/zero-protocol/src/protocol-flag-enum.js.map +1 -0
  348. package/out/zero-protocol/src/protocol-flag.d.ts +14 -0
  349. package/out/zero-protocol/src/protocol-flag.d.ts.map +1 -0
  350. package/out/zero-protocol/src/protocol-flag.js +8 -0
  351. package/out/zero-protocol/src/protocol-flag.js.map +1 -0
  352. package/out/zero-protocol/src/protocol-version.d.ts +30 -6
  353. package/out/zero-protocol/src/protocol-version.d.ts.map +1 -1
  354. package/out/zero-protocol/src/protocol-version.js +1 -1
  355. package/out/zero-protocol/src/protocol-version.js.map +1 -1
  356. package/out/zero-protocol/src/query-hash.d.ts +2 -7
  357. package/out/zero-protocol/src/query-hash.d.ts.map +1 -1
  358. package/out/zero-protocol/src/query-hash.js +10 -10
  359. package/out/zero-protocol/src/query-hash.js.map +1 -1
  360. package/out/zero-react/src/use-query.d.ts +4 -5
  361. package/out/zero-react/src/use-query.d.ts.map +1 -1
  362. package/out/zero-react/src/use-query.js +9 -86
  363. package/out/zero-react/src/use-query.js.map +1 -1
  364. package/out/zero-solid/src/solid-view.d.ts +0 -17
  365. package/out/zero-solid/src/solid-view.d.ts.map +1 -1
  366. package/out/zero-solid/src/solid-view.js +1 -39
  367. package/out/zero-solid/src/solid-view.js.map +1 -1
  368. package/out/zero-solid/src/use-query.js +3 -5
  369. package/out/zero-solid/src/use-query.js.map +1 -1
  370. package/out/zql/src/builder/builder.d.ts +0 -19
  371. package/out/zql/src/builder/builder.d.ts.map +1 -1
  372. package/out/zql/src/builder/builder.js +11 -28
  373. package/out/zql/src/builder/builder.js.map +1 -1
  374. package/out/zql/src/builder/debug-delegate.d.ts +1 -6
  375. package/out/zql/src/builder/debug-delegate.d.ts.map +1 -1
  376. package/out/zql/src/builder/debug-delegate.js +2 -14
  377. package/out/zql/src/builder/debug-delegate.js.map +1 -1
  378. package/out/zql/src/ivm/array-view.d.ts +0 -29
  379. package/out/zql/src/ivm/array-view.d.ts.map +1 -1
  380. package/out/zql/src/ivm/array-view.js +12 -63
  381. package/out/zql/src/ivm/array-view.js.map +1 -1
  382. package/out/zql/src/ivm/cap.d.ts.map +1 -1
  383. package/out/zql/src/ivm/cap.js +3 -5
  384. package/out/zql/src/ivm/cap.js.map +1 -1
  385. package/out/zql/src/ivm/data.d.ts.map +1 -1
  386. package/out/zql/src/ivm/data.js +3 -8
  387. package/out/zql/src/ivm/data.js.map +1 -1
  388. package/out/zql/src/ivm/exists.d.ts +1 -1
  389. package/out/zql/src/ivm/exists.d.ts.map +1 -1
  390. package/out/zql/src/ivm/exists.js.map +1 -1
  391. package/out/zql/src/ivm/fan-in.d.ts +2 -2
  392. package/out/zql/src/ivm/fan-in.d.ts.map +1 -1
  393. package/out/zql/src/ivm/fan-in.js +5 -6
  394. package/out/zql/src/ivm/fan-in.js.map +1 -1
  395. package/out/zql/src/ivm/fan-out.d.ts +2 -2
  396. package/out/zql/src/ivm/fan-out.d.ts.map +1 -1
  397. package/out/zql/src/ivm/fan-out.js.map +1 -1
  398. package/out/zql/src/ivm/filter-operators.d.ts +6 -7
  399. package/out/zql/src/ivm/filter-operators.d.ts.map +1 -1
  400. package/out/zql/src/ivm/filter-operators.js +12 -29
  401. package/out/zql/src/ivm/filter-operators.js.map +1 -1
  402. package/out/zql/src/ivm/filter.d.ts +2 -2
  403. package/out/zql/src/ivm/filter.d.ts.map +1 -1
  404. package/out/zql/src/ivm/filter.js +4 -7
  405. package/out/zql/src/ivm/filter.js.map +1 -1
  406. package/out/zql/src/ivm/flipped-join.js +2 -2
  407. package/out/zql/src/ivm/flipped-join.js.map +1 -1
  408. package/out/zql/src/ivm/maybe-split-and-push-edit-change.d.ts +1 -1
  409. package/out/zql/src/ivm/maybe-split-and-push-edit-change.d.ts.map +1 -1
  410. package/out/zql/src/ivm/maybe-split-and-push-edit-change.js +4 -6
  411. package/out/zql/src/ivm/maybe-split-and-push-edit-change.js.map +1 -1
  412. package/out/zql/src/ivm/memory-source.d.ts +3 -15
  413. package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
  414. package/out/zql/src/ivm/memory-source.js +23 -57
  415. package/out/zql/src/ivm/memory-source.js.map +1 -1
  416. package/out/zql/src/ivm/operator.d.ts +0 -40
  417. package/out/zql/src/ivm/operator.d.ts.map +1 -1
  418. package/out/zql/src/ivm/operator.js.map +1 -1
  419. package/out/zql/src/ivm/take.d.ts.map +1 -1
  420. package/out/zql/src/ivm/take.js +4 -3
  421. package/out/zql/src/ivm/take.js.map +1 -1
  422. package/out/zql/src/ivm/union-fan-in.d.ts.map +1 -1
  423. package/out/zql/src/ivm/union-fan-in.js +7 -9
  424. package/out/zql/src/ivm/union-fan-in.js.map +1 -1
  425. package/out/zql/src/ivm/view-apply-change.d.ts.map +1 -1
  426. package/out/zql/src/ivm/view-apply-change.js +4 -9
  427. package/out/zql/src/ivm/view-apply-change.js.map +1 -1
  428. package/out/zql/src/ivm/view.d.ts +0 -15
  429. package/out/zql/src/ivm/view.d.ts.map +1 -1
  430. package/out/zql/src/mutate/mutator-registry.d.ts.map +1 -1
  431. package/out/zql/src/mutate/mutator-registry.js +2 -2
  432. package/out/zql/src/mutate/mutator-registry.js.map +1 -1
  433. package/out/zql/src/planner/planner-builder.d.ts +3 -12
  434. package/out/zql/src/planner/planner-builder.d.ts.map +1 -1
  435. package/out/zql/src/planner/planner-builder.js +20 -40
  436. package/out/zql/src/planner/planner-builder.js.map +1 -1
  437. package/out/zql/src/planner/planner-connection.d.ts +2 -28
  438. package/out/zql/src/planner/planner-connection.d.ts.map +1 -1
  439. package/out/zql/src/planner/planner-connection.js +8 -108
  440. package/out/zql/src/planner/planner-connection.js.map +1 -1
  441. package/out/zql/src/planner/planner-debug.d.ts +1 -1
  442. package/out/zql/src/planner/planner-debug.d.ts.map +1 -1
  443. package/out/zql/src/planner/planner-debug.js +8 -3
  444. package/out/zql/src/planner/planner-debug.js.map +1 -1
  445. package/out/zql/src/planner/planner-fan-out.d.ts +0 -1
  446. package/out/zql/src/planner/planner-fan-out.d.ts.map +1 -1
  447. package/out/zql/src/planner/planner-fan-out.js +0 -3
  448. package/out/zql/src/planner/planner-fan-out.js.map +1 -1
  449. package/out/zql/src/planner/planner-graph.d.ts +0 -2
  450. package/out/zql/src/planner/planner-graph.d.ts.map +1 -1
  451. package/out/zql/src/planner/planner-graph.js +0 -2
  452. package/out/zql/src/planner/planner-graph.js.map +1 -1
  453. package/out/zql/src/planner/planner-join.d.ts +0 -2
  454. package/out/zql/src/planner/planner-join.d.ts.map +1 -1
  455. package/out/zql/src/planner/planner-join.js +0 -7
  456. package/out/zql/src/planner/planner-join.js.map +1 -1
  457. package/out/zql/src/planner/planner-node.d.ts +1 -2
  458. package/out/zql/src/planner/planner-node.d.ts.map +1 -1
  459. package/out/zql/src/planner/planner-node.js.map +1 -1
  460. package/out/zql/src/planner/planner-source.d.ts +2 -2
  461. package/out/zql/src/planner/planner-source.d.ts.map +1 -1
  462. package/out/zql/src/planner/planner-source.js +2 -2
  463. package/out/zql/src/planner/planner-source.js.map +1 -1
  464. package/out/zql/src/query/query-delegate-base.d.ts +1 -9
  465. package/out/zql/src/query/query-delegate-base.d.ts.map +1 -1
  466. package/out/zql/src/query/query-delegate-base.js +36 -132
  467. package/out/zql/src/query/query-delegate-base.js.map +1 -1
  468. package/out/zql/src/query/query-delegate.d.ts +1 -50
  469. package/out/zql/src/query/query-delegate.d.ts.map +1 -1
  470. package/out/zql/src/query/query-impl.d.ts +14 -25
  471. package/out/zql/src/query/query-impl.d.ts.map +1 -1
  472. package/out/zql/src/query/query-impl.js +94 -397
  473. package/out/zql/src/query/query-impl.js.map +1 -1
  474. package/out/zql/src/query/query-internals.d.ts +11 -21
  475. package/out/zql/src/query/query-internals.d.ts.map +1 -1
  476. package/out/zql/src/query/query-internals.js.map +1 -1
  477. package/out/zql/src/query/query.d.ts +2 -11
  478. package/out/zql/src/query/query.d.ts.map +1 -1
  479. package/out/zql/src/query/runnable-query-impl.d.ts +2 -3
  480. package/out/zql/src/query/runnable-query-impl.d.ts.map +1 -1
  481. package/out/zql/src/query/runnable-query-impl.js +2 -15
  482. package/out/zql/src/query/runnable-query-impl.js.map +1 -1
  483. package/out/zql/src/query/typed-view.d.ts +1 -1
  484. package/out/zql/src/query/typed-view.d.ts.map +1 -1
  485. package/out/zqlite/src/db.d.ts +1 -9
  486. package/out/zqlite/src/db.d.ts.map +1 -1
  487. package/out/zqlite/src/db.js +2 -8
  488. package/out/zqlite/src/db.js.map +1 -1
  489. package/out/zqlite/src/query-builder.d.ts +1 -1
  490. package/out/zqlite/src/query-builder.d.ts.map +1 -1
  491. package/out/zqlite/src/query-builder.js +2 -4
  492. package/out/zqlite/src/query-builder.js.map +1 -1
  493. package/out/zqlite/src/query-delegate.d.ts.map +1 -1
  494. package/out/zqlite/src/query-delegate.js +6 -5
  495. package/out/zqlite/src/query-delegate.js.map +1 -1
  496. package/out/zqlite/src/sqlite-cost-model.d.ts.map +1 -1
  497. package/out/zqlite/src/sqlite-cost-model.js +30 -2
  498. package/out/zqlite/src/sqlite-cost-model.js.map +1 -1
  499. package/out/zqlite/src/sqlite-stat-fanout.d.ts.map +1 -1
  500. package/out/zqlite/src/sqlite-stat-fanout.js +5 -4
  501. package/out/zqlite/src/sqlite-stat-fanout.js.map +1 -1
  502. package/out/zqlite/src/table-source.d.ts +3 -16
  503. package/out/zqlite/src/table-source.d.ts.map +1 -1
  504. package/out/zqlite/src/table-source.js +14 -33
  505. package/out/zqlite/src/table-source.js.map +1 -1
  506. package/package.json +3 -2
  507. package/out/replicache/src/dag/invalid-ref-count-error.d.ts +0 -12
  508. package/out/replicache/src/dag/invalid-ref-count-error.d.ts.map +0 -1
  509. package/out/replicache/src/dag/invalid-ref-count-error.js +0 -19
  510. package/out/replicache/src/dag/invalid-ref-count-error.js.map +0 -1
  511. package/out/shared/src/xxhash32.d.ts +0 -36
  512. package/out/shared/src/xxhash32.d.ts.map +0 -1
  513. package/out/shared/src/xxhash32.js +0 -51
  514. package/out/shared/src/xxhash32.js.map +0 -1
  515. package/out/zero-cache/src/db/index-predicate.d.ts +0 -4
  516. package/out/zero-cache/src/db/index-predicate.d.ts.map +0 -1
  517. package/out/zero-cache/src/db/index-predicate.js +0 -46
  518. package/out/zero-cache/src/db/index-predicate.js.map +0 -1
  519. package/out/zero-cache/src/services/change-source/pg/schema/index-predicate.d.ts +0 -19
  520. package/out/zero-cache/src/services/change-source/pg/schema/index-predicate.d.ts.map +0 -1
  521. package/out/zero-cache/src/services/change-source/pg/schema/index-predicate.js +0 -581
  522. package/out/zero-cache/src/services/change-source/pg/schema/index-predicate.js.map +0 -1
  523. package/out/zero-cache/src/services/litestream/litestream-checkpointer.js +0 -131
  524. package/out/zero-cache/src/services/litestream/litestream-checkpointer.js.map +0 -1
  525. package/out/zero-cache/src/services/litestream/litestream-controller.d.ts +0 -70
  526. package/out/zero-cache/src/services/litestream/litestream-controller.d.ts.map +0 -1
  527. package/out/zero-cache/src/services/litestream/litestream-controller.js +0 -101
  528. package/out/zero-cache/src/services/litestream/litestream-controller.js.map +0 -1
  529. package/out/zero-cache/src/services/profz.d.ts +0 -7
  530. package/out/zero-cache/src/services/profz.d.ts.map +0 -1
  531. package/out/zero-cache/src/services/profz.js +0 -103
  532. package/out/zero-cache/src/services/profz.js.map +0 -1
  533. package/out/zero-cache/src/services/view-syncer/hydration-budget.d.ts +0 -33
  534. package/out/zero-cache/src/services/view-syncer/hydration-budget.d.ts.map +0 -1
  535. package/out/zero-cache/src/services/view-syncer/hydration-budget.js +0 -62
  536. package/out/zero-cache/src/services/view-syncer/hydration-budget.js.map +0 -1
  537. package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.d.ts +0 -51
  538. package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.d.ts.map +0 -1
  539. package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.js +0 -78
  540. package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.js.map +0 -1
  541. package/out/zero-cache/src/services/view-syncer/snapshot-row-cache.d.ts +0 -95
  542. package/out/zero-cache/src/services/view-syncer/snapshot-row-cache.d.ts.map +0 -1
  543. package/out/zero-cache/src/services/view-syncer/snapshot-row-cache.js +0 -155
  544. package/out/zero-cache/src/services/view-syncer/snapshot-row-cache.js.map +0 -1
  545. package/out/zero-protocol/src/query-hash-visitor.d.ts +0 -81
  546. package/out/zero-protocol/src/query-hash-visitor.d.ts.map +0 -1
  547. package/out/zero-protocol/src/query-hash-visitor.js +0 -324
  548. package/out/zero-protocol/src/query-hash-visitor.js.map +0 -1
  549. package/out/zql/src/builder/correlated-predicate-pushdown.d.ts +0 -43
  550. package/out/zql/src/builder/correlated-predicate-pushdown.d.ts.map +0 -1
  551. package/out/zql/src/builder/correlated-predicate-pushdown.js +0 -161
  552. package/out/zql/src/builder/correlated-predicate-pushdown.js.map +0 -1
  553. package/out/zql/src/ivm/connection-index.d.ts +0 -68
  554. package/out/zql/src/ivm/connection-index.d.ts.map +0 -1
  555. package/out/zql/src/ivm/connection-index.js +0 -149
  556. package/out/zql/src/ivm/connection-index.js.map +0 -1
  557. package/out/zql/src/ivm/deferred-input.d.ts +0 -44
  558. package/out/zql/src/ivm/deferred-input.d.ts.map +0 -1
  559. package/out/zql/src/ivm/deferred-input.js +0 -89
  560. package/out/zql/src/ivm/deferred-input.js.map +0 -1
  561. package/out/zql/src/planner/planner-filter.d.ts +0 -59
  562. package/out/zql/src/planner/planner-filter.d.ts.map +0 -1
  563. package/out/zql/src/planner/planner-filter.js +0 -116
  564. package/out/zql/src/planner/planner-filter.js.map +0 -1
  565. package/out/zql/src/query/query-transitions.d.ts +0 -171
  566. package/out/zql/src/query/query-transitions.d.ts.map +0 -1
  567. package/out/zql/src/query/query-transitions.js +0 -204
  568. package/out/zql/src/query/query-transitions.js.map +0 -1
@@ -1,131 +0,0 @@
1
- import { AbortError } from "../../../../shared/src/abort-error.js";
2
- import { RunningState } from "../running-state.js";
3
- //#region ../zero-cache/src/services/litestream/litestream-checkpointer.ts
4
- var SOFT_CHECKPOINT_WAIT_MS = 1e4;
5
- var LITESTREAM_SYNC_TIMEOUT_MS = 5 * 6e4;
6
- var PAUSE_POLL_INTERVAL_MS = 1e3;
7
- var PAUSE_LOG_INTERVAL_POLLS = 30;
8
- /**
9
- * Forces litestream to checkpoint the WAL from the write path, so a sustained
10
- * high write rate can't grow the WAL until litestream's own blocking TRUNCATE
11
- * checkpoint locks the db (see ReplicationPauseCheckpointConfig).
12
- *
13
- * Two tiers:
14
- * - Soft (`checkpointThresholdPages`): after each committed transaction,
15
- * once the un-checkpointed WAL backlog reaches the threshold, force an
16
- * immediate litestream sync (which seals the WAL to LTX and attempts
17
- * litestream's own PASSIVE checkpoint) and block the write path until it
18
- * completes, but only up to {@link SOFT_CHECKPOINT_WAIT_MS}. Waiting is the
19
- * backpressure: it throttles upstream reads to litestream's WAL-seal rate
20
- * and, in the common case, gives litestream a window to checkpoint without
21
- * writer interference. A single sync is kept in flight at a time
22
- * (`#pendingSync`): if one is still running when the budget elapses, the
23
- * writer proceeds and the next commit waits for that sync rather than
24
- * issuing (and orphaning) another. Backs off by a full threshold's worth of
25
- * WAL growth whenever an attempt fails to drain the WAL (e.g. litestream
26
- * is mid-snapshot and its checkpoints are being skipped), so repeated
27
- * failures don't reattempt on every commit.
28
- * - Hard (`walMaxPages`, optional): if the WAL still exceeds this cap after
29
- * a soft attempt, pause (block the caller) polling litestream until the
30
- * WAL drains below it. This is the fail-safe against unbounded WAL growth
31
- * when litestream structurally cannot checkpoint — e.g. an in-progress
32
- * snapshot holds litestream's checkpoint lock for its full duration, so
33
- * neither PASSIVE nor TRUNCATE checkpoints can run until it completes.
34
- */
35
- var LitestreamCheckpointer = class {
36
- #lc;
37
- #db;
38
- #litestream;
39
- #attemptChunk;
40
- #maxWalPages;
41
- #state = new RunningState("litestream-checkpointer");
42
- #nextWalThreshold;
43
- #pendingSync;
44
- constructor(lc, db, litestream, config) {
45
- this.#lc = lc.withContext("component", "litestream-checkpointer");
46
- this.#db = db;
47
- this.#litestream = litestream;
48
- this.#attemptChunk = config.checkpointThresholdPages;
49
- this.#nextWalThreshold = config.checkpointThresholdPages;
50
- this.#maxWalPages = config.maxWalPages;
51
- }
52
- #getNumWalPages() {
53
- const [{ log, checkpointed }] = this.#db.pragma("wal_checkpoint(NOOP)");
54
- return log - checkpointed;
55
- }
56
- /**
57
- * Call after a committed transaction. No-ops unless the WAL has grown to
58
- * at least the current threshold, in which case it triggers a litestream
59
- * sync to perform a checkpoint. Assuming that snapshots are disabled, the
60
- * checkpoint always succeeds. In the case where the server is configured to
61
- * perform snapshots and checkpoints fail, the "emergency break"
62
- * {@link #pauseUntilWalDrained()} option provides the disk use protection
63
- * that litestream's (disabled) truncate-page-n would have served.
64
- */
65
- async maybeCheckpoint() {
66
- let walPages = this.#getNumWalPages();
67
- if (walPages < this.#nextWalThreshold) return;
68
- this.#pendingSync ??= this.#sync(walPages);
69
- await this.#waitFor(this.#pendingSync, SOFT_CHECKPOINT_WAIT_MS);
70
- walPages = this.#getNumWalPages();
71
- if (this.#maxWalPages !== void 0 && walPages > this.#maxWalPages) walPages = await this.#pauseUntilWalDrained(this.#maxWalPages);
72
- this.#nextWalThreshold = walPages + this.#attemptChunk;
73
- }
74
- async #waitFor(p, timeoutMs) {
75
- if (await Promise.race([p, this.#state.sleep(timeoutMs).then(() => "timed-out")]) === "timed-out") this.#lc.warn?.(`timed out waiting for /sync result (${timeoutMs}ms)`);
76
- }
77
- /**
78
- * Runs a single litestream sync, logs its outcome, and clears
79
- * {@link #pendingSync} when it settles. Never rejects: sync failures and
80
- * post-sync bookkeeping errors (e.g. the db being closed during shutdown)
81
- * are caught and logged, so the shared promise can be awaited from multiple
82
- * places without risking an unhandled rejection.
83
- */
84
- async #sync(walPagesBefore) {
85
- const start = performance.now();
86
- let result;
87
- let err;
88
- try {
89
- try {
90
- result = await this.#litestream.sync({
91
- wait: false,
92
- timeoutMs: LITESTREAM_SYNC_TIMEOUT_MS
93
- }, this.#state.signal);
94
- } catch (e) {
95
- err = e;
96
- }
97
- const elapsed = performance.now() - start;
98
- const newWalPages = this.#getNumWalPages();
99
- if (newWalPages < this.#nextWalThreshold) this.#lc.info?.(`checkpointed ${walPagesBefore} -> ${newWalPages} wal pages (${elapsed.toFixed(2)} ms)`, result);
100
- else if (result) this.#lc.warn?.(`checkpoint skipped ${walPagesBefore} -> ${newWalPages}. a snapshot may be in progress (${elapsed.toFixed(2)} ms)`, result);
101
- else this.#lc.warn?.(`checkpoint failed ${walPagesBefore} -> ${newWalPages} (${elapsed.toFixed(2)} ms)`, err);
102
- } catch (e) {
103
- this.#lc.warn?.("litestream-checkpointer sync post-processing failed", e);
104
- } finally {
105
- this.#pendingSync = void 0;
106
- }
107
- }
108
- async #pauseUntilWalDrained(maxWalPages) {
109
- for (let i = 0; this.#state.shouldRun(); i++) {
110
- const walPages = this.#getNumWalPages();
111
- if (walPages < maxWalPages) {
112
- this.#lc.info?.(`wal size (${walPages} pages) is under the max limit of ${maxWalPages}`);
113
- return walPages;
114
- }
115
- if (i % PAUSE_LOG_INTERVAL_POLLS === 0) this.#lc.warn?.(`waiting for litestream to successfully checkpoint ${walPages} wal pages`);
116
- await this.#state.sleep(PAUSE_POLL_INTERVAL_MS);
117
- this.#pendingSync ??= this.#sync(this.#getNumWalPages());
118
- await this.#pendingSync;
119
- }
120
- throw new AbortError("litestream-controller stopped");
121
- }
122
- /** Releases the underlying litestream controller's connection. */
123
- close() {
124
- this.#litestream.close();
125
- this.#state.stop(this.#lc);
126
- }
127
- };
128
- //#endregion
129
- export { LitestreamCheckpointer };
130
-
131
- //# sourceMappingURL=litestream-checkpointer.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"litestream-checkpointer.js","names":["#lc","#db","#litestream","#attemptChunk","#maxWalPages","#state","#nextWalThreshold","#getNumWalPages","#pendingSync","#sync","#waitFor","#pauseUntilWalDrained"],"sources":["../../../../../../zero-cache/src/services/litestream/litestream-checkpointer.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {AbortError} from '../../../../shared/src/abort-error.ts';\nimport type {Database} from '../../../../zqlite/src/db.ts';\nimport type {ForceCheckpointConfig} from '../replicator/write-worker-client.ts';\nimport {RunningState} from '../running-state.ts';\nimport type {\n LitestreamController,\n SyncResponse,\n} from './litestream-controller.ts';\n\n// How long the soft path blocks the write path waiting for an in-flight sync\n// before letting the writer proceed. This is a backpressure knob, *not* a\n// request timeout: letting it elapse leaves the sync running (see #pendingSync)\n// rather than abandoning it. In normal operation litestream seals + runs its\n// PASSIVE checkpoint well within this budget; a sync that regularly exceeds it\n// indicates a litestream-side problem to fix (e.g. unintended snapshot), not a\n// value to raise.\nexport const SOFT_CHECKPOINT_WAIT_MS = 10_000;\n// Liveness bound on the /sync request itself, well above the soft wait budget.\n// It exists only to recover from a genuinely wedged litestream (so #pendingSync\n// can't hang forever).\nconst LITESTREAM_SYNC_TIMEOUT_MS = 5 * 60_000;\nconst PAUSE_POLL_INTERVAL_MS = 1_000;\nconst PAUSE_LOG_INTERVAL_POLLS = 30;\n\n/**\n * Forces litestream to checkpoint the WAL from the write path, so a sustained\n * high write rate can't grow the WAL until litestream's own blocking TRUNCATE\n * checkpoint locks the db (see ReplicationPauseCheckpointConfig).\n *\n * Two tiers:\n * - Soft (`checkpointThresholdPages`): after each committed transaction,\n * once the un-checkpointed WAL backlog reaches the threshold, force an\n * immediate litestream sync (which seals the WAL to LTX and attempts\n * litestream's own PASSIVE checkpoint) and block the write path until it\n * completes, but only up to {@link SOFT_CHECKPOINT_WAIT_MS}. Waiting is the\n * backpressure: it throttles upstream reads to litestream's WAL-seal rate\n * and, in the common case, gives litestream a window to checkpoint without\n * writer interference. A single sync is kept in flight at a time\n * (`#pendingSync`): if one is still running when the budget elapses, the\n * writer proceeds and the next commit waits for that sync rather than\n * issuing (and orphaning) another. Backs off by a full threshold's worth of\n * WAL growth whenever an attempt fails to drain the WAL (e.g. litestream\n * is mid-snapshot and its checkpoints are being skipped), so repeated\n * failures don't reattempt on every commit.\n * - Hard (`walMaxPages`, optional): if the WAL still exceeds this cap after\n * a soft attempt, pause (block the caller) polling litestream until the\n * WAL drains below it. This is the fail-safe against unbounded WAL growth\n * when litestream structurally cannot checkpoint — e.g. an in-progress\n * snapshot holds litestream's checkpoint lock for its full duration, so\n * neither PASSIVE nor TRUNCATE checkpoints can run until it completes.\n */\nexport class LitestreamCheckpointer {\n readonly #lc: LogContext;\n readonly #db: Database;\n readonly #litestream: LitestreamController;\n readonly #attemptChunk: number;\n readonly #maxWalPages: number | undefined;\n readonly #state = new RunningState('litestream-checkpointer');\n #nextWalThreshold: number;\n #pendingSync: Promise<void> | undefined;\n\n constructor(\n lc: LogContext,\n db: Database,\n litestream: LitestreamController,\n config: ForceCheckpointConfig,\n ) {\n this.#lc = lc.withContext('component', 'litestream-checkpointer');\n this.#db = db;\n this.#litestream = litestream;\n this.#attemptChunk = config.checkpointThresholdPages;\n this.#nextWalThreshold = config.checkpointThresholdPages;\n this.#maxWalPages = config.maxWalPages;\n }\n\n #getNumWalPages(): number {\n // wal_checkpoint(NOOP) reads WAL status without doing any work: `log` is\n // the current WAL frame count and `checkpointed` is how many of those\n // frames are already applied to the main db, so `log - checkpointed` is\n // the un-checkpointed backlog that a forced sync would actually drain.\n // (Both reset once litestream restarts the WAL.)\n const [{log, checkpointed}] = this.#db.pragma<{\n log: number;\n checkpointed: number;\n }>('wal_checkpoint(NOOP)');\n return log - checkpointed;\n }\n\n /**\n * Call after a committed transaction. No-ops unless the WAL has grown to\n * at least the current threshold, in which case it triggers a litestream\n * sync to perform a checkpoint. Assuming that snapshots are disabled, the\n * checkpoint always succeeds. In the case where the server is configured to\n * perform snapshots and checkpoints fail, the \"emergency break\"\n * {@link #pauseUntilWalDrained()} option provides the disk use protection\n * that litestream's (disabled) truncate-page-n would have served.\n */\n async maybeCheckpoint(): Promise<void> {\n let walPages = this.#getNumWalPages();\n if (walPages < this.#nextWalThreshold) {\n return;\n }\n\n // Single-flight: reuse the outstanding sync if one is already running.\n this.#pendingSync ??= this.#sync(walPages);\n\n // Soft backpressure: block the write path until the sync completes, but no\n // longer than the wait budget. Letting the budget elapse lets the writer\n // proceed *without* cancelling the sync (it keeps running, tracked by\n // #pendingSync); unbounded WAL growth is caught by the hard cap below.\n await this.#waitFor(this.#pendingSync, SOFT_CHECKPOINT_WAIT_MS);\n\n walPages = this.#getNumWalPages();\n if (this.#maxWalPages !== undefined && walPages > this.#maxWalPages) {\n // Emergency brake when best-effort checkpoints are being skipped\n // (i.e. during a snapshot) and the WAL is approaching disk capacity.\n // Pausing replication is favorable to litestream's truncate-page-n\n // because the latter involves re-encoding the database under the lock\n // (https://github.com/benbjohnson/litestream/issues/1332), which would\n // incur the full latency of an additional snapshot.\n walPages = await this.#pauseUntilWalDrained(this.#maxWalPages);\n }\n\n // In the common case where checkpoints are successful, this is always\n // just `attemptChunk`. When a checkpoint doesn't drain the WAL (e.g.\n // litestream is performing a snapshot), wait for another chunk of growth\n // before the next attempt.\n this.#nextWalThreshold = walPages + this.#attemptChunk;\n }\n\n async #waitFor(p: Promise<void>, timeoutMs: number): Promise<void> {\n const result = await Promise.race([\n p,\n this.#state.sleep(timeoutMs).then(() => 'timed-out' as const),\n ]);\n if (result === 'timed-out') {\n this.#lc.warn?.(`timed out waiting for /sync result (${timeoutMs}ms)`);\n }\n }\n\n /**\n * Runs a single litestream sync, logs its outcome, and clears\n * {@link #pendingSync} when it settles. Never rejects: sync failures and\n * post-sync bookkeeping errors (e.g. the db being closed during shutdown)\n * are caught and logged, so the shared promise can be awaited from multiple\n * places without risking an unhandled rejection.\n */\n async #sync(walPagesBefore: number): Promise<void> {\n const start = performance.now();\n let result: SyncResponse | undefined;\n let err: unknown;\n try {\n try {\n result = await this.#litestream.sync(\n {wait: false, timeoutMs: LITESTREAM_SYNC_TIMEOUT_MS},\n this.#state.signal,\n );\n } catch (e) {\n err = e;\n }\n\n const elapsed = performance.now() - start;\n const newWalPages = this.#getNumWalPages();\n if (newWalPages < this.#nextWalThreshold) {\n this.#lc.info?.(\n `checkpointed ${walPagesBefore} -> ${newWalPages} wal pages (${elapsed.toFixed(2)} ms)`,\n result,\n );\n } else if (result) {\n this.#lc.warn?.(\n `checkpoint skipped ${walPagesBefore} -> ${newWalPages}. a snapshot may be in progress (${elapsed.toFixed(2)} ms)`,\n result,\n );\n } else {\n this.#lc.warn?.(\n `checkpoint failed ${walPagesBefore} -> ${newWalPages} (${elapsed.toFixed(2)} ms)`,\n err,\n );\n }\n } catch (e) {\n this.#lc.warn?.('litestream-checkpointer sync post-processing failed', e);\n } finally {\n this.#pendingSync = undefined;\n }\n }\n\n async #pauseUntilWalDrained(maxWalPages: number): Promise<number> {\n for (let i = 0; this.#state.shouldRun(); i++) {\n const walPages = this.#getNumWalPages();\n if (walPages < maxWalPages) {\n this.#lc.info?.(\n `wal size (${walPages} pages) is under the max limit of ${maxWalPages}`,\n );\n return walPages;\n }\n\n // Log every 30 seconds.\n if (i % PAUSE_LOG_INTERVAL_POLLS === 0) {\n this.#lc.warn?.(\n `waiting for litestream to successfully checkpoint ${walPages} wal pages`,\n );\n }\n await this.#state.sleep(PAUSE_POLL_INTERVAL_MS);\n // Single-flight: reuse the outstanding sync if one is already running.\n this.#pendingSync ??= this.#sync(this.#getNumWalPages());\n // await the full liveness timeout configured in #sync()\n await this.#pendingSync;\n }\n throw new AbortError('litestream-controller stopped');\n }\n\n /** Releases the underlying litestream controller's connection. */\n close(): void {\n this.#litestream.close();\n this.#state.stop(this.#lc);\n }\n}\n"],"mappings":";;;AAiBA,IAAa,0BAA0B;AAIvC,IAAM,6BAA6B,IAAI;AACvC,IAAM,yBAAyB;AAC/B,IAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BjC,IAAa,yBAAb,MAAoC;CAClC;CACA;CACA;CACA;CACA;CACA,SAAkB,IAAI,aAAa,yBAAyB;CAC5D;CACA;CAEA,YACE,IACA,IACA,YACA,QACA;EACA,KAAKA,MAAM,GAAG,YAAY,aAAa,yBAAyB;EAChE,KAAKC,MAAM;EACX,KAAKC,cAAc;EACnB,KAAKC,gBAAgB,OAAO;EAC5B,KAAKG,oBAAoB,OAAO;EAChC,KAAKF,eAAe,OAAO;CAC7B;CAEA,kBAA0B;EAMxB,MAAM,CAAC,EAAC,KAAK,kBAAiB,KAAKH,IAAI,OAGpC,sBAAsB;EACzB,OAAO,MAAM;CACf;;;;;;;;;;CAWA,MAAM,kBAAiC;EACrC,IAAI,WAAW,KAAKM,gBAAgB;EACpC,IAAI,WAAW,KAAKD,mBAClB;EAIF,KAAKE,iBAAiB,KAAKC,MAAM,QAAQ;EAMzC,MAAM,KAAKC,SAAS,KAAKF,cAAc,uBAAuB;EAE9D,WAAW,KAAKD,gBAAgB;EAChC,IAAI,KAAKH,iBAAiB,KAAA,KAAa,WAAW,KAAKA,cAOrD,WAAW,MAAM,KAAKO,sBAAsB,KAAKP,YAAY;EAO/D,KAAKE,oBAAoB,WAAW,KAAKH;CAC3C;CAEA,MAAMO,SAAS,GAAkB,WAAkC;EAKjE,IAAI,MAJiB,QAAQ,KAAK,CAChC,GACA,KAAKL,OAAO,MAAM,SAAS,EAAE,WAAW,WAAoB,CAC9D,CAAC,MACc,aACb,KAAKL,IAAI,OAAO,uCAAuC,UAAU,IAAI;CAEzE;;;;;;;;CASA,MAAMS,MAAM,gBAAuC;EACjD,MAAM,QAAQ,YAAY,IAAI;EAC9B,IAAI;EACJ,IAAI;EACJ,IAAI;GACF,IAAI;IACF,SAAS,MAAM,KAAKP,YAAY,KAC9B;KAAC,MAAM;KAAO,WAAW;IAA0B,GACnD,KAAKG,OAAO,MACd;GACF,SAAS,GAAG;IACV,MAAM;GACR;GAEA,MAAM,UAAU,YAAY,IAAI,IAAI;GACpC,MAAM,cAAc,KAAKE,gBAAgB;GACzC,IAAI,cAAc,KAAKD,mBACrB,KAAKN,IAAI,OACP,gBAAgB,eAAe,MAAM,YAAY,cAAc,QAAQ,QAAQ,CAAC,EAAE,OAClF,MACF;QACK,IAAI,QACT,KAAKA,IAAI,OACP,sBAAsB,eAAe,MAAM,YAAY,mCAAmC,QAAQ,QAAQ,CAAC,EAAE,OAC7G,MACF;QAEA,KAAKA,IAAI,OACP,qBAAqB,eAAe,MAAM,YAAY,IAAI,QAAQ,QAAQ,CAAC,EAAE,OAC7E,GACF;EAEJ,SAAS,GAAG;GACV,KAAKA,IAAI,OAAO,uDAAuD,CAAC;EAC1E,UAAU;GACR,KAAKQ,eAAe,KAAA;EACtB;CACF;CAEA,MAAMG,sBAAsB,aAAsC;EAChE,KAAK,IAAI,IAAI,GAAG,KAAKN,OAAO,UAAU,GAAG,KAAK;GAC5C,MAAM,WAAW,KAAKE,gBAAgB;GACtC,IAAI,WAAW,aAAa;IAC1B,KAAKP,IAAI,OACP,aAAa,SAAS,oCAAoC,aAC5D;IACA,OAAO;GACT;GAGA,IAAI,IAAI,6BAA6B,GACnC,KAAKA,IAAI,OACP,qDAAqD,SAAS,WAChE;GAEF,MAAM,KAAKK,OAAO,MAAM,sBAAsB;GAE9C,KAAKG,iBAAiB,KAAKC,MAAM,KAAKF,gBAAgB,CAAC;GAEvD,MAAM,KAAKC;EACb;EACA,MAAM,IAAI,WAAW,+BAA+B;CACtD;;CAGA,QAAc;EACZ,KAAKN,YAAY,MAAM;EACvB,KAAKG,OAAO,KAAK,KAAKL,GAAG;CAC3B;AACF"}
@@ -1,70 +0,0 @@
1
- import type { LogContext } from '@rocicorp/logger';
2
- /**
3
- * Path of the litestream control socket, derived from the replica file's
4
- * directory. The socket must live on a filesystem the (non-root) runtime user
5
- * can write — the replica directory is guaranteed writable since litestream
6
- * writes the replica there — so it must NOT default to a root-owned location
7
- * like /var/run. Kept in sync with config-v5.yml's `socket.path`, which is set
8
- * from `ZERO_LITESTREAM_SOCKET_PATH` (see getLitestream() in commands.ts).
9
- */
10
- export declare function litestreamSocketPath(replicaFile: string): string;
11
- /** Response body from litestream's `POST /sync` control endpoint. */
12
- export type SyncResponse = {
13
- /**
14
- * `synced` when `wait` was true and the upload completed, `synced_local`
15
- * when the WAL was sealed locally without waiting on the remote replica, or
16
- * `no_change` when there was nothing to sync.
17
- */
18
- status: 'synced' | 'synced_local' | 'no_change';
19
- path: string;
20
- txid: number;
21
- replicated_txid: number;
22
- };
23
- export type SyncOptions = {
24
- /**
25
- * When true, block until the sealed WAL has been uploaded to the remote
26
- * replica (litestream's SyncAndWait). When false (the default), litestream
27
- * only seals the WAL into local LTX files and runs its checkpoint thresholds,
28
- * returning without waiting on the backup store. Use false on the write path
29
- * where the goal is to keep the WAL small, not to durably back it up.
30
- */
31
- wait?: boolean;
32
- /** Overall request timeout in milliseconds. Defaults to 30s. */
33
- timeoutMs?: number;
34
- };
35
- /**
36
- * IPC client for the litestream control server. litestream serves an HTTP API
37
- * over a Unix domain socket (enabled via the `socket:` block in config-v5.yml);
38
- * because zero-cache runs litestream as a subprocess in the same container, the
39
- * socket is reachable directly on the local filesystem.
40
- *
41
- * A single keep-alive connection is held open and reused across calls, so a
42
- * high-frequency caller (e.g. write-path backpressure) does not pay a
43
- * connect/handshake per request.
44
- */
45
- export declare class LitestreamController {
46
- #private;
47
- /**
48
- * @param replicaFile Path of the replica database litestream is managing —
49
- * the same value passed to litestream as `ZERO_REPLICA_FILE`. This is the
50
- * `path` litestream matches control requests against.
51
- * @param socketPath Path of the control socket; defaults to the path derived
52
- * from `replicaFile`, matching config-v5.yml's `socket.path`.
53
- */
54
- constructor(lc: LogContext, replicaFile: string, socketPath?: string);
55
- /**
56
- * Forces litestream to sync the WAL into LTX files immediately and run its
57
- * checkpoint thresholds, instead of waiting for the next monitor-interval
58
- * tick. The checkpoint itself is still litestream's usual (non-blocking)
59
- * PASSIVE attempt, so it is skipped if the database is busy — call this once
60
- * writes are quiesced.
61
- *
62
- * Best-effort: callers should tolerate rejection (e.g. ECONNREFUSED/ENOENT
63
- * while litestream is restarting or before it has created the socket) rather
64
- * than blocking application progress on it.
65
- */
66
- sync(opts?: SyncOptions, signal?: AbortSignal): Promise<SyncResponse>;
67
- /** Releases the pooled keep-alive connection. */
68
- close(): void;
69
- }
70
- //# sourceMappingURL=litestream-controller.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"litestream-controller.d.ts","sourceRoot":"","sources":["../../../../../../zero-cache/src/services/litestream/litestream-controller.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAEjD;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAEhE;AAID,qEAAqE;AACrE,MAAM,MAAM,YAAY,GAAG;IACzB;;;;OAIG;IACH,MAAM,EAAE,QAAQ,GAAG,cAAc,GAAG,WAAW,CAAC;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IAEf,gEAAgE;IAChE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF;;;;;;;;;GASG;AACH,qBAAa,oBAAoB;;IAM/B;;;;;;OAMG;gBAED,EAAE,EAAE,UAAU,EACd,WAAW,EAAE,MAAM,EACnB,UAAU,SAAoC;IAUhD;;;;;;;;;;OAUG;IACG,IAAI,CACR,IAAI,GAAE,WAAgB,EACtB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,YAAY,CAAC;IAYxB,iDAAiD;IACjD,KAAK,IAAI,IAAI;CA8Dd"}
@@ -1,101 +0,0 @@
1
- import { Agent, request } from "node:http";
2
- import { json } from "node:stream/consumers";
3
- //#region ../zero-cache/src/services/litestream/litestream-controller.ts
4
- /**
5
- * Path of the litestream control socket, derived from the replica file's
6
- * directory. The socket must live on a filesystem the (non-root) runtime user
7
- * can write — the replica directory is guaranteed writable since litestream
8
- * writes the replica there — so it must NOT default to a root-owned location
9
- * like /var/run. Kept in sync with config-v5.yml's `socket.path`, which is set
10
- * from `ZERO_LITESTREAM_SOCKET_PATH` (see getLitestream() in commands.ts).
11
- */
12
- function litestreamSocketPath(replicaFile) {
13
- return `${replicaFile}.sock`;
14
- }
15
- var DEFAULT_REQUEST_TIMEOUT_MS = 3e4;
16
- /**
17
- * IPC client for the litestream control server. litestream serves an HTTP API
18
- * over a Unix domain socket (enabled via the `socket:` block in config-v5.yml);
19
- * because zero-cache runs litestream as a subprocess in the same container, the
20
- * socket is reachable directly on the local filesystem.
21
- *
22
- * A single keep-alive connection is held open and reused across calls, so a
23
- * high-frequency caller (e.g. write-path backpressure) does not pay a
24
- * connect/handshake per request.
25
- */
26
- var LitestreamController = class {
27
- #lc;
28
- #replicaFile;
29
- #socketPath;
30
- #agent;
31
- /**
32
- * @param replicaFile Path of the replica database litestream is managing —
33
- * the same value passed to litestream as `ZERO_REPLICA_FILE`. This is the
34
- * `path` litestream matches control requests against.
35
- * @param socketPath Path of the control socket; defaults to the path derived
36
- * from `replicaFile`, matching config-v5.yml's `socket.path`.
37
- */
38
- constructor(lc, replicaFile, socketPath = litestreamSocketPath(replicaFile)) {
39
- this.#lc = lc.withContext("component", "litestream-controller");
40
- this.#replicaFile = replicaFile;
41
- this.#socketPath = socketPath;
42
- this.#agent = new Agent({
43
- keepAlive: true,
44
- maxSockets: 1
45
- });
46
- }
47
- /**
48
- * Forces litestream to sync the WAL into LTX files immediately and run its
49
- * checkpoint thresholds, instead of waiting for the next monitor-interval
50
- * tick. The checkpoint itself is still litestream's usual (non-blocking)
51
- * PASSIVE attempt, so it is skipped if the database is busy — call this once
52
- * writes are quiesced.
53
- *
54
- * Best-effort: callers should tolerate rejection (e.g. ECONNREFUSED/ENOENT
55
- * while litestream is restarting or before it has created the socket) rather
56
- * than blocking application progress on it.
57
- */
58
- async sync(opts = {}, signal) {
59
- const { wait = false, timeoutMs = DEFAULT_REQUEST_TIMEOUT_MS } = opts;
60
- const result = await this.#post("/sync", {
61
- path: this.#replicaFile,
62
- wait
63
- }, timeoutMs, signal);
64
- this.#lc.debug?.("litestream sync", result);
65
- return result;
66
- }
67
- /** Releases the pooled keep-alive connection. */
68
- close() {
69
- this.#agent.destroy();
70
- }
71
- #post(path, body, timeoutMs, signal) {
72
- const payload = JSON.stringify(body);
73
- return new Promise((resolve, reject) => {
74
- const req = request({
75
- socketPath: this.#socketPath,
76
- method: "POST",
77
- path,
78
- agent: this.#agent,
79
- timeout: timeoutMs,
80
- headers: {
81
- "content-type": "application/json",
82
- "content-length": Buffer.byteLength(payload)
83
- },
84
- signal
85
- }, (res) => {
86
- const status = res.statusCode ?? 0;
87
- json(res).then((body) => {
88
- if (status < 200 || status >= 300) reject(/* @__PURE__ */ new Error(`litestream ${path} failed: ${status} ${JSON.stringify(body)}`));
89
- else resolve(body);
90
- }, (e) => reject(new Error(`litestream ${path} returned invalid JSON`, { cause: e })));
91
- });
92
- req.on("timeout", () => req.destroy(/* @__PURE__ */ new Error(`litestream ${path} timed out after ${timeoutMs}ms`)));
93
- req.on("error", reject);
94
- req.end(payload);
95
- });
96
- }
97
- };
98
- //#endregion
99
- export { LitestreamController, litestreamSocketPath };
100
-
101
- //# sourceMappingURL=litestream-controller.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"litestream-controller.js","names":["#lc","#replicaFile","#socketPath","#agent","#post"],"sources":["../../../../../../zero-cache/src/services/litestream/litestream-controller.ts"],"sourcesContent":["import type {IncomingMessage} from 'node:http';\nimport {Agent, request} from 'node:http';\nimport {json as readJSON} from 'node:stream/consumers';\nimport type {LogContext} from '@rocicorp/logger';\n\n/**\n * Path of the litestream control socket, derived from the replica file's\n * directory. The socket must live on a filesystem the (non-root) runtime user\n * can write — the replica directory is guaranteed writable since litestream\n * writes the replica there — so it must NOT default to a root-owned location\n * like /var/run. Kept in sync with config-v5.yml's `socket.path`, which is set\n * from `ZERO_LITESTREAM_SOCKET_PATH` (see getLitestream() in commands.ts).\n */\nexport function litestreamSocketPath(replicaFile: string): string {\n return `${replicaFile}.sock`;\n}\n\nconst DEFAULT_REQUEST_TIMEOUT_MS = 30_000;\n\n/** Response body from litestream's `POST /sync` control endpoint. */\nexport type SyncResponse = {\n /**\n * `synced` when `wait` was true and the upload completed, `synced_local`\n * when the WAL was sealed locally without waiting on the remote replica, or\n * `no_change` when there was nothing to sync.\n */\n status: 'synced' | 'synced_local' | 'no_change';\n path: string;\n txid: number;\n replicated_txid: number;\n};\n\nexport type SyncOptions = {\n /**\n * When true, block until the sealed WAL has been uploaded to the remote\n * replica (litestream's SyncAndWait). When false (the default), litestream\n * only seals the WAL into local LTX files and runs its checkpoint thresholds,\n * returning without waiting on the backup store. Use false on the write path\n * where the goal is to keep the WAL small, not to durably back it up.\n */\n wait?: boolean;\n\n /** Overall request timeout in milliseconds. Defaults to 30s. */\n timeoutMs?: number;\n};\n\n/**\n * IPC client for the litestream control server. litestream serves an HTTP API\n * over a Unix domain socket (enabled via the `socket:` block in config-v5.yml);\n * because zero-cache runs litestream as a subprocess in the same container, the\n * socket is reachable directly on the local filesystem.\n *\n * A single keep-alive connection is held open and reused across calls, so a\n * high-frequency caller (e.g. write-path backpressure) does not pay a\n * connect/handshake per request.\n */\nexport class LitestreamController {\n readonly #lc: LogContext;\n readonly #replicaFile: string;\n readonly #socketPath: string;\n readonly #agent: Agent;\n\n /**\n * @param replicaFile Path of the replica database litestream is managing —\n * the same value passed to litestream as `ZERO_REPLICA_FILE`. This is the\n * `path` litestream matches control requests against.\n * @param socketPath Path of the control socket; defaults to the path derived\n * from `replicaFile`, matching config-v5.yml's `socket.path`.\n */\n constructor(\n lc: LogContext,\n replicaFile: string,\n socketPath = litestreamSocketPath(replicaFile),\n ) {\n this.#lc = lc.withContext('component', 'litestream-controller');\n this.#replicaFile = replicaFile;\n this.#socketPath = socketPath;\n // keepAlive with a single socket keeps one warm connection to the control\n // socket that is reused across calls.\n this.#agent = new Agent({keepAlive: true, maxSockets: 1});\n }\n\n /**\n * Forces litestream to sync the WAL into LTX files immediately and run its\n * checkpoint thresholds, instead of waiting for the next monitor-interval\n * tick. The checkpoint itself is still litestream's usual (non-blocking)\n * PASSIVE attempt, so it is skipped if the database is busy — call this once\n * writes are quiesced.\n *\n * Best-effort: callers should tolerate rejection (e.g. ECONNREFUSED/ENOENT\n * while litestream is restarting or before it has created the socket) rather\n * than blocking application progress on it.\n */\n async sync(\n opts: SyncOptions = {},\n signal?: AbortSignal,\n ): Promise<SyncResponse> {\n const {wait = false, timeoutMs = DEFAULT_REQUEST_TIMEOUT_MS} = opts;\n const result = await this.#post<SyncResponse>(\n '/sync',\n {path: this.#replicaFile, wait},\n timeoutMs,\n signal,\n );\n this.#lc.debug?.('litestream sync', result);\n return result;\n }\n\n /** Releases the pooled keep-alive connection. */\n close(): void {\n this.#agent.destroy();\n }\n\n // Note: Uses ye'old node:http for its unix socketPath support.\n // fetch() would have less boiler-plate, but it would require importing\n // the `unidici` package to provide a fetch Agent that supports sockets.\n #post<T>(\n path: string,\n body: unknown,\n timeoutMs: number,\n signal?: AbortSignal,\n ): Promise<T> {\n const payload = JSON.stringify(body);\n return new Promise<T>((resolve, reject) => {\n const req = request(\n {\n socketPath: this.#socketPath,\n method: 'POST',\n path,\n agent: this.#agent,\n timeout: timeoutMs,\n headers: {\n 'content-type': 'application/json',\n 'content-length': Buffer.byteLength(payload),\n },\n signal,\n },\n (res: IncomingMessage) => {\n const status = res.statusCode ?? 0;\n // litestream's success and error responses are both always JSON\n // (writeJSON / writeJSONError in server.go).\n readJSON(res).then(\n body => {\n if (status < 200 || status >= 300) {\n reject(\n new Error(\n `litestream ${path} failed: ${status} ${JSON.stringify(body)}`,\n ),\n );\n } else {\n resolve(body as T);\n }\n },\n (e: unknown) =>\n reject(\n new Error(`litestream ${path} returned invalid JSON`, {\n cause: e,\n }),\n ),\n );\n },\n );\n req.on('timeout', () =>\n req.destroy(\n new Error(`litestream ${path} timed out after ${timeoutMs}ms`),\n ),\n );\n req.on('error', reject);\n req.end(payload);\n });\n }\n}\n"],"mappings":";;;;;;;;;;;AAaA,SAAgB,qBAAqB,aAA6B;CAChE,OAAO,GAAG,YAAY;AACxB;AAEA,IAAM,6BAA6B;;;;;;;;;;;AAuCnC,IAAa,uBAAb,MAAkC;CAChC;CACA;CACA;CACA;;;;;;;;CASA,YACE,IACA,aACA,aAAa,qBAAqB,WAAW,GAC7C;EACA,KAAKA,MAAM,GAAG,YAAY,aAAa,uBAAuB;EAC9D,KAAKC,eAAe;EACpB,KAAKC,cAAc;EAGnB,KAAKC,SAAS,IAAI,MAAM;GAAC,WAAW;GAAM,YAAY;EAAC,CAAC;CAC1D;;;;;;;;;;;;CAaA,MAAM,KACJ,OAAoB,CAAC,GACrB,QACuB;EACvB,MAAM,EAAC,OAAO,OAAO,YAAY,+BAA8B;EAC/D,MAAM,SAAS,MAAM,KAAKC,MACxB,SACA;GAAC,MAAM,KAAKH;GAAc;EAAI,GAC9B,WACA,MACF;EACA,KAAKD,IAAI,QAAQ,mBAAmB,MAAM;EAC1C,OAAO;CACT;;CAGA,QAAc;EACZ,KAAKG,OAAO,QAAQ;CACtB;CAKA,MACE,MACA,MACA,WACA,QACY;EACZ,MAAM,UAAU,KAAK,UAAU,IAAI;EACnC,OAAO,IAAI,SAAY,SAAS,WAAW;GACzC,MAAM,MAAM,QACV;IACE,YAAY,KAAKD;IACjB,QAAQ;IACR;IACA,OAAO,KAAKC;IACZ,SAAS;IACT,SAAS;KACP,gBAAgB;KAChB,kBAAkB,OAAO,WAAW,OAAO;IAC7C;IACA;GACF,IACC,QAAyB;IACxB,MAAM,SAAS,IAAI,cAAc;IAGjC,KAAS,GAAG,EAAE,MACZ,SAAQ;KACN,IAAI,SAAS,OAAO,UAAU,KAC5B,uBACE,IAAI,MACF,cAAc,KAAK,WAAW,OAAO,GAAG,KAAK,UAAU,IAAI,GAC7D,CACF;UAEA,QAAQ,IAAS;IAErB,IACC,MACC,OACE,IAAI,MAAM,cAAc,KAAK,yBAAyB,EACpD,OAAO,EACT,CAAC,CACH,CACJ;GACF,CACF;GACA,IAAI,GAAG,iBACL,IAAI,wBACF,IAAI,MAAM,cAAc,KAAK,mBAAmB,UAAU,GAAG,CAC/D,CACF;GACA,IAAI,GAAG,SAAS,MAAM;GACtB,IAAI,IAAI,OAAO;EACjB,CAAC;CACH;AACF"}
@@ -1,7 +0,0 @@
1
- import type { LogContext } from '@rocicorp/logger';
2
- import type { FastifyReply, FastifyRequest } from 'fastify';
3
- import type { NormalizedZeroConfig } from '../config/normalize.ts';
4
- import { type Worker } from '../types/processes.ts';
5
- export declare function handleProfzRequest(lc: LogContext, config: Pick<NormalizedZeroConfig, 'adminPassword'>, req: FastifyRequest, res: FastifyReply, getWorker?: (() => Promise<Worker>) | undefined, forcedWorker?: string | undefined, localProcessName?: string): Promise<void>;
6
- export declare function handleProfrmzRequest(lc: LogContext, config: NormalizedZeroConfig, req: FastifyRequest, res: FastifyReply, getWorker?: (() => Promise<Worker>) | undefined): Promise<void>;
7
- //# sourceMappingURL=profz.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"profz.d.ts","sourceRoot":"","sources":["../../../../../zero-cache/src/services/profz.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAEjD,OAAO,KAAK,EAAC,YAAY,EAAE,cAAc,EAAC,MAAM,SAAS,CAAC;AAE1D,OAAO,KAAK,EAAC,oBAAoB,EAAC,MAAM,wBAAwB,CAAC;AAEjE,OAAO,EAKL,KAAK,MAAM,EACZ,MAAM,uBAAuB,CAAC;AAI/B,wBAAsB,kBAAkB,CACtC,EAAE,EAAE,UAAU,EACd,MAAM,EAAE,IAAI,CAAC,oBAAoB,EAAE,eAAe,CAAC,EACnD,GAAG,EAAE,cAAc,EACnB,GAAG,EAAE,YAAY,EACjB,SAAS,CAAC,EAAE,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,SAAS,EAC/C,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,EACjC,gBAAgB,GAAE,MAAqB,GACtC,OAAO,CAAC,IAAI,CAAC,CAgIf;AAED,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,UAAU,EACd,MAAM,EAAE,oBAAoB,EAC5B,GAAG,EAAE,cAAc,EACnB,GAAG,EAAE,YAAY,EACjB,SAAS,CAAC,EAAE,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,SAAS,GAC9C,OAAO,CAAC,IAAI,CAAC,CAkDf"}
@@ -1,103 +0,0 @@
1
- import { sleep } from "../../../shared/src/sleep.js";
2
- import { singleProcessMode, subscribeToMessageType } from "../types/processes.js";
3
- import { isAdminPasswordValid } from "../config/zero-config.js";
4
- import { CpuProfiler } from "../types/profiler.js";
5
- import { URLParams } from "../types/url-params.js";
6
- import { randomUUID } from "node:crypto";
7
- import auth from "basic-auth";
8
- //#region ../zero-cache/src/services/profz.ts
9
- async function handleProfzRequest(lc, config, req, res, getWorker, forcedWorker, localProcessName = "dispatcher") {
10
- if (!isAdminPasswordValid(lc, config, auth(req)?.pass)) {
11
- res.code(401).header("WWW-Authenticate", "Basic realm=\"Profz Protected Area\"").send("Unauthorized");
12
- return;
13
- }
14
- const params = new URLParams(new URL(req.url, "http://localhost"));
15
- const rawDuration = params.getInteger("duration", false) ?? params.getInteger("seconds", false) ?? 5;
16
- const durationMs = Math.max(1, Math.min(60, rawDuration)) * 1e3;
17
- const targetWorker = forcedWorker ?? params.get("worker", false) ?? void 0;
18
- const targetWorkerIndex = params.getInteger("index", false) ?? void 0;
19
- const id = randomUUID();
20
- const responses = /* @__PURE__ */ new Map();
21
- const localProfilePromise = singleProcessMode() || getWorker === void 0 || targetWorker === void 0 || targetWorker === localProcessName ? CpuProfiler.profile(durationMs).catch((err) => {
22
- lc.warn?.("Failed to capture local CPU profile:", err);
23
- return null;
24
- }) : Promise.resolve(null);
25
- if (!singleProcessMode() && getWorker !== void 0) try {
26
- const worker = await getWorker();
27
- const onMessage = (msg) => {
28
- if (msg.id === id && msg.profile) responses.set(msg.name, msg.profile);
29
- else if (msg.id === id && msg.error) lc.warn?.(`Worker ${msg.name} profile error: ${msg.error}`);
30
- };
31
- const unsubscribe = subscribeToMessageType(worker, "profileResponse", onMessage);
32
- try {
33
- worker.send(["profile", {
34
- id,
35
- durationMs,
36
- worker: targetWorker === localProcessName ? "__none__" : targetWorker,
37
- workerIndex: targetWorkerIndex
38
- }]);
39
- await sleep(durationMs + 500);
40
- } finally {
41
- unsubscribe();
42
- }
43
- } catch (err) {
44
- lc.warn?.("Failed to dispatch profile request to child workers:", err);
45
- }
46
- const localProfile = await localProfilePromise;
47
- if (localProfile) {
48
- const localName = targetWorker ?? (singleProcessMode() ? "zero-cache" : localProcessName);
49
- responses.set(localName, localProfile);
50
- }
51
- if (targetWorker !== void 0 && targetWorker !== "all") {
52
- let matchedProfile = responses.get(targetWorker);
53
- if (!matchedProfile) {
54
- for (const [name, prof] of responses.entries()) if (name === targetWorker || name.startsWith(`${targetWorker}-`)) {
55
- matchedProfile = prof;
56
- break;
57
- }
58
- }
59
- if (matchedProfile) {
60
- res.header("Content-Type", "application/json").header("Content-Disposition", `attachment; filename="${targetWorker}.cpuprofile"`).send(matchedProfile);
61
- return;
62
- }
63
- res.code(404).send({ error: `No profile captured for worker "${targetWorker}". Available: ${[...responses.keys()].join(", ")}` });
64
- return;
65
- }
66
- const bundle = {};
67
- for (const [name, prof] of responses.entries()) bundle[name] = prof;
68
- res.header("Content-Type", "application/json").header("Content-Disposition", `attachment; filename="zero-profile-bundle-${Date.now()}.json"`).send(bundle);
69
- }
70
- async function handleProfrmzRequest(lc, config, req, res, getWorker) {
71
- if (!isAdminPasswordValid(lc, config, auth(req)?.pass)) {
72
- res.code(401).header("WWW-Authenticate", "Basic realm=\"Profrmz Protected Area\"").send("Unauthorized");
73
- return;
74
- }
75
- if (config.changeStreamer.uri) {
76
- const upstreamURL = new URL("/profz", config.changeStreamer.uri);
77
- const incomingURL = new URL(req.url, "http://localhost");
78
- for (const [key, value] of incomingURL.searchParams.entries()) upstreamURL.searchParams.set(key, value);
79
- try {
80
- const headers = {};
81
- if (req.headers.authorization) headers.authorization = req.headers.authorization;
82
- const response = await fetch(upstreamURL.toString(), {
83
- method: "GET",
84
- headers
85
- });
86
- res.code(response.status);
87
- const contentType = response.headers.get("content-type");
88
- if (contentType) res.header("content-type", contentType);
89
- const contentDisposition = response.headers.get("content-disposition");
90
- if (contentDisposition) res.header("content-disposition", contentDisposition);
91
- const body = await response.text();
92
- return res.send(body);
93
- } catch (err) {
94
- lc.error?.(`Failed to proxy /profrmz to RM at ${upstreamURL}:`, err);
95
- return res.code(502).send({ error: `Failed to proxy profiling request to RM at ${upstreamURL}: ${String(err)}` });
96
- }
97
- }
98
- return handleProfzRequest(lc, config, req, res, getWorker, "change-streamer");
99
- }
100
- //#endregion
101
- export { handleProfrmzRequest, handleProfzRequest };
102
-
103
- //# sourceMappingURL=profz.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"profz.js","names":[],"sources":["../../../../../zero-cache/src/services/profz.ts"],"sourcesContent":["import {randomUUID} from 'node:crypto';\nimport type {LogContext} from '@rocicorp/logger';\nimport auth from 'basic-auth';\nimport type {FastifyReply, FastifyRequest} from 'fastify';\nimport {sleep} from '../../../shared/src/sleep.ts';\nimport type {NormalizedZeroConfig} from '../config/normalize.ts';\nimport {isAdminPasswordValid} from '../config/zero-config.ts';\nimport {\n singleProcessMode,\n subscribeToMessageType,\n type ProfileResponse,\n type ProfileResponseMessage,\n type Worker,\n} from '../types/processes.ts';\nimport {CpuProfiler} from '../types/profiler.ts';\nimport {URLParams} from '../types/url-params.ts';\n\nexport async function handleProfzRequest(\n lc: LogContext,\n config: Pick<NormalizedZeroConfig, 'adminPassword'>,\n req: FastifyRequest,\n res: FastifyReply,\n getWorker?: (() => Promise<Worker>) | undefined,\n forcedWorker?: string | undefined,\n localProcessName: string = 'dispatcher',\n): Promise<void> {\n const credentials = auth(req);\n if (!isAdminPasswordValid(lc, config, credentials?.pass)) {\n void res\n .code(401)\n .header('WWW-Authenticate', 'Basic realm=\"Profz Protected Area\"')\n .send('Unauthorized');\n return;\n }\n\n const params = new URLParams(new URL(req.url, 'http://localhost'));\n const rawDuration =\n params.getInteger('duration', false) ??\n params.getInteger('seconds', false) ??\n 5;\n const durationSec = Math.max(1, Math.min(60, rawDuration));\n const durationMs = durationSec * 1000;\n const targetWorker = forcedWorker ?? params.get('worker', false) ?? undefined;\n const targetWorkerIndex = params.getInteger('index', false) ?? undefined;\n const id = randomUUID();\n\n const responses = new Map<string, unknown>();\n\n // Profile dispatcher / local process if requested, when profiling all processes,\n // or when no worker dispatcher is available (single process / standalone mode)\n const shouldProfileLocal =\n singleProcessMode() ||\n getWorker === undefined ||\n targetWorker === undefined ||\n targetWorker === localProcessName;\n\n const localProfilePromise = shouldProfileLocal\n ? CpuProfiler.profile(durationMs).catch(err => {\n lc.warn?.('Failed to capture local CPU profile:', err);\n return null;\n })\n : Promise.resolve(null);\n\n if (!singleProcessMode() && getWorker !== undefined) {\n try {\n const worker = await getWorker();\n const onMessage = (msg: ProfileResponse) => {\n if (msg.id === id && msg.profile) {\n responses.set(msg.name, msg.profile);\n } else if (msg.id === id && msg.error) {\n lc.warn?.(`Worker ${msg.name} profile error: ${msg.error}`);\n }\n };\n\n // The worker is long-lived (and shared across requests), so the\n // per-request handler must be removed once this request is done.\n const unsubscribe = subscribeToMessageType<ProfileResponseMessage>(\n worker,\n 'profileResponse',\n onMessage,\n );\n try {\n worker.send([\n 'profile',\n {\n id,\n durationMs,\n worker:\n targetWorker === localProcessName ? '__none__' : targetWorker,\n workerIndex: targetWorkerIndex,\n },\n ]);\n\n // Wait for duration plus grace period for IPC transfer\n await sleep(durationMs + 500);\n } finally {\n unsubscribe();\n }\n } catch (err) {\n lc.warn?.('Failed to dispatch profile request to child workers:', err);\n }\n }\n\n const localProfile = await localProfilePromise;\n if (localProfile) {\n const localName =\n targetWorker ?? (singleProcessMode() ? 'zero-cache' : localProcessName);\n responses.set(localName, localProfile);\n }\n\n // If a single specific worker was requested, return that profile directly\n if (targetWorker !== undefined && targetWorker !== 'all') {\n let matchedProfile = responses.get(targetWorker);\n if (!matchedProfile) {\n // Try matching by prefix or substring (e.g. 'syncer' matches 'syncer-0')\n for (const [name, prof] of responses.entries()) {\n if (name === targetWorker || name.startsWith(`${targetWorker}-`)) {\n matchedProfile = prof;\n break;\n }\n }\n }\n\n if (matchedProfile) {\n void res\n .header('Content-Type', 'application/json')\n .header(\n 'Content-Disposition',\n `attachment; filename=\"${targetWorker}.cpuprofile\"`,\n )\n .send(matchedProfile);\n return;\n }\n\n void res.code(404).send({\n error: `No profile captured for worker \"${targetWorker}\". Available: ${[...responses.keys()].join(', ')}`,\n });\n return;\n }\n\n // Default (Option A): Return multi-process profile bundle as a JSON map\n const bundle: Record<string, unknown> = {};\n for (const [name, prof] of responses.entries()) {\n bundle[name] = prof;\n }\n\n void res\n .header('Content-Type', 'application/json')\n .header(\n 'Content-Disposition',\n `attachment; filename=\"zero-profile-bundle-${Date.now()}.json\"`,\n )\n .send(bundle);\n}\n\nexport async function handleProfrmzRequest(\n lc: LogContext,\n config: NormalizedZeroConfig,\n req: FastifyRequest,\n res: FastifyReply,\n getWorker?: (() => Promise<Worker>) | undefined,\n): Promise<void> {\n const credentials = auth(req);\n if (!isAdminPasswordValid(lc, config, credentials?.pass)) {\n void res\n .code(401)\n .header('WWW-Authenticate', 'Basic realm=\"Profrmz Protected Area\"')\n .send('Unauthorized');\n return;\n }\n\n // In distributed mode, proxy to the upstream Replication Manager\n if (config.changeStreamer.uri) {\n const upstreamURL = new URL('/profz', config.changeStreamer.uri);\n const incomingURL = new URL(req.url, 'http://localhost');\n for (const [key, value] of incomingURL.searchParams.entries()) {\n upstreamURL.searchParams.set(key, value);\n }\n\n try {\n const headers: Record<string, string> = {};\n if (req.headers.authorization) {\n headers.authorization = req.headers.authorization;\n }\n const response = await fetch(upstreamURL.toString(), {\n method: 'GET',\n headers,\n });\n\n res.code(response.status);\n const contentType = response.headers.get('content-type');\n if (contentType) {\n res.header('content-type', contentType);\n }\n const contentDisposition = response.headers.get('content-disposition');\n if (contentDisposition) {\n res.header('content-disposition', contentDisposition);\n }\n\n const body = await response.text();\n return res.send(body);\n } catch (err) {\n lc.error?.(`Failed to proxy /profrmz to RM at ${upstreamURL}:`, err);\n return res.code(502).send({\n error: `Failed to proxy profiling request to RM at ${upstreamURL}: ${String(err)}`,\n });\n }\n }\n\n // In single-node mode, profile local change-streamer / RM process\n return handleProfzRequest(lc, config, req, res, getWorker, 'change-streamer');\n}\n"],"mappings":"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"}
@@ -1,33 +0,0 @@
1
- export type MonotonicClock = () => number;
2
- /**
3
- * A soft wall-clock budget for one view-syncer hydration pass.
4
- *
5
- * Callers check the budget only at query boundaries. Consequently, a query
6
- * that starts before the limit is reached is always allowed to finish.
7
- *
8
- * The budget measures hydration work. Intervals that are not hydration --
9
- * notably the remote custom-query transform round trips -- are discounted via
10
- * {@link excluding}, so that endpoint latency cannot spend a budget that only
11
- * evicting queries could recover.
12
- */
13
- export declare class HydrationBudget {
14
- #private;
15
- readonly limitMs: number;
16
- constructor(limitMs: number, now?: MonotonicClock);
17
- /**
18
- * Runs `fn`, discounting the time it takes as non-hydration work. The
19
- * interval is measured with this budget's own clock, so an injected clock
20
- * governs both the elapsed time and what is excluded from it.
21
- */
22
- excluding<T>(fn: () => Promise<T>): Promise<T>;
23
- elapsedMs(): number;
24
- /**
25
- * Whether the budget is spent. A disabled budget (`limitMs === 0`) is never
26
- * exhausted. The elapsed time at the first exhausted check is retained in
27
- * {@link exhaustedAtMs} so that reporting does not re-read the clock.
28
- */
29
- exhausted(): boolean;
30
- /** The elapsed time at which {@link exhausted} first returned true. */
31
- get exhaustedAtMs(): number | undefined;
32
- }
33
- //# sourceMappingURL=hydration-budget.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"hydration-budget.d.ts","sourceRoot":"","sources":["../../../../../../zero-cache/src/services/view-syncer/hydration-budget.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,cAAc,GAAG,MAAM,MAAM,CAAC;AAE1C;;;;;;;;;;GAUG;AACH,qBAAa,eAAe;;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;gBAOvB,OAAO,EAAE,MAAM,EACf,GAAG,GAAE,cAAkD;IAWzD;;;;OAIG;IACG,SAAS,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IASpD,SAAS,IAAI,MAAM;IAInB;;;;OAIG;IACH,SAAS,IAAI,OAAO;IAYpB,uEAAuE;IACvE,IAAI,aAAa,IAAI,MAAM,GAAG,SAAS,CAEtC;CACF"}
@@ -1,62 +0,0 @@
1
- import { assert } from "../../../../shared/src/asserts.js";
2
- //#region ../zero-cache/src/services/view-syncer/hydration-budget.ts
3
- /**
4
- * A soft wall-clock budget for one view-syncer hydration pass.
5
- *
6
- * Callers check the budget only at query boundaries. Consequently, a query
7
- * that starts before the limit is reached is always allowed to finish.
8
- *
9
- * The budget measures hydration work. Intervals that are not hydration --
10
- * notably the remote custom-query transform round trips -- are discounted via
11
- * {@link excluding}, so that endpoint latency cannot spend a budget that only
12
- * evicting queries could recover.
13
- */
14
- var HydrationBudget = class {
15
- limitMs;
16
- #now;
17
- #startedAt;
18
- #excludedMs = 0;
19
- #exhaustedAtMs;
20
- constructor(limitMs, now = performance.now.bind(performance)) {
21
- assert(Number.isSafeInteger(limitMs) && limitMs >= 0, "Hydration budget must be a nonnegative integer");
22
- this.limitMs = limitMs;
23
- this.#now = now;
24
- this.#startedAt = now();
25
- }
26
- /**
27
- * Runs `fn`, discounting the time it takes as non-hydration work. The
28
- * interval is measured with this budget's own clock, so an injected clock
29
- * governs both the elapsed time and what is excluded from it.
30
- */
31
- async excluding(fn) {
32
- const start = this.#now();
33
- try {
34
- return await fn();
35
- } finally {
36
- this.#excludedMs += this.#now() - start;
37
- }
38
- }
39
- elapsedMs() {
40
- return this.#now() - this.#startedAt - this.#excludedMs;
41
- }
42
- /**
43
- * Whether the budget is spent. A disabled budget (`limitMs === 0`) is never
44
- * exhausted. The elapsed time at the first exhausted check is retained in
45
- * {@link exhaustedAtMs} so that reporting does not re-read the clock.
46
- */
47
- exhausted() {
48
- if (this.limitMs === 0) return false;
49
- const elapsed = this.elapsedMs();
50
- if (elapsed < this.limitMs) return false;
51
- this.#exhaustedAtMs ??= elapsed;
52
- return true;
53
- }
54
- /** The elapsed time at which {@link exhausted} first returned true. */
55
- get exhaustedAtMs() {
56
- return this.#exhaustedAtMs;
57
- }
58
- };
59
- //#endregion
60
- export { HydrationBudget };
61
-
62
- //# sourceMappingURL=hydration-budget.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"hydration-budget.js","names":["#now","#startedAt","#excludedMs","#exhaustedAtMs"],"sources":["../../../../../../zero-cache/src/services/view-syncer/hydration-budget.ts"],"sourcesContent":["import {assert} from '../../../../shared/src/asserts.ts';\n\nexport type MonotonicClock = () => number;\n\n/**\n * A soft wall-clock budget for one view-syncer hydration pass.\n *\n * Callers check the budget only at query boundaries. Consequently, a query\n * that starts before the limit is reached is always allowed to finish.\n *\n * The budget measures hydration work. Intervals that are not hydration --\n * notably the remote custom-query transform round trips -- are discounted via\n * {@link excluding}, so that endpoint latency cannot spend a budget that only\n * evicting queries could recover.\n */\nexport class HydrationBudget {\n readonly limitMs: number;\n readonly #now: MonotonicClock;\n readonly #startedAt: number;\n #excludedMs = 0;\n #exhaustedAtMs: number | undefined;\n\n constructor(\n limitMs: number,\n now: MonotonicClock = performance.now.bind(performance),\n ) {\n assert(\n Number.isSafeInteger(limitMs) && limitMs >= 0,\n 'Hydration budget must be a nonnegative integer',\n );\n this.limitMs = limitMs;\n this.#now = now;\n this.#startedAt = now();\n }\n\n /**\n * Runs `fn`, discounting the time it takes as non-hydration work. The\n * interval is measured with this budget's own clock, so an injected clock\n * governs both the elapsed time and what is excluded from it.\n */\n async excluding<T>(fn: () => Promise<T>): Promise<T> {\n const start = this.#now();\n try {\n return await fn();\n } finally {\n this.#excludedMs += this.#now() - start;\n }\n }\n\n elapsedMs(): number {\n return this.#now() - this.#startedAt - this.#excludedMs;\n }\n\n /**\n * Whether the budget is spent. A disabled budget (`limitMs === 0`) is never\n * exhausted. The elapsed time at the first exhausted check is retained in\n * {@link exhaustedAtMs} so that reporting does not re-read the clock.\n */\n exhausted(): boolean {\n if (this.limitMs === 0) {\n return false;\n }\n const elapsed = this.elapsedMs();\n if (elapsed < this.limitMs) {\n return false;\n }\n this.#exhaustedAtMs ??= elapsed;\n return true;\n }\n\n /** The elapsed time at which {@link exhausted} first returned true. */\n get exhaustedAtMs(): number | undefined {\n return this.#exhaustedAtMs;\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAeA,IAAa,kBAAb,MAA6B;CAC3B;CACA;CACA;CACA,cAAc;CACd;CAEA,YACE,SACA,MAAsB,YAAY,IAAI,KAAK,WAAW,GACtD;EACA,OACE,OAAO,cAAc,OAAO,KAAK,WAAW,GAC5C,gDACF;EACA,KAAK,UAAU;EACf,KAAKA,OAAO;EACZ,KAAKC,aAAa,IAAI;CACxB;;;;;;CAOA,MAAM,UAAa,IAAkC;EACnD,MAAM,QAAQ,KAAKD,KAAK;EACxB,IAAI;GACF,OAAO,MAAM,GAAG;EAClB,UAAU;GACR,KAAKE,eAAe,KAAKF,KAAK,IAAI;EACpC;CACF;CAEA,YAAoB;EAClB,OAAO,KAAKA,KAAK,IAAI,KAAKC,aAAa,KAAKC;CAC9C;;;;;;CAOA,YAAqB;EACnB,IAAI,KAAK,YAAY,GACnB,OAAO;EAET,MAAM,UAAU,KAAK,UAAU;EAC/B,IAAI,UAAU,KAAK,SACjB,OAAO;EAET,KAAKC,mBAAmB;EACxB,OAAO;CACT;;CAGA,IAAI,gBAAoC;EACtC,OAAO,KAAKA;CACd;AACF"}