@rocicorp/zero 1.11.0-canary.4 → 1.11.0-canary.41

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 (1015) hide show
  1. package/out/analyze-query/src/analyze-cli.js +4 -4
  2. package/out/analyze-query/src/analyze-cli.js.map +1 -1
  3. package/out/analyze-query/src/bin-analyze.js +13 -12
  4. package/out/analyze-query/src/bin-analyze.js.map +1 -1
  5. package/out/analyze-query/src/bin-transform.js +1 -1
  6. package/out/analyze-query/src/bin-transform.js.map +1 -1
  7. package/out/ast-to-zql/src/ast-to-zql.d.ts +8 -1
  8. package/out/ast-to-zql/src/ast-to-zql.d.ts.map +1 -1
  9. package/out/ast-to-zql/src/ast-to-zql.js +25 -25
  10. package/out/ast-to-zql/src/ast-to-zql.js.map +1 -1
  11. package/out/otel/src/log-options.d.ts +16 -0
  12. package/out/otel/src/log-options.d.ts.map +1 -1
  13. package/out/otel/src/log-options.js +60 -6
  14. package/out/otel/src/log-options.js.map +1 -1
  15. package/out/replicache/src/bg-interval.d.ts +2 -1
  16. package/out/replicache/src/bg-interval.d.ts.map +1 -1
  17. package/out/replicache/src/bg-interval.js +13 -4
  18. package/out/replicache/src/bg-interval.js.map +1 -1
  19. package/out/replicache/src/btree/node.d.ts.map +1 -1
  20. package/out/replicache/src/btree/node.js +3 -6
  21. package/out/replicache/src/btree/node.js.map +1 -1
  22. package/out/replicache/src/dag/gc.d.ts.map +1 -1
  23. package/out/replicache/src/dag/gc.js +8 -11
  24. package/out/replicache/src/dag/gc.js.map +1 -1
  25. package/out/replicache/src/dag/invalid-ref-count-error.d.ts +12 -0
  26. package/out/replicache/src/dag/invalid-ref-count-error.d.ts.map +1 -0
  27. package/out/replicache/src/dag/invalid-ref-count-error.js +19 -0
  28. package/out/replicache/src/dag/invalid-ref-count-error.js.map +1 -0
  29. package/out/replicache/src/dag/lazy-store.d.ts +17 -4
  30. package/out/replicache/src/dag/lazy-store.d.ts.map +1 -1
  31. package/out/replicache/src/dag/lazy-store.js +35 -9
  32. package/out/replicache/src/dag/lazy-store.js.map +1 -1
  33. package/out/replicache/src/dag/store-impl.d.ts +12 -2
  34. package/out/replicache/src/dag/store-impl.d.ts.map +1 -1
  35. package/out/replicache/src/dag/store-impl.js +29 -9
  36. package/out/replicache/src/dag/store-impl.js.map +1 -1
  37. package/out/replicache/src/db/rebase.d.ts +14 -2
  38. package/out/replicache/src/db/rebase.d.ts.map +1 -1
  39. package/out/replicache/src/db/rebase.js +27 -5
  40. package/out/replicache/src/db/rebase.js.map +1 -1
  41. package/out/replicache/src/get-kv-store-provider.d.ts +1 -1
  42. package/out/replicache/src/get-kv-store-provider.d.ts.map +1 -1
  43. package/out/replicache/src/get-kv-store-provider.js +4 -4
  44. package/out/replicache/src/get-kv-store-provider.js.map +1 -1
  45. package/out/replicache/src/kv/expo-sqlite/store.d.ts.map +1 -1
  46. package/out/replicache/src/kv/expo-sqlite/store.js +28 -5
  47. package/out/replicache/src/kv/expo-sqlite/store.js.map +1 -1
  48. package/out/replicache/src/kv/idb-store.d.ts +18 -0
  49. package/out/replicache/src/kv/idb-store.d.ts.map +1 -1
  50. package/out/replicache/src/kv/idb-store.js +30 -2
  51. package/out/replicache/src/kv/idb-store.js.map +1 -1
  52. package/out/replicache/src/kv/mem-fallback-store.d.ts +54 -0
  53. package/out/replicache/src/kv/mem-fallback-store.d.ts.map +1 -0
  54. package/out/replicache/src/kv/mem-fallback-store.js +177 -0
  55. package/out/replicache/src/kv/mem-fallback-store.js.map +1 -0
  56. package/out/replicache/src/kv/mem-store.d.ts +1 -0
  57. package/out/replicache/src/kv/mem-store.d.ts.map +1 -1
  58. package/out/replicache/src/kv/mem-store.js +3 -0
  59. package/out/replicache/src/kv/mem-store.js.map +1 -1
  60. package/out/replicache/src/kv/op-sqlite/store.d.ts.map +1 -1
  61. package/out/replicache/src/kv/op-sqlite/store.js +4 -4
  62. package/out/replicache/src/kv/op-sqlite/store.js.map +1 -1
  63. package/out/replicache/src/kv/sqlite-store.d.ts +22 -1
  64. package/out/replicache/src/kv/sqlite-store.d.ts.map +1 -1
  65. package/out/replicache/src/kv/sqlite-store.js +159 -14
  66. package/out/replicache/src/kv/sqlite-store.js.map +1 -1
  67. package/out/replicache/src/kv/store.d.ts +6 -0
  68. package/out/replicache/src/kv/store.d.ts.map +1 -1
  69. package/out/replicache/src/new-client-channel.js.map +1 -1
  70. package/out/replicache/src/persist/client-gc.d.ts +2 -1
  71. package/out/replicache/src/persist/client-gc.d.ts.map +1 -1
  72. package/out/replicache/src/persist/client-gc.js +2 -2
  73. package/out/replicache/src/persist/client-gc.js.map +1 -1
  74. package/out/replicache/src/persist/client-group-gc.d.ts +2 -1
  75. package/out/replicache/src/persist/client-group-gc.d.ts.map +1 -1
  76. package/out/replicache/src/persist/client-group-gc.js +2 -2
  77. package/out/replicache/src/persist/client-group-gc.js.map +1 -1
  78. package/out/replicache/src/persist/clients.d.ts +2 -2
  79. package/out/replicache/src/persist/collect-idb-databases.d.ts +28 -8
  80. package/out/replicache/src/persist/collect-idb-databases.d.ts.map +1 -1
  81. package/out/replicache/src/persist/collect-idb-databases.js +97 -20
  82. package/out/replicache/src/persist/collect-idb-databases.js.map +1 -1
  83. package/out/replicache/src/persist/heartbeat.d.ts +2 -1
  84. package/out/replicache/src/persist/heartbeat.d.ts.map +1 -1
  85. package/out/replicache/src/persist/heartbeat.js +2 -2
  86. package/out/replicache/src/persist/heartbeat.js.map +1 -1
  87. package/out/replicache/src/persist/idb-databases-store-db-name.js +1 -1
  88. package/out/replicache/src/persist/idb-databases-store-db-name.js.map +1 -1
  89. package/out/replicache/src/persist/persist.d.ts.map +1 -1
  90. package/out/replicache/src/persist/persist.js +18 -8
  91. package/out/replicache/src/persist/persist.js.map +1 -1
  92. package/out/replicache/src/persist/refresh.js +6 -2
  93. package/out/replicache/src/persist/refresh.js.map +1 -1
  94. package/out/replicache/src/replicache-impl.d.ts +85 -3
  95. package/out/replicache/src/replicache-impl.d.ts.map +1 -1
  96. package/out/replicache/src/replicache-impl.js +321 -29
  97. package/out/replicache/src/replicache-impl.js.map +1 -1
  98. package/out/replicache/src/replicache-options.d.ts +9 -0
  99. package/out/replicache/src/replicache-options.d.ts.map +1 -1
  100. package/out/replicache/src/storage-failure.d.ts +37 -0
  101. package/out/replicache/src/storage-failure.d.ts.map +1 -0
  102. package/out/replicache/src/storage-failure.js +31 -0
  103. package/out/replicache/src/storage-failure.js.map +1 -0
  104. package/out/shared/src/arrays.d.ts +5 -0
  105. package/out/shared/src/arrays.d.ts.map +1 -1
  106. package/out/shared/src/arrays.js +8 -10
  107. package/out/shared/src/arrays.js.map +1 -1
  108. package/out/shared/src/centroid.d.ts +0 -1
  109. package/out/shared/src/centroid.d.ts.map +1 -1
  110. package/out/shared/src/centroid.js +1 -4
  111. package/out/shared/src/centroid.js.map +1 -1
  112. package/out/shared/src/error.d.ts +11 -0
  113. package/out/shared/src/error.d.ts.map +1 -1
  114. package/out/shared/src/error.js +35 -1
  115. package/out/shared/src/error.js.map +1 -1
  116. package/out/shared/src/hash.d.ts.map +1 -1
  117. package/out/shared/src/hash.js +32 -7
  118. package/out/shared/src/hash.js.map +1 -1
  119. package/out/shared/src/iterables.d.ts +2 -0
  120. package/out/shared/src/iterables.d.ts.map +1 -1
  121. package/out/shared/src/iterables.js +18 -1
  122. package/out/shared/src/iterables.js.map +1 -1
  123. package/out/shared/src/map.d.ts +24 -2
  124. package/out/shared/src/map.d.ts.map +1 -1
  125. package/out/shared/src/map.js +18 -4
  126. package/out/shared/src/map.js.map +1 -1
  127. package/out/shared/src/options-types.d.ts +2 -2
  128. package/out/shared/src/options.d.ts.map +1 -1
  129. package/out/shared/src/options.js +10 -7
  130. package/out/shared/src/options.js.map +1 -1
  131. package/out/shared/src/random-values.js +12 -1
  132. package/out/shared/src/random-values.js.map +1 -1
  133. package/out/shared/src/ring-buffer.d.ts +10 -0
  134. package/out/shared/src/ring-buffer.d.ts.map +1 -1
  135. package/out/shared/src/ring-buffer.js +26 -1
  136. package/out/shared/src/ring-buffer.js.map +1 -1
  137. package/out/shared/src/tdigest.d.ts +10 -0
  138. package/out/shared/src/tdigest.d.ts.map +1 -1
  139. package/out/shared/src/tdigest.js +147 -63
  140. package/out/shared/src/tdigest.js.map +1 -1
  141. package/out/shared/src/valita.d.ts +88 -0
  142. package/out/shared/src/valita.d.ts.map +1 -1
  143. package/out/shared/src/valita.js +141 -23
  144. package/out/shared/src/valita.js.map +1 -1
  145. package/out/z2s/src/compiler.d.ts.map +1 -1
  146. package/out/z2s/src/compiler.js +10 -6
  147. package/out/z2s/src/compiler.js.map +1 -1
  148. package/out/z2s/src/sql.d.ts.map +1 -1
  149. package/out/z2s/src/sql.js +9 -5
  150. package/out/z2s/src/sql.js.map +1 -1
  151. package/out/zero/package.js +5 -6
  152. package/out/zero/package.js.map +1 -1
  153. package/out/zero/src/zero.js +2 -1
  154. package/out/zero-cache/src/auth/write-authorizer.d.ts.map +1 -1
  155. package/out/zero-cache/src/auth/write-authorizer.js +1 -0
  156. package/out/zero-cache/src/auth/write-authorizer.js.map +1 -1
  157. package/out/zero-cache/src/config/normalize.d.ts +1 -0
  158. package/out/zero-cache/src/config/normalize.d.ts.map +1 -1
  159. package/out/zero-cache/src/config/normalize.js +47 -4
  160. package/out/zero-cache/src/config/normalize.js.map +1 -1
  161. package/out/zero-cache/src/config/zero-config.d.ts +148 -25
  162. package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
  163. package/out/zero-cache/src/config/zero-config.js +500 -167
  164. package/out/zero-cache/src/config/zero-config.js.map +1 -1
  165. package/out/zero-cache/src/custom/fetch.d.ts +1 -1
  166. package/out/zero-cache/src/custom/fetch.d.ts.map +1 -1
  167. package/out/zero-cache/src/custom/fetch.js.map +1 -1
  168. package/out/zero-cache/src/db/lite-tables.d.ts.map +1 -1
  169. package/out/zero-cache/src/db/lite-tables.js +3 -4
  170. package/out/zero-cache/src/db/lite-tables.js.map +1 -1
  171. package/out/zero-cache/src/db/migration-lite.d.ts.map +1 -1
  172. package/out/zero-cache/src/db/migration-lite.js +5 -3
  173. package/out/zero-cache/src/db/migration-lite.js.map +1 -1
  174. package/out/zero-cache/src/observability/events.js +4 -1
  175. package/out/zero-cache/src/observability/events.js.map +1 -1
  176. package/out/zero-cache/src/observability/log-throttle.d.ts +44 -0
  177. package/out/zero-cache/src/observability/log-throttle.d.ts.map +1 -0
  178. package/out/zero-cache/src/observability/log-throttle.js +76 -0
  179. package/out/zero-cache/src/observability/log-throttle.js.map +1 -0
  180. package/out/zero-cache/src/observability/metrics.d.ts.map +1 -1
  181. package/out/zero-cache/src/observability/metrics.js +2 -7
  182. package/out/zero-cache/src/observability/metrics.js.map +1 -1
  183. package/out/zero-cache/src/scripts/permissions.d.ts +16 -0
  184. package/out/zero-cache/src/scripts/permissions.d.ts.map +1 -1
  185. package/out/zero-cache/src/scripts/permissions.js +3 -3
  186. package/out/zero-cache/src/scripts/permissions.js.map +1 -1
  187. package/out/zero-cache/src/server/change-streamer.d.ts.map +1 -1
  188. package/out/zero-cache/src/server/change-streamer.js +123 -87
  189. package/out/zero-cache/src/server/change-streamer.js.map +1 -1
  190. package/out/zero-cache/src/server/inspector-delegate.d.ts +28 -2
  191. package/out/zero-cache/src/server/inspector-delegate.d.ts.map +1 -1
  192. package/out/zero-cache/src/server/inspector-delegate.js +37 -17
  193. package/out/zero-cache/src/server/inspector-delegate.js.map +1 -1
  194. package/out/zero-cache/src/server/main.d.ts.map +1 -1
  195. package/out/zero-cache/src/server/main.js +13 -2
  196. package/out/zero-cache/src/server/main.js.map +1 -1
  197. package/out/zero-cache/src/server/mutator.js +2 -0
  198. package/out/zero-cache/src/server/mutator.js.map +1 -1
  199. package/out/zero-cache/src/server/reaper.d.ts.map +1 -1
  200. package/out/zero-cache/src/server/reaper.js +2 -0
  201. package/out/zero-cache/src/server/reaper.js.map +1 -1
  202. package/out/zero-cache/src/server/replicator.d.ts +7 -0
  203. package/out/zero-cache/src/server/replicator.d.ts.map +1 -1
  204. package/out/zero-cache/src/server/replicator.js +103 -22
  205. package/out/zero-cache/src/server/replicator.js.map +1 -1
  206. package/out/zero-cache/src/server/runner/run-worker.d.ts.map +1 -1
  207. package/out/zero-cache/src/server/runner/run-worker.js +12 -6
  208. package/out/zero-cache/src/server/runner/run-worker.js.map +1 -1
  209. package/out/zero-cache/src/server/runner/zero-dispatcher.d.ts.map +1 -1
  210. package/out/zero-cache/src/server/runner/zero-dispatcher.js +5 -0
  211. package/out/zero-cache/src/server/runner/zero-dispatcher.js.map +1 -1
  212. package/out/zero-cache/src/server/slot-keeper.d.ts +26 -0
  213. package/out/zero-cache/src/server/slot-keeper.d.ts.map +1 -0
  214. package/out/zero-cache/src/server/slot-keeper.js +181 -0
  215. package/out/zero-cache/src/server/slot-keeper.js.map +1 -0
  216. package/out/zero-cache/src/server/syncer-assigner.d.ts +14 -0
  217. package/out/zero-cache/src/server/syncer-assigner.d.ts.map +1 -0
  218. package/out/zero-cache/src/server/syncer-assigner.js +72 -0
  219. package/out/zero-cache/src/server/syncer-assigner.js.map +1 -0
  220. package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
  221. package/out/zero-cache/src/server/syncer.js +40 -2
  222. package/out/zero-cache/src/server/syncer.js.map +1 -1
  223. package/out/zero-cache/src/server/worker-dispatcher.d.ts.map +1 -1
  224. package/out/zero-cache/src/server/worker-dispatcher.js +21 -4
  225. package/out/zero-cache/src/server/worker-dispatcher.js.map +1 -1
  226. package/out/zero-cache/src/server/worker-urls.d.ts +1 -0
  227. package/out/zero-cache/src/server/worker-urls.d.ts.map +1 -1
  228. package/out/zero-cache/src/server/worker-urls.js +2 -1
  229. package/out/zero-cache/src/server/worker-urls.js.map +1 -1
  230. package/out/zero-cache/src/services/analyze.d.ts.map +1 -1
  231. package/out/zero-cache/src/services/analyze.js +11 -9
  232. package/out/zero-cache/src/services/analyze.js.map +1 -1
  233. package/out/zero-cache/src/services/change-source/common/backfill-manager.d.ts.map +1 -1
  234. package/out/zero-cache/src/services/change-source/common/backfill-manager.js +198 -24
  235. package/out/zero-cache/src/services/change-source/common/backfill-manager.js.map +1 -1
  236. package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.d.ts.map +1 -1
  237. package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.js +16 -4
  238. package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.js.map +1 -1
  239. package/out/zero-cache/src/services/change-source/common/init-cleanup.d.ts +24 -0
  240. package/out/zero-cache/src/services/change-source/common/init-cleanup.d.ts.map +1 -0
  241. package/out/zero-cache/src/services/change-source/common/init-cleanup.js +44 -0
  242. package/out/zero-cache/src/services/change-source/common/init-cleanup.js.map +1 -0
  243. package/out/zero-cache/src/services/change-source/common/replica-restore.d.ts +82 -2
  244. package/out/zero-cache/src/services/change-source/common/replica-restore.d.ts.map +1 -1
  245. package/out/zero-cache/src/services/change-source/common/replica-restore.js +21 -10
  246. package/out/zero-cache/src/services/change-source/common/replica-restore.js.map +1 -1
  247. package/out/zero-cache/src/services/change-source/common/replica-schema.d.ts +1 -0
  248. package/out/zero-cache/src/services/change-source/common/replica-schema.d.ts.map +1 -1
  249. package/out/zero-cache/src/services/change-source/common/replica-schema.js +15 -3
  250. package/out/zero-cache/src/services/change-source/common/replica-schema.js.map +1 -1
  251. package/out/zero-cache/src/services/change-source/custom/change-source.d.ts +1 -1
  252. package/out/zero-cache/src/services/change-source/custom/change-source.d.ts.map +1 -1
  253. package/out/zero-cache/src/services/change-source/custom/change-source.js +7 -3
  254. package/out/zero-cache/src/services/change-source/custom/change-source.js.map +1 -1
  255. package/out/zero-cache/src/services/change-source/pg/backfill-stream.d.ts +9 -0
  256. package/out/zero-cache/src/services/change-source/pg/backfill-stream.d.ts.map +1 -1
  257. package/out/zero-cache/src/services/change-source/pg/backfill-stream.js +213 -21
  258. package/out/zero-cache/src/services/change-source/pg/backfill-stream.js.map +1 -1
  259. package/out/zero-cache/src/services/change-source/pg/change-source-init.d.ts +65 -0
  260. package/out/zero-cache/src/services/change-source/pg/change-source-init.d.ts.map +1 -0
  261. package/out/zero-cache/src/services/change-source/pg/change-source-init.js +312 -0
  262. package/out/zero-cache/src/services/change-source/pg/change-source-init.js.map +1 -0
  263. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts +31 -18
  264. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts.map +1 -1
  265. package/out/zero-cache/src/services/change-source/pg/change-source.js +132 -157
  266. package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
  267. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts +44 -2
  268. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts.map +1 -1
  269. package/out/zero-cache/src/services/change-source/pg/initial-sync.js +65 -28
  270. package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
  271. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.d.ts +66 -1
  272. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.d.ts.map +1 -1
  273. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js +207 -24
  274. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js.map +1 -1
  275. package/out/zero-cache/src/services/change-source/pg/replication-slot-cleanup-monitor.d.ts +16 -0
  276. package/out/zero-cache/src/services/change-source/pg/replication-slot-cleanup-monitor.d.ts.map +1 -0
  277. package/out/zero-cache/src/services/change-source/pg/replication-slot-cleanup-monitor.js +113 -0
  278. package/out/zero-cache/src/services/change-source/pg/replication-slot-cleanup-monitor.js.map +1 -0
  279. package/out/zero-cache/src/services/change-source/pg/replication-slots.d.ts +66 -21
  280. package/out/zero-cache/src/services/change-source/pg/replication-slots.d.ts.map +1 -1
  281. package/out/zero-cache/src/services/change-source/pg/replication-slots.js +274 -68
  282. package/out/zero-cache/src/services/change-source/pg/replication-slots.js.map +1 -1
  283. package/out/zero-cache/src/services/change-source/pg/schema/index-predicate.d.ts.map +1 -1
  284. package/out/zero-cache/src/services/change-source/pg/schema/index-predicate.js +68 -8
  285. package/out/zero-cache/src/services/change-source/pg/schema/index-predicate.js.map +1 -1
  286. package/out/zero-cache/src/services/change-source/pg/schema/init.d.ts.map +1 -1
  287. package/out/zero-cache/src/services/change-source/pg/schema/init.js +46 -1
  288. package/out/zero-cache/src/services/change-source/pg/schema/init.js.map +1 -1
  289. package/out/zero-cache/src/services/change-source/pg/schema/replica-stage-enum.d.ts +10 -0
  290. package/out/zero-cache/src/services/change-source/pg/schema/replica-stage-enum.d.ts.map +1 -0
  291. package/out/zero-cache/src/services/change-source/pg/schema/replica-stage-enum.js +6 -0
  292. package/out/zero-cache/src/services/change-source/pg/schema/replica-stage-enum.js.map +1 -0
  293. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts +68 -27
  294. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts.map +1 -1
  295. package/out/zero-cache/src/services/change-source/pg/schema/shard.js +116 -35
  296. package/out/zero-cache/src/services/change-source/pg/schema/shard.js.map +1 -1
  297. package/out/zero-cache/src/services/change-source/protocol/backfill-progress.d.ts +68 -0
  298. package/out/zero-cache/src/services/change-source/protocol/backfill-progress.d.ts.map +1 -0
  299. package/out/zero-cache/src/services/change-source/protocol/backfill-progress.js +141 -0
  300. package/out/zero-cache/src/services/change-source/protocol/backfill-progress.js.map +1 -0
  301. package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts +45 -2
  302. package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts.map +1 -1
  303. package/out/zero-cache/src/services/change-source/protocol/current/data.js +10 -1
  304. package/out/zero-cache/src/services/change-source/protocol/current/data.js.map +1 -1
  305. package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts +60 -3
  306. package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts.map +1 -1
  307. package/out/zero-cache/src/services/change-source/protocol/current/upstream.d.ts +23 -10
  308. package/out/zero-cache/src/services/change-source/protocol/current/upstream.d.ts.map +1 -1
  309. package/out/zero-cache/src/services/change-source/protocol/current/upstream.js +17 -7
  310. package/out/zero-cache/src/services/change-source/protocol/current/upstream.js.map +1 -1
  311. package/out/zero-cache/src/services/change-source/protocol/current.js +2 -1
  312. package/out/zero-cache/src/services/change-streamer/backfill-state-tracker.d.ts +72 -0
  313. package/out/zero-cache/src/services/change-streamer/backfill-state-tracker.d.ts.map +1 -0
  314. package/out/zero-cache/src/services/change-streamer/backfill-state-tracker.js +162 -0
  315. package/out/zero-cache/src/services/change-streamer/backfill-state-tracker.js.map +1 -0
  316. package/out/zero-cache/src/services/change-streamer/backfill-state.d.ts +50 -0
  317. package/out/zero-cache/src/services/change-streamer/backfill-state.d.ts.map +1 -0
  318. package/out/zero-cache/src/services/change-streamer/backfill-state.js +268 -0
  319. package/out/zero-cache/src/services/change-streamer/backfill-state.js.map +1 -0
  320. package/out/zero-cache/src/services/change-streamer/backup-cleanup-monitor-factory.d.ts.map +1 -1
  321. package/out/zero-cache/src/services/change-streamer/backup-cleanup-monitor-factory.js +6 -17
  322. package/out/zero-cache/src/services/change-streamer/backup-cleanup-monitor-factory.js.map +1 -1
  323. package/out/zero-cache/src/services/change-streamer/backup-monitor.d.ts.map +1 -1
  324. package/out/zero-cache/src/services/change-streamer/backup-monitor.js +59 -8
  325. package/out/zero-cache/src/services/change-streamer/backup-monitor.js.map +1 -1
  326. package/out/zero-cache/src/services/change-streamer/broadcast.d.ts +8 -2
  327. package/out/zero-cache/src/services/change-streamer/broadcast.d.ts.map +1 -1
  328. package/out/zero-cache/src/services/change-streamer/broadcast.js +24 -4
  329. package/out/zero-cache/src/services/change-streamer/broadcast.js.map +1 -1
  330. package/out/zero-cache/src/services/change-streamer/change-log-codec.d.ts +19 -4
  331. package/out/zero-cache/src/services/change-streamer/change-log-codec.d.ts.map +1 -1
  332. package/out/zero-cache/src/services/change-streamer/change-log-codec.js +28 -8
  333. package/out/zero-cache/src/services/change-streamer/change-log-codec.js.map +1 -1
  334. package/out/zero-cache/src/services/change-streamer/change-log-initializer.d.ts +17 -0
  335. package/out/zero-cache/src/services/change-streamer/change-log-initializer.d.ts.map +1 -1
  336. package/out/zero-cache/src/services/change-streamer/change-log-initializer.js +44 -1
  337. package/out/zero-cache/src/services/change-streamer/change-log-initializer.js.map +1 -1
  338. package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts +54 -6
  339. package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts.map +1 -1
  340. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +145 -35
  341. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
  342. package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts +36 -0
  343. package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts.map +1 -1
  344. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js +267 -118
  345. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -1
  346. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts +161 -17
  347. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts.map +1 -1
  348. package/out/zero-cache/src/services/change-streamer/change-streamer.js +33 -2
  349. package/out/zero-cache/src/services/change-streamer/change-streamer.js.map +1 -1
  350. package/out/zero-cache/src/services/change-streamer/drain-tracker.d.ts +24 -0
  351. package/out/zero-cache/src/services/change-streamer/drain-tracker.d.ts.map +1 -0
  352. package/out/zero-cache/src/services/change-streamer/drain-tracker.js +67 -0
  353. package/out/zero-cache/src/services/change-streamer/drain-tracker.js.map +1 -0
  354. package/out/zero-cache/src/services/change-streamer/forwarder.d.ts +3 -3
  355. package/out/zero-cache/src/services/change-streamer/forwarder.d.ts.map +1 -1
  356. package/out/zero-cache/src/services/change-streamer/forwarder.js +36 -5
  357. package/out/zero-cache/src/services/change-streamer/forwarder.js.map +1 -1
  358. package/out/zero-cache/src/services/change-streamer/litestream-sync-requester.d.ts +53 -0
  359. package/out/zero-cache/src/services/change-streamer/litestream-sync-requester.d.ts.map +1 -0
  360. package/out/zero-cache/src/services/change-streamer/litestream-sync-requester.js +156 -0
  361. package/out/zero-cache/src/services/change-streamer/litestream-sync-requester.js.map +1 -0
  362. package/out/zero-cache/src/services/change-streamer/restore-admission.d.ts +243 -0
  363. package/out/zero-cache/src/services/change-streamer/restore-admission.d.ts.map +1 -0
  364. package/out/zero-cache/src/services/change-streamer/restore-admission.js +317 -0
  365. package/out/zero-cache/src/services/change-streamer/restore-admission.js.map +1 -0
  366. package/out/zero-cache/src/services/change-streamer/schema/tables.d.ts +78 -1
  367. package/out/zero-cache/src/services/change-streamer/schema/tables.d.ts.map +1 -1
  368. package/out/zero-cache/src/services/change-streamer/schema/tables.js +173 -47
  369. package/out/zero-cache/src/services/change-streamer/schema/tables.js.map +1 -1
  370. package/out/zero-cache/src/services/change-streamer/snapshot-message.d.ts +92 -0
  371. package/out/zero-cache/src/services/change-streamer/snapshot-message.d.ts.map +1 -0
  372. package/out/zero-cache/src/services/change-streamer/snapshot-message.js +42 -0
  373. package/out/zero-cache/src/services/change-streamer/snapshot-message.js.map +1 -0
  374. package/out/zero-cache/src/services/change-streamer/snapshot-reservations.d.ts +14 -2
  375. package/out/zero-cache/src/services/change-streamer/snapshot-reservations.d.ts.map +1 -1
  376. package/out/zero-cache/src/services/change-streamer/snapshot-reservations.js +23 -10
  377. package/out/zero-cache/src/services/change-streamer/snapshot-reservations.js.map +1 -1
  378. package/out/zero-cache/src/services/change-streamer/snapshot.d.ts +7 -69
  379. package/out/zero-cache/src/services/change-streamer/snapshot.d.ts.map +1 -1
  380. package/out/zero-cache/src/services/change-streamer/snapshot.js +21 -53
  381. package/out/zero-cache/src/services/change-streamer/snapshot.js.map +1 -1
  382. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.d.ts +6 -1
  383. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.d.ts.map +1 -1
  384. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.js +27 -9
  385. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.js.map +1 -1
  386. package/out/zero-cache/src/services/change-streamer/storer.d.ts +106 -5
  387. package/out/zero-cache/src/services/change-streamer/storer.d.ts.map +1 -1
  388. package/out/zero-cache/src/services/change-streamer/storer.js +299 -86
  389. package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
  390. package/out/zero-cache/src/services/change-streamer/subscribe.d.ts +485 -0
  391. package/out/zero-cache/src/services/change-streamer/subscribe.d.ts.map +1 -0
  392. package/out/zero-cache/src/services/change-streamer/subscribe.js +93 -0
  393. package/out/zero-cache/src/services/change-streamer/subscribe.js.map +1 -0
  394. package/out/zero-cache/src/services/change-streamer/subscriber.d.ts +80 -2
  395. package/out/zero-cache/src/services/change-streamer/subscriber.d.ts.map +1 -1
  396. package/out/zero-cache/src/services/change-streamer/subscriber.js +157 -20
  397. package/out/zero-cache/src/services/change-streamer/subscriber.js.map +1 -1
  398. package/out/zero-cache/src/services/change-streamer/upstream-acker.d.ts +19 -1
  399. package/out/zero-cache/src/services/change-streamer/upstream-acker.d.ts.map +1 -1
  400. package/out/zero-cache/src/services/change-streamer/upstream-acker.js +23 -3
  401. package/out/zero-cache/src/services/change-streamer/upstream-acker.js.map +1 -1
  402. package/out/zero-cache/src/services/http-service.d.ts +7 -1
  403. package/out/zero-cache/src/services/http-service.d.ts.map +1 -1
  404. package/out/zero-cache/src/services/http-service.js +14 -2
  405. package/out/zero-cache/src/services/http-service.js.map +1 -1
  406. package/out/zero-cache/src/services/life-cycle.d.ts +68 -2
  407. package/out/zero-cache/src/services/life-cycle.d.ts.map +1 -1
  408. package/out/zero-cache/src/services/life-cycle.js +155 -19
  409. package/out/zero-cache/src/services/life-cycle.js.map +1 -1
  410. package/out/zero-cache/src/services/litestream/commands.d.ts +35 -3
  411. package/out/zero-cache/src/services/litestream/commands.d.ts.map +1 -1
  412. package/out/zero-cache/src/services/litestream/commands.js +137 -35
  413. package/out/zero-cache/src/services/litestream/commands.js.map +1 -1
  414. package/out/zero-cache/src/services/litestream/config-v5.yml +6 -7
  415. package/out/zero-cache/src/services/litestream/litestream-checkpointer.js +51 -24
  416. package/out/zero-cache/src/services/litestream/litestream-checkpointer.js.map +1 -1
  417. package/out/zero-cache/src/services/litestream/litestream-controller.d.ts +10 -2
  418. package/out/zero-cache/src/services/litestream/litestream-controller.d.ts.map +1 -1
  419. package/out/zero-cache/src/services/litestream/litestream-controller.js +3 -2
  420. package/out/zero-cache/src/services/litestream/litestream-controller.js.map +1 -1
  421. package/out/zero-cache/src/services/litestream/restore-progress.d.ts +24 -0
  422. package/out/zero-cache/src/services/litestream/restore-progress.d.ts.map +1 -0
  423. package/out/zero-cache/src/services/litestream/restore-progress.js +91 -0
  424. package/out/zero-cache/src/services/litestream/restore-progress.js.map +1 -0
  425. package/out/zero-cache/src/services/mutagen/mutagen.d.ts +5 -0
  426. package/out/zero-cache/src/services/mutagen/mutagen.d.ts.map +1 -1
  427. package/out/zero-cache/src/services/mutagen/mutagen.js +7 -1
  428. package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -1
  429. package/out/zero-cache/src/services/mutagen/pusher.d.ts.map +1 -1
  430. package/out/zero-cache/src/services/mutagen/pusher.js +5 -6
  431. package/out/zero-cache/src/services/mutagen/pusher.js.map +1 -1
  432. package/out/zero-cache/src/services/plannerz.d.ts +163 -0
  433. package/out/zero-cache/src/services/plannerz.d.ts.map +1 -0
  434. package/out/zero-cache/src/services/plannerz.js +267 -0
  435. package/out/zero-cache/src/services/plannerz.js.map +1 -0
  436. package/out/zero-cache/src/services/profz.d.ts +30 -0
  437. package/out/zero-cache/src/services/profz.d.ts.map +1 -0
  438. package/out/zero-cache/src/services/profz.js +163 -0
  439. package/out/zero-cache/src/services/profz.js.map +1 -0
  440. package/out/zero-cache/src/services/replicator/change-log-cookies.js +1 -1
  441. package/out/zero-cache/src/services/replicator/change-log-cookies.js.map +1 -1
  442. package/out/zero-cache/src/services/replicator/change-log-stream-writer.d.ts +5 -4
  443. package/out/zero-cache/src/services/replicator/change-log-stream-writer.d.ts.map +1 -1
  444. package/out/zero-cache/src/services/replicator/change-log-stream-writer.js +20 -22
  445. package/out/zero-cache/src/services/replicator/change-log-stream-writer.js.map +1 -1
  446. package/out/zero-cache/src/services/replicator/change-processor.d.ts.map +1 -1
  447. package/out/zero-cache/src/services/replicator/change-processor.js +51 -5
  448. package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
  449. package/out/zero-cache/src/services/replicator/drain-handler.d.ts +74 -0
  450. package/out/zero-cache/src/services/replicator/drain-handler.d.ts.map +1 -0
  451. package/out/zero-cache/src/services/replicator/drain-handler.js +185 -0
  452. package/out/zero-cache/src/services/replicator/drain-handler.js.map +1 -0
  453. package/out/zero-cache/src/services/replicator/incremental-sync.d.ts +6 -2
  454. package/out/zero-cache/src/services/replicator/incremental-sync.d.ts.map +1 -1
  455. package/out/zero-cache/src/services/replicator/incremental-sync.js +114 -28
  456. package/out/zero-cache/src/services/replicator/incremental-sync.js.map +1 -1
  457. package/out/zero-cache/src/services/replicator/replication-status.d.ts +35 -1
  458. package/out/zero-cache/src/services/replicator/replication-status.d.ts.map +1 -1
  459. package/out/zero-cache/src/services/replicator/replication-status.js +99 -8
  460. package/out/zero-cache/src/services/replicator/replication-status.js.map +1 -1
  461. package/out/zero-cache/src/services/replicator/replicator.d.ts +5 -1
  462. package/out/zero-cache/src/services/replicator/replicator.d.ts.map +1 -1
  463. package/out/zero-cache/src/services/replicator/replicator.js +5 -2
  464. package/out/zero-cache/src/services/replicator/replicator.js.map +1 -1
  465. package/out/zero-cache/src/services/replicator/reporter/recorder.d.ts +16 -1
  466. package/out/zero-cache/src/services/replicator/reporter/recorder.d.ts.map +1 -1
  467. package/out/zero-cache/src/services/replicator/reporter/recorder.js +70 -27
  468. package/out/zero-cache/src/services/replicator/reporter/recorder.js.map +1 -1
  469. package/out/zero-cache/src/services/replicator/schema/backfilling.d.ts +23 -2
  470. package/out/zero-cache/src/services/replicator/schema/backfilling.d.ts.map +1 -1
  471. package/out/zero-cache/src/services/replicator/schema/backfilling.js +54 -2
  472. package/out/zero-cache/src/services/replicator/schema/backfilling.js.map +1 -1
  473. package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.d.ts +6 -6
  474. package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.d.ts.map +1 -1
  475. package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.js +19 -14
  476. package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.js.map +1 -1
  477. package/out/zero-cache/src/services/replicator/write-worker-client.d.ts +11 -3
  478. package/out/zero-cache/src/services/replicator/write-worker-client.d.ts.map +1 -1
  479. package/out/zero-cache/src/services/replicator/write-worker-client.js.map +1 -1
  480. package/out/zero-cache/src/services/replicator/write-worker.js +5 -1
  481. package/out/zero-cache/src/services/replicator/write-worker.js.map +1 -1
  482. package/out/zero-cache/src/services/run-ast.d.ts +12 -0
  483. package/out/zero-cache/src/services/run-ast.d.ts.map +1 -1
  484. package/out/zero-cache/src/services/run-ast.js +42 -22
  485. package/out/zero-cache/src/services/run-ast.js.map +1 -1
  486. package/out/zero-cache/src/services/runner.d.ts +2 -1
  487. package/out/zero-cache/src/services/runner.d.ts.map +1 -1
  488. package/out/zero-cache/src/services/runner.js +10 -2
  489. package/out/zero-cache/src/services/runner.js.map +1 -1
  490. package/out/zero-cache/src/services/statz.d.ts +4 -0
  491. package/out/zero-cache/src/services/statz.d.ts.map +1 -1
  492. package/out/zero-cache/src/services/statz.js +22 -5
  493. package/out/zero-cache/src/services/statz.js.map +1 -1
  494. package/out/zero-cache/src/services/view-syncer/advancement-metrics.d.ts +26 -0
  495. package/out/zero-cache/src/services/view-syncer/advancement-metrics.d.ts.map +1 -0
  496. package/out/zero-cache/src/services/view-syncer/advancement-metrics.js +26 -0
  497. package/out/zero-cache/src/services/view-syncer/advancement-metrics.js.map +1 -0
  498. package/out/zero-cache/src/services/view-syncer/batch-pacer.d.ts +79 -0
  499. package/out/zero-cache/src/services/view-syncer/batch-pacer.d.ts.map +1 -0
  500. package/out/zero-cache/src/services/view-syncer/batch-pacer.js +249 -0
  501. package/out/zero-cache/src/services/view-syncer/batch-pacer.js.map +1 -0
  502. package/out/zero-cache/src/services/view-syncer/client-handler.d.ts +19 -2
  503. package/out/zero-cache/src/services/view-syncer/client-handler.d.ts.map +1 -1
  504. package/out/zero-cache/src/services/view-syncer/client-handler.js +42 -30
  505. package/out/zero-cache/src/services/view-syncer/client-handler.js.map +1 -1
  506. package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts +27 -2
  507. package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts.map +1 -1
  508. package/out/zero-cache/src/services/view-syncer/cvr-store.js +86 -21
  509. package/out/zero-cache/src/services/view-syncer/cvr-store.js.map +1 -1
  510. package/out/zero-cache/src/services/view-syncer/cvr.d.ts +75 -12
  511. package/out/zero-cache/src/services/view-syncer/cvr.d.ts.map +1 -1
  512. package/out/zero-cache/src/services/view-syncer/cvr.js +234 -43
  513. package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
  514. package/out/zero-cache/src/services/view-syncer/deferred-writes-budget.d.ts +81 -0
  515. package/out/zero-cache/src/services/view-syncer/deferred-writes-budget.d.ts.map +1 -0
  516. package/out/zero-cache/src/services/view-syncer/deferred-writes-budget.js +128 -0
  517. package/out/zero-cache/src/services/view-syncer/deferred-writes-budget.js.map +1 -0
  518. package/out/zero-cache/src/services/view-syncer/drain-coordinator.d.ts +14 -1
  519. package/out/zero-cache/src/services/view-syncer/drain-coordinator.d.ts.map +1 -1
  520. package/out/zero-cache/src/services/view-syncer/drain-coordinator.js +30 -4
  521. package/out/zero-cache/src/services/view-syncer/drain-coordinator.js.map +1 -1
  522. package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.d.ts +51 -0
  523. package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.d.ts.map +1 -0
  524. package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.js +78 -0
  525. package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.js.map +1 -0
  526. package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts +12 -2
  527. package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts.map +1 -1
  528. package/out/zero-cache/src/services/view-syncer/inspect-handler.js +29 -5
  529. package/out/zero-cache/src/services/view-syncer/inspect-handler.js.map +1 -1
  530. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts +165 -9
  531. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
  532. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +953 -209
  533. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
  534. package/out/zero-cache/src/services/view-syncer/plan-warnings.d.ts +7 -0
  535. package/out/zero-cache/src/services/view-syncer/plan-warnings.d.ts.map +1 -0
  536. package/out/zero-cache/src/services/view-syncer/plan-warnings.js +35 -0
  537. package/out/zero-cache/src/services/view-syncer/plan-warnings.js.map +1 -0
  538. package/out/zero-cache/src/services/view-syncer/push-cost.d.ts +132 -0
  539. package/out/zero-cache/src/services/view-syncer/push-cost.d.ts.map +1 -0
  540. package/out/zero-cache/src/services/view-syncer/push-cost.js +164 -0
  541. package/out/zero-cache/src/services/view-syncer/push-cost.js.map +1 -0
  542. package/out/zero-cache/src/services/view-syncer/push-cutoff.d.ts +55 -0
  543. package/out/zero-cache/src/services/view-syncer/push-cutoff.d.ts.map +1 -0
  544. package/out/zero-cache/src/services/view-syncer/push-cutoff.js +56 -0
  545. package/out/zero-cache/src/services/view-syncer/push-cutoff.js.map +1 -0
  546. package/out/zero-cache/src/services/view-syncer/query-covering.d.ts.map +1 -1
  547. package/out/zero-cache/src/services/view-syncer/query-covering.js +2 -6
  548. package/out/zero-cache/src/services/view-syncer/query-covering.js.map +1 -1
  549. package/out/zero-cache/src/services/view-syncer/query-shape.d.ts +25 -0
  550. package/out/zero-cache/src/services/view-syncer/query-shape.d.ts.map +1 -0
  551. package/out/zero-cache/src/services/view-syncer/query-shape.js +28 -0
  552. package/out/zero-cache/src/services/view-syncer/query-shape.js.map +1 -0
  553. package/out/zero-cache/src/services/view-syncer/query-stats.d.ts +89 -0
  554. package/out/zero-cache/src/services/view-syncer/query-stats.d.ts.map +1 -0
  555. package/out/zero-cache/src/services/view-syncer/query-stats.js +233 -0
  556. package/out/zero-cache/src/services/view-syncer/query-stats.js.map +1 -0
  557. package/out/zero-cache/src/services/view-syncer/schema/types.d.ts +2 -107
  558. package/out/zero-cache/src/services/view-syncer/schema/types.d.ts.map +1 -1
  559. package/out/zero-cache/src/services/view-syncer/schema/types.js +5 -20
  560. package/out/zero-cache/src/services/view-syncer/schema/types.js.map +1 -1
  561. package/out/zero-cache/src/services/view-syncer/snapshot-row-cache.d.ts +95 -0
  562. package/out/zero-cache/src/services/view-syncer/snapshot-row-cache.d.ts.map +1 -0
  563. package/out/zero-cache/src/services/view-syncer/snapshot-row-cache.js +155 -0
  564. package/out/zero-cache/src/services/view-syncer/snapshot-row-cache.js.map +1 -0
  565. package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts +229 -16
  566. package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts.map +1 -1
  567. package/out/zero-cache/src/services/view-syncer/snapshotter.js +455 -43
  568. package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
  569. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts +8 -2
  570. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
  571. package/out/zero-cache/src/services/view-syncer/view-syncer.js +788 -71
  572. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  573. package/out/zero-cache/src/types/pg-data-type.d.ts +2 -0
  574. package/out/zero-cache/src/types/pg-data-type.d.ts.map +1 -1
  575. package/out/zero-cache/src/types/pg-data-type.js +6 -1
  576. package/out/zero-cache/src/types/pg-data-type.js.map +1 -1
  577. package/out/zero-cache/src/types/pg.d.ts.map +1 -1
  578. package/out/zero-cache/src/types/pg.js +2 -2
  579. package/out/zero-cache/src/types/pg.js.map +1 -1
  580. package/out/zero-cache/src/types/processes.d.ts +50 -0
  581. package/out/zero-cache/src/types/processes.d.ts.map +1 -1
  582. package/out/zero-cache/src/types/processes.js +43 -4
  583. package/out/zero-cache/src/types/processes.js.map +1 -1
  584. package/out/zero-cache/src/types/profiler.d.ts +12 -0
  585. package/out/zero-cache/src/types/profiler.d.ts.map +1 -1
  586. package/out/zero-cache/src/types/profiler.js +46 -1
  587. package/out/zero-cache/src/types/profiler.js.map +1 -1
  588. package/out/zero-cache/src/types/row-key.d.ts +1 -15
  589. package/out/zero-cache/src/types/row-key.d.ts.map +1 -1
  590. package/out/zero-cache/src/types/row-key.js +6 -8
  591. package/out/zero-cache/src/types/row-key.js.map +1 -1
  592. package/out/zero-cache/src/types/streams.d.ts +49 -7
  593. package/out/zero-cache/src/types/streams.d.ts.map +1 -1
  594. package/out/zero-cache/src/types/streams.js +190 -58
  595. package/out/zero-cache/src/types/streams.js.map +1 -1
  596. package/out/zero-cache/src/types/subscription.d.ts +15 -0
  597. package/out/zero-cache/src/types/subscription.d.ts.map +1 -1
  598. package/out/zero-cache/src/types/subscription.js +123 -31
  599. package/out/zero-cache/src/types/subscription.js.map +1 -1
  600. package/out/zero-cache/src/types/websocket-handoff.d.ts +1 -1
  601. package/out/zero-cache/src/types/websocket-handoff.d.ts.map +1 -1
  602. package/out/zero-cache/src/types/websocket-handoff.js +18 -9
  603. package/out/zero-cache/src/types/websocket-handoff.js.map +1 -1
  604. package/out/zero-cache/src/types/ws.d.ts.map +1 -1
  605. package/out/zero-cache/src/types/ws.js +1 -16
  606. package/out/zero-cache/src/types/ws.js.map +1 -1
  607. package/out/zero-cache/src/workers/connect-params.d.ts +1 -0
  608. package/out/zero-cache/src/workers/connect-params.d.ts.map +1 -1
  609. package/out/zero-cache/src/workers/connect-params.js.map +1 -1
  610. package/out/zero-cache/src/workers/connection.d.ts +2 -1
  611. package/out/zero-cache/src/workers/connection.d.ts.map +1 -1
  612. package/out/zero-cache/src/workers/connection.js +9 -1
  613. package/out/zero-cache/src/workers/connection.js.map +1 -1
  614. package/out/zero-cache/src/workers/replicator.d.ts.map +1 -1
  615. package/out/zero-cache/src/workers/replicator.js +24 -7
  616. package/out/zero-cache/src/workers/replicator.js.map +1 -1
  617. package/out/zero-cache/src/workers/syncer-ws-message-handler.d.ts.map +1 -1
  618. package/out/zero-cache/src/workers/syncer-ws-message-handler.js +21 -16
  619. package/out/zero-cache/src/workers/syncer-ws-message-handler.js.map +1 -1
  620. package/out/zero-cache/src/workers/syncer.d.ts.map +1 -1
  621. package/out/zero-cache/src/workers/syncer.js +55 -4
  622. package/out/zero-cache/src/workers/syncer.js.map +1 -1
  623. package/out/zero-client/src/client/active-clients-manager.d.ts.map +1 -1
  624. package/out/zero-client/src/client/active-clients-manager.js +4 -1
  625. package/out/zero-client/src/client/active-clients-manager.js.map +1 -1
  626. package/out/zero-client/src/client/connection-manager.d.ts +20 -0
  627. package/out/zero-client/src/client/connection-manager.d.ts.map +1 -1
  628. package/out/zero-client/src/client/connection-manager.js +77 -13
  629. package/out/zero-client/src/client/connection-manager.js.map +1 -1
  630. package/out/zero-client/src/client/connection-status-enum.d.ts +2 -0
  631. package/out/zero-client/src/client/connection-status-enum.d.ts.map +1 -1
  632. package/out/zero-client/src/client/connection-status-enum.js +3 -1
  633. package/out/zero-client/src/client/connection-status-enum.js.map +1 -1
  634. package/out/zero-client/src/client/connection.d.ts +6 -0
  635. package/out/zero-client/src/client/connection.d.ts.map +1 -1
  636. package/out/zero-client/src/client/connection.js +2 -1
  637. package/out/zero-client/src/client/connection.js.map +1 -1
  638. package/out/zero-client/src/client/context.d.ts +23 -13
  639. package/out/zero-client/src/client/context.d.ts.map +1 -1
  640. package/out/zero-client/src/client/context.js +94 -26
  641. package/out/zero-client/src/client/context.js.map +1 -1
  642. package/out/zero-client/src/client/crud-impl.d.ts.map +1 -1
  643. package/out/zero-client/src/client/crud-impl.js +1 -1
  644. package/out/zero-client/src/client/crud-impl.js.map +1 -1
  645. package/out/zero-client/src/client/custom.d.ts +5 -4
  646. package/out/zero-client/src/client/custom.d.ts.map +1 -1
  647. package/out/zero-client/src/client/custom.js +3 -3
  648. package/out/zero-client/src/client/custom.js.map +1 -1
  649. package/out/zero-client/src/client/inspector/lazy-inspector.js +1 -1
  650. package/out/zero-client/src/client/ivm-branch.d.ts.map +1 -1
  651. package/out/zero-client/src/client/ivm-branch.js +20 -3
  652. package/out/zero-client/src/client/ivm-branch.js.map +1 -1
  653. package/out/zero-client/src/client/keys.d.ts.map +1 -1
  654. package/out/zero-client/src/client/keys.js +19 -1
  655. package/out/zero-client/src/client/keys.js.map +1 -1
  656. package/out/zero-client/src/client/make-mutate-property.d.ts +1 -1
  657. package/out/zero-client/src/client/make-mutate-property.d.ts.map +1 -1
  658. package/out/zero-client/src/client/make-mutate-property.js.map +1 -1
  659. package/out/zero-client/src/client/make-replicache-mutators.d.ts.map +1 -1
  660. package/out/zero-client/src/client/make-replicache-mutators.js +1 -1
  661. package/out/zero-client/src/client/make-replicache-mutators.js.map +1 -1
  662. package/out/zero-client/src/client/mutation-tracker.d.ts +2 -2
  663. package/out/zero-client/src/client/mutation-tracker.d.ts.map +1 -1
  664. package/out/zero-client/src/client/mutation-tracker.js +3 -7
  665. package/out/zero-client/src/client/mutation-tracker.js.map +1 -1
  666. package/out/zero-client/src/client/mutator-proxy.d.ts.map +1 -1
  667. package/out/zero-client/src/client/mutator-proxy.js +9 -4
  668. package/out/zero-client/src/client/mutator-proxy.js.map +1 -1
  669. package/out/zero-client/src/client/options.d.ts +33 -0
  670. package/out/zero-client/src/client/options.d.ts.map +1 -1
  671. package/out/zero-client/src/client/options.js.map +1 -1
  672. package/out/zero-client/src/client/query-manager.d.ts +9 -0
  673. package/out/zero-client/src/client/query-manager.d.ts.map +1 -1
  674. package/out/zero-client/src/client/query-manager.js +47 -14
  675. package/out/zero-client/src/client/query-manager.js.map +1 -1
  676. package/out/zero-client/src/client/reload-error-handler.js +2 -2
  677. package/out/zero-client/src/client/reload-error-handler.js.map +1 -1
  678. package/out/zero-client/src/client/storage-version.d.ts +23 -0
  679. package/out/zero-client/src/client/storage-version.d.ts.map +1 -0
  680. package/out/zero-client/src/client/version.js +1 -1
  681. package/out/zero-client/src/client/zero-rep.d.ts +1 -0
  682. package/out/zero-client/src/client/zero-rep.d.ts.map +1 -1
  683. package/out/zero-client/src/client/zero-rep.js +8 -6
  684. package/out/zero-client/src/client/zero-rep.js.map +1 -1
  685. package/out/zero-client/src/client/zero.d.ts +18 -3
  686. package/out/zero-client/src/client/zero.d.ts.map +1 -1
  687. package/out/zero-client/src/client/zero.js +86 -48
  688. package/out/zero-client/src/client/zero.js.map +1 -1
  689. package/out/zero-client/src/mod.d.ts +2 -1
  690. package/out/zero-client/src/mod.d.ts.map +1 -1
  691. package/out/zero-client/src/mod.js +1 -0
  692. package/out/zero-client/src/types/query-result.d.ts +2 -0
  693. package/out/zero-client/src/types/query-result.d.ts.map +1 -1
  694. package/out/zero-events/src/status.d.ts +64 -0
  695. package/out/zero-events/src/status.d.ts.map +1 -1
  696. package/out/zero-protocol/src/analyze-query-result.d.ts +12 -12
  697. package/out/zero-protocol/src/analyze-query-result.d.ts.map +1 -1
  698. package/out/zero-protocol/src/analyze-query-result.js +3 -3
  699. package/out/zero-protocol/src/analyze-query-result.js.map +1 -1
  700. package/out/zero-protocol/src/ast.d.ts +24 -0
  701. package/out/zero-protocol/src/ast.d.ts.map +1 -1
  702. package/out/zero-protocol/src/ast.js +39 -16
  703. package/out/zero-protocol/src/ast.js.map +1 -1
  704. package/out/zero-protocol/src/down.d.ts +36 -36
  705. package/out/zero-protocol/src/inspect-down.d.ts +31 -31
  706. package/out/zero-protocol/src/inspect-up.d.ts +158 -61
  707. package/out/zero-protocol/src/inspect-up.d.ts.map +1 -1
  708. package/out/zero-protocol/src/inspect-up.js +12 -6
  709. package/out/zero-protocol/src/inspect-up.js.map +1 -1
  710. package/out/zero-protocol/src/protocol-version.d.ts +4 -1
  711. package/out/zero-protocol/src/protocol-version.d.ts.map +1 -1
  712. package/out/zero-protocol/src/protocol-version.js.map +1 -1
  713. package/out/zero-protocol/src/queries-patch.js +2 -2
  714. package/out/zero-protocol/src/queries-patch.js.map +1 -1
  715. package/out/zero-protocol/src/query-hash.d.ts.map +1 -1
  716. package/out/zero-protocol/src/query-hash.js +2 -5
  717. package/out/zero-protocol/src/query-hash.js.map +1 -1
  718. package/out/zero-protocol/src/up.d.ts +766 -256
  719. package/out/zero-protocol/src/up.d.ts.map +1 -1
  720. package/out/zero-protocol/src/up.js +25 -3
  721. package/out/zero-protocol/src/up.js.map +1 -1
  722. package/out/zero-react/src/use-query.d.ts +5 -4
  723. package/out/zero-react/src/use-query.d.ts.map +1 -1
  724. package/out/zero-react/src/use-query.js +75 -8
  725. package/out/zero-react/src/use-query.js.map +1 -1
  726. package/out/zero-react/src/zero.js +1 -0
  727. package/out/zero-server/src/adapters/drizzle.d.ts +16 -4
  728. package/out/zero-server/src/adapters/drizzle.d.ts.map +1 -1
  729. package/out/zero-server/src/adapters/drizzle.js +19 -11
  730. package/out/zero-server/src/adapters/drizzle.js.map +1 -1
  731. package/out/zero-server/src/adapters/kysely.d.ts +6 -3
  732. package/out/zero-server/src/adapters/kysely.d.ts.map +1 -1
  733. package/out/zero-server/src/adapters/kysely.js +16 -6
  734. package/out/zero-server/src/adapters/kysely.js.map +1 -1
  735. package/out/zero-server/src/adapters/pg.d.ts +7 -2
  736. package/out/zero-server/src/adapters/pg.d.ts.map +1 -1
  737. package/out/zero-server/src/adapters/pg.js +34 -10
  738. package/out/zero-server/src/adapters/pg.js.map +1 -1
  739. package/out/zero-server/src/adapters/postgresjs.d.ts +4 -2
  740. package/out/zero-server/src/adapters/postgresjs.d.ts.map +1 -1
  741. package/out/zero-server/src/adapters/postgresjs.js +15 -5
  742. package/out/zero-server/src/adapters/postgresjs.js.map +1 -1
  743. package/out/zero-server/src/adapters/prisma.d.ts +17 -5
  744. package/out/zero-server/src/adapters/prisma.d.ts.map +1 -1
  745. package/out/zero-server/src/adapters/prisma.js +20 -6
  746. package/out/zero-server/src/adapters/prisma.js.map +1 -1
  747. package/out/zero-server/src/closable-db-transaction.d.ts +16 -0
  748. package/out/zero-server/src/closable-db-transaction.d.ts.map +1 -0
  749. package/out/zero-server/src/closable-db-transaction.js +31 -0
  750. package/out/zero-server/src/closable-db-transaction.js.map +1 -0
  751. package/out/zero-server/src/custom.d.ts +10 -4
  752. package/out/zero-server/src/custom.d.ts.map +1 -1
  753. package/out/zero-server/src/custom.js +15 -6
  754. package/out/zero-server/src/custom.js.map +1 -1
  755. package/out/zero-server/src/logging.d.ts +2 -2
  756. package/out/zero-server/src/logging.d.ts.map +1 -1
  757. package/out/zero-server/src/logging.js +2 -2
  758. package/out/zero-server/src/logging.js.map +1 -1
  759. package/out/zero-server/src/mod.d.ts +2 -1
  760. package/out/zero-server/src/mod.d.ts.map +1 -1
  761. package/out/zero-server/src/pg-query-executor.d.ts +2 -2
  762. package/out/zero-server/src/pg-query-executor.d.ts.map +1 -1
  763. package/out/zero-server/src/pg-query-executor.js +2 -2
  764. package/out/zero-server/src/pg-query-executor.js.map +1 -1
  765. package/out/zero-server/src/process-mutations.d.ts +25 -4
  766. package/out/zero-server/src/process-mutations.d.ts.map +1 -1
  767. package/out/zero-server/src/process-mutations.js +103 -52
  768. package/out/zero-server/src/process-mutations.js.map +1 -1
  769. package/out/zero-server/src/push-processor.d.ts +8 -2
  770. package/out/zero-server/src/push-processor.d.ts.map +1 -1
  771. package/out/zero-server/src/push-processor.js +12 -4
  772. package/out/zero-server/src/push-processor.js.map +1 -1
  773. package/out/zero-server/src/queries/process-queries.d.ts.map +1 -1
  774. package/out/zero-server/src/queries/process-queries.js +1 -1
  775. package/out/zero-server/src/queries/process-queries.js.map +1 -1
  776. package/out/zero-server/src/schema.d.ts +2 -2
  777. package/out/zero-server/src/schema.d.ts.map +1 -1
  778. package/out/zero-server/src/schema.js +3 -2
  779. package/out/zero-server/src/schema.js.map +1 -1
  780. package/out/zero-server/src/transaction-options.d.ts +24 -0
  781. package/out/zero-server/src/transaction-options.d.ts.map +1 -0
  782. package/out/zero-server/src/transaction-options.js +11 -0
  783. package/out/zero-server/src/transaction-options.js.map +1 -0
  784. package/out/zero-server/src/zql-database.d.ts +21 -1
  785. package/out/zero-server/src/zql-database.d.ts.map +1 -1
  786. package/out/zero-server/src/zql-database.js +61 -24
  787. package/out/zero-server/src/zql-database.js.map +1 -1
  788. package/out/zero-solid/src/solid-view.d.ts +17 -0
  789. package/out/zero-solid/src/solid-view.d.ts.map +1 -1
  790. package/out/zero-solid/src/solid-view.js +39 -1
  791. package/out/zero-solid/src/solid-view.js.map +1 -1
  792. package/out/zero-solid/src/use-query.js +1 -2
  793. package/out/zero-solid/src/use-query.js.map +1 -1
  794. package/out/zero-solid/src/zero.js +1 -0
  795. package/out/zql/src/builder/builder.d.ts +25 -0
  796. package/out/zql/src/builder/builder.d.ts.map +1 -1
  797. package/out/zql/src/builder/builder.js +69 -19
  798. package/out/zql/src/builder/builder.js.map +1 -1
  799. package/out/zql/src/builder/correlated-predicate-pushdown.d.ts +43 -0
  800. package/out/zql/src/builder/correlated-predicate-pushdown.d.ts.map +1 -0
  801. package/out/zql/src/builder/correlated-predicate-pushdown.js +161 -0
  802. package/out/zql/src/builder/correlated-predicate-pushdown.js.map +1 -0
  803. package/out/zql/src/builder/debug-delegate.d.ts +6 -1
  804. package/out/zql/src/builder/debug-delegate.d.ts.map +1 -1
  805. package/out/zql/src/builder/debug-delegate.js +14 -2
  806. package/out/zql/src/builder/debug-delegate.js.map +1 -1
  807. package/out/zql/src/ivm/array-view.d.ts +29 -0
  808. package/out/zql/src/ivm/array-view.d.ts.map +1 -1
  809. package/out/zql/src/ivm/array-view.js +74 -16
  810. package/out/zql/src/ivm/array-view.js.map +1 -1
  811. package/out/zql/src/ivm/cap.d.ts +2 -1
  812. package/out/zql/src/ivm/cap.d.ts.map +1 -1
  813. package/out/zql/src/ivm/cap.js +14 -4
  814. package/out/zql/src/ivm/cap.js.map +1 -1
  815. package/out/zql/src/ivm/data.d.ts.map +1 -1
  816. package/out/zql/src/ivm/data.js +8 -3
  817. package/out/zql/src/ivm/data.js.map +1 -1
  818. package/out/zql/src/ivm/deferred-input.d.ts.map +1 -1
  819. package/out/zql/src/ivm/deferred-input.js +3 -2
  820. package/out/zql/src/ivm/deferred-input.js.map +1 -1
  821. package/out/zql/src/ivm/exists.d.ts +3 -1
  822. package/out/zql/src/ivm/exists.d.ts.map +1 -1
  823. package/out/zql/src/ivm/exists.js +4 -1
  824. package/out/zql/src/ivm/exists.js.map +1 -1
  825. package/out/zql/src/ivm/fan-in.d.ts +6 -2
  826. package/out/zql/src/ivm/fan-in.d.ts.map +1 -1
  827. package/out/zql/src/ivm/fan-in.js +13 -5
  828. package/out/zql/src/ivm/fan-in.js.map +1 -1
  829. package/out/zql/src/ivm/fan-out.d.ts +5 -2
  830. package/out/zql/src/ivm/fan-out.d.ts.map +1 -1
  831. package/out/zql/src/ivm/fan-out.js +4 -0
  832. package/out/zql/src/ivm/fan-out.js.map +1 -1
  833. package/out/zql/src/ivm/filter-operators.d.ts +8 -6
  834. package/out/zql/src/ivm/filter-operators.d.ts.map +1 -1
  835. package/out/zql/src/ivm/filter-operators.js +19 -8
  836. package/out/zql/src/ivm/filter-operators.js.map +1 -1
  837. package/out/zql/src/ivm/filter.d.ts +5 -2
  838. package/out/zql/src/ivm/filter.d.ts.map +1 -1
  839. package/out/zql/src/ivm/filter.js +10 -4
  840. package/out/zql/src/ivm/filter.js.map +1 -1
  841. package/out/zql/src/ivm/flipped-join.d.ts +9 -4
  842. package/out/zql/src/ivm/flipped-join.d.ts.map +1 -1
  843. package/out/zql/src/ivm/flipped-join.js +97 -46
  844. package/out/zql/src/ivm/flipped-join.js.map +1 -1
  845. package/out/zql/src/ivm/join-index-tap.d.ts +33 -0
  846. package/out/zql/src/ivm/join-index-tap.d.ts.map +1 -0
  847. package/out/zql/src/ivm/join-index-tap.js +70 -0
  848. package/out/zql/src/ivm/join-index-tap.js.map +1 -0
  849. package/out/zql/src/ivm/join-index.d.ts +35 -0
  850. package/out/zql/src/ivm/join-index.d.ts.map +1 -0
  851. package/out/zql/src/ivm/join-index.js +141 -0
  852. package/out/zql/src/ivm/join-index.js.map +1 -0
  853. package/out/zql/src/ivm/join-utils.d.ts +6 -0
  854. package/out/zql/src/ivm/join-utils.d.ts.map +1 -1
  855. package/out/zql/src/ivm/join-utils.js +22 -1
  856. package/out/zql/src/ivm/join-utils.js.map +1 -1
  857. package/out/zql/src/ivm/join.d.ts +19 -1
  858. package/out/zql/src/ivm/join.d.ts.map +1 -1
  859. package/out/zql/src/ivm/join.js +107 -15
  860. package/out/zql/src/ivm/join.js.map +1 -1
  861. package/out/zql/src/ivm/maybe-split-and-push-edit-change.d.ts +1 -1
  862. package/out/zql/src/ivm/maybe-split-and-push-edit-change.d.ts.map +1 -1
  863. package/out/zql/src/ivm/maybe-split-and-push-edit-change.js +6 -4
  864. package/out/zql/src/ivm/maybe-split-and-push-edit-change.js.map +1 -1
  865. package/out/zql/src/ivm/memory-source.d.ts +29 -4
  866. package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
  867. package/out/zql/src/ivm/memory-source.js +70 -34
  868. package/out/zql/src/ivm/memory-source.js.map +1 -1
  869. package/out/zql/src/ivm/memory-storage.d.ts +1 -0
  870. package/out/zql/src/ivm/memory-storage.d.ts.map +1 -1
  871. package/out/zql/src/ivm/memory-storage.js +1 -0
  872. package/out/zql/src/ivm/memory-storage.js.map +1 -1
  873. package/out/zql/src/ivm/operator.d.ts +45 -10
  874. package/out/zql/src/ivm/operator.d.ts.map +1 -1
  875. package/out/zql/src/ivm/operator.js +9 -4
  876. package/out/zql/src/ivm/operator.js.map +1 -1
  877. package/out/zql/src/ivm/push-accumulated.d.ts +6 -1
  878. package/out/zql/src/ivm/push-accumulated.d.ts.map +1 -1
  879. package/out/zql/src/ivm/push-accumulated.js +47 -2
  880. package/out/zql/src/ivm/push-accumulated.js.map +1 -1
  881. package/out/zql/src/ivm/skip.d.ts +2 -1
  882. package/out/zql/src/ivm/skip.d.ts.map +1 -1
  883. package/out/zql/src/ivm/skip.js +3 -0
  884. package/out/zql/src/ivm/skip.js.map +1 -1
  885. package/out/zql/src/ivm/take-gate.d.ts +57 -0
  886. package/out/zql/src/ivm/take-gate.d.ts.map +1 -0
  887. package/out/zql/src/ivm/take-gate.js +106 -0
  888. package/out/zql/src/ivm/take-gate.js.map +1 -0
  889. package/out/zql/src/ivm/take.d.ts +8 -2
  890. package/out/zql/src/ivm/take.d.ts.map +1 -1
  891. package/out/zql/src/ivm/take.js +139 -103
  892. package/out/zql/src/ivm/take.js.map +1 -1
  893. package/out/zql/src/ivm/union-fan-in.d.ts +3 -0
  894. package/out/zql/src/ivm/union-fan-in.d.ts.map +1 -1
  895. package/out/zql/src/ivm/union-fan-in.js +63 -10
  896. package/out/zql/src/ivm/union-fan-in.js.map +1 -1
  897. package/out/zql/src/ivm/union-fan-out.d.ts +2 -1
  898. package/out/zql/src/ivm/union-fan-out.d.ts.map +1 -1
  899. package/out/zql/src/ivm/union-fan-out.js +5 -0
  900. package/out/zql/src/ivm/union-fan-out.js.map +1 -1
  901. package/out/zql/src/ivm/view-apply-change.d.ts.map +1 -1
  902. package/out/zql/src/ivm/view-apply-change.js +9 -4
  903. package/out/zql/src/ivm/view-apply-change.js.map +1 -1
  904. package/out/zql/src/ivm/view.d.ts +15 -0
  905. package/out/zql/src/ivm/view.d.ts.map +1 -1
  906. package/out/zql/src/mutate/custom.d.ts +53 -1
  907. package/out/zql/src/mutate/custom.d.ts.map +1 -1
  908. package/out/zql/src/mutate/custom.js.map +1 -1
  909. package/out/zql/src/mutate/mutator-registry.d.ts.map +1 -1
  910. package/out/zql/src/mutate/mutator-registry.js +3 -3
  911. package/out/zql/src/mutate/mutator-registry.js.map +1 -1
  912. package/out/zql/src/mutate/mutator.d.ts +2 -2
  913. package/out/zql/src/mutate/mutator.d.ts.map +1 -1
  914. package/out/zql/src/mutate/mutator.js.map +1 -1
  915. package/out/zql/src/planner/planner-builder.d.ts +23 -3
  916. package/out/zql/src/planner/planner-builder.d.ts.map +1 -1
  917. package/out/zql/src/planner/planner-builder.js +34 -17
  918. package/out/zql/src/planner/planner-builder.js.map +1 -1
  919. package/out/zql/src/planner/planner-connection.d.ts +58 -2
  920. package/out/zql/src/planner/planner-connection.d.ts.map +1 -1
  921. package/out/zql/src/planner/planner-connection.js +103 -11
  922. package/out/zql/src/planner/planner-connection.js.map +1 -1
  923. package/out/zql/src/planner/planner-debug.d.ts.map +1 -1
  924. package/out/zql/src/planner/planner-debug.js +3 -8
  925. package/out/zql/src/planner/planner-debug.js.map +1 -1
  926. package/out/zql/src/planner/planner-graph.d.ts +10 -0
  927. package/out/zql/src/planner/planner-graph.d.ts.map +1 -1
  928. package/out/zql/src/planner/planner-graph.js +14 -0
  929. package/out/zql/src/planner/planner-graph.js.map +1 -1
  930. package/out/zql/src/planner/planner-source.d.ts +2 -2
  931. package/out/zql/src/planner/planner-source.d.ts.map +1 -1
  932. package/out/zql/src/planner/planner-source.js +2 -2
  933. package/out/zql/src/planner/planner-source.js.map +1 -1
  934. package/out/zql/src/planner/planner-warnings.d.ts +83 -0
  935. package/out/zql/src/planner/planner-warnings.d.ts.map +1 -0
  936. package/out/zql/src/planner/planner-warnings.js +78 -0
  937. package/out/zql/src/planner/planner-warnings.js.map +1 -0
  938. package/out/zql/src/query/expression.d.ts +2 -2
  939. package/out/zql/src/query/expression.d.ts.map +1 -1
  940. package/out/zql/src/query/expression.js.map +1 -1
  941. package/out/zql/src/query/measure-push-operator.d.ts +9 -2
  942. package/out/zql/src/query/measure-push-operator.d.ts.map +1 -1
  943. package/out/zql/src/query/measure-push-operator.js +52 -5
  944. package/out/zql/src/query/measure-push-operator.js.map +1 -1
  945. package/out/zql/src/query/query-delegate-base.d.ts +4 -2
  946. package/out/zql/src/query/query-delegate-base.d.ts.map +1 -1
  947. package/out/zql/src/query/query-delegate-base.js +66 -33
  948. package/out/zql/src/query/query-delegate-base.js.map +1 -1
  949. package/out/zql/src/query/query-delegate.d.ts +33 -6
  950. package/out/zql/src/query/query-delegate.d.ts.map +1 -1
  951. package/out/zql/src/query/query-impl.d.ts +1 -0
  952. package/out/zql/src/query/query-impl.d.ts.map +1 -1
  953. package/out/zql/src/query/query-impl.js +6 -23
  954. package/out/zql/src/query/query-impl.js.map +1 -1
  955. package/out/zql/src/query/query-registry.js +1 -1
  956. package/out/zql/src/query/query-transitions.d.ts.map +1 -1
  957. package/out/zql/src/query/query-transitions.js +2 -5
  958. package/out/zql/src/query/query-transitions.js.map +1 -1
  959. package/out/zql/src/query/query.d.ts +26 -10
  960. package/out/zql/src/query/query.d.ts.map +1 -1
  961. package/out/zql/src/query/runnable-query-impl.d.ts +1 -0
  962. package/out/zql/src/query/runnable-query-impl.d.ts.map +1 -1
  963. package/out/zql/src/query/runnable-query-impl.js +2 -10
  964. package/out/zql/src/query/runnable-query-impl.js.map +1 -1
  965. package/out/zql/src/query/typed-view.d.ts +1 -1
  966. package/out/zql/src/query/typed-view.d.ts.map +1 -1
  967. package/out/zqlite/src/database-storage.d.ts.map +1 -1
  968. package/out/zqlite/src/database-storage.js +9 -1
  969. package/out/zqlite/src/database-storage.js.map +1 -1
  970. package/out/zqlite/src/db.d.ts +17 -1
  971. package/out/zqlite/src/db.d.ts.map +1 -1
  972. package/out/zqlite/src/db.js +73 -30
  973. package/out/zqlite/src/db.js.map +1 -1
  974. package/out/zqlite/src/index-usage.d.ts +19 -0
  975. package/out/zqlite/src/index-usage.d.ts.map +1 -0
  976. package/out/zqlite/src/index-usage.js +49 -0
  977. package/out/zqlite/src/index-usage.js.map +1 -0
  978. package/out/zqlite/src/pending-delta.d.ts +110 -0
  979. package/out/zqlite/src/pending-delta.d.ts.map +1 -0
  980. package/out/zqlite/src/pending-delta.js +278 -0
  981. package/out/zqlite/src/pending-delta.js.map +1 -0
  982. package/out/zqlite/src/query-builder.d.ts +17 -1
  983. package/out/zqlite/src/query-builder.d.ts.map +1 -1
  984. package/out/zqlite/src/query-builder.js +111 -20
  985. package/out/zqlite/src/query-builder.js.map +1 -1
  986. package/out/zqlite/src/query-delegate.d.ts.map +1 -1
  987. package/out/zqlite/src/query-delegate.js +10 -7
  988. package/out/zqlite/src/query-delegate.js.map +1 -1
  989. package/out/zqlite/src/resolve-scalar-subqueries.d.ts +3 -1
  990. package/out/zqlite/src/resolve-scalar-subqueries.d.ts.map +1 -1
  991. package/out/zqlite/src/resolve-scalar-subqueries.js +1 -0
  992. package/out/zqlite/src/resolve-scalar-subqueries.js.map +1 -1
  993. package/out/zqlite/src/sqlite-cost-model.d.ts.map +1 -1
  994. package/out/zqlite/src/sqlite-cost-model.js +53 -1
  995. package/out/zqlite/src/sqlite-cost-model.js.map +1 -1
  996. package/out/zqlite/src/sqlite-stat-fanout.d.ts.map +1 -1
  997. package/out/zqlite/src/sqlite-stat-fanout.js +5 -31
  998. package/out/zqlite/src/sqlite-stat-fanout.js.map +1 -1
  999. package/out/zqlite/src/sqlite-stat4-sample.d.ts +37 -0
  1000. package/out/zqlite/src/sqlite-stat4-sample.d.ts.map +1 -0
  1001. package/out/zqlite/src/sqlite-stat4-sample.js +61 -0
  1002. package/out/zqlite/src/sqlite-stat4-sample.js.map +1 -0
  1003. package/out/zqlite/src/table-source.d.ts +87 -2
  1004. package/out/zqlite/src/table-source.d.ts.map +1 -1
  1005. package/out/zqlite/src/table-source.js +276 -42
  1006. package/out/zqlite/src/table-source.js.map +1 -1
  1007. package/package.json +5 -6
  1008. package/out/replicache/src/kv/idb-store-with-mem-fallback.d.ts +0 -25
  1009. package/out/replicache/src/kv/idb-store-with-mem-fallback.d.ts.map +0 -1
  1010. package/out/replicache/src/kv/idb-store-with-mem-fallback.js +0 -83
  1011. package/out/replicache/src/kv/idb-store-with-mem-fallback.js.map +0 -1
  1012. package/out/zero-cache/src/services/change-streamer/vfs-watermark-poller.d.ts +0 -29
  1013. package/out/zero-cache/src/services/change-streamer/vfs-watermark-poller.d.ts.map +0 -1
  1014. package/out/zero-cache/src/services/change-streamer/vfs-watermark-poller.js +0 -154
  1015. package/out/zero-cache/src/services/change-streamer/vfs-watermark-poller.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"snapshot-reservations.js","names":["#lc","#backupConfig","#onClose","#reservations","#close","#metricAttrs","#downstream","#watermark","#delayNoted"],"sources":["../../../../../../zero-cache/src/services/change-streamer/snapshot-reservations.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport type {Source} from '../../types/streams.ts';\nimport {Subscription} from '../../types/subscription.ts';\nimport {\n litestreamMonitorMetricAttrs,\n litestreamSnapshotReservationConfirmDuration,\n litestreamSnapshotReservationDuration,\n} from '../litestream/metrics.ts';\nimport type {BackupConfig} from './change-streamer-service.ts';\nimport type {SnapshotMessage} from './snapshot.ts';\nimport type {ChangeLogReadSource} from './sqlite-change-log-read-router.ts';\n\nexport class SnapshotReservations {\n readonly #lc: LogContext;\n readonly #backupConfig: BackupConfig;\n readonly #onClose: ((taskID: string) => void) | undefined;\n readonly #reservations = new Map<string, Reservation>();\n\n constructor(\n lc: LogContext,\n backupConfig: BackupConfig,\n onClose?: ((taskID: string) => void) | undefined,\n ) {\n this.#lc = lc.withContext('component', 'snapshot-reserver');\n this.#backupConfig = backupConfig;\n this.#onClose = onClose;\n }\n\n open(taskID: string): Source<SnapshotMessage> {\n this.close(taskID);\n\n const instanceID = {};\n const downstream = Subscription.create<SnapshotMessage>({\n cleanup: () => this.#close(taskID, instanceID),\n });\n this.#reservations.set(taskID, new Reservation(instanceID, downstream));\n this.#lc.info?.(`created snasphot reservation for ${taskID}`);\n return downstream;\n }\n\n close(taskID: string) {\n this.#close(taskID, undefined);\n }\n\n isCurrent(taskID: string, source: Source<SnapshotMessage>): boolean {\n return this.#reservations.get(taskID)?.owns(source) ?? false;\n }\n\n #metricAttrs() {\n return litestreamMonitorMetricAttrs(\n this.#backupConfig.backupURL,\n this.#backupConfig.litestreamVersion,\n 'view_syncer',\n );\n }\n\n #close(taskID: string, cancelledInstanceID: InstanceID | undefined) {\n const res = this.#reservations.get(taskID);\n if (\n res &&\n (!cancelledInstanceID || res.instanceID === cancelledInstanceID)\n ) {\n // Note: delete first, so that the reservation is gone when close() is called.\n this.#reservations.delete(taskID);\n this.#onClose?.(taskID);\n res.close();\n\n const duration = Date.now() - res.startTime.getTime();\n this.#lc.info?.(\n `ended snapshot reservation for ${taskID} (${duration} ms)`,\n );\n // `result` reports how the reservation ended and `confirmed` whether it\n // ever received its bounds. They are separate dimensions: a follower\n // that gives up while waiting for a confirmation is\n // `result=cancelled, confirmed=false`, which a single collapsed\n // attribute cannot distinguish from a client that simply went away.\n litestreamSnapshotReservationDuration().recordMs(duration, {\n ...this.#metricAttrs(),\n result: cancelledInstanceID ? 'cancelled' : 'closed',\n confirmed: res.confirmed(),\n });\n }\n }\n\n confirmationsRequired() {\n for (const res of this.#reservations.values()) {\n if (!res.confirmed()) {\n return true;\n }\n }\n return false;\n }\n\n unconfirmedTaskIDs(): string[] {\n return [...this.#reservations.entries()]\n .filter(([, reservation]) => !reservation.confirmed())\n .map(([taskID]) => taskID);\n }\n\n /** Confirms one reservation with the bounds of its pinned read source. */\n confirmFor(\n taskID: string,\n replicaVersion: string,\n minWatermark: string,\n source: ChangeLogReadSource,\n ): void {\n const res = this.#reservations.get(taskID);\n if (res && !res.confirmed()) {\n this.#lc.info?.(\n `reserving change-log entries since ${minWatermark} for ${taskID}`,\n );\n res.confirm(this.#backupConfig.backupURL, replicaVersion, minWatermark);\n // Measured from `open()`, not from the first confirmation attempt: what\n // matters is how long the follower waited before it could restore.\n litestreamSnapshotReservationConfirmDuration().recordMs(\n Date.now() - res.startTime.getTime(),\n {...this.#metricAttrs(), source},\n );\n }\n }\n\n /**\n * Notes that a confirmation was deferred, returning true only the first time\n * for this reservation. Confirmation is retried on every backup, so an\n * undeduplicated count would measure backups rather than delayed followers.\n */\n noteConfirmationDelayed(taskID: string): boolean {\n return this.#reservations.get(taskID)?.noteDelayed() ?? false;\n }\n\n getReservedWatermarks() {\n return Array.from(\n this.#reservations.values(),\n ({reservedWatermark}) => reservedWatermark,\n ).filter(watermark => watermark !== null);\n }\n}\n\ntype InstanceID = {};\n\nclass Reservation {\n readonly instanceID: InstanceID;\n readonly startTime: Date = new Date();\n readonly #downstream: Subscription<SnapshotMessage>;\n #watermark: string | null = null;\n #delayNoted = false;\n\n constructor(\n instanceID: InstanceID,\n downstream: Subscription<SnapshotMessage>,\n ) {\n this.instanceID = instanceID;\n this.#downstream = downstream;\n }\n\n get reservedWatermark() {\n return this.#watermark;\n }\n\n confirmed() {\n return this.#watermark !== null;\n }\n\n owns(source: Source<SnapshotMessage>): boolean {\n return this.#downstream === source;\n }\n\n noteDelayed(): boolean {\n if (this.#delayNoted) {\n return false;\n }\n this.#delayNoted = true;\n return true;\n }\n\n confirm(backupURL: string, replicaVersion: string, minWatermark: string) {\n if (this.#watermark === null) {\n if (this.#downstream.active) {\n this.#downstream.push([\n 'status',\n {tag: 'status', backupURL, replicaVersion, minWatermark},\n ]);\n }\n this.#watermark = minWatermark;\n }\n }\n\n close() {\n this.#downstream.cancel();\n }\n}\n"],"mappings":";;;AAYA,IAAa,uBAAb,MAAkC;CAChC;CACA;CACA;CACA,gCAAyB,IAAI,IAAyB;CAEtD,YACE,IACA,cACA,SACA;EACA,KAAKA,MAAM,GAAG,YAAY,aAAa,mBAAmB;EAC1D,KAAKC,gBAAgB;EACrB,KAAKC,WAAW;CAClB;CAEA,KAAK,QAAyC;EAC5C,KAAK,MAAM,MAAM;EAEjB,MAAM,aAAa,CAAC;EACpB,MAAM,aAAa,aAAa,OAAwB,EACtD,eAAe,KAAKE,OAAO,QAAQ,UAAU,EAC/C,CAAC;EACD,KAAKD,cAAc,IAAI,QAAQ,IAAI,YAAY,YAAY,UAAU,CAAC;EACtE,KAAKH,IAAI,OAAO,oCAAoC,QAAQ;EAC5D,OAAO;CACT;CAEA,MAAM,QAAgB;EACpB,KAAKI,OAAO,QAAQ,KAAA,CAAS;CAC/B;CAEA,UAAU,QAAgB,QAA0C;EAClE,OAAO,KAAKD,cAAc,IAAI,MAAM,GAAG,KAAK,MAAM,KAAK;CACzD;CAEA,eAAe;EACb,OAAO,6BACL,KAAKF,cAAc,WACnB,KAAKA,cAAc,mBACnB,aACF;CACF;CAEA,OAAO,QAAgB,qBAA6C;EAClE,MAAM,MAAM,KAAKE,cAAc,IAAI,MAAM;EACzC,IACE,QACC,CAAC,uBAAuB,IAAI,eAAe,sBAC5C;GAEA,KAAKA,cAAc,OAAO,MAAM;GAChC,KAAKD,WAAW,MAAM;GACtB,IAAI,MAAM;GAEV,MAAM,WAAW,KAAK,IAAI,IAAI,IAAI,UAAU,QAAQ;GACpD,KAAKF,IAAI,OACP,kCAAkC,OAAO,IAAI,SAAS,KACxD;GAMA,sCAAsC,EAAE,SAAS,UAAU;IACzD,GAAG,KAAKK,aAAa;IACrB,QAAQ,sBAAsB,cAAc;IAC5C,WAAW,IAAI,UAAU;GAC3B,CAAC;EACH;CACF;CAEA,wBAAwB;EACtB,KAAK,MAAM,OAAO,KAAKF,cAAc,OAAO,GAC1C,IAAI,CAAC,IAAI,UAAU,GACjB,OAAO;EAGX,OAAO;CACT;CAEA,qBAA+B;EAC7B,OAAO,CAAC,GAAG,KAAKA,cAAc,QAAQ,CAAC,EACpC,QAAQ,GAAG,iBAAiB,CAAC,YAAY,UAAU,CAAC,EACpD,KAAK,CAAC,YAAY,MAAM;CAC7B;;CAGA,WACE,QACA,gBACA,cACA,QACM;EACN,MAAM,MAAM,KAAKA,cAAc,IAAI,MAAM;EACzC,IAAI,OAAO,CAAC,IAAI,UAAU,GAAG;GAC3B,KAAKH,IAAI,OACP,sCAAsC,aAAa,OAAO,QAC5D;GACA,IAAI,QAAQ,KAAKC,cAAc,WAAW,gBAAgB,YAAY;GAGtE,6CAA6C,EAAE,SAC7C,KAAK,IAAI,IAAI,IAAI,UAAU,QAAQ,GACnC;IAAC,GAAG,KAAKI,aAAa;IAAG;GAAM,CACjC;EACF;CACF;;;;;;CAOA,wBAAwB,QAAyB;EAC/C,OAAO,KAAKF,cAAc,IAAI,MAAM,GAAG,YAAY,KAAK;CAC1D;CAEA,wBAAwB;EACtB,OAAO,MAAM,KACX,KAAKA,cAAc,OAAO,IACzB,EAAC,wBAAuB,iBAC3B,EAAE,QAAO,cAAa,cAAc,IAAI;CAC1C;AACF;AAIA,IAAM,cAAN,MAAkB;CAChB;CACA,4BAA2B,IAAI,KAAK;CACpC;CACA,aAA4B;CAC5B,cAAc;CAEd,YACE,YACA,YACA;EACA,KAAK,aAAa;EAClB,KAAKG,cAAc;CACrB;CAEA,IAAI,oBAAoB;EACtB,OAAO,KAAKC;CACd;CAEA,YAAY;EACV,OAAO,KAAKA,eAAe;CAC7B;CAEA,KAAK,QAA0C;EAC7C,OAAO,KAAKD,gBAAgB;CAC9B;CAEA,cAAuB;EACrB,IAAI,KAAKE,aACP,OAAO;EAET,KAAKA,cAAc;EACnB,OAAO;CACT;CAEA,QAAQ,WAAmB,gBAAwB,cAAsB;EACvE,IAAI,KAAKD,eAAe,MAAM;GAC5B,IAAI,KAAKD,YAAY,QACnB,KAAKA,YAAY,KAAK,CACpB,UACA;IAAC,KAAK;IAAU;IAAW;IAAgB;GAAY,CACzD,CAAC;GAEH,KAAKC,aAAa;EACpB;CACF;CAEA,QAAQ;EACN,KAAKD,YAAY,OAAO;CAC1B;AACF"}
1
+ {"version":3,"file":"snapshot-reservations.js","names":["#lc","#backupConfig","#callbacks","#reservations","#close","#metricAttrs","#replicaSize","#downstream","#watermark","#delayNoted"],"sources":["../../../../../../zero-cache/src/services/change-streamer/snapshot-reservations.ts"],"sourcesContent":["import {statSync} from 'node:fs';\nimport type {LogContext} from '@rocicorp/logger';\nimport type {Source} from '../../types/streams.ts';\nimport {Subscription} from '../../types/subscription.ts';\nimport {\n litestreamMonitorMetricAttrs,\n litestreamSnapshotReservationConfirmDuration,\n litestreamSnapshotReservationDuration,\n} from '../litestream/metrics.ts';\nimport type {BackupConfig} from './change-streamer-service.ts';\nimport type {SnapshotMessage} from './snapshot-message.ts';\nimport type {ChangeLogReadSource} from './sqlite-change-log-read-router.ts';\n\nexport type ReservationCallbacks = {\n /**\n * Called whenever a reservation is closed, including when it is replaced\n * by a new reservation (e.g. a retry) for the same task.\n */\n onClose?: ((taskID: string) => void) | undefined;\n\n /**\n * Called when a task's reservation is closed without being replaced,\n * i.e. when the task no longer holds a reservation.\n */\n onEnd?: ((taskID: string) => void) | undefined;\n};\n\nexport class SnapshotReservations {\n readonly #lc: LogContext;\n readonly #backupConfig: BackupConfig;\n readonly #callbacks: ReservationCallbacks;\n readonly #reservations = new Map<string, Reservation>();\n\n constructor(\n lc: LogContext,\n backupConfig: BackupConfig,\n callbacks: ReservationCallbacks = {},\n ) {\n this.#lc = lc.withContext('component', 'snapshot-reserver');\n this.#backupConfig = backupConfig;\n this.#callbacks = callbacks;\n }\n\n open(taskID: string): Source<SnapshotMessage> {\n this.#close(taskID, undefined, true);\n\n const instanceID = {};\n const downstream = Subscription.create<SnapshotMessage>({\n cleanup: () => this.#close(taskID, instanceID),\n });\n this.#reservations.set(taskID, new Reservation(instanceID, downstream));\n this.#lc.info?.(`created snapshot reservation for ${taskID}`);\n return downstream;\n }\n\n close(taskID: string) {\n this.#close(taskID, undefined);\n }\n\n isCurrent(taskID: string, source: Source<SnapshotMessage>): boolean {\n return this.#reservations.get(taskID)?.owns(source) ?? false;\n }\n\n #metricAttrs() {\n return litestreamMonitorMetricAttrs(\n this.#backupConfig.backupURL,\n this.#backupConfig.litestreamVersion,\n 'view_syncer',\n );\n }\n\n #close(\n taskID: string,\n cancelledInstanceID: InstanceID | undefined,\n replaced = false,\n ) {\n const res = this.#reservations.get(taskID);\n if (\n res &&\n (!cancelledInstanceID || res.instanceID === cancelledInstanceID)\n ) {\n // Note: delete first, so that the reservation is gone when close() is called.\n this.#reservations.delete(taskID);\n this.#callbacks.onClose?.(taskID);\n if (!replaced) {\n this.#callbacks.onEnd?.(taskID);\n }\n res.close();\n\n const duration = Date.now() - res.startTime.getTime();\n this.#lc.info?.(\n `ended snapshot reservation for ${taskID} (${duration} ms)`,\n );\n // `result` reports how the reservation ended and `confirmed` whether it\n // ever received its bounds. They are separate dimensions: a follower\n // that gives up while waiting for a confirmation is\n // `result=cancelled, confirmed=false`, which a single collapsed\n // attribute cannot distinguish from a client that simply went away.\n litestreamSnapshotReservationDuration().recordMs(duration, {\n ...this.#metricAttrs(),\n result: cancelledInstanceID ? 'cancelled' : 'closed',\n confirmed: res.confirmed(),\n });\n }\n }\n\n confirmationsRequired() {\n for (const res of this.#reservations.values()) {\n if (!res.confirmed()) {\n return true;\n }\n }\n return false;\n }\n\n unconfirmedTaskIDs(): string[] {\n return [...this.#reservations.entries()]\n .filter(([, reservation]) => !reservation.confirmed())\n .map(([taskID]) => taskID);\n }\n\n /** Confirms one reservation with the bounds of its pinned read source. */\n confirmFor(\n taskID: string,\n replicaVersion: string,\n minWatermark: string,\n source: ChangeLogReadSource,\n ): void {\n const res = this.#reservations.get(taskID);\n if (res && !res.confirmed()) {\n this.#lc.info?.(\n `reserving change-log entries since ${minWatermark} for ${taskID}`,\n );\n res.confirm(\n this.#backupConfig.backupURL,\n replicaVersion,\n minWatermark,\n this.#replicaSize(),\n );\n // Measured from `open()`, not from the first confirmation attempt: what\n // matters is how long the follower waited before it could restore.\n litestreamSnapshotReservationConfirmDuration().recordMs(\n Date.now() - res.startTime.getTime(),\n {...this.#metricAttrs(), source},\n );\n }\n }\n\n #replicaSize(): number | undefined {\n const {replicaFile} = this.#backupConfig;\n if (!replicaFile) {\n return undefined;\n }\n try {\n return statSync(replicaFile).size;\n } catch (e) {\n this.#lc.warn?.(`Unable to get the size of ${replicaFile}`, e);\n return undefined;\n }\n }\n\n /**\n * Notes that a confirmation was deferred, returning true only the first time\n * for this reservation. Confirmation is retried on every backup, so an\n * undeduplicated count would measure backups rather than delayed followers.\n */\n noteConfirmationDelayed(taskID: string): boolean {\n return this.#reservations.get(taskID)?.noteDelayed() ?? false;\n }\n\n getReservedWatermarks() {\n return Array.from(\n this.#reservations.values(),\n ({reservedWatermark}) => reservedWatermark,\n ).filter(watermark => watermark !== null);\n }\n}\n\ntype InstanceID = {};\n\nclass Reservation {\n readonly instanceID: InstanceID;\n readonly startTime: Date = new Date();\n readonly #downstream: Subscription<SnapshotMessage>;\n #watermark: string | null = null;\n #delayNoted = false;\n\n constructor(\n instanceID: InstanceID,\n downstream: Subscription<SnapshotMessage>,\n ) {\n this.instanceID = instanceID;\n this.#downstream = downstream;\n }\n\n get reservedWatermark() {\n return this.#watermark;\n }\n\n confirmed() {\n return this.#watermark !== null;\n }\n\n owns(source: Source<SnapshotMessage>): boolean {\n return this.#downstream === source;\n }\n\n noteDelayed(): boolean {\n if (this.#delayNoted) {\n return false;\n }\n this.#delayNoted = true;\n return true;\n }\n\n confirm(\n backupURL: string,\n replicaVersion: string,\n minWatermark: string,\n replicaSize: number | undefined,\n ) {\n if (this.#watermark === null) {\n if (this.#downstream.active) {\n this.#downstream.push([\n 'status',\n {tag: 'status', backupURL, replicaVersion, minWatermark, replicaSize},\n ]);\n }\n this.#watermark = minWatermark;\n }\n }\n\n close() {\n this.#downstream.cancel();\n }\n}\n"],"mappings":"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"}
@@ -12,73 +12,11 @@
12
12
  * backed up changes.
13
13
  */
14
14
  import type { LogContext } from '@rocicorp/logger';
15
- import * as v from '../../../../shared/src/valita.ts';
16
- import { type NormalizedZeroConfig } from '../../config/normalize.ts';
17
- declare const statusSchema: v.ObjectType<{
18
- tag: v.Type<"status">;
19
- /**
20
- * The location from which litestream should perform the restore.
21
- */
22
- backupURL: v.Type<string>;
23
- /**
24
- * The `replicaVersion` of the backup. If a subscriber's restored or
25
- * existing replica is of a different version, it should delete it and
26
- * retry the restore from litestream (i.e. equivalent to a
27
- * `WrongReplicaVersion` response from a `/changes` subscription).
28
- */
29
- replicaVersion: v.Type<string>;
30
- /**
31
- * The earliest watermark from which catchup is possible. If the
32
- * subscriber's replica is older that this watermark, it should delete it
33
- * and (retry the) restore from litestream (i.e. equivalent to a
34
- * `WatermarkTooOld` response from a `/changes` subscription).
35
- */
36
- minWatermark: v.Type<string>;
37
- }, undefined>;
38
- export type SnapshotStatus = v.Infer<typeof statusSchema>;
39
- declare const statusMessageSchema: v.TupleType<[v.Type<"status">, v.ObjectType<{
40
- tag: v.Type<"status">;
41
- /**
42
- * The location from which litestream should perform the restore.
43
- */
44
- backupURL: v.Type<string>;
45
- /**
46
- * The `replicaVersion` of the backup. If a subscriber's restored or
47
- * existing replica is of a different version, it should delete it and
48
- * retry the restore from litestream (i.e. equivalent to a
49
- * `WrongReplicaVersion` response from a `/changes` subscription).
50
- */
51
- replicaVersion: v.Type<string>;
52
- /**
53
- * The earliest watermark from which catchup is possible. If the
54
- * subscriber's replica is older that this watermark, it should delete it
55
- * and (retry the) restore from litestream (i.e. equivalent to a
56
- * `WatermarkTooOld` response from a `/changes` subscription).
57
- */
58
- minWatermark: v.Type<string>;
59
- }, undefined>]>;
60
- export declare const snapshotMessageSchema: v.UnionType<[v.TupleType<[v.Type<"status">, v.ObjectType<{
61
- tag: v.Type<"status">;
62
- /**
63
- * The location from which litestream should perform the restore.
64
- */
65
- backupURL: v.Type<string>;
66
- /**
67
- * The `replicaVersion` of the backup. If a subscriber's restored or
68
- * existing replica is of a different version, it should delete it and
69
- * retry the restore from litestream (i.e. equivalent to a
70
- * `WrongReplicaVersion` response from a `/changes` subscription).
71
- */
72
- replicaVersion: v.Type<string>;
73
- /**
74
- * The earliest watermark from which catchup is possible. If the
75
- * subscriber's replica is older that this watermark, it should delete it
76
- * and (retry the) restore from litestream (i.e. equivalent to a
77
- * `WatermarkTooOld` response from a `/changes` subscription).
78
- */
79
- minWatermark: v.Type<string>;
80
- }, undefined>]>]>;
81
- export type SnapshotMessage = v.Infer<typeof statusMessageSchema>;
82
- export declare function reserveAndGetSnapshotStatus(lc: LogContext, config: NormalizedZeroConfig): Promise<SnapshotStatus>;
83
- export {};
15
+ import type { ReservationFollowup, SnapshotReserver } from './change-streamer-http.ts';
16
+ import type { LocalReplica, SnapshotStatus } from './subscribe.ts';
17
+ export type { SnapshotStatus };
18
+ export declare function reserveAndGetSnapshotStatus(lc: LogContext, taskID: string, changeStreamer: SnapshotReserver, localReplica?: LocalReplica | undefined): Promise<{
19
+ reserved: SnapshotStatus;
20
+ followup: ReservationFollowup;
21
+ }>;
84
22
  //# sourceMappingURL=snapshot.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"snapshot.d.ts","sourceRoot":"","sources":["../../../../../../zero-cache/src/services/change-streamer/snapshot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAGjD,OAAO,KAAK,CAAC,MAAM,kCAAkC,CAAC;AACtD,OAAO,EAAC,KAAK,oBAAoB,EAAC,MAAM,2BAA2B,CAAC;AAKpE,QAAA,MAAM,YAAY;;IAGhB;;OAEG;;IAGH;;;;;OAKG;;IAGH;;;;;OAKG;;aAEH,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAE1D,QAAA,MAAM,mBAAmB;;IAxBvB;;OAEG;;IAGH;;;;;OAKG;;IAGH;;;;;OAKG;;eAMmE,CAAC;AAEzE,eAAO,MAAM,qBAAqB;;IA1BhC;;OAEG;;IAGH;;;;;OAKG;;IAGH;;;;;OAKG;;iBAQ4D,CAAC;AAElE,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAElE,wBAAgB,2BAA2B,CACzC,EAAE,EAAE,UAAU,EACd,MAAM,EAAE,oBAAoB,GAC3B,OAAO,CAAC,cAAc,CAAC,CAiDzB"}
1
+ {"version":3,"file":"snapshot.d.ts","sourceRoot":"","sources":["../../../../../../zero-cache/src/services/change-streamer/snapshot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AASjD,OAAO,KAAK,EACV,mBAAmB,EACnB,gBAAgB,EACjB,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAC,YAAY,EAAE,cAAc,EAAC,MAAM,gBAAgB,CAAC;AAEjE,YAAY,EAAC,cAAc,EAAC,CAAC;AAE7B,wBAAsB,2BAA2B,CAC/C,EAAE,EAAE,UAAU,EACd,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,gBAAgB,EAChC,YAAY,CAAC,EAAE,YAAY,GAAG,SAAS,GACtC,OAAO,CAAC;IAAC,QAAQ,EAAE,cAAc,CAAC;IAAC,QAAQ,EAAE,mBAAmB,CAAA;CAAC,CAAC,CAmDpE"}
@@ -1,67 +1,35 @@
1
+ import { AbortError } from "../../../../shared/src/abort-error.js";
1
2
  import { sleep } from "../../../../shared/src/sleep.js";
2
- import { valita_exports } from "../../../../shared/src/valita.js";
3
- import { getShardConfig } from "../../types/shards.js";
4
- import "../../config/normalize.js";
5
- import { ChangeStreamerHttpClient } from "./change-streamer-http.js";
6
- import { resolver } from "@rocicorp/resolver";
3
+ import { promiseOrAbort } from "../../../../shared/src/promise-race.js";
7
4
  //#region ../zero-cache/src/services/change-streamer/snapshot.ts
8
- var statusSchema = valita_exports.object({
9
- tag: valita_exports.literal("status"),
10
- /**
11
- * The location from which litestream should perform the restore.
12
- */
13
- backupURL: valita_exports.string(),
14
- /**
15
- * The `replicaVersion` of the backup. If a subscriber's restored or
16
- * existing replica is of a different version, it should delete it and
17
- * retry the restore from litestream (i.e. equivalent to a
18
- * `WrongReplicaVersion` response from a `/changes` subscription).
19
- */
20
- replicaVersion: valita_exports.string(),
21
- /**
22
- * The earliest watermark from which catchup is possible. If the
23
- * subscriber's replica is older that this watermark, it should delete it
24
- * and (retry the) restore from litestream (i.e. equivalent to a
25
- * `WatermarkTooOld` response from a `/changes` subscription).
26
- */
27
- minWatermark: valita_exports.string()
28
- });
29
- var statusMessageSchema = valita_exports.tuple([valita_exports.literal("status"), statusSchema]);
30
- var snapshotMessageSchema = valita_exports.union(statusMessageSchema);
31
- function reserveAndGetSnapshotStatus(lc, config) {
32
- const { promise: status, resolve, reject } = resolver();
33
- (async function() {
34
- const abort = new AbortController();
35
- process.on("SIGINT", () => abort.abort());
36
- process.on("SIGTERM", () => abort.abort());
5
+ async function reserveAndGetSnapshotStatus(lc, taskID, changeStreamer, localReplica) {
6
+ const abort = new AbortController();
7
+ const { signal } = abort;
8
+ const onSignal = () => abort.abort(new AbortError("SIGTERM/SIGINT"));
9
+ process.on("SIGINT", onSignal);
10
+ process.on("SIGTERM", onSignal);
11
+ try {
37
12
  for (let i = 0;; i++) {
38
13
  let err;
14
+ const reservation = changeStreamer.reserveSnapshot(taskID, localReplica);
39
15
  try {
40
- let resolved = false;
41
- const stream = await reserveSnapshot(lc, config);
42
- for await (const msg of stream) {
43
- resolve(msg[1]);
44
- resolved = true;
45
- }
46
- if (resolved) break;
16
+ return await promiseOrAbort(reservation, signal);
47
17
  } catch (e) {
48
18
  err = e;
49
19
  }
50
- lc.warn?.(`Unable to reserve snapshot (attempt ${i + 1}). Retrying in 5 seconds.`, String(err));
51
- try {
52
- await sleep(5e3, abort.signal);
53
- } catch (e) {
54
- return reject(e);
20
+ if (signal.aborted) {
21
+ reservation.then(({ followup }) => followup.cancel(), () => {});
22
+ throw err;
55
23
  }
24
+ lc.warn?.(`Unable to reserve snapshot (attempt ${i + 1}). Retrying in 5 seconds.`, String(err));
25
+ await sleep(5e3, signal);
56
26
  }
57
- })();
58
- return status;
59
- }
60
- function reserveSnapshot(lc, config) {
61
- const { taskID, change, changeStreamer } = config;
62
- return new ChangeStreamerHttpClient(lc, getShardConfig(config), change.db, changeStreamer.uri).reserveSnapshot(taskID);
27
+ } finally {
28
+ process.off("SIGINT", onSignal);
29
+ process.off("SIGTERM", onSignal);
30
+ }
63
31
  }
64
32
  //#endregion
65
- export { reserveAndGetSnapshotStatus, snapshotMessageSchema };
33
+ export { reserveAndGetSnapshotStatus };
66
34
 
67
35
  //# sourceMappingURL=snapshot.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"snapshot.js","names":[],"sources":["../../../../../../zero-cache/src/services/change-streamer/snapshot.ts"],"sourcesContent":["/**\n * The `snapshot` API serves the purpose of:\n * - informing subscribers (i.e. view-syncers) of the (litestream)\n * backup location from which to restore a replica snapshot\n * - checking whether a restored backup or existing replica is\n * compatible with the change-streamer\n * - preventing change-log cleanup while a snapshot restore is in\n * progress\n * - tracking the approximate time it takes from the beginning of\n * snapshot \"reservation\" to the subsequent subscription, which\n * serves as the minimum interval to wait before cleaning up\n * backed up changes.\n */\n\nimport type {LogContext} from '@rocicorp/logger';\nimport {resolver} from '@rocicorp/resolver';\nimport {sleep} from '../../../../shared/src/sleep.ts';\nimport * as v from '../../../../shared/src/valita.ts';\nimport {type NormalizedZeroConfig} from '../../config/normalize.ts';\nimport {getShardConfig} from '../../types/shards.ts';\nimport type {Source} from '../../types/streams.ts';\nimport {ChangeStreamerHttpClient} from './change-streamer-http.ts';\n\nconst statusSchema = v.object({\n tag: v.literal('status'),\n\n /**\n * The location from which litestream should perform the restore.\n */\n backupURL: v.string(),\n\n /**\n * The `replicaVersion` of the backup. If a subscriber's restored or\n * existing replica is of a different version, it should delete it and\n * retry the restore from litestream (i.e. equivalent to a\n * `WrongReplicaVersion` response from a `/changes` subscription).\n */\n replicaVersion: v.string(),\n\n /**\n * The earliest watermark from which catchup is possible. If the\n * subscriber's replica is older that this watermark, it should delete it\n * and (retry the) restore from litestream (i.e. equivalent to a\n * `WatermarkTooOld` response from a `/changes` subscription).\n */\n minWatermark: v.string(),\n});\n\nexport type SnapshotStatus = v.Infer<typeof statusSchema>;\n\nconst statusMessageSchema = v.tuple([v.literal('status'), statusSchema]);\n\nexport const snapshotMessageSchema = v.union(statusMessageSchema);\n\nexport type SnapshotMessage = v.Infer<typeof statusMessageSchema>;\n\nexport function reserveAndGetSnapshotStatus(\n lc: LogContext,\n config: NormalizedZeroConfig,\n): Promise<SnapshotStatus> {\n const {promise: status, resolve, reject} = resolver<SnapshotStatus>();\n\n void (async function () {\n const abort = new AbortController();\n process.on('SIGINT', () => abort.abort());\n process.on('SIGTERM', () => abort.abort());\n\n for (let i = 0; ; i++) {\n let err: unknown;\n try {\n let resolved = false;\n const stream = await reserveSnapshot(lc, config);\n for await (const msg of stream) {\n // Capture the value of the status message that the change-streamer\n // backup monitor returns, and hold the connection open to\n // \"reserve\" the snapshot and prevent change log cleanup.\n resolve(msg[1]);\n resolved = true;\n }\n // The change-streamer itself closes the connection when the\n // subscription is started (or the reservation retried).\n if (resolved) {\n break;\n }\n } catch (e) {\n err = e;\n }\n // Retry in the view-syncer since it cannot proceed until it connects\n // to a (compatible) replication-manager. In particular, a\n // replication-manager that does not support the view-syncer's\n // change-streamer protocol will close the stream with an error; this\n // retry logic essentially delays the startup of a view-syncer until\n // a compatible replication-manager has been rolled out, allowing\n // replication-manager and view-syncer services to be updated in\n // parallel.\n lc.warn?.(\n `Unable to reserve snapshot (attempt ${i + 1}). Retrying in 5 seconds.`,\n String(err),\n );\n try {\n await sleep(5000, abort.signal);\n } catch (e) {\n return reject(e);\n }\n }\n })();\n\n return status;\n}\n\nfunction reserveSnapshot(\n lc: LogContext,\n config: NormalizedZeroConfig,\n): Promise<Source<SnapshotMessage>> {\n const {taskID, change, changeStreamer} = config;\n const shardID = getShardConfig(config);\n\n const changeStreamerClient = new ChangeStreamerHttpClient(\n lc,\n shardID,\n change.db,\n changeStreamer.uri,\n );\n\n return changeStreamerClient.reserveSnapshot(taskID);\n}\n"],"mappings":";;;;;;;AAuBA,IAAM,eAAe,eAAE,OAAO;CAC5B,KAAK,eAAE,QAAQ,QAAQ;;;;CAKvB,WAAW,eAAE,OAAO;;;;;;;CAQpB,gBAAgB,eAAE,OAAO;;;;;;;CAQzB,cAAc,eAAE,OAAO;AACzB,CAAC;AAID,IAAM,sBAAsB,eAAE,MAAM,CAAC,eAAE,QAAQ,QAAQ,GAAG,YAAY,CAAC;AAEvE,IAAa,wBAAwB,eAAE,MAAM,mBAAmB;AAIhE,SAAgB,4BACd,IACA,QACyB;CACzB,MAAM,EAAC,SAAS,QAAQ,SAAS,WAAU,SAAyB;CAEpE,CAAM,iBAAkB;EACtB,MAAM,QAAQ,IAAI,gBAAgB;EAClC,QAAQ,GAAG,gBAAgB,MAAM,MAAM,CAAC;EACxC,QAAQ,GAAG,iBAAiB,MAAM,MAAM,CAAC;EAEzC,KAAK,IAAI,IAAI,IAAK,KAAK;GACrB,IAAI;GACJ,IAAI;IACF,IAAI,WAAW;IACf,MAAM,SAAS,MAAM,gBAAgB,IAAI,MAAM;IAC/C,WAAW,MAAM,OAAO,QAAQ;KAI9B,QAAQ,IAAI,EAAE;KACd,WAAW;IACb;IAGA,IAAI,UACF;GAEJ,SAAS,GAAG;IACV,MAAM;GACR;GASA,GAAG,OACD,uCAAuC,IAAI,EAAE,4BAC7C,OAAO,GAAG,CACZ;GACA,IAAI;IACF,MAAM,MAAM,KAAM,MAAM,MAAM;GAChC,SAAS,GAAG;IACV,OAAO,OAAO,CAAC;GACjB;EACF;CACF,GAAG;CAEH,OAAO;AACT;AAEA,SAAS,gBACP,IACA,QACkC;CAClC,MAAM,EAAC,QAAQ,QAAQ,mBAAkB;CAUzC,OAAO,IAP0B,yBAC/B,IAHc,eAAe,MAI7B,GACA,OAAO,IACP,eAAe,GAGV,EAAqB,gBAAgB,MAAM;AACpD"}
1
+ {"version":3,"file":"snapshot.js","names":[],"sources":["../../../../../../zero-cache/src/services/change-streamer/snapshot.ts"],"sourcesContent":["/**\n * The `snapshot` API serves the purpose of:\n * - informing subscribers (i.e. view-syncers) of the (litestream)\n * backup location from which to restore a replica snapshot\n * - checking whether a restored backup or existing replica is\n * compatible with the change-streamer\n * - preventing change-log cleanup while a snapshot restore is in\n * progress\n * - tracking the approximate time it takes from the beginning of\n * snapshot \"reservation\" to the subsequent subscription, which\n * serves as the minimum interval to wait before cleaning up\n * backed up changes.\n */\n\nimport type {LogContext} from '@rocicorp/logger';\nimport {AbortError} from '../../../../shared/src/abort-error.ts';\nimport {promiseOrAbort} from '../../../../shared/src/promise-race.ts';\nimport {sleep} from '../../../../shared/src/sleep.ts';\n\n// The schema definitions live in the pure schema module (with no dependency on\n// the HTTP client) so that subscribe.ts can import them without forming an\n// import cycle through change-streamer-http.ts. Imported here for local use and\n// re-exported for existing consumers.\nimport type {\n ReservationFollowup,\n SnapshotReserver,\n} from './change-streamer-http.ts';\nimport type {LocalReplica, SnapshotStatus} from './subscribe.ts';\n\nexport type {SnapshotStatus};\n\nexport async function reserveAndGetSnapshotStatus(\n lc: LogContext,\n taskID: string,\n changeStreamer: SnapshotReserver,\n localReplica?: LocalReplica | undefined,\n): Promise<{reserved: SnapshotStatus; followup: ReservationFollowup}> {\n const abort = new AbortController();\n const {signal} = abort;\n // Use our own AbortError as the abort reason (rather than the native\n // DOMException that AbortController.abort() defaults to) so that\n // promiseOrAbort()'s rejection, which propagates `signal.reason` verbatim,\n // is always an instance of the shared AbortError type.\n const onSignal = () => abort.abort(new AbortError('SIGTERM/SIGINT'));\n process.on('SIGINT', onSignal);\n process.on('SIGTERM', onSignal);\n\n try {\n for (let i = 0; ; i++) {\n let err: unknown;\n const reservation = changeStreamer.reserveSnapshot(taskID, localReplica);\n try {\n return await promiseOrAbort(reservation, signal);\n } catch (e) {\n err = e;\n }\n if (signal.aborted) {\n // promiseOrAbort() does not cancel the loser of the race: the\n // reservation may still resolve later. If it does, cancel its\n // connection rather than leaking it, since this function has already\n // given up and nobody will call followup.subscribe().\n reservation.then(\n ({followup}) => followup.cancel(),\n () => {},\n );\n throw err;\n }\n // Retry in the view-syncer since it cannot proceed until it connects\n // to a (compatible) replication-manager. In particular, a\n // replication-manager that does not support the view-syncer's\n // change-streamer protocol will close the stream with an error; this\n // retry logic essentially delays the startup of a view-syncer until\n // a compatible replication-manager has been rolled out, allowing\n // replication-manager and view-syncer services to be updated in\n // parallel.\n lc.warn?.(\n `Unable to reserve snapshot (attempt ${i + 1}). Retrying in 5 seconds.`,\n String(err),\n );\n await sleep(5000, signal);\n }\n } finally {\n // This function is called repeatedly (e.g. by the replicator's restore\n // loop), so the signal handlers must not outlive the reservation.\n process.off('SIGINT', onSignal);\n process.off('SIGTERM', onSignal);\n }\n}\n"],"mappings":";;;;AA+BA,eAAsB,4BACpB,IACA,QACA,gBACA,cACoE;CACpE,MAAM,QAAQ,IAAI,gBAAgB;CAClC,MAAM,EAAC,WAAU;CAKjB,MAAM,iBAAiB,MAAM,MAAM,IAAI,WAAW,gBAAgB,CAAC;CACnE,QAAQ,GAAG,UAAU,QAAQ;CAC7B,QAAQ,GAAG,WAAW,QAAQ;CAE9B,IAAI;EACF,KAAK,IAAI,IAAI,IAAK,KAAK;GACrB,IAAI;GACJ,MAAM,cAAc,eAAe,gBAAgB,QAAQ,YAAY;GACvE,IAAI;IACF,OAAO,MAAM,eAAe,aAAa,MAAM;GACjD,SAAS,GAAG;IACV,MAAM;GACR;GACA,IAAI,OAAO,SAAS;IAKlB,YAAY,MACT,EAAC,eAAc,SAAS,OAAO,SAC1B,CAAC,CACT;IACA,MAAM;GACR;GASA,GAAG,OACD,uCAAuC,IAAI,EAAE,4BAC7C,OAAO,GAAG,CACZ;GACA,MAAM,MAAM,KAAM,MAAM;EAC1B;CACF,UAAU;EAGR,QAAQ,IAAI,UAAU,QAAQ;EAC9B,QAAQ,IAAI,WAAW,QAAQ;CACjC;AACF"}
@@ -25,6 +25,11 @@ export type SQLiteChangeLogWriterOptions = {
25
25
  onRebuilt?: (() => void) | undefined;
26
26
  /** Overridable for tests. */
27
27
  now?: (() => number) | undefined;
28
+ /**
29
+ * Percentage of transactions that retain the rollout-only per-message
30
+ * timing and source-vs-stored hash validation. Defaults to 1.
31
+ */
32
+ shadowValidationPercent?: number | undefined;
28
33
  };
29
34
  /**
30
35
  * Appends the canonical change stream to the SQLite change log, from the
@@ -98,7 +103,7 @@ export declare class SQLiteChangeLogWriter {
98
103
  * Writes one stream message, committing at transaction boundaries. Never
99
104
  * throws: a write failure disables the writer instead of failing the stream.
100
105
  */
101
- write(change: ChangeStreamData, json: string): void;
106
+ write(change: ChangeStreamData, json: string, storedChange?: string): void;
102
107
  /**
103
108
  * Discards the open transaction, if any. Called when the change stream is
104
109
  * interrupted mid-transaction.
@@ -1 +1 @@
1
- {"version":3,"file":"sqlite-change-log-writer.d.ts","sourceRoot":"","sources":["../../../../../../zero-cache/src/services/change-streamer/sqlite-change-log-writer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAGjD,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,8BAA8B,CAAC;AAM3D,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,iDAAiD,CAAC;AAKtF,OAAO,EAUL,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EAE1B,MAAM,gCAAgC,CAAC;AAExC,OAAO,EAML,KAAK,iCAAiC,EACvC,MAAM,kDAAkD,CAAC;AAE1D,MAAM,MAAM,4BAA4B,GAAG;IACzC,iFAAiF;IACjF,WAAW,EAAE,MAAM,CAAC;IACpB,sDAAsD;IACtD,QAAQ,EAAE,iBAAiB,CAAC;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CAAC,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IACrD;;;;;OAKG;IACH,UAAU,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;IACtC,6EAA6E;IAC7E,SAAS,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;IACrC,6BAA6B;IAC7B,GAAG,CAAC,EAAE,CAAC,MAAM,MAAM,CAAC,GAAG,SAAS,CAAC;CAClC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,qBAAa,qBAAqB;;IAUhC,YAAY,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,4BAA4B,EAI7D;IAED,qEAAqE;IACrE,IAAI,OAAO,IAAI,OAAO,CAErB;IAED;;;;;;;OAOG;IACH,IAAI,UAAU,IAAI,QAAQ,GAAG,SAAS,CAErC;IAED,2EAA2E;IAC3E,KAAK,IAAI,iCAAiC,GAAG,SAAS,CAErD;IAED;;;;;;;;;;;;;OAaG;IACH,SAAS,CACP,UAAU,EAAE,oBAAoB,GAC/B,oBAAoB,GAAG,SAAS,CAElC;IAED;;;;;OAKG;IACH,gBAAgB,CACd,IAAI,EAAE,MAAM,oBAAoB,GAC/B,oBAAoB,GAAG,SAAS,CAElC;IA2GD;;;OAGG;IACH,KAAK,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAgElD;IAED;;;OAGG;IACH,KAAK,IAAI,IAAI,CAWZ;IAED,KAAK,IAAI,IAAI,CAWZ;CA6BF"}
1
+ {"version":3,"file":"sqlite-change-log-writer.d.ts","sourceRoot":"","sources":["../../../../../../zero-cache/src/services/change-streamer/sqlite-change-log-writer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAKjD,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,8BAA8B,CAAC;AAM3D,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,iDAAiD,CAAC;AAKtF,OAAO,EAUL,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EAE1B,MAAM,gCAAgC,CAAC;AAExC,OAAO,EAML,KAAK,iCAAiC,EACvC,MAAM,kDAAkD,CAAC;AAG1D,MAAM,MAAM,4BAA4B,GAAG;IACzC,iFAAiF;IACjF,WAAW,EAAE,MAAM,CAAC;IACpB,sDAAsD;IACtD,QAAQ,EAAE,iBAAiB,CAAC;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CAAC,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IACrD;;;;;OAKG;IACH,UAAU,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;IACtC,6EAA6E;IAC7E,SAAS,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;IACrC,6BAA6B;IAC7B,GAAG,CAAC,EAAE,CAAC,MAAM,MAAM,CAAC,GAAG,SAAS,CAAC;IACjC;;;OAGG;IACH,uBAAuB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC9C,CAAC;AAIF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,qBAAa,qBAAqB;;IAYhC,YAAY,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,4BAA4B,EAY7D;IAED,qEAAqE;IACrE,IAAI,OAAO,IAAI,OAAO,CAErB;IAED;;;;;;;OAOG;IACH,IAAI,UAAU,IAAI,QAAQ,GAAG,SAAS,CAErC;IAED,2EAA2E;IAC3E,KAAK,IAAI,iCAAiC,GAAG,SAAS,CAErD;IAED;;;;;;;;;;;;;OAaG;IACH,SAAS,CACP,UAAU,EAAE,oBAAoB,GAC/B,oBAAoB,GAAG,SAAS,CAElC;IAED;;;;;OAKG;IACH,gBAAgB,CACd,IAAI,EAAE,MAAM,oBAAoB,GAC/B,oBAAoB,GAAG,SAAS,CAElC;IA2GD;;;OAGG;IACH,KAAK,CACH,MAAM,EAAE,gBAAgB,EACxB,IAAI,EAAE,MAAM,EACZ,YAAY,SAA8C,GACzD,IAAI,CA4FN;IAeD;;;OAGG;IACH,KAAK,IAAI,IAAI,CAYZ;IAED,KAAK,IAAI,IAAI,CAYZ;CA6BF"}
@@ -1,12 +1,16 @@
1
+ import { assert } from "../../../../shared/src/asserts.js";
1
2
  import { must } from "../../../../shared/src/must.js";
3
+ import { h32 } from "../../../../shared/src/hash.js";
2
4
  import { readCookieRowCounts, readCookies } from "../replicator/change-log-cookies.js";
3
5
  import { StatementRunner } from "../../db/statements.js";
4
6
  import { isSQLiteCorruption, logSQLiteCorruptionDiagnostics } from "../../db/sqlite-corruption.js";
5
7
  import { ChangeLogRebuildRequired, changeLogFileName, changeLogWipeReason, deleteChangeLogDB, openChangeLogDBForWriting, readChangeLogHead, rebuildChangeLogDBForWriting, reconcileChangeLog } from "../replicator/change-log-db.js";
8
+ import { extractChangeSubstring } from "./change-log-codec.js";
6
9
  import { ChangeLogStreamWriter } from "../replicator/change-log-stream-writer.js";
7
10
  import { SQLiteChangeLogObserver, getSQLiteChangeLogInfo, logSQLiteChangeLogStartup, recordSQLiteChangeLogReconcile } from "../replicator/sqlite-change-log-observability.js";
8
11
  import { SqliteError } from "@rocicorp/zero-sqlite3";
9
12
  //#region ../zero-cache/src/services/change-streamer/sqlite-change-log-writer.ts
13
+ var DEFAULT_SHADOW_VALIDATION_PERCENT = 1;
10
14
  /**
11
15
  * Appends the canonical change stream to the SQLite change log, from the
12
16
  * change-streamer's own stream loop.
@@ -41,14 +45,18 @@ var SQLiteChangeLogWriter = class {
41
45
  #lc;
42
46
  #opts;
43
47
  #now;
48
+ #shadowValidationPercent;
44
49
  #db;
45
50
  #writer;
46
51
  #observer;
47
52
  #disabled = false;
53
+ #validateTransaction = false;
48
54
  constructor(lc, opts) {
49
55
  this.#lc = lc.withContext("component", "sqlite-change-log-writer");
50
56
  this.#opts = opts;
51
57
  this.#now = opts.now ?? Date.now;
58
+ this.#shadowValidationPercent = opts.shadowValidationPercent ?? DEFAULT_SHADOW_VALIDATION_PERCENT;
59
+ assert(Number.isInteger(this.#shadowValidationPercent) && this.#shadowValidationPercent >= 0 && this.#shadowValidationPercent <= 100, "SQLite change-log shadow validation percentage must be an integer between 0 and 100");
52
60
  }
53
61
  /** False once the writer has failed soft, or after {@link close}. */
54
62
  get enabled() {
@@ -161,26 +169,28 @@ var SQLiteChangeLogWriter = class {
161
169
  * Writes one stream message, committing at transaction boundaries. Never
162
170
  * throws: a write failure disables the writer instead of failing the stream.
163
171
  */
164
- write(change, json) {
172
+ write(change, json, storedChange = extractChangeSubstring(json, change[1].tag)) {
165
173
  const writer = this.#writer;
166
174
  const db = this.#db;
167
175
  if (this.#disabled || writer === void 0 || db === void 0) return;
168
- const observer = this.#observer;
169
- observer?.messageReceived(change, json);
170
176
  const [type, msg] = change;
171
- const startedAt = performance.now();
177
+ if (type === "begin") this.#validateTransaction = this.#isSelectedForShadowValidation(change[2].commitWatermark);
178
+ const validateTransaction = this.#validateTransaction;
179
+ const observer = this.#observer;
180
+ observer?.messageReceived(change, json, validateTransaction, storedChange);
181
+ const startedAt = validateTransaction ? performance.now() : void 0;
172
182
  try {
173
183
  let commit = null;
174
184
  switch (type) {
175
185
  case "begin":
176
- writer.begin(change[2].commitWatermark, json);
186
+ writer.begin(change[2].commitWatermark, json, storedChange, validateTransaction);
177
187
  break;
178
188
  case "commit": {
179
189
  const { watermark } = change[2];
180
190
  const commitStart = performance.now();
181
191
  commit = {
182
192
  watermark,
183
- stats: writer.commit(watermark, json, this.#now()),
193
+ stats: writer.commit(watermark, json, this.#now(), storedChange),
184
194
  logCommitMs: performance.now() - commitStart
185
195
  };
186
196
  break;
@@ -189,14 +199,16 @@ var SQLiteChangeLogWriter = class {
189
199
  writer.rollback();
190
200
  break;
191
201
  default:
192
- writer.append(json, msg);
202
+ writer.append(json, msg, storedChange);
193
203
  break;
194
204
  }
195
- observer?.messageProcessed(change, commit, performance.now() - startedAt);
205
+ observer?.messageProcessed(change, commit, startedAt === void 0 ? void 0 : performance.now() - startedAt);
196
206
  if (commit !== null && commit.stats.cookieMutations.length > 0) observer?.cookiesMutated(commit.stats.cookieMutations, readCookieRowCounts(db));
197
207
  if (commit !== null) this.#opts.onCommit?.(commit.watermark);
208
+ if (type === "commit" || type === "rollback") this.#validateTransaction = false;
198
209
  } catch (e) {
199
- observer?.messageFailed(change, e, performance.now() - startedAt);
210
+ observer?.messageFailed(change, e, startedAt === void 0 ? void 0 : performance.now() - startedAt);
211
+ this.#validateTransaction = false;
200
212
  if (isConstraintViolation(e)) observer?.invariantFailure("SQLite change-log insert violated a constraint, which means a transaction above the resume watermark was not truncated", {
201
213
  tag: msg.tag,
202
214
  error: String(e)
@@ -204,12 +216,17 @@ var SQLiteChangeLogWriter = class {
204
216
  this.#failSoft("writing to the SQLite change log", e);
205
217
  }
206
218
  }
219
+ #isSelectedForShadowValidation(watermark) {
220
+ const percent = this.#shadowValidationPercent;
221
+ return percent >= 100 || percent > 0 && h32(`${this.#opts.identity.generation}/${this.#opts.identity.replicaID ?? ""}:${watermark}`) % 100 < percent;
222
+ }
207
223
  /**
208
224
  * Discards the open transaction, if any. Called when the change stream is
209
225
  * interrupted mid-transaction.
210
226
  */
211
227
  abort() {
212
228
  const writer = this.#writer;
229
+ this.#validateTransaction = false;
213
230
  if (this.#disabled || writer === void 0) return;
214
231
  this.#observer?.abort();
215
232
  try {
@@ -220,6 +237,7 @@ var SQLiteChangeLogWriter = class {
220
237
  }
221
238
  close() {
222
239
  this.#disabled = true;
240
+ this.#validateTransaction = false;
223
241
  this.#writer = void 0;
224
242
  this.#observer = void 0;
225
243
  const db = this.#db;
@@ -1 +1 @@
1
- {"version":3,"file":"sqlite-change-log-writer.js","names":["#lc","#opts","#now","#disabled","#db","#observer","#reconcile","#resumeFromLog","#writer","#failSoft"],"sources":["../../../../../../zero-cache/src/services/change-streamer/sqlite-change-log-writer.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {SqliteError} from '@rocicorp/zero-sqlite3';\nimport {must} from '../../../../shared/src/must.ts';\nimport type {Database} from '../../../../zqlite/src/db.ts';\nimport {\n isSQLiteCorruption,\n logSQLiteCorruptionDiagnostics,\n} from '../../db/sqlite-corruption.ts';\nimport {StatementRunner} from '../../db/statements.ts';\nimport type {ChangeStreamData} from '../change-source/protocol/current/downstream.ts';\nimport {\n readCookieRowCounts,\n readCookies,\n} from '../replicator/change-log-cookies.ts';\nimport {\n ChangeLogRebuildRequired,\n changeLogFileName,\n changeLogWipeReason,\n deleteChangeLogDB,\n openChangeLogDBForWriting,\n readChangeLogHead,\n rebuildChangeLogDBForWriting,\n reconcileChangeLog,\n type ChangeLogAnchor,\n type ChangeLogIdentity,\n type ChangeLogResumePoint,\n type ReconcileResult,\n} from '../replicator/change-log-db.ts';\nimport {ChangeLogStreamWriter} from '../replicator/change-log-stream-writer.ts';\nimport {\n getSQLiteChangeLogInfo,\n logSQLiteChangeLogStartup,\n recordSQLiteChangeLogReconcile,\n SQLiteChangeLogObserver,\n type ChangeLogCommit,\n type SQLiteChangeLogObservabilityState,\n} from '../replicator/sqlite-change-log-observability.ts';\n\nexport type SQLiteChangeLogWriterOptions = {\n /** The replica file the log is named after, i.e. `${replicaFile}-change-log`. */\n replicaFile: string;\n /** The replica whose contents this log belongs to. */\n identity: ChangeLogIdentity;\n /**\n * Called after each transaction's log commit, with the log's new head. This\n * is what releases the catchup barrier: after the writer moved in-process,\n * the head advances here rather than at a subscriber's ACK.\n */\n onCommit?: ((watermark: string) => void) | undefined;\n /**\n * Called when the writer disables itself and deletes the file. The reader is\n * cached on the service, so a delete that leaves it open would leave an\n * in-process reader serving an unlinked inode while every new open sees\n * nothing.\n */\n onDisabled?: (() => void) | undefined;\n /** Called when reconciliation replaces the file, to close cached readers. */\n onRebuilt?: (() => void) | undefined;\n /** Overridable for tests. */\n now?: (() => number) | undefined;\n};\n\n/**\n * Appends the canonical change stream to the SQLite change log, from the\n * change-streamer's own stream loop.\n *\n * ### Ordering\n *\n * The log's commit for a transaction precedes the forward of that transaction's\n * `commit` message, and nothing `await`s in between. Everything that can\n * advance the watermark the stream would resume from — the storer's Postgres\n * commit, `lastWatermark`, the upstream ACK — runs strictly after it, so the\n * log's head is always at or above the resume point. A *hole* is therefore\n * unreachable at any crash timing, and a *phantom* is the normal state, which is\n * what makes truncate-above the whole of reconciliation.\n *\n * ### Fail-soft\n *\n * The log is a catchup cache: nothing in it is not either already durable in the\n * replica's litestream backup or re-derivable from the replication slot. A write\n * failure must therefore not stop replication for the shard. Corruption is\n * rebuilt once at open; any other write error — a full disk, an I/O error, a\n * permissions problem — logs, disables the writer, deletes the file, closes the\n * reader, and lets the stream continue. The cost is catchup reach, and reach is\n * recoverable: `too-old` sends a subscriber to a restore.\n *\n * One carve-out keeps that from hiding the bug class this topology introduces. A\n * missed truncate-above surfaces as `SQLITE_CONSTRAINT` on the writer's plain\n * `INSERT`, which is \"any write error other than corruption\" and would be\n * absorbed quietly. It is counted as an invariant failure and alerted on before\n * failing soft.\n */\nexport class SQLiteChangeLogWriter {\n readonly #lc: LogContext;\n readonly #opts: SQLiteChangeLogWriterOptions;\n readonly #now: () => number;\n\n #db: Database | undefined;\n #writer: ChangeLogStreamWriter | undefined;\n #observer: SQLiteChangeLogObserver | undefined;\n #disabled = false;\n\n constructor(lc: LogContext, opts: SQLiteChangeLogWriterOptions) {\n this.#lc = lc.withContext('component', 'sqlite-change-log-writer');\n this.#opts = opts;\n this.#now = opts.now ?? Date.now;\n }\n\n /** False once the writer has failed soft, or after {@link close}. */\n get enabled(): boolean {\n return !this.#disabled;\n }\n\n /**\n * The writer's own connection, which is the one purge runs on (§3.3): one\n * process appends *and* deletes, on one handle, with no second writable\n * connection and no cross-process barrier. `undefined` until the stream\n * loop's first reconcile creates the log, and again once the writer has\n * failed soft and deleted the file — both of which a purge cycle treats as\n * \"skip\", not as an error.\n */\n get connection(): Database | undefined {\n return this.#db;\n }\n\n /** Exposed for tests and for the integration assertions on the metrics. */\n state(): SQLiteChangeLogObservabilityState | undefined {\n return this.#observer?.state();\n }\n\n /**\n * Opens the log if necessary and reconciles it with the Postgres resume\n * point. Returns the resume point stored in the log.\n *\n * Returns `undefined` when the writer is disabled. The caller must then use\n * another source.\n *\n * This runs for every connection because Postgres supplies a new resume point\n * after each reconnect. The log can contain transactions above that point.\n * Reconciliation removes them before Postgres sends them again.\n *\n * `resumeFrom` includes cookies because the cookies must match the resume\n * watermark.\n */\n reconcile(\n resumeFrom: ChangeLogResumePoint,\n ): ChangeLogResumePoint | undefined {\n return this.#reconcile(() => resumeFrom);\n }\n\n /**\n * Reconciles the log without a Postgres resume point.\n *\n * A valid log uses its own head and cookies. A new or invalid log uses the\n * replica values returned by `seed`.\n */\n reconcileFromLog(\n seed: () => ChangeLogResumePoint,\n ): ChangeLogResumePoint | undefined {\n return this.#reconcile(db => this.#resumeFromLog(db, seed));\n }\n\n #reconcile(\n resolve: (db: Database) => ChangeLogResumePoint,\n ): ChangeLogResumePoint | undefined {\n if (this.#disabled) {\n return undefined;\n }\n const {replicaFile, identity} = this.#opts;\n const nowMs = this.#now();\n const anchor = (db: Database): ChangeLogAnchor => ({\n ...resolve(db),\n identity,\n nowMs,\n });\n try {\n const db = this.#db;\n if (db === undefined) {\n const opened = openChangeLogDBForWriting(this.#lc, replicaFile, anchor);\n this.#db = opened.db;\n if (opened.replacedFile) {\n this.#opts.onRebuilt?.();\n }\n recordSQLiteChangeLogReconcile(this.#lc, opened.result);\n const info = getSQLiteChangeLogInfo(opened.db);\n logSQLiteChangeLogStartup(\n this.#lc,\n changeLogFileName(replicaFile),\n info,\n );\n this.#observer = new SQLiteChangeLogObserver(this.#lc, info);\n } else {\n const resolved = anchor(db);\n let result: ReconcileResult;\n try {\n result = reconcileChangeLog(this.#lc, db, resolved, {\n rebuildInsteadOfUnboundedWork: true,\n });\n } catch (e) {\n if (!(e instanceof ChangeLogRebuildRequired)) {\n throw e;\n }\n // Close every handle to the old inode before unlinking it. The writer\n // is reconstructed below against the replacement connection.\n this.#writer = undefined;\n this.#db = undefined;\n db.close();\n this.#opts.onRebuilt?.();\n const rebuilt = rebuildChangeLogDBForWriting(\n this.#lc,\n replicaFile,\n resolved,\n e,\n );\n this.#db = rebuilt.db;\n result = rebuilt.result;\n }\n recordSQLiteChangeLogReconcile(this.#lc, result);\n if (result.action !== 'none') {\n this.#observer?.reconciled(\n getSQLiteChangeLogInfo(\n must(this.#db, 'the SQLite change log is not open'),\n ),\n );\n }\n }\n // A reseed drops and recreates the stream table, so the append statements\n // are prepared fresh against whatever the reconciliation left behind.\n const reconciledDB = must(this.#db, 'the SQLite change log is not open');\n this.#writer = new ChangeLogStreamWriter(\n new StatementRunner(reconciledDB),\n );\n // Read both values after reconciliation. A truncate or reseed updates the\n // head and cookies in the same transaction.\n return {\n resumeWatermark: must(\n readChangeLogHead(reconciledDB),\n 'the SQLite change log has no head after reconciliation',\n ),\n cookies: readCookies(reconciledDB),\n };\n } catch (e) {\n this.#failSoft('reconciling the SQLite change log', e);\n return undefined;\n }\n }\n\n /**\n * Returns the resume point supplied by the log.\n *\n * A valid log uses its own head and cookies. A log that must be recreated uses\n * the replica values returned by `seed`.\n */\n #resumeFromLog(\n db: Database,\n seed: () => ChangeLogResumePoint,\n ): ChangeLogResumePoint {\n if (changeLogWipeReason(db, this.#opts.identity) !== undefined) {\n return seed();\n }\n const head = readChangeLogHead(db);\n // An empty log has no resume point, so use the replica seed.\n return head === null\n ? seed()\n : {resumeWatermark: head, cookies: readCookies(db)};\n }\n\n /**\n * Writes one stream message, committing at transaction boundaries. Never\n * throws: a write failure disables the writer instead of failing the stream.\n */\n write(change: ChangeStreamData, json: string): void {\n const writer = this.#writer;\n const db = this.#db;\n if (this.#disabled || writer === undefined || db === undefined) {\n return;\n }\n const observer = this.#observer;\n observer?.messageReceived(change, json);\n const [type, msg] = change;\n const startedAt = performance.now();\n try {\n let commit: ChangeLogCommit | null = null;\n switch (type) {\n case 'begin':\n writer.begin(change[2].commitWatermark, json);\n break;\n case 'commit': {\n const {watermark} = change[2];\n const commitStart = performance.now();\n const stats = writer.commit(watermark, json, this.#now());\n commit = {\n watermark,\n stats,\n logCommitMs: performance.now() - commitStart,\n };\n break;\n }\n case 'rollback':\n writer.rollback();\n break;\n default:\n writer.append(json, msg);\n break;\n }\n observer?.messageProcessed(change, commit, performance.now() - startedAt);\n if (commit !== null && commit.stats.cookieMutations.length > 0) {\n // Only re-counted when a schema change actually moved the cookie jar,\n // which keeps the count off the forward path of every other\n // transaction. The counts are read after the commit, so they are what\n // a reader of the file would see.\n observer?.cookiesMutated(\n commit.stats.cookieMutations,\n readCookieRowCounts(db),\n );\n }\n if (commit !== null) {\n // The head advanced, and it is durable. Releasing the barrier here is\n // what makes its poll interval a backstop rather than the mechanism.\n this.#opts.onCommit?.(commit.watermark);\n }\n } catch (e) {\n observer?.messageFailed(change, e, performance.now() - startedAt);\n if (isConstraintViolation(e)) {\n // Reconciliation should have truncated whatever this collided with.\n // Report it as an invariant failure before failing soft, so that a\n // truncate-above bug cannot look like a lost cache.\n observer?.invariantFailure(\n 'SQLite change-log insert violated a constraint, which means a ' +\n 'transaction above the resume watermark was not truncated',\n {tag: msg.tag, error: String(e)},\n );\n }\n this.#failSoft('writing to the SQLite change log', e);\n }\n }\n\n /**\n * Discards the open transaction, if any. Called when the change stream is\n * interrupted mid-transaction.\n */\n abort(): void {\n const writer = this.#writer;\n if (this.#disabled || writer === undefined) {\n return;\n }\n this.#observer?.abort();\n try {\n writer.rollback();\n } catch (e) {\n this.#failSoft('rolling back the SQLite change log', e);\n }\n }\n\n close(): void {\n this.#disabled = true;\n this.#writer = undefined;\n this.#observer = undefined;\n const db = this.#db;\n this.#db = undefined;\n try {\n db?.close();\n } catch (e) {\n this.#lc.warn?.('error closing the SQLite change log', e);\n }\n }\n\n /**\n * Logs, disables the writer, deletes the file, and closes the reader, leaving\n * replication running. Disabling is for the life of the process: a log that\n * failed a write is not re-opened until the task restarts, so the behavior a\n * subscriber sees is the same as `sqliteChangeLogMode=off`.\n */\n #failSoft(what: string, e: unknown): void {\n const file = changeLogFileName(this.#opts.replicaFile);\n if (isSQLiteCorruption(e)) {\n // Open-time corruption is rebuilt by openChangeLogDBForWriting. Reaching\n // here means the file went bad under an open handle, which the same\n // delete-and-reseed answers -- on the next process start rather than now.\n logSQLiteCorruptionDiagnostics(this.#lc, 'change-log', file, e);\n }\n this.#lc.error?.(\n `error ${what}: disabling the writer and deleting ${file}. ` +\n `Replication continues; catchup reach is lost until this task restarts.`,\n e,\n );\n this.close();\n try {\n deleteChangeLogDB(this.#opts.replicaFile);\n } catch (deleteError) {\n this.#lc.error?.(`unable to delete ${file}`, deleteError);\n }\n this.#opts.onDisabled?.();\n }\n}\n\nfunction isConstraintViolation(e: unknown): boolean {\n return e instanceof SqliteError && e.code.startsWith('SQLITE_CONSTRAINT');\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"sqlite-change-log-writer.js","names":["#lc","#opts","#now","#shadowValidationPercent","#disabled","#db","#observer","#reconcile","#resumeFromLog","#writer","#failSoft","#validateTransaction","#isSelectedForShadowValidation"],"sources":["../../../../../../zero-cache/src/services/change-streamer/sqlite-change-log-writer.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {SqliteError} from '@rocicorp/zero-sqlite3';\nimport {assert} from '../../../../shared/src/asserts.ts';\nimport {h32} from '../../../../shared/src/hash.ts';\nimport {must} from '../../../../shared/src/must.ts';\nimport type {Database} from '../../../../zqlite/src/db.ts';\nimport {\n isSQLiteCorruption,\n logSQLiteCorruptionDiagnostics,\n} from '../../db/sqlite-corruption.ts';\nimport {StatementRunner} from '../../db/statements.ts';\nimport type {ChangeStreamData} from '../change-source/protocol/current/downstream.ts';\nimport {\n readCookieRowCounts,\n readCookies,\n} from '../replicator/change-log-cookies.ts';\nimport {\n ChangeLogRebuildRequired,\n changeLogFileName,\n changeLogWipeReason,\n deleteChangeLogDB,\n openChangeLogDBForWriting,\n readChangeLogHead,\n rebuildChangeLogDBForWriting,\n reconcileChangeLog,\n type ChangeLogAnchor,\n type ChangeLogIdentity,\n type ChangeLogResumePoint,\n type ReconcileResult,\n} from '../replicator/change-log-db.ts';\nimport {ChangeLogStreamWriter} from '../replicator/change-log-stream-writer.ts';\nimport {\n getSQLiteChangeLogInfo,\n logSQLiteChangeLogStartup,\n recordSQLiteChangeLogReconcile,\n SQLiteChangeLogObserver,\n type ChangeLogCommit,\n type SQLiteChangeLogObservabilityState,\n} from '../replicator/sqlite-change-log-observability.ts';\nimport {extractChangeSubstring} from './change-log-codec.ts';\n\nexport type SQLiteChangeLogWriterOptions = {\n /** The replica file the log is named after, i.e. `${replicaFile}-change-log`. */\n replicaFile: string;\n /** The replica whose contents this log belongs to. */\n identity: ChangeLogIdentity;\n /**\n * Called after each transaction's log commit, with the log's new head. This\n * is what releases the catchup barrier: after the writer moved in-process,\n * the head advances here rather than at a subscriber's ACK.\n */\n onCommit?: ((watermark: string) => void) | undefined;\n /**\n * Called when the writer disables itself and deletes the file. The reader is\n * cached on the service, so a delete that leaves it open would leave an\n * in-process reader serving an unlinked inode while every new open sees\n * nothing.\n */\n onDisabled?: (() => void) | undefined;\n /** Called when reconciliation replaces the file, to close cached readers. */\n onRebuilt?: (() => void) | undefined;\n /** Overridable for tests. */\n now?: (() => number) | undefined;\n /**\n * Percentage of transactions that retain the rollout-only per-message\n * timing and source-vs-stored hash validation. Defaults to 1.\n */\n shadowValidationPercent?: number | undefined;\n};\n\nconst DEFAULT_SHADOW_VALIDATION_PERCENT = 1;\n\n/**\n * Appends the canonical change stream to the SQLite change log, from the\n * change-streamer's own stream loop.\n *\n * ### Ordering\n *\n * The log's commit for a transaction precedes the forward of that transaction's\n * `commit` message, and nothing `await`s in between. Everything that can\n * advance the watermark the stream would resume from — the storer's Postgres\n * commit, `lastWatermark`, the upstream ACK — runs strictly after it, so the\n * log's head is always at or above the resume point. A *hole* is therefore\n * unreachable at any crash timing, and a *phantom* is the normal state, which is\n * what makes truncate-above the whole of reconciliation.\n *\n * ### Fail-soft\n *\n * The log is a catchup cache: nothing in it is not either already durable in the\n * replica's litestream backup or re-derivable from the replication slot. A write\n * failure must therefore not stop replication for the shard. Corruption is\n * rebuilt once at open; any other write error — a full disk, an I/O error, a\n * permissions problem — logs, disables the writer, deletes the file, closes the\n * reader, and lets the stream continue. The cost is catchup reach, and reach is\n * recoverable: `too-old` sends a subscriber to a restore.\n *\n * One carve-out keeps that from hiding the bug class this topology introduces. A\n * missed truncate-above surfaces as `SQLITE_CONSTRAINT` on the writer's plain\n * `INSERT`, which is \"any write error other than corruption\" and would be\n * absorbed quietly. It is counted as an invariant failure and alerted on before\n * failing soft.\n */\nexport class SQLiteChangeLogWriter {\n readonly #lc: LogContext;\n readonly #opts: SQLiteChangeLogWriterOptions;\n readonly #now: () => number;\n readonly #shadowValidationPercent: number;\n\n #db: Database | undefined;\n #writer: ChangeLogStreamWriter | undefined;\n #observer: SQLiteChangeLogObserver | undefined;\n #disabled = false;\n #validateTransaction = false;\n\n constructor(lc: LogContext, opts: SQLiteChangeLogWriterOptions) {\n this.#lc = lc.withContext('component', 'sqlite-change-log-writer');\n this.#opts = opts;\n this.#now = opts.now ?? Date.now;\n this.#shadowValidationPercent =\n opts.shadowValidationPercent ?? DEFAULT_SHADOW_VALIDATION_PERCENT;\n assert(\n Number.isInteger(this.#shadowValidationPercent) &&\n this.#shadowValidationPercent >= 0 &&\n this.#shadowValidationPercent <= 100,\n 'SQLite change-log shadow validation percentage must be an integer between 0 and 100',\n );\n }\n\n /** False once the writer has failed soft, or after {@link close}. */\n get enabled(): boolean {\n return !this.#disabled;\n }\n\n /**\n * The writer's own connection, which is the one purge runs on (§3.3): one\n * process appends *and* deletes, on one handle, with no second writable\n * connection and no cross-process barrier. `undefined` until the stream\n * loop's first reconcile creates the log, and again once the writer has\n * failed soft and deleted the file — both of which a purge cycle treats as\n * \"skip\", not as an error.\n */\n get connection(): Database | undefined {\n return this.#db;\n }\n\n /** Exposed for tests and for the integration assertions on the metrics. */\n state(): SQLiteChangeLogObservabilityState | undefined {\n return this.#observer?.state();\n }\n\n /**\n * Opens the log if necessary and reconciles it with the Postgres resume\n * point. Returns the resume point stored in the log.\n *\n * Returns `undefined` when the writer is disabled. The caller must then use\n * another source.\n *\n * This runs for every connection because Postgres supplies a new resume point\n * after each reconnect. The log can contain transactions above that point.\n * Reconciliation removes them before Postgres sends them again.\n *\n * `resumeFrom` includes cookies because the cookies must match the resume\n * watermark.\n */\n reconcile(\n resumeFrom: ChangeLogResumePoint,\n ): ChangeLogResumePoint | undefined {\n return this.#reconcile(() => resumeFrom);\n }\n\n /**\n * Reconciles the log without a Postgres resume point.\n *\n * A valid log uses its own head and cookies. A new or invalid log uses the\n * replica values returned by `seed`.\n */\n reconcileFromLog(\n seed: () => ChangeLogResumePoint,\n ): ChangeLogResumePoint | undefined {\n return this.#reconcile(db => this.#resumeFromLog(db, seed));\n }\n\n #reconcile(\n resolve: (db: Database) => ChangeLogResumePoint,\n ): ChangeLogResumePoint | undefined {\n if (this.#disabled) {\n return undefined;\n }\n const {replicaFile, identity} = this.#opts;\n const nowMs = this.#now();\n const anchor = (db: Database): ChangeLogAnchor => ({\n ...resolve(db),\n identity,\n nowMs,\n });\n try {\n const db = this.#db;\n if (db === undefined) {\n const opened = openChangeLogDBForWriting(this.#lc, replicaFile, anchor);\n this.#db = opened.db;\n if (opened.replacedFile) {\n this.#opts.onRebuilt?.();\n }\n recordSQLiteChangeLogReconcile(this.#lc, opened.result);\n const info = getSQLiteChangeLogInfo(opened.db);\n logSQLiteChangeLogStartup(\n this.#lc,\n changeLogFileName(replicaFile),\n info,\n );\n this.#observer = new SQLiteChangeLogObserver(this.#lc, info);\n } else {\n const resolved = anchor(db);\n let result: ReconcileResult;\n try {\n result = reconcileChangeLog(this.#lc, db, resolved, {\n rebuildInsteadOfUnboundedWork: true,\n });\n } catch (e) {\n if (!(e instanceof ChangeLogRebuildRequired)) {\n throw e;\n }\n // Close every handle to the old inode before unlinking it. The writer\n // is reconstructed below against the replacement connection.\n this.#writer = undefined;\n this.#db = undefined;\n db.close();\n this.#opts.onRebuilt?.();\n const rebuilt = rebuildChangeLogDBForWriting(\n this.#lc,\n replicaFile,\n resolved,\n e,\n );\n this.#db = rebuilt.db;\n result = rebuilt.result;\n }\n recordSQLiteChangeLogReconcile(this.#lc, result);\n if (result.action !== 'none') {\n this.#observer?.reconciled(\n getSQLiteChangeLogInfo(\n must(this.#db, 'the SQLite change log is not open'),\n ),\n );\n }\n }\n // A reseed drops and recreates the stream table, so the append statements\n // are prepared fresh against whatever the reconciliation left behind.\n const reconciledDB = must(this.#db, 'the SQLite change log is not open');\n this.#writer = new ChangeLogStreamWriter(\n new StatementRunner(reconciledDB),\n );\n // Read both values after reconciliation. A truncate or reseed updates the\n // head and cookies in the same transaction.\n return {\n resumeWatermark: must(\n readChangeLogHead(reconciledDB),\n 'the SQLite change log has no head after reconciliation',\n ),\n cookies: readCookies(reconciledDB),\n };\n } catch (e) {\n this.#failSoft('reconciling the SQLite change log', e);\n return undefined;\n }\n }\n\n /**\n * Returns the resume point supplied by the log.\n *\n * A valid log uses its own head and cookies. A log that must be recreated uses\n * the replica values returned by `seed`.\n */\n #resumeFromLog(\n db: Database,\n seed: () => ChangeLogResumePoint,\n ): ChangeLogResumePoint {\n if (changeLogWipeReason(db, this.#opts.identity) !== undefined) {\n return seed();\n }\n const head = readChangeLogHead(db);\n // An empty log has no resume point, so use the replica seed.\n return head === null\n ? seed()\n : {resumeWatermark: head, cookies: readCookies(db)};\n }\n\n /**\n * Writes one stream message, committing at transaction boundaries. Never\n * throws: a write failure disables the writer instead of failing the stream.\n */\n write(\n change: ChangeStreamData,\n json: string,\n storedChange = extractChangeSubstring(json, change[1].tag),\n ): void {\n const writer = this.#writer;\n const db = this.#db;\n if (this.#disabled || writer === undefined || db === undefined) {\n return;\n }\n const [type, msg] = change;\n if (type === 'begin') {\n this.#validateTransaction = this.#isSelectedForShadowValidation(\n change[2].commitWatermark,\n );\n }\n const validateTransaction = this.#validateTransaction;\n const observer = this.#observer;\n observer?.messageReceived(change, json, validateTransaction, storedChange);\n const startedAt = validateTransaction ? performance.now() : undefined;\n try {\n let commit: ChangeLogCommit | null = null;\n switch (type) {\n case 'begin':\n writer.begin(\n change[2].commitWatermark,\n json,\n storedChange,\n validateTransaction,\n );\n break;\n case 'commit': {\n const {watermark} = change[2];\n const commitStart = performance.now();\n const stats = writer.commit(\n watermark,\n json,\n this.#now(),\n storedChange,\n );\n commit = {\n watermark,\n stats,\n logCommitMs: performance.now() - commitStart,\n };\n break;\n }\n case 'rollback':\n writer.rollback();\n break;\n default:\n writer.append(json, msg, storedChange);\n break;\n }\n observer?.messageProcessed(\n change,\n commit,\n startedAt === undefined ? undefined : performance.now() - startedAt,\n );\n if (commit !== null && commit.stats.cookieMutations.length > 0) {\n // Only re-counted when a schema change actually moved the cookie jar,\n // which keeps the count off the forward path of every other\n // transaction. The counts are read after the commit, so they are what\n // a reader of the file would see.\n observer?.cookiesMutated(\n commit.stats.cookieMutations,\n readCookieRowCounts(db),\n );\n }\n if (commit !== null) {\n // The head advanced, and it is durable. Releasing the barrier here is\n // what makes its poll interval a backstop rather than the mechanism.\n this.#opts.onCommit?.(commit.watermark);\n }\n if (type === 'commit' || type === 'rollback') {\n this.#validateTransaction = false;\n }\n } catch (e) {\n observer?.messageFailed(\n change,\n e,\n startedAt === undefined ? undefined : performance.now() - startedAt,\n );\n this.#validateTransaction = false;\n if (isConstraintViolation(e)) {\n // Reconciliation should have truncated whatever this collided with.\n // Report it as an invariant failure before failing soft, so that a\n // truncate-above bug cannot look like a lost cache.\n observer?.invariantFailure(\n 'SQLite change-log insert violated a constraint, which means a ' +\n 'transaction above the resume watermark was not truncated',\n {tag: msg.tag, error: String(e)},\n );\n }\n this.#failSoft('writing to the SQLite change log', e);\n }\n }\n\n #isSelectedForShadowValidation(watermark: string): boolean {\n const percent = this.#shadowValidationPercent;\n return (\n percent >= 100 ||\n (percent > 0 &&\n h32(\n `${this.#opts.identity.generation}/${this.#opts.identity.replicaID ?? ''}:${watermark}`,\n ) %\n 100 <\n percent)\n );\n }\n\n /**\n * Discards the open transaction, if any. Called when the change stream is\n * interrupted mid-transaction.\n */\n abort(): void {\n const writer = this.#writer;\n this.#validateTransaction = false;\n if (this.#disabled || writer === undefined) {\n return;\n }\n this.#observer?.abort();\n try {\n writer.rollback();\n } catch (e) {\n this.#failSoft('rolling back the SQLite change log', e);\n }\n }\n\n close(): void {\n this.#disabled = true;\n this.#validateTransaction = false;\n this.#writer = undefined;\n this.#observer = undefined;\n const db = this.#db;\n this.#db = undefined;\n try {\n db?.close();\n } catch (e) {\n this.#lc.warn?.('error closing the SQLite change log', e);\n }\n }\n\n /**\n * Logs, disables the writer, deletes the file, and closes the reader, leaving\n * replication running. Disabling is for the life of the process: a log that\n * failed a write is not re-opened until the task restarts, so the behavior a\n * subscriber sees is the same as `sqliteChangeLogMode=off`.\n */\n #failSoft(what: string, e: unknown): void {\n const file = changeLogFileName(this.#opts.replicaFile);\n if (isSQLiteCorruption(e)) {\n // Open-time corruption is rebuilt by openChangeLogDBForWriting. Reaching\n // here means the file went bad under an open handle, which the same\n // delete-and-reseed answers -- on the next process start rather than now.\n logSQLiteCorruptionDiagnostics(this.#lc, 'change-log', file, e);\n }\n this.#lc.error?.(\n `error ${what}: disabling the writer and deleting ${file}. ` +\n `Replication continues; catchup reach is lost until this task restarts.`,\n e,\n );\n this.close();\n try {\n deleteChangeLogDB(this.#opts.replicaFile);\n } catch (deleteError) {\n this.#lc.error?.(`unable to delete ${file}`, deleteError);\n }\n this.#opts.onDisabled?.();\n }\n}\n\nfunction isConstraintViolation(e: unknown): boolean {\n return e instanceof SqliteError && e.code.startsWith('SQLITE_CONSTRAINT');\n}\n"],"mappings":"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"}