@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,6 +1,6 @@
1
1
  import { populateFromExistingTables } from "../../replicator/schema/column-metadata.js";
2
2
  import { listTables } from "../../../db/lite-tables.js";
3
- import { CREATE_BACKFILLING_TABLE, populateBackfillingFromColumnMetadata } from "../../replicator/schema/backfilling.js";
3
+ import { BACKFILLING_TABLE, populateBackfillingFromColumnMetadata } from "../../replicator/schema/backfilling.js";
4
4
  import { CREATE_RUNTIME_EVENTS_TABLE, recordEvent } from "../../replicator/schema/replication-state.js";
5
5
  import { isSQLiteCorruption, logSQLiteCorruptionDiagnostics } from "../../../db/sqlite-corruption.js";
6
6
  import { deleteLiteDB } from "../../../db/delete-lite-db.js";
@@ -70,6 +70,15 @@ var CREATE_V9_TABLE_METADATA_TABLE = `
70
70
  PRIMARY KEY ("schema", "table")
71
71
  );
72
72
  `;
73
+ var CREATE_V17_BACKFILLING_TABLE = `
74
+ CREATE TABLE "${BACKFILLING_TABLE}" (
75
+ "schema" TEXT NOT NULL,
76
+ "table" TEXT NOT NULL,
77
+ "column" TEXT NOT NULL,
78
+ "backfill" TEXT NOT NULL,
79
+ PRIMARY KEY ("schema", "table", "column")
80
+ );
81
+ `;
73
82
  var V14_CHANGE_LOG_STREAM_TABLE = "_zero.changeLogStream";
74
83
  var V14_CHANGE_LOG_STREAM_WRITE_TIME_INDEX = "_zero.changeLogStream_writeTimeMs";
75
84
  `${V14_CHANGE_LOG_STREAM_TABLE}${V14_CHANGE_LOG_STREAM_WRITE_TIME_INDEX}${V14_CHANGE_LOG_STREAM_TABLE}`;
@@ -181,12 +190,15 @@ var schemaVersionMigrationMap = {
181
190
  } },
182
191
  17: {
183
192
  migrateSchema: (_, db) => {
184
- db.exec(CREATE_BACKFILLING_TABLE);
193
+ db.exec(CREATE_V17_BACKFILLING_TABLE);
185
194
  },
186
195
  migrateData: (lc, db) => {
187
196
  populateBackfillingFromColumnMetadata(lc, db);
188
197
  }
189
- }
198
+ },
199
+ 18: { migrateSchema: (_, db) => {
200
+ db.exec(`ALTER TABLE "${BACKFILLING_TABLE}" ADD COLUMN "progress" TEXT`);
201
+ } }
190
202
  };
191
203
  Object.keys(schemaVersionMigrationMap).reduce((prev, curr) => Math.max(prev, parseInt(curr)), 0);
192
204
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"replica-schema.js","names":[],"sources":["../../../../../../../zero-cache/src/services/change-source/common/replica-schema.ts"],"sourcesContent":["import {existsSync, renameSync} from 'node:fs';\nimport type {LogContext} from '@rocicorp/logger';\nimport type {Database} from '../../../../../zqlite/src/db.ts';\nimport {deleteLiteDB} from '../../../db/delete-lite-db.ts';\nimport {listTables} from '../../../db/lite-tables.ts';\nimport {\n runSchemaMigrations,\n type IncrementalMigrationMap,\n type Migration,\n} from '../../../db/migration-lite.ts';\nimport {\n isSQLiteCorruption,\n logSQLiteCorruptionDiagnostics,\n} from '../../../db/sqlite-corruption.ts';\nimport {AutoResetSignal} from '../../change-streamer/schema/tables.ts';\nimport {\n CREATE_BACKFILLING_TABLE,\n populateBackfillingFromColumnMetadata,\n} from '../../replicator/schema/backfilling.ts';\nimport {populateFromExistingTables} from '../../replicator/schema/column-metadata.ts';\nimport {\n CREATE_RUNTIME_EVENTS_TABLE,\n recordEvent,\n} from '../../replicator/schema/replication-state.ts';\n\nexport async function initReplica(\n log: LogContext,\n debugName: string,\n dbPath: string,\n initialSync: (lc: LogContext, tx: Database) => Promise<void>,\n): Promise<void> {\n const isInitialSync = !existsSync(dbPath);\n const migrationPath = isInitialSync ? `${dbPath}.tmp` : dbPath;\n if (isInitialSync) {\n deleteLiteDB(migrationPath);\n }\n\n const setupMigration: Migration = {\n migrateSchema: (log, tx) => initialSync(log, tx),\n minSafeVersion: 1,\n };\n\n try {\n await runSchemaMigrations(\n log,\n debugName,\n migrationPath,\n setupMigration,\n schemaVersionMigrationMap,\n );\n if (isInitialSync) {\n renameSync(migrationPath, dbPath);\n }\n } catch (e) {\n throwAutoResetForCorruption(log, debugName, migrationPath, e);\n }\n}\n\nexport async function upgradeReplica(\n log: LogContext,\n debugName: string,\n dbPath: string,\n) {\n try {\n await runSchemaMigrations(\n log,\n debugName,\n dbPath,\n // setupMigration should never be invoked\n {\n migrateSchema: () => {\n throw new Error(\n 'This should only be called for already synced replicas',\n );\n },\n },\n schemaVersionMigrationMap,\n );\n } catch (e) {\n throwAutoResetForCorruption(log, debugName, dbPath, e);\n }\n}\n\nfunction throwAutoResetForCorruption(\n log: LogContext,\n debugName: string,\n dbPath: string,\n e: unknown,\n): never {\n if (isSQLiteCorruption(e)) {\n logSQLiteCorruptionDiagnostics(log, debugName, dbPath, e);\n throw new AutoResetSignal(\n `replica database appears corrupt: ${String(e)}`,\n {cause: e},\n );\n }\n throw e;\n}\n\nexport const CREATE_V6_COLUMN_METADATA_TABLE = /*sql*/ `\n CREATE TABLE \"_zero.column_metadata\" (\n table_name TEXT NOT NULL,\n column_name TEXT NOT NULL,\n upstream_type TEXT NOT NULL,\n is_not_null INTEGER NOT NULL,\n is_enum INTEGER NOT NULL,\n is_array INTEGER NOT NULL,\n character_max_length INTEGER,\n PRIMARY KEY (table_name, column_name)\n );\n`;\n\nexport const CREATE_V7_CHANGE_LOG = /*sql*/ `\n CREATE TABLE \"_zero.changeLog2\" (\n \"stateVersion\" TEXT NOT NULL,\n \"pos\" INT NOT NULL,\n \"table\" TEXT NOT NULL,\n \"rowKey\" TEXT NOT NULL,\n \"op\" TEXT NOT NULL,\n PRIMARY KEY(\"stateVersion\", \"pos\"),\n UNIQUE(\"table\", \"rowKey\")\n );\n`;\n\nexport const CREATE_V9_TABLE_METADATA_TABLE = /*sql*/ `\n CREATE TABLE \"_zero.tableMetadata\" (\n \"schema\" TEXT NOT NULL,\n \"table\" TEXT NOT NULL,\n \"metadata\" TEXT NOT NULL,\n PRIMARY KEY (\"schema\", \"table\")\n );\n`;\n\n// Deliberately shadows the same names in `replicator/change-log-db.ts`: these\n// describe replica files created by pre-release v14 builds, while that module\n// describes the separate change-log database. The two are frozen apart.\nexport const V14_CHANGE_LOG_STREAM_TABLE = '_zero.changeLogStream';\nconst V14_CHANGE_LOG_STREAM_WRITE_TIME_INDEX =\n '_zero.changeLogStream_writeTimeMs';\n\n// The change-log stream table created by pre-release v14 builds and dropped by\n// migration 16. Retained at its old shape for migration tests only.\nexport const CREATE_V14_CHANGE_LOG_STREAM = /*sql*/ `\n CREATE TABLE \"${V14_CHANGE_LOG_STREAM_TABLE}\" (\n \"watermark\" TEXT NOT NULL,\n \"pos\" INTEGER NOT NULL,\n \"change\" TEXT NOT NULL,\n \"precommit\" TEXT,\n \"writeTimeMs\" INTEGER,\n PRIMARY KEY (\"watermark\", \"pos\")\n );\n\n CREATE INDEX \"${V14_CHANGE_LOG_STREAM_WRITE_TIME_INDEX}\"\n ON \"${V14_CHANGE_LOG_STREAM_TABLE}\" (\"writeTimeMs\", \"watermark\")\n WHERE \"writeTimeMs\" IS NOT NULL;\n`;\n\nexport const schemaVersionMigrationMap: IncrementalMigrationMap = {\n // There's no incremental migration from v1. Just reset the replica.\n 4: {\n migrateSchema: () => {\n throw new AutoResetSignal('upgrading replica to new schema');\n },\n minSafeVersion: 3,\n },\n\n 5: {\n migrateSchema: (_, db) => {\n db.exec(CREATE_RUNTIME_EVENTS_TABLE);\n },\n migrateData: (_, db) => {\n recordEvent(db, 'upgrade');\n },\n },\n\n // Revised in the migration to v8 because the v6 code was incomplete.\n 6: {},\n\n 7: {\n migrateSchema: (_, db) => {\n // Note: The original \"changeLog\" table is kept so that the replica file\n // is compatible with older zero-caches. However, it is truncated for\n // space savings (since historic changes were never read).\n db.exec(`DELETE FROM \"_zero.changeLog\"`);\n // First version of changeLog2\n db.exec(CREATE_V7_CHANGE_LOG);\n },\n },\n\n 8: {\n migrateSchema: (_, db) => {\n const tableExists = db\n .prepare(\n `SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = '_zero.column_metadata'`,\n )\n .get();\n\n if (!tableExists) {\n db.exec(CREATE_V6_COLUMN_METADATA_TABLE);\n }\n },\n migrateData: (_, db) => {\n // Re-populate the ColumnMetadataStore; the original migration\n // at v6 was incomplete, as covered replicas migrated from earlier\n // versions but did not initialize the table for new replicas.\n db.exec(/*sql*/ `DELETE FROM \"_zero.column_metadata\"`);\n\n const tables = listTables(db, false, false);\n populateFromExistingTables(db, tables);\n },\n },\n\n 9: {\n migrateSchema: (_, db) => {\n db.exec(\n /*sql*/ `\n ALTER TABLE \"_zero.changeLog2\" \n ADD COLUMN \"backfillingColumnVersions\" TEXT DEFAULT '{}';\n ALTER TABLE \"_zero.column_metadata\"\n ADD COLUMN backfill TEXT;\n ` + CREATE_V9_TABLE_METADATA_TABLE,\n );\n },\n },\n\n 10: {\n migrateSchema: (_, db) => {\n db.exec(/*sql*/ `\n ALTER TABLE \"_zero.replicationConfig\" \n ADD COLUMN \"initialSyncContext\" TEXT DEFAULT '{}';\n `);\n },\n },\n\n 11: {\n migrateSchema: (_, db) => {\n db.exec(/*sql*/ `\n ALTER TABLE \"_zero.tableMetadata\"\n ADD COLUMN \"minRowVersion\" TEXT NOT NULL DEFAULT '00';\n\n -- Removing the NOT NULL constraint from \"metadata\" requires copying\n -- the column. We piggyback the rename to \"upstreamMetadata\" here.\n ALTER TABLE \"_zero.tableMetadata\"\n ADD COLUMN \"upstreamMetadata\" TEXT;\n UPDATE \"_zero.tableMetadata\" SET \"upstreamMetadata\" = \"metadata\";\n ALTER TABLE \"_zero.tableMetadata\" DROP \"metadata\";\n `);\n },\n },\n\n 12: {\n migrateSchema: (_, db) => {\n // Bring back the \"metadata\" column removed in v11, but as a NULL-able column.\n // It is needed for backwards compatibility.\n db.exec(/*sql*/ `\n ALTER TABLE \"_zero.tableMetadata\"\n ADD COLUMN \"metadata\" TEXT;\n `);\n },\n\n migrateData: (_, db) => {\n // For rollback then roll forward, re-copy anything written to metadata.\n db.exec(/*sql*/ `\n UPDATE \"_zero.tableMetadata\" \n SET \"upstreamMetadata\" = COALESCE(\"metadata\", \"upstreamMetadata\"),\n \"metadata\" = NULL;\n `);\n },\n },\n\n 13: {\n migrateSchema: (_, db) => {\n db.exec(/*sql*/ `\n ALTER TABLE \"_zero.replicationState\" ADD COLUMN writeTimeMs INTEGER;\n `);\n },\n\n migrateData: (_, db) => {\n db.exec(/*sql*/ `\n UPDATE \"_zero.replicationState\" \n SET writeTimeMs = COALESCE(writeTimeMs, unixepoch('subsec') * 1000)`);\n },\n },\n\n // The replica-local change log moved to its own database before v14 shipped.\n 14: {},\n\n 15: {\n migrateSchema: (_, db) => {\n // Make writeTimeMs NOT NULL. In SQLite the only way to do this is to\n // create a new table, copy the data over, delete the old table, and\n // rename. This is cheap because it's a single row table.\n db.exec(/*sql*/ `\n CREATE TABLE \"_zero.replicationState2\" (\n stateVersion TEXT NOT NULL,\n writeTimeMs INTEGER NOT NULL,\n lock INTEGER PRIMARY KEY DEFAULT 1 CHECK (lock=1)\n );\n\n INSERT INTO \"_zero.replicationState2\" (stateVersion, writeTimeMs, lock)\n SELECT stateVersion, writeTimeMs, lock FROM \"_zero.replicationState\";\n\n DROP TABLE \"_zero.replicationState\";\n\n ALTER TABLE \"_zero.replicationState2\" RENAME TO \"_zero.replicationState\";\n `);\n },\n },\n\n // The change log moved out of the replica and into its own database\n // (`${replicaFile}-change-log`), so the replica's copy is dead weight in\n // every file the backup ships and every follower downloads. Nothing reads it\n // as of this version.\n //\n // `IF EXISTS` because fresh and post-v13 replicas never create this table.\n // Pre-release v14 builds did, so keep their cleanup idempotent.\n //\n // The freed pages are reclaimed by the existing `vacuumIntervalHours`\n // trigger in `workers/replicator.ts`; no special handling here.\n //\n // No `minSafeVersion`: an older zero-cache still runs against a v16 replica,\n // and with `sqliteChangeLogMode=off` (the default) it never looks for this\n // table. Bumping the rollback limit would turn every rollback into a hard\n // startup failure to protect a configuration that is not enabled anywhere.\n 16: {\n migrateSchema: (_, db) => {\n db.exec(/*sql*/ `\n DROP INDEX IF EXISTS \"${V14_CHANGE_LOG_STREAM_WRITE_TIME_INDEX}\";\n DROP TABLE IF EXISTS \"${V14_CHANGE_LOG_STREAM_TABLE}\";\n `);\n },\n },\n\n // `_zero.column_metadata.backfill` records which columns are backfilling but\n // is keyed by lite table name, which has no inverse: it cannot be turned back\n // into the `BackfillRequest`s that a change log initialized from this replica\n // would have to send. This table carries the upstream identity alongside the\n // same state. See `replicator/schema/backfilling.ts`.\n //\n // No `minSafeVersion`: an older zero-cache runs fine against a v17 replica,\n // since nothing at v16 reads the new table. Its writes to\n // `column_metadata.backfill` are what `migrateData` rebuilds from when rolling\n // forward again, so a rollback costs nothing but the re-seed.\n 17: {\n migrateSchema: (_, db) => {\n db.exec(CREATE_BACKFILLING_TABLE);\n },\n\n migrateData: (lc, db) => {\n populateBackfillingFromColumnMetadata(lc, db);\n },\n },\n};\n\n// Referenced in tests.\nexport const CURRENT_SCHEMA_VERSION = Object.keys(\n schemaVersionMigrationMap,\n).reduce((prev, curr) => Math.max(prev, parseInt(curr)), 0);\n"],"mappings":"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"}
1
+ {"version":3,"file":"replica-schema.js","names":[],"sources":["../../../../../../../zero-cache/src/services/change-source/common/replica-schema.ts"],"sourcesContent":["import {existsSync, renameSync} from 'node:fs';\nimport type {LogContext} from '@rocicorp/logger';\nimport type {Database} from '../../../../../zqlite/src/db.ts';\nimport {deleteLiteDB} from '../../../db/delete-lite-db.ts';\nimport {listTables} from '../../../db/lite-tables.ts';\nimport {\n runSchemaMigrations,\n type IncrementalMigrationMap,\n type Migration,\n} from '../../../db/migration-lite.ts';\nimport {\n isSQLiteCorruption,\n logSQLiteCorruptionDiagnostics,\n} from '../../../db/sqlite-corruption.ts';\nimport {AutoResetSignal} from '../../change-streamer/schema/tables.ts';\nimport {\n BACKFILLING_TABLE,\n populateBackfillingFromColumnMetadata,\n} from '../../replicator/schema/backfilling.ts';\nimport {populateFromExistingTables} from '../../replicator/schema/column-metadata.ts';\nimport {\n CREATE_RUNTIME_EVENTS_TABLE,\n recordEvent,\n} from '../../replicator/schema/replication-state.ts';\n\nexport async function initReplica(\n log: LogContext,\n debugName: string,\n dbPath: string,\n initialSync: (lc: LogContext, tx: Database) => Promise<void>,\n): Promise<void> {\n const isInitialSync = !existsSync(dbPath);\n const migrationPath = isInitialSync ? `${dbPath}.tmp` : dbPath;\n if (isInitialSync) {\n deleteLiteDB(migrationPath);\n }\n\n const setupMigration: Migration = {\n migrateSchema: (log, tx) => initialSync(log, tx),\n minSafeVersion: 1,\n };\n\n try {\n await runSchemaMigrations(\n log,\n debugName,\n migrationPath,\n setupMigration,\n schemaVersionMigrationMap,\n );\n if (isInitialSync) {\n renameSync(migrationPath, dbPath);\n }\n } catch (e) {\n throwAutoResetForCorruption(log, debugName, migrationPath, e);\n }\n}\n\nexport async function upgradeReplica(\n log: LogContext,\n debugName: string,\n dbPath: string,\n) {\n try {\n await runSchemaMigrations(\n log,\n debugName,\n dbPath,\n // setupMigration should never be invoked\n {\n migrateSchema: () => {\n throw new Error(\n 'This should only be called for already synced replicas',\n );\n },\n },\n schemaVersionMigrationMap,\n );\n } catch (e) {\n throwAutoResetForCorruption(log, debugName, dbPath, e);\n }\n}\n\nfunction throwAutoResetForCorruption(\n log: LogContext,\n debugName: string,\n dbPath: string,\n e: unknown,\n): never {\n if (isSQLiteCorruption(e)) {\n logSQLiteCorruptionDiagnostics(log, debugName, dbPath, e);\n throw new AutoResetSignal(\n `replica database appears corrupt: ${String(e)}`,\n {cause: e},\n );\n }\n throw e;\n}\n\nexport const CREATE_V6_COLUMN_METADATA_TABLE = /*sql*/ `\n CREATE TABLE \"_zero.column_metadata\" (\n table_name TEXT NOT NULL,\n column_name TEXT NOT NULL,\n upstream_type TEXT NOT NULL,\n is_not_null INTEGER NOT NULL,\n is_enum INTEGER NOT NULL,\n is_array INTEGER NOT NULL,\n character_max_length INTEGER,\n PRIMARY KEY (table_name, column_name)\n );\n`;\n\nexport const CREATE_V7_CHANGE_LOG = /*sql*/ `\n CREATE TABLE \"_zero.changeLog2\" (\n \"stateVersion\" TEXT NOT NULL,\n \"pos\" INT NOT NULL,\n \"table\" TEXT NOT NULL,\n \"rowKey\" TEXT NOT NULL,\n \"op\" TEXT NOT NULL,\n PRIMARY KEY(\"stateVersion\", \"pos\"),\n UNIQUE(\"table\", \"rowKey\")\n );\n`;\n\nexport const CREATE_V9_TABLE_METADATA_TABLE = /*sql*/ `\n CREATE TABLE \"_zero.tableMetadata\" (\n \"schema\" TEXT NOT NULL,\n \"table\" TEXT NOT NULL,\n \"metadata\" TEXT NOT NULL,\n PRIMARY KEY (\"schema\", \"table\")\n );\n`;\n\nexport const CREATE_V17_BACKFILLING_TABLE = /*sql*/ `\n CREATE TABLE \"${BACKFILLING_TABLE}\" (\n \"schema\" TEXT NOT NULL,\n \"table\" TEXT NOT NULL,\n \"column\" TEXT NOT NULL,\n \"backfill\" TEXT NOT NULL,\n PRIMARY KEY (\"schema\", \"table\", \"column\")\n );\n`;\n\n// Deliberately shadows the same names in `replicator/change-log-db.ts`: these\n// describe replica files created by pre-release v14 builds, while that module\n// describes the separate change-log database. The two are frozen apart.\nexport const V14_CHANGE_LOG_STREAM_TABLE = '_zero.changeLogStream';\nconst V14_CHANGE_LOG_STREAM_WRITE_TIME_INDEX =\n '_zero.changeLogStream_writeTimeMs';\n\n// The change-log stream table created by pre-release v14 builds and dropped by\n// migration 16. Retained at its old shape for migration tests only.\nexport const CREATE_V14_CHANGE_LOG_STREAM = /*sql*/ `\n CREATE TABLE \"${V14_CHANGE_LOG_STREAM_TABLE}\" (\n \"watermark\" TEXT NOT NULL,\n \"pos\" INTEGER NOT NULL,\n \"change\" TEXT NOT NULL,\n \"precommit\" TEXT,\n \"writeTimeMs\" INTEGER,\n PRIMARY KEY (\"watermark\", \"pos\")\n );\n\n CREATE INDEX \"${V14_CHANGE_LOG_STREAM_WRITE_TIME_INDEX}\"\n ON \"${V14_CHANGE_LOG_STREAM_TABLE}\" (\"writeTimeMs\", \"watermark\")\n WHERE \"writeTimeMs\" IS NOT NULL;\n`;\n\nexport const schemaVersionMigrationMap: IncrementalMigrationMap = {\n // There's no incremental migration from v1. Just reset the replica.\n 4: {\n migrateSchema: () => {\n throw new AutoResetSignal('upgrading replica to new schema');\n },\n minSafeVersion: 3,\n },\n\n 5: {\n migrateSchema: (_, db) => {\n db.exec(CREATE_RUNTIME_EVENTS_TABLE);\n },\n migrateData: (_, db) => {\n recordEvent(db, 'upgrade');\n },\n },\n\n // Revised in the migration to v8 because the v6 code was incomplete.\n 6: {},\n\n 7: {\n migrateSchema: (_, db) => {\n // Note: The original \"changeLog\" table is kept so that the replica file\n // is compatible with older zero-caches. However, it is truncated for\n // space savings (since historic changes were never read).\n db.exec(`DELETE FROM \"_zero.changeLog\"`);\n // First version of changeLog2\n db.exec(CREATE_V7_CHANGE_LOG);\n },\n },\n\n 8: {\n migrateSchema: (_, db) => {\n const tableExists = db\n .prepare(\n `SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = '_zero.column_metadata'`,\n )\n .get();\n\n if (!tableExists) {\n db.exec(CREATE_V6_COLUMN_METADATA_TABLE);\n }\n },\n migrateData: (_, db) => {\n // Re-populate the ColumnMetadataStore; the original migration\n // at v6 was incomplete, as covered replicas migrated from earlier\n // versions but did not initialize the table for new replicas.\n db.exec(/*sql*/ `DELETE FROM \"_zero.column_metadata\"`);\n\n const tables = listTables(db, false, false);\n populateFromExistingTables(db, tables);\n },\n },\n\n 9: {\n migrateSchema: (_, db) => {\n db.exec(\n /*sql*/ `\n ALTER TABLE \"_zero.changeLog2\" \n ADD COLUMN \"backfillingColumnVersions\" TEXT DEFAULT '{}';\n ALTER TABLE \"_zero.column_metadata\"\n ADD COLUMN backfill TEXT;\n ` + CREATE_V9_TABLE_METADATA_TABLE,\n );\n },\n },\n\n 10: {\n migrateSchema: (_, db) => {\n db.exec(/*sql*/ `\n ALTER TABLE \"_zero.replicationConfig\" \n ADD COLUMN \"initialSyncContext\" TEXT DEFAULT '{}';\n `);\n },\n },\n\n 11: {\n migrateSchema: (_, db) => {\n db.exec(/*sql*/ `\n ALTER TABLE \"_zero.tableMetadata\"\n ADD COLUMN \"minRowVersion\" TEXT NOT NULL DEFAULT '00';\n\n -- Removing the NOT NULL constraint from \"metadata\" requires copying\n -- the column. We piggyback the rename to \"upstreamMetadata\" here.\n ALTER TABLE \"_zero.tableMetadata\"\n ADD COLUMN \"upstreamMetadata\" TEXT;\n UPDATE \"_zero.tableMetadata\" SET \"upstreamMetadata\" = \"metadata\";\n ALTER TABLE \"_zero.tableMetadata\" DROP \"metadata\";\n `);\n },\n },\n\n 12: {\n migrateSchema: (_, db) => {\n // Bring back the \"metadata\" column removed in v11, but as a NULL-able column.\n // It is needed for backwards compatibility.\n db.exec(/*sql*/ `\n ALTER TABLE \"_zero.tableMetadata\"\n ADD COLUMN \"metadata\" TEXT;\n `);\n },\n\n migrateData: (_, db) => {\n // For rollback then roll forward, re-copy anything written to metadata.\n db.exec(/*sql*/ `\n UPDATE \"_zero.tableMetadata\" \n SET \"upstreamMetadata\" = COALESCE(\"metadata\", \"upstreamMetadata\"),\n \"metadata\" = NULL;\n `);\n },\n },\n\n 13: {\n migrateSchema: (_, db) => {\n db.exec(/*sql*/ `\n ALTER TABLE \"_zero.replicationState\" ADD COLUMN writeTimeMs INTEGER;\n `);\n },\n\n migrateData: (_, db) => {\n db.exec(/*sql*/ `\n UPDATE \"_zero.replicationState\" \n SET writeTimeMs = COALESCE(writeTimeMs, unixepoch('subsec') * 1000)`);\n },\n },\n\n // The replica-local change log moved to its own database before v14 shipped.\n 14: {},\n\n 15: {\n migrateSchema: (_, db) => {\n // Make writeTimeMs NOT NULL. In SQLite the only way to do this is to\n // create a new table, copy the data over, delete the old table, and\n // rename. This is cheap because it's a single row table.\n db.exec(/*sql*/ `\n CREATE TABLE \"_zero.replicationState2\" (\n stateVersion TEXT NOT NULL,\n writeTimeMs INTEGER NOT NULL,\n lock INTEGER PRIMARY KEY DEFAULT 1 CHECK (lock=1)\n );\n\n INSERT INTO \"_zero.replicationState2\" (stateVersion, writeTimeMs, lock)\n SELECT stateVersion, writeTimeMs, lock FROM \"_zero.replicationState\";\n\n DROP TABLE \"_zero.replicationState\";\n\n ALTER TABLE \"_zero.replicationState2\" RENAME TO \"_zero.replicationState\";\n `);\n },\n },\n\n // The change log moved out of the replica and into its own database\n // (`${replicaFile}-change-log`), so the replica's copy is dead weight in\n // every file the backup ships and every follower downloads. Nothing reads it\n // as of this version.\n //\n // `IF EXISTS` because fresh and post-v13 replicas never create this table.\n // Pre-release v14 builds did, so keep their cleanup idempotent.\n //\n // The freed pages are reclaimed by the existing `vacuumIntervalHours`\n // trigger in `workers/replicator.ts`; no special handling here.\n //\n // No `minSafeVersion`: an older zero-cache still runs against a v16 replica,\n // and with `sqliteChangeLogMode=off` (the default) it never looks for this\n // table. Bumping the rollback limit would turn every rollback into a hard\n // startup failure to protect a configuration that is not enabled anywhere.\n 16: {\n migrateSchema: (_, db) => {\n db.exec(/*sql*/ `\n DROP INDEX IF EXISTS \"${V14_CHANGE_LOG_STREAM_WRITE_TIME_INDEX}\";\n DROP TABLE IF EXISTS \"${V14_CHANGE_LOG_STREAM_TABLE}\";\n `);\n },\n },\n\n // `_zero.column_metadata.backfill` records which columns are backfilling but\n // is keyed by lite table name, which has no inverse: it cannot be turned back\n // into the `BackfillRequest`s that a change log initialized from this replica\n // would have to send. This table carries the upstream identity alongside the\n // same state. See `replicator/schema/backfilling.ts`.\n //\n // No `minSafeVersion`: an older zero-cache runs fine against a v17 replica,\n // since nothing at v16 reads the new table. Its writes to\n // `column_metadata.backfill` are what `migrateData` rebuilds from when rolling\n // forward again, so a rollback costs nothing but the re-seed.\n 17: {\n migrateSchema: (_, db) => {\n db.exec(CREATE_V17_BACKFILLING_TABLE);\n },\n\n migrateData: (lc, db) => {\n populateBackfillingFromColumnMetadata(lc, db);\n },\n },\n\n // Adds `_zero.backfilling.progress`, with which the replica tracks the\n // progress of its pending backfills and reports it to the change-streamer\n // (protocol v8).\n //\n // No `minSafeVersion`: an older zero-cache ignores the column (its writes\n // name their columns explicitly), and a `progress` left stale by one is at\n // or before the actual progress, which only results in redundant backfill.\n 18: {\n migrateSchema: (_, db) => {\n db.exec(\n /*sql*/ `ALTER TABLE \"${BACKFILLING_TABLE}\" ADD COLUMN \"progress\" TEXT`,\n );\n },\n },\n};\n\n// Referenced in tests.\nexport const CURRENT_SCHEMA_VERSION = Object.keys(\n schemaVersionMigrationMap,\n).reduce((prev, curr) => Math.max(prev, parseInt(curr)), 0);\n"],"mappings":";;;;;;;;;;AAyBA,eAAsB,YACpB,KACA,WACA,QACA,aACe;CACf,MAAM,gBAAgB,CAAC,WAAW,MAAM;CACxC,MAAM,gBAAgB,gBAAgB,GAAG,OAAO,QAAQ;CACxD,IAAI,eACF,aAAa,aAAa;CAG5B,MAAM,iBAA4B;EAChC,gBAAgB,KAAK,OAAO,YAAY,KAAK,EAAE;EAC/C,gBAAgB;CAClB;CAEA,IAAI;EACF,MAAM,oBACJ,KACA,WACA,eACA,gBACA,yBACF;EACA,IAAI,eACF,WAAW,eAAe,MAAM;CAEpC,SAAS,GAAG;EACV,4BAA4B,KAAK,WAAW,eAAe,CAAC;CAC9D;AACF;AAEA,eAAsB,eACpB,KACA,WACA,QACA;CACA,IAAI;EACF,MAAM,oBACJ,KACA,WACA,QAEA,EACE,qBAAqB;GACnB,MAAM,IAAI,MACR,wDACF;EACF,EACF,GACA,yBACF;CACF,SAAS,GAAG;EACV,4BAA4B,KAAK,WAAW,QAAQ,CAAC;CACvD;AACF;AAEA,SAAS,4BACP,KACA,WACA,QACA,GACO;CACP,IAAI,mBAAmB,CAAC,GAAG;EACzB,+BAA+B,KAAK,WAAW,QAAQ,CAAC;EACxD,MAAM,IAAI,gBACR,qCAAqC,OAAO,CAAC,KAC7C,EAAC,OAAO,EAAC,CACX;CACF;CACA,MAAM;AACR;AAEA,IAAa,kCAA0C;;;;;;;;;;;;AAavD,IAAa,uBAA+B;;;;;;;;;;;AAY5C,IAAa,iCAAyC;;;;;;;;AAStD,IAAa,+BAAuC;kBAClC,kBAAkB;;;;;;;;AAYpC,IAAa,8BAA8B;AAC3C,IAAM,yCACJ;AAIkD,GAClC,4BADkC,EAUlC,uCAVkC,EAW1C,4BAX0C;AAepD,IAAa,4BAAqD;CAEhE,GAAG;EACD,qBAAqB;GACnB,MAAM,IAAI,gBAAgB,iCAAiC;EAC7D;EACA,gBAAgB;CAClB;CAEA,GAAG;EACD,gBAAgB,GAAG,OAAO;GACxB,GAAG,KAAK,2BAA2B;EACrC;EACA,cAAc,GAAG,OAAO;GACtB,YAAY,IAAI,SAAS;EAC3B;CACF;CAGA,GAAG,CAAC;CAEJ,GAAG,EACD,gBAAgB,GAAG,OAAO;EAIxB,GAAG,KAAK,+BAA+B;EAEvC,GAAG,KAAK,oBAAoB;CAC9B,EACF;CAEA,GAAG;EACD,gBAAgB,GAAG,OAAO;GAOxB,IAAI,CANgB,GACjB,QACC,qFACF,EACC,IAEE,GACH,GAAG,KAAK,+BAA+B;EAE3C;EACA,cAAc,GAAG,OAAO;GAItB,GAAG,KAAa,qCAAqC;GAGrD,2BAA2B,IADZ,WAAW,IAAI,OAAO,KACN,CAAM;EACvC;CACF;CAEA,GAAG,EACD,gBAAgB,GAAG,OAAO;EACxB,GAAG,KACO;;;;;UAKN,8BACJ;CACF,EACF;CAEA,IAAI,EACF,gBAAgB,GAAG,OAAO;EACxB,GAAG,KAAa;;;OAGf;CACH,EACF;CAEA,IAAI,EACF,gBAAgB,GAAG,OAAO;EACxB,GAAG,KAAa;;;;;;;;;;OAUf;CACH,EACF;CAEA,IAAI;EACF,gBAAgB,GAAG,OAAO;GAGxB,GAAG,KAAa;;;OAGf;EACH;EAEA,cAAc,GAAG,OAAO;GAEtB,GAAG,KAAa;;;;OAIf;EACH;CACF;CAEA,IAAI;EACF,gBAAgB,GAAG,OAAO;GACxB,GAAG,KAAa;;OAEf;EACH;EAEA,cAAc,GAAG,OAAO;GACtB,GAAG,KAAa;;8EAEwD;EAC1E;CACF;CAGA,IAAI,CAAC;CAEL,IAAI,EACF,gBAAgB,GAAG,OAAO;EAIxB,GAAG,KAAa;;;;;;;;;;;;;OAaf;CACH,EACF;CAiBA,IAAI,EACF,gBAAgB,GAAG,OAAO;EACxB,GAAG,KAAa;gCACU,uCAAuC;gCACvC,4BAA4B;OACrD;CACH,EACF;CAYA,IAAI;EACF,gBAAgB,GAAG,OAAO;GACxB,GAAG,KAAK,4BAA4B;EACtC;EAEA,cAAc,IAAI,OAAO;GACvB,sCAAsC,IAAI,EAAE;EAC9C;CACF;CASA,IAAI,EACF,gBAAgB,GAAG,OAAO;EACxB,GAAG,KACO,gBAAgB,kBAAkB,6BAC5C;CACF,EACF;AACF;AAGsC,OAAO,KAC3C,yBACF,EAAE,QAAQ,MAAM,SAAS,KAAK,IAAI,MAAM,SAAS,IAAI,CAAC,GAAG,CAAC"}
@@ -9,7 +9,7 @@ export type ServerContext = JSONObject;
9
9
  * Initializes a Custom change source before streaming changes from the
10
10
  * corresponding logical replication stream.
11
11
  */
12
- export declare function initializeCustomChangeSource(lc: LogContext, upstreamURI: string, shard: ShardConfig, replicaDbFile: string, context: ServerContext, { litestream, constraints }?: RestoreOptions): Promise<InitializeResult>;
12
+ export declare function initializeCustomChangeSource(lc: LogContext, upstreamURI: string, shard: ShardConfig, replicaDbFile: string, context: ServerContext, { litestream, acquirePurgeLock }?: RestoreOptions): Promise<InitializeResult>;
13
13
  /**
14
14
  * Initial sync for a custom change source makes a request to the
15
15
  * change source endpoint with no `replicaVersion` or `lastWatermark`.
@@ -1 +1 @@
1
- {"version":3,"file":"change-source.d.ts","sourceRoot":"","sources":["../../../../../../../zero-cache/src/services/change-source/custom/change-source.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAGjD,OAAO,EAEL,KAAK,UAAU,EAChB,MAAM,0CAA0C,CAAC;AAGlD,OAAO,EAAC,QAAQ,EAAC,MAAM,iCAAiC,CAAC;AAGzD,OAAO,KAAK,EAAC,WAAW,EAAU,MAAM,0BAA0B,CAAC;AAcnE,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACpB,MAAM,8BAA8B,CAAC;AAQtC,4EAA4E;AAC5E,MAAM,MAAM,aAAa,GAAG,UAAU,CAAC;AAEvC;;;GAGG;AACH,wBAAsB,4BAA4B,CAChD,EAAE,EAAE,UAAU,EACd,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,WAAW,EAClB,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,aAAa,EACtB,EAAC,UAAU,EAAE,WAAW,EAAC,GAAE,cAAmB,GAC7C,OAAO,CAAC,gBAAgB,CAAC,CAwD3B;AA2ED;;;;;;;;;;GAUG;AACH,wBAAsB,WAAW,CAC/B,EAAE,EAAE,UAAU,EACd,KAAK,EAAE,WAAW,EAClB,EAAE,EAAE,QAAQ,EACZ,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,aAAa,iBAqFvB"}
1
+ {"version":3,"file":"change-source.d.ts","sourceRoot":"","sources":["../../../../../../../zero-cache/src/services/change-source/custom/change-source.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAGjD,OAAO,EAEL,KAAK,UAAU,EAChB,MAAM,0CAA0C,CAAC;AAGlD,OAAO,EAAC,QAAQ,EAAC,MAAM,iCAAiC,CAAC;AAGzD,OAAO,KAAK,EAAC,WAAW,EAAU,MAAM,0BAA0B,CAAC;AAcnE,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACpB,MAAM,8BAA8B,CAAC;AAQtC,4EAA4E;AAC5E,MAAM,MAAM,aAAa,GAAG,UAAU,CAAC;AAEvC;;;GAGG;AACH,wBAAsB,4BAA4B,CAChD,EAAE,EAAE,UAAU,EACd,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,WAAW,EAClB,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,aAAa,EACtB,EAAC,UAAU,EAAE,gBAAgB,EAAC,GAAE,cAAmB,GAClD,OAAO,CAAC,gBAAgB,CAAC,CA8D3B;AA2ED;;;;;;;;;;GAUG;AACH,wBAAsB,WAAW,CAC/B,EAAE,EAAE,UAAU,EACd,KAAK,EAAE,WAAW,EAClB,EAAE,EAAE,QAAQ,EACZ,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,aAAa,iBAqFvB"}
@@ -19,8 +19,11 @@ import { WebSocket } from "ws";
19
19
  * Initializes a Custom change source before streaming changes from the
20
20
  * corresponding logical replication stream.
21
21
  */
22
- async function initializeCustomChangeSource(lc, upstreamURI, shard, replicaDbFile, context, { litestream, constraints } = {}) {
23
- if (litestream?.backupURL) await restoreReplica(lc, litestream, replicaDbFile, constraints);
22
+ async function initializeCustomChangeSource(lc, upstreamURI, shard, replicaDbFile, context, { litestream, acquirePurgeLock } = {}) {
23
+ if (litestream?.backupURL) {
24
+ const lock = await acquirePurgeLock?.();
25
+ await restoreReplica(lc, litestream, replicaDbFile, lock === "behind-slot" ? void 0 : lock ?? void 0);
26
+ }
24
27
  let initialSynced = false;
25
28
  await initReplica(lc, `replica-${shard.appID}-${shard.shardNum}`, replicaDbFile, (log, tx) => {
26
29
  initialSynced = true;
@@ -39,7 +42,8 @@ async function initializeCustomChangeSource(lc, upstreamURI, shard, replicaDbFil
39
42
  changeSource: new CustomChangeSource(lc, upstreamURI, shard, subscriptionState),
40
43
  destinationBackupURL: litestream?.backupURL,
41
44
  replicaID: null,
42
- waitForBackupBeforeServing: initialSynced
45
+ waitForBackupBeforeServing: initialSynced,
46
+ newBackupLineage: false
43
47
  };
44
48
  }
45
49
  var CustomChangeSource = class {
@@ -1 +1 @@
1
- {"version":3,"file":"change-source.js","names":["#lc","#upstreamUri","#shard","#replicationConfig","#startStream"],"sources":["../../../../../../../zero-cache/src/services/change-source/custom/change-source.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {WebSocket} from 'ws';\nimport {assert, unreachable} from '../../../../../shared/src/asserts.ts';\nimport {\n stringify,\n type JSONObject,\n} from '../../../../../shared/src/bigint-json.ts';\nimport {deepEqual} from '../../../../../shared/src/json.ts';\nimport type {SchemaValue} from '../../../../../zero-schema/src/table-schema.ts';\nimport {Database} from '../../../../../zqlite/src/db.ts';\nimport {computeZqlSpecs} from '../../../db/lite-tables.ts';\nimport {StatementRunner} from '../../../db/statements.ts';\nimport type {ShardConfig, ShardID} from '../../../types/shards.ts';\nimport {stream} from '../../../types/streams.ts';\nimport {\n AutoResetSignal,\n type ReplicationConfig,\n} from '../../change-streamer/schema/tables.ts';\nimport {ChangeProcessor} from '../../replicator/change-processor.ts';\nimport {ReplicationStatusPublisher} from '../../replicator/replication-status.ts';\nimport {\n createReplicationStateTables,\n getSubscriptionState,\n initReplicationState,\n} from '../../replicator/schema/replication-state.ts';\nimport type {ChangeSource, ChangeStream} from '../change-source.ts';\nimport {\n restoreReplica,\n type InitializeResult,\n type RestoreOptions,\n} from '../common/replica-restore.ts';\nimport {initReplica} from '../common/replica-schema.ts';\nimport {changeStreamMessageSchema} from '../protocol/current/downstream.ts';\nimport {\n type BackfillRequest,\n type ChangeSourceUpstream,\n} from '../protocol/current/upstream.ts';\n\n/** Server context to store with the initial sync metadata for debugging. */\nexport type ServerContext = JSONObject;\n\n/**\n * Initializes a Custom change source before streaming changes from the\n * corresponding logical replication stream.\n */\nexport async function initializeCustomChangeSource(\n lc: LogContext,\n upstreamURI: string,\n shard: ShardConfig,\n replicaDbFile: string,\n context: ServerContext,\n {litestream, constraints}: RestoreOptions = {},\n): Promise<InitializeResult> {\n // At the moment, the custom change-source implementation does not support\n // per-RM backups (and thus does not support litestream v5 or RMv2). The\n // current proposal to support this without requiring additional upstream\n // state tracking is to:\n // - use litestream to (ltx) query a fixed pool of subfolders within the\n // backupURL (e.g. /a/, /b/, /c/, /d/, /e/)\n // - restore from the subfolder with the latest ltx file\n // - backup to the subfolder with the oldest (or non-existent) ltx file\n if (litestream?.backupURL) {\n await restoreReplica(lc, litestream, replicaDbFile, constraints);\n }\n\n let initialSynced = false;\n await initReplica(\n lc,\n `replica-${shard.appID}-${shard.shardNum}`,\n replicaDbFile,\n (log, tx) => {\n initialSynced = true;\n return initialSync(log, shard, tx, upstreamURI, context);\n },\n );\n\n const replica = new Database(lc, replicaDbFile);\n const subscriptionState = getSubscriptionState(new StatementRunner(replica));\n replica.close();\n\n if (shard.publications.length) {\n // Verify that the publications match what has been synced.\n const requested = shard.publications.toSorted();\n const replicated = subscriptionState.publications.sort();\n if (!deepEqual(requested, replicated)) {\n throw new Error(\n `Invalid ShardConfig. Requested publications [${requested}] do not match synced publications: [${replicated}]`,\n );\n }\n }\n\n const changeSource = new CustomChangeSource(\n lc,\n upstreamURI,\n shard,\n subscriptionState,\n );\n\n return {\n subscriptionState,\n changeSource,\n destinationBackupURL: litestream?.backupURL,\n // A custom change source has no upstream `replicas` table to identify\n // itself from, so the generation is the whole of the SQLite change log's\n // identity here.\n replicaID: null,\n waitForBackupBeforeServing: initialSynced,\n };\n}\n\nclass CustomChangeSource implements ChangeSource {\n readonly #lc: LogContext;\n readonly #upstreamUri: string;\n readonly #shard: ShardID;\n readonly #replicationConfig: ReplicationConfig;\n\n constructor(\n lc: LogContext,\n upstreamUri: string,\n shard: ShardID,\n replicationConfig: ReplicationConfig,\n ) {\n this.#lc = lc.withContext('component', 'change-source');\n this.#upstreamUri = upstreamUri;\n this.#shard = shard;\n this.#replicationConfig = replicationConfig;\n }\n\n initialSync(): ChangeStream {\n return this.#startStream();\n }\n\n startLagReporter() {\n return null; // Not supported for custom sources\n }\n\n stop(): Promise<void> {\n return Promise.resolve();\n }\n\n startStream(\n clientWatermark: string,\n backfillRequests: BackfillRequest[] = [],\n ): Promise<ChangeStream> {\n if (backfillRequests?.length) {\n throw new Error(\n 'backfill is yet not supported for custom change sources',\n );\n }\n return Promise.resolve(this.#startStream(clientWatermark));\n }\n\n #startStream(clientWatermark?: string): ChangeStream {\n const {publications, replicaVersion} = this.#replicationConfig;\n const {appID, shardNum} = this.#shard;\n const url = new URL(this.#upstreamUri);\n url.searchParams.set('appID', appID);\n url.searchParams.set('shardNum', String(shardNum));\n for (const pub of publications) {\n url.searchParams.append('publications', pub);\n }\n if (clientWatermark) {\n assert(\n replicaVersion.length,\n 'replicaVersion is required when clientWatermark is set',\n );\n url.searchParams.set('lastWatermark', clientWatermark);\n url.searchParams.set('replicaVersion', replicaVersion);\n }\n\n const ws = new WebSocket(url);\n const {instream, outstream} = stream(\n this.#lc,\n ws,\n changeStreamMessageSchema,\n // Upstream acks coalesce. If upstream exhibits back-pressure,\n // only the last ACK is kept / buffered.\n {coalesce: (curr: ChangeSourceUpstream) => curr},\n );\n return {changes: instream, acks: outstream};\n }\n}\n\n/**\n * Initial sync for a custom change source makes a request to the\n * change source endpoint with no `replicaVersion` or `lastWatermark`.\n * The initial transaction returned by the endpoint is treated as\n * the initial sync, and the commit watermark of that transaction\n * becomes the `replicaVersion` of the initialized replica.\n *\n * Note that this is equivalent to how the LSN of the Postgres WAL\n * at initial sync time is the `replicaVersion` (and starting\n * version for all initially-synced rows).\n */\nexport async function initialSync(\n lc: LogContext,\n shard: ShardConfig,\n tx: Database,\n upstreamURI: string,\n context: ServerContext,\n) {\n const {appID: id, publications} = shard;\n const changeSource = new CustomChangeSource(lc, upstreamURI, shard, {\n replicaVersion: '', // ignored for initialSync()\n publications,\n });\n const {changes} = changeSource.initialSync();\n\n createReplicationStateTables(tx);\n const processor = new ChangeProcessor(\n new StatementRunner(tx),\n 'initial-sync',\n (_, err) => {\n throw err;\n },\n );\n\n const statusPublisher = ReplicationStatusPublisher.forRunningTransaction(tx);\n try {\n let num = 0;\n for await (const change of changes) {\n const [tag] = change;\n switch (tag) {\n case 'begin': {\n const {commitWatermark} = change[2];\n lc.info?.(\n `initial sync of shard ${id} at replicaVersion ${commitWatermark}`,\n );\n statusPublisher.publish(\n lc,\n 'Initializing',\n `Copying upstream tables at version ${commitWatermark}`,\n 5000,\n );\n initReplicationState(\n tx,\n publications.toSorted(),\n commitWatermark,\n context,\n false,\n );\n processor.processMessage(lc, change);\n break;\n }\n case 'data':\n processor.processMessage(lc, change);\n if (++num % 1000 === 0) {\n lc.debug?.(`processed ${num} changes`);\n }\n break;\n case 'commit':\n processor.processMessage(lc, change);\n validateInitiallySyncedData(lc, tx, shard);\n lc.info?.(`finished initial-sync of ${num} changes`);\n return;\n\n case 'status':\n break; // Ignored\n // @ts-expect-error: falls through if the tag is not 'reset-required\n case 'control': {\n const {tag, message} = change[1];\n if (tag === 'reset-required') {\n throw new AutoResetSignal(\n message ?? 'auto-reset signaled by change source',\n );\n }\n }\n // falls through\n case 'rollback':\n throw new Error(\n `unexpected message during initial-sync: ${stringify(change)}`,\n );\n default:\n unreachable(change);\n }\n }\n throw new Error(\n `change source ${upstreamURI} closed before initial-sync completed`,\n );\n } catch (e) {\n await statusPublisher.publishAndThrowError(lc, 'Initializing', e);\n } finally {\n statusPublisher.stop();\n }\n}\n\n// Verify that the upstream tables expected by the sync logic\n// have been properly initialized.\nfunction getRequiredTables({\n appID,\n shardNum,\n}: ShardID): Record<string, Record<string, SchemaValue>> {\n return {\n [`${appID}_${shardNum}.clients`]: {\n clientGroupID: {type: 'string'},\n clientID: {type: 'string'},\n lastMutationID: {type: 'number'},\n userID: {type: 'string'},\n },\n [`${appID}_${shardNum}.mutations`]: {\n clientGroupID: {type: 'string'},\n clientID: {type: 'string'},\n mutationID: {type: 'number'},\n mutation: {type: 'json'},\n },\n [`${appID}.permissions`]: {\n permissions: {type: 'json'},\n hash: {type: 'string'},\n },\n };\n}\n\nfunction validateInitiallySyncedData(\n lc: LogContext,\n db: Database,\n shard: ShardID,\n) {\n const tables = computeZqlSpecs(lc, db, {includeBackfillingColumns: true});\n const required = getRequiredTables(shard);\n for (const [name, columns] of Object.entries(required)) {\n const table = tables.get(name)?.zqlSpec;\n if (!table) {\n throw new Error(\n `Upstream is missing the \"${name}\" table. (Found ${[\n ...tables.keys(),\n ]})` +\n `Please ensure that each table has a unique index over one ` +\n `or more non-null columns.`,\n );\n }\n for (const [col, {type}] of Object.entries(columns)) {\n const found = table[col];\n if (!found) {\n throw new Error(\n `Upstream \"${table}\" table is missing the \"${col}\" column`,\n );\n }\n if (found.type !== type) {\n throw new Error(\n `Upstream \"${table}.${col}\" column is a ${found.type} type but must be a ${type} type.`,\n );\n }\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"change-source.js","names":["#lc","#upstreamUri","#shard","#replicationConfig","#startStream"],"sources":["../../../../../../../zero-cache/src/services/change-source/custom/change-source.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {WebSocket} from 'ws';\nimport {assert, unreachable} from '../../../../../shared/src/asserts.ts';\nimport {\n stringify,\n type JSONObject,\n} from '../../../../../shared/src/bigint-json.ts';\nimport {deepEqual} from '../../../../../shared/src/json.ts';\nimport type {SchemaValue} from '../../../../../zero-schema/src/table-schema.ts';\nimport {Database} from '../../../../../zqlite/src/db.ts';\nimport {computeZqlSpecs} from '../../../db/lite-tables.ts';\nimport {StatementRunner} from '../../../db/statements.ts';\nimport type {ShardConfig, ShardID} from '../../../types/shards.ts';\nimport {stream} from '../../../types/streams.ts';\nimport {\n AutoResetSignal,\n type ReplicationConfig,\n} from '../../change-streamer/schema/tables.ts';\nimport {ChangeProcessor} from '../../replicator/change-processor.ts';\nimport {ReplicationStatusPublisher} from '../../replicator/replication-status.ts';\nimport {\n createReplicationStateTables,\n getSubscriptionState,\n initReplicationState,\n} from '../../replicator/schema/replication-state.ts';\nimport type {ChangeSource, ChangeStream} from '../change-source.ts';\nimport {\n restoreReplica,\n type InitializeResult,\n type RestoreOptions,\n} from '../common/replica-restore.ts';\nimport {initReplica} from '../common/replica-schema.ts';\nimport {changeStreamMessageSchema} from '../protocol/current/downstream.ts';\nimport {\n type BackfillRequest,\n type ChangeSourceUpstream,\n} from '../protocol/current/upstream.ts';\n\n/** Server context to store with the initial sync metadata for debugging. */\nexport type ServerContext = JSONObject;\n\n/**\n * Initializes a Custom change source before streaming changes from the\n * corresponding logical replication stream.\n */\nexport async function initializeCustomChangeSource(\n lc: LogContext,\n upstreamURI: string,\n shard: ShardConfig,\n replicaDbFile: string,\n context: ServerContext,\n {litestream, acquirePurgeLock}: RestoreOptions = {},\n): Promise<InitializeResult> {\n // At the moment, the custom change-source implementation does not support\n // per-RM backups (and thus does not support litestream v5 or RMv2). The\n // current proposal to support this without requiring additional upstream\n // state tracking is to:\n // - use litestream to (ltx) query a fixed pool of subfolders within the\n // backupURL (e.g. /a/, /b/, /c/, /d/, /e/)\n // - restore from the subfolder with the latest ltx file\n // - backup to the subfolder with the oldest (or non-existent) ltx file\n if (litestream?.backupURL) {\n // Without a replication slot, the change-log is never behind one.\n const lock = await acquirePurgeLock?.();\n const constraints =\n lock === 'behind-slot' ? undefined : (lock ?? undefined);\n await restoreReplica(lc, litestream, replicaDbFile, constraints);\n }\n\n let initialSynced = false;\n await initReplica(\n lc,\n `replica-${shard.appID}-${shard.shardNum}`,\n replicaDbFile,\n (log, tx) => {\n initialSynced = true;\n return initialSync(log, shard, tx, upstreamURI, context);\n },\n );\n\n const replica = new Database(lc, replicaDbFile);\n const subscriptionState = getSubscriptionState(new StatementRunner(replica));\n replica.close();\n\n if (shard.publications.length) {\n // Verify that the publications match what has been synced.\n const requested = shard.publications.toSorted();\n const replicated = subscriptionState.publications.sort();\n if (!deepEqual(requested, replicated)) {\n throw new Error(\n `Invalid ShardConfig. Requested publications [${requested}] do not match synced publications: [${replicated}]`,\n );\n }\n }\n\n const changeSource = new CustomChangeSource(\n lc,\n upstreamURI,\n shard,\n subscriptionState,\n );\n\n return {\n subscriptionState,\n changeSource,\n destinationBackupURL: litestream?.backupURL,\n // A custom change source has no upstream `replicas` table to identify\n // itself from, so the generation is the whole of the SQLite change log's\n // identity here.\n replicaID: null,\n waitForBackupBeforeServing: initialSynced,\n // Backs up to the (non-lineage) base URL.\n newBackupLineage: false,\n };\n}\n\nclass CustomChangeSource implements ChangeSource {\n readonly #lc: LogContext;\n readonly #upstreamUri: string;\n readonly #shard: ShardID;\n readonly #replicationConfig: ReplicationConfig;\n\n constructor(\n lc: LogContext,\n upstreamUri: string,\n shard: ShardID,\n replicationConfig: ReplicationConfig,\n ) {\n this.#lc = lc.withContext('component', 'change-source');\n this.#upstreamUri = upstreamUri;\n this.#shard = shard;\n this.#replicationConfig = replicationConfig;\n }\n\n initialSync(): ChangeStream {\n return this.#startStream();\n }\n\n startLagReporter() {\n return null; // Not supported for custom sources\n }\n\n stop(): Promise<void> {\n return Promise.resolve();\n }\n\n startStream(\n clientWatermark: string,\n backfillRequests: BackfillRequest[] = [],\n ): Promise<ChangeStream> {\n if (backfillRequests?.length) {\n throw new Error(\n 'backfill is yet not supported for custom change sources',\n );\n }\n return Promise.resolve(this.#startStream(clientWatermark));\n }\n\n #startStream(clientWatermark?: string): ChangeStream {\n const {publications, replicaVersion} = this.#replicationConfig;\n const {appID, shardNum} = this.#shard;\n const url = new URL(this.#upstreamUri);\n url.searchParams.set('appID', appID);\n url.searchParams.set('shardNum', String(shardNum));\n for (const pub of publications) {\n url.searchParams.append('publications', pub);\n }\n if (clientWatermark) {\n assert(\n replicaVersion.length,\n 'replicaVersion is required when clientWatermark is set',\n );\n url.searchParams.set('lastWatermark', clientWatermark);\n url.searchParams.set('replicaVersion', replicaVersion);\n }\n\n const ws = new WebSocket(url);\n const {instream, outstream} = stream(\n this.#lc,\n ws,\n changeStreamMessageSchema,\n // Upstream acks coalesce. If upstream exhibits back-pressure,\n // only the last ACK is kept / buffered.\n {coalesce: (curr: ChangeSourceUpstream) => curr},\n );\n return {changes: instream, acks: outstream};\n }\n}\n\n/**\n * Initial sync for a custom change source makes a request to the\n * change source endpoint with no `replicaVersion` or `lastWatermark`.\n * The initial transaction returned by the endpoint is treated as\n * the initial sync, and the commit watermark of that transaction\n * becomes the `replicaVersion` of the initialized replica.\n *\n * Note that this is equivalent to how the LSN of the Postgres WAL\n * at initial sync time is the `replicaVersion` (and starting\n * version for all initially-synced rows).\n */\nexport async function initialSync(\n lc: LogContext,\n shard: ShardConfig,\n tx: Database,\n upstreamURI: string,\n context: ServerContext,\n) {\n const {appID: id, publications} = shard;\n const changeSource = new CustomChangeSource(lc, upstreamURI, shard, {\n replicaVersion: '', // ignored for initialSync()\n publications,\n });\n const {changes} = changeSource.initialSync();\n\n createReplicationStateTables(tx);\n const processor = new ChangeProcessor(\n new StatementRunner(tx),\n 'initial-sync',\n (_, err) => {\n throw err;\n },\n );\n\n const statusPublisher = ReplicationStatusPublisher.forRunningTransaction(tx);\n try {\n let num = 0;\n for await (const change of changes) {\n const [tag] = change;\n switch (tag) {\n case 'begin': {\n const {commitWatermark} = change[2];\n lc.info?.(\n `initial sync of shard ${id} at replicaVersion ${commitWatermark}`,\n );\n statusPublisher.publish(\n lc,\n 'Initializing',\n `Copying upstream tables at version ${commitWatermark}`,\n 5000,\n );\n initReplicationState(\n tx,\n publications.toSorted(),\n commitWatermark,\n context,\n false,\n );\n processor.processMessage(lc, change);\n break;\n }\n case 'data':\n processor.processMessage(lc, change);\n if (++num % 1000 === 0) {\n lc.debug?.(`processed ${num} changes`);\n }\n break;\n case 'commit':\n processor.processMessage(lc, change);\n validateInitiallySyncedData(lc, tx, shard);\n lc.info?.(`finished initial-sync of ${num} changes`);\n return;\n\n case 'status':\n break; // Ignored\n // @ts-expect-error: falls through if the tag is not 'reset-required\n case 'control': {\n const {tag, message} = change[1];\n if (tag === 'reset-required') {\n throw new AutoResetSignal(\n message ?? 'auto-reset signaled by change source',\n );\n }\n }\n // falls through\n case 'rollback':\n throw new Error(\n `unexpected message during initial-sync: ${stringify(change)}`,\n );\n default:\n unreachable(change);\n }\n }\n throw new Error(\n `change source ${upstreamURI} closed before initial-sync completed`,\n );\n } catch (e) {\n await statusPublisher.publishAndThrowError(lc, 'Initializing', e);\n } finally {\n statusPublisher.stop();\n }\n}\n\n// Verify that the upstream tables expected by the sync logic\n// have been properly initialized.\nfunction getRequiredTables({\n appID,\n shardNum,\n}: ShardID): Record<string, Record<string, SchemaValue>> {\n return {\n [`${appID}_${shardNum}.clients`]: {\n clientGroupID: {type: 'string'},\n clientID: {type: 'string'},\n lastMutationID: {type: 'number'},\n userID: {type: 'string'},\n },\n [`${appID}_${shardNum}.mutations`]: {\n clientGroupID: {type: 'string'},\n clientID: {type: 'string'},\n mutationID: {type: 'number'},\n mutation: {type: 'json'},\n },\n [`${appID}.permissions`]: {\n permissions: {type: 'json'},\n hash: {type: 'string'},\n },\n };\n}\n\nfunction validateInitiallySyncedData(\n lc: LogContext,\n db: Database,\n shard: ShardID,\n) {\n const tables = computeZqlSpecs(lc, db, {includeBackfillingColumns: true});\n const required = getRequiredTables(shard);\n for (const [name, columns] of Object.entries(required)) {\n const table = tables.get(name)?.zqlSpec;\n if (!table) {\n throw new Error(\n `Upstream is missing the \"${name}\" table. (Found ${[\n ...tables.keys(),\n ]})` +\n `Please ensure that each table has a unique index over one ` +\n `or more non-null columns.`,\n );\n }\n for (const [col, {type}] of Object.entries(columns)) {\n const found = table[col];\n if (!found) {\n throw new Error(\n `Upstream \"${table}\" table is missing the \"${col}\" column`,\n );\n }\n if (found.type !== type) {\n throw new Error(\n `Upstream \"${table}.${col}\" column is a ${found.type} type but must be a ${type} type.`,\n );\n }\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AA6CA,eAAsB,6BACpB,IACA,aACA,OACA,eACA,SACA,EAAC,YAAY,qBAAoC,CAAC,GACvB;CAS3B,IAAI,YAAY,WAAW;EAEzB,MAAM,OAAO,MAAM,mBAAmB;EAGtC,MAAM,eAAe,IAAI,YAAY,eADnC,SAAS,gBAAgB,KAAA,IAAa,QAAQ,KAAA,CACe;CACjE;CAEA,IAAI,gBAAgB;CACpB,MAAM,YACJ,IACA,WAAW,MAAM,MAAM,GAAG,MAAM,YAChC,gBACC,KAAK,OAAO;EACX,gBAAgB;EAChB,OAAO,YAAY,KAAK,OAAO,IAAI,aAAa,OAAO;CACzD,CACF;CAEA,MAAM,UAAU,IAAI,SAAS,IAAI,aAAa;CAC9C,MAAM,oBAAoB,qBAAqB,IAAI,gBAAgB,OAAO,CAAC;CAC3E,QAAQ,MAAM;CAEd,IAAI,MAAM,aAAa,QAAQ;EAE7B,MAAM,YAAY,MAAM,aAAa,SAAS;EAC9C,MAAM,aAAa,kBAAkB,aAAa,KAAK;EACvD,IAAI,CAAC,UAAU,WAAW,UAAU,GAClC,MAAM,IAAI,MACR,gDAAgD,UAAU,uCAAuC,WAAW,EAC9G;CAEJ;CASA,OAAO;EACL;EACA,cAAA,IATuB,mBACvB,IACA,aACA,OACA,iBAKA;EACA,sBAAsB,YAAY;EAIlC,WAAW;EACX,4BAA4B;EAE5B,kBAAkB;CACpB;AACF;AAEA,IAAM,qBAAN,MAAiD;CAC/C;CACA;CACA;CACA;CAEA,YACE,IACA,aACA,OACA,mBACA;EACA,KAAKA,MAAM,GAAG,YAAY,aAAa,eAAe;EACtD,KAAKC,eAAe;EACpB,KAAKC,SAAS;EACd,KAAKC,qBAAqB;CAC5B;CAEA,cAA4B;EAC1B,OAAO,KAAKC,aAAa;CAC3B;CAEA,mBAAmB;EACjB,OAAO;CACT;CAEA,OAAsB;EACpB,OAAO,QAAQ,QAAQ;CACzB;CAEA,YACE,iBACA,mBAAsC,CAAC,GAChB;EACvB,IAAI,kBAAkB,QACpB,MAAM,IAAI,MACR,yDACF;EAEF,OAAO,QAAQ,QAAQ,KAAKA,aAAa,eAAe,CAAC;CAC3D;CAEA,aAAa,iBAAwC;EACnD,MAAM,EAAC,cAAc,mBAAkB,KAAKD;EAC5C,MAAM,EAAC,OAAO,aAAY,KAAKD;EAC/B,MAAM,MAAM,IAAI,IAAI,KAAKD,YAAY;EACrC,IAAI,aAAa,IAAI,SAAS,KAAK;EACnC,IAAI,aAAa,IAAI,YAAY,OAAO,QAAQ,CAAC;EACjD,KAAK,MAAM,OAAO,cAChB,IAAI,aAAa,OAAO,gBAAgB,GAAG;EAE7C,IAAI,iBAAiB;GACnB,OACE,eAAe,QACf,wDACF;GACA,IAAI,aAAa,IAAI,iBAAiB,eAAe;GACrD,IAAI,aAAa,IAAI,kBAAkB,cAAc;EACvD;EAEA,MAAM,KAAK,IAAI,UAAU,GAAG;EAC5B,MAAM,EAAC,UAAU,cAAa,OAC5B,KAAKD,KACL,IACA,2BAGA,EAAC,WAAW,SAA+B,KAAI,CACjD;EACA,OAAO;GAAC,SAAS;GAAU,MAAM;EAAS;CAC5C;AACF;;;;;;;;;;;;AAaA,eAAsB,YACpB,IACA,OACA,IACA,aACA,SACA;CACA,MAAM,EAAC,OAAO,IAAI,iBAAgB;CAKlC,MAAM,EAAC,YAAW,IAJO,mBAAmB,IAAI,aAAa,OAAO;EAClE,gBAAgB;EAChB;CACF,CACkB,EAAa,YAAY;CAE3C,6BAA6B,EAAE;CAC/B,MAAM,YAAY,IAAI,gBACpB,IAAI,gBAAgB,EAAE,GACtB,iBACC,GAAG,QAAQ;EACV,MAAM;CACR,CACF;CAEA,MAAM,kBAAkB,2BAA2B,sBAAsB,EAAE;CAC3E,IAAI;EACF,IAAI,MAAM;EACV,WAAW,MAAM,UAAU,SAAS;GAClC,MAAM,CAAC,OAAO;GACd,QAAQ,KAAR;IACE,KAAK,SAAS;KACZ,MAAM,EAAC,oBAAmB,OAAO;KACjC,GAAG,OACD,yBAAyB,GAAG,qBAAqB,iBACnD;KACA,gBAAgB,QACd,IACA,gBACA,sCAAsC,mBACtC,GACF;KACA,qBACE,IACA,aAAa,SAAS,GACtB,iBACA,SACA,KACF;KACA,UAAU,eAAe,IAAI,MAAM;KACnC;IACF;IACA,KAAK;KACH,UAAU,eAAe,IAAI,MAAM;KACnC,IAAI,EAAE,MAAM,QAAS,GACnB,GAAG,QAAQ,aAAa,IAAI,SAAS;KAEvC;IACF,KAAK;KACH,UAAU,eAAe,IAAI,MAAM;KACnC,4BAA4B,IAAI,IAAI,KAAK;KACzC,GAAG,OAAO,4BAA4B,IAAI,SAAS;KACnD;IAEF,KAAK,UACH;IAEF,KAAK,WAAW;KACd,MAAM,EAAC,KAAK,YAAW,OAAO;KAC9B,IAAI,QAAQ,kBACV,MAAM,IAAI,gBACR,WAAW,sCACb;IAEJ;IAEA,KAAK,YACH,MAAM,IAAI,MACR,2CAA2C,UAAU,MAAM,GAC7D;IACF,SACE,YAAY,MAAM;GACtB;EACF;EACA,MAAM,IAAI,MACR,iBAAiB,YAAY,sCAC/B;CACF,SAAS,GAAG;EACV,MAAM,gBAAgB,qBAAqB,IAAI,gBAAgB,CAAC;CAClE,UAAU;EACR,gBAAgB,KAAK;CACvB;AACF;AAIA,SAAS,kBAAkB,EACzB,OACA,YACuD;CACvD,OAAO;GACJ,GAAG,MAAM,GAAG,SAAS,YAAY;GAChC,eAAe,EAAC,MAAM,SAAQ;GAC9B,UAAU,EAAC,MAAM,SAAQ;GACzB,gBAAgB,EAAC,MAAM,SAAQ;GAC/B,QAAQ,EAAC,MAAM,SAAQ;EACzB;GACC,GAAG,MAAM,GAAG,SAAS,cAAc;GAClC,eAAe,EAAC,MAAM,SAAQ;GAC9B,UAAU,EAAC,MAAM,SAAQ;GACzB,YAAY,EAAC,MAAM,SAAQ;GAC3B,UAAU,EAAC,MAAM,OAAM;EACzB;GACC,GAAG,MAAM,gBAAgB;GACxB,aAAa,EAAC,MAAM,OAAM;GAC1B,MAAM,EAAC,MAAM,SAAQ;EACvB;CACF;AACF;AAEA,SAAS,4BACP,IACA,IACA,OACA;CACA,MAAM,SAAS,gBAAgB,IAAI,IAAI,EAAC,2BAA2B,KAAI,CAAC;CACxE,MAAM,WAAW,kBAAkB,KAAK;CACxC,KAAK,MAAM,CAAC,MAAM,YAAY,OAAO,QAAQ,QAAQ,GAAG;EACtD,MAAM,QAAQ,OAAO,IAAI,IAAI,GAAG;EAChC,IAAI,CAAC,OACH,MAAM,IAAI,MACR,4BAA4B,KAAK,kBAAkB,CACjD,GAAG,OAAO,KAAK,CACjB,EAAE,qFAGJ;EAEF,KAAK,MAAM,CAAC,KAAK,EAAC,WAAU,OAAO,QAAQ,OAAO,GAAG;GACnD,MAAM,QAAQ,MAAM;GACpB,IAAI,CAAC,OACH,MAAM,IAAI,MACR,aAAa,MAAM,0BAA0B,IAAI,SACnD;GAEF,IAAI,MAAM,SAAS,MACjB,MAAM,IAAI,MACR,aAAa,MAAM,GAAG,IAAI,gBAAgB,MAAM,KAAK,sBAAsB,KAAK,OAClF;EAEJ;CACF;AACF"}
@@ -2,6 +2,9 @@ import type { LogContext } from '@rocicorp/logger';
2
2
  import { type BackfillMessage } from '../common/backfill-manager.ts';
3
3
  import type { BackfillRequest } from '../protocol/current.ts';
4
4
  import type { Replica } from './schema/shard.ts';
5
+ export declare function ctidToProgressMark(ctid: string): string;
6
+ /** The inverse of {@link ctidToProgressMark}, as a `tid` literal. */
7
+ export declare function progressMarkToCtid(mark: string): string;
5
8
  type StreamOptions = {
6
9
  /**
7
10
  * The number of bytes at which to flush a batch of rows in a
@@ -15,6 +18,12 @@ type StreamOptions = {
15
18
  * revert to the old code path if needed.
16
19
  */
17
20
  textCopy?: boolean | undefined;
21
+ /**
22
+ * @visibleForTesting
23
+ * Called after the snapshot transaction is opened, before the table is
24
+ * locked, e.g. to run a concurrent heap rewrite in between.
25
+ */
26
+ afterSnapshotForTesting?: (() => Promise<void>) | undefined;
18
27
  };
19
28
  /**
20
29
  * Streams a series of `backfill` messages (ending with `backfill-complete`)
@@ -1 +1 @@
1
- {"version":3,"file":"backfill-stream.d.ts","sourceRoot":"","sources":["../../../../../../../zero-cache/src/services/change-source/pg/backfill-stream.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAkBjD,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,+BAA+B,CAAC;AACvC,OAAO,KAAK,EAEV,eAAe,EAGhB,MAAM,wBAAwB,CAAC;AAahC,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,mBAAmB,CAAC;AAI/C,KAAK,aAAa,GAAG;IACnB;;;OAGG;IACH,mBAAmB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAEzC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAChC,CAAC;AAYF;;;;;GAKG;AACH,wBAAuB,cAAc,CACnC,EAAE,EAAE,UAAU,EACd,WAAW,EAAE,MAAM,EACnB,EAAC,IAAI,EAAE,YAAY,EAAC,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CAAC,EAC5D,EAAE,EAAE,eAAe,EACnB,IAAI,GAAE,aAAkB,GACvB,cAAc,CAAC,eAAe,CAAC,CAsGjC"}
1
+ {"version":3,"file":"backfill-stream.d.ts","sourceRoot":"","sources":["../../../../../../../zero-cache/src/services/change-source/pg/backfill-stream.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAqBjD,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,+BAA+B,CAAC;AAEvC,OAAO,KAAK,EAGV,eAAe,EAGhB,MAAM,wBAAwB,CAAC;AAahC,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,mBAAmB,CAAC;AAoC/C,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIvD;AAED,qEAAqE;AACrE,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIvD;AAmCD,KAAK,aAAa,GAAG;IACnB;;;OAGG;IACH,mBAAmB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAEzC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAE/B;;;;OAIG;IACH,uBAAuB,CAAC,EAAE,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC;CAC7D,CAAC;AAYF;;;;;GAKG;AACH,wBAAuB,cAAc,CACnC,EAAE,EAAE,UAAU,EACd,WAAW,EAAE,MAAM,EACnB,EAAC,IAAI,EAAE,YAAY,EAAC,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CAAC,EAC5D,EAAE,EAAE,eAAe,EACnB,IAAI,GAAE,aAAkB,GACvB,cAAc,CAAC,eAAe,CAAC,CAkJjC"}
@@ -1,11 +1,15 @@
1
1
  import { assert } from "../../../../../shared/src/asserts.js";
2
2
  import { parse } from "../../../../../shared/src/valita.js";
3
+ import { must } from "../../../../../shared/src/must.js";
4
+ import { randomCharacters } from "../../../../../shared/src/random-values.js";
3
5
  import { equals } from "../../../../../shared/src/set-utils.js";
6
+ import { id } from "../../../types/sql.js";
4
7
  import { connectPgClient, pgClient } from "../../../types/pg.js";
5
8
  import { toStateVersionString } from "./lsn.js";
6
9
  import { READONLY } from "../../../db/mode-enum.js";
7
10
  import { getPublicationInfo } from "./schema/published.js";
8
11
  import { Queue } from "../../../../../shared/src/queue.js";
12
+ import { resumePoint } from "../protocol/backfill-progress.js";
9
13
  import { SchemaIncompatibilityError } from "../common/backfill-manager.js";
10
14
  import { BinaryCopyParser, hasBinaryDecoder, makeBinaryDecoder, textCastDecoder } from "../../../db/pg-copy-binary.js";
11
15
  import { TsvParser } from "../../../db/pg-copy.js";
@@ -17,6 +21,52 @@ import { makeBinarySelectExprs, makeDownloadStatements } from "./initial-sync.js
17
21
  import postgres from "postgres";
18
22
  import { PG_UNDEFINED_COLUMN, PG_UNDEFINED_TABLE } from "@drdgvhbh/postgres-error-codes";
19
23
  //#region ../zero-cache/src/services/change-source/pg/backfill-stream.ts
24
+ /**
25
+ * Encodes a `ctid` text representation, e.g. `(123,4)`, as a
26
+ * fixed-width string that sorts lexicographically in `ctid` order.
27
+ */
28
+ var CTID_RE = /^\((\d+),(\d+)\)$/;
29
+ var CTID_MARK_RE = /^(\d{10})\.(\d{5})$/;
30
+ function ctidToProgressMark(ctid) {
31
+ const match = CTID_RE.exec(ctid);
32
+ assert(match, () => `invalid ctid: ${ctid}`);
33
+ return `${match[1].padStart(10, "0")}.${match[2].padStart(5, "0")}`;
34
+ }
35
+ /** The inverse of {@link ctidToProgressMark}, as a `tid` literal. */
36
+ function progressMarkToCtid(mark) {
37
+ const match = CTID_MARK_RE.exec(mark);
38
+ assert(match, () => `invalid ctid progress mark: ${mark}`);
39
+ return `(${Number(match[1])},${Number(match[2])})`;
40
+ }
41
+ function progressMarks(previous, current) {
42
+ return previous ? {
43
+ previous,
44
+ current
45
+ } : { current };
46
+ }
47
+ /** The `ctid` of each row is appended as the last column of the download. */
48
+ var CTID_SELECT = "ctid::text";
49
+ /**
50
+ * Settings that ensure that the COPY scans the table in physical (i.e.
51
+ * `ctid`) order, which is necessary for the progress marks of a resumable
52
+ * backfill to be meaningful. (Monotonicity is nonetheless verified as rows
53
+ * are streamed.)
54
+ *
55
+ * * Synchronized seqscans can start in the middle of the table.
56
+ * * Parallel scans interleave the rows of different workers.
57
+ * * Index scans follow index order. (A publication row filter could
58
+ * otherwise be satisfied with an index.)
59
+ */
60
+ var PHYSICAL_ORDER_SETTINGS = [
61
+ "synchronize_seqscans = off",
62
+ "max_parallel_workers_per_gather = 0",
63
+ "enable_indexscan = off",
64
+ "enable_indexonlyscan = off",
65
+ "enable_bitmapscan = off"
66
+ ];
67
+ function rowCountMark(rows) {
68
+ return String(rows).padStart(16, "0");
69
+ }
20
70
  var POSTGRES_COPY_CHUNK_SIZE = 64 * 1024;
21
71
  var SAMPLE_OR_LIMIT_RE = /\sTABLESAMPLE\s+BERNOULLI\b|\sLIMIT\s+\d/i;
22
72
  /**
@@ -27,42 +77,50 @@ var SAMPLE_OR_LIMIT_RE = /\sTABLESAMPLE\s+BERNOULLI\b|\sLIMIT\s+\d/i;
27
77
  */
28
78
  async function* streamBackfill(lc, upstreamURI, { slot, publications }, bf, opts = {}) {
29
79
  lc = lc.withContext("component", "backfill").withContext("table", bf.table.name);
30
- const { flushThresholdBytes = POSTGRES_COPY_CHUNK_SIZE, textCopy = false } = opts;
80
+ const { flushThresholdBytes = POSTGRES_COPY_CHUNK_SIZE, textCopy = false, afterSnapshotForTesting } = opts;
31
81
  const db = await connectPgClient(lc, upstreamURI, "backfill-stream", {
32
82
  ["max_lifetime"]: 1440 * 60,
33
83
  liveness: "keepalive"
34
84
  });
35
85
  let tx;
36
86
  let watermark;
87
+ let completed = false;
37
88
  try {
38
89
  ({tx, watermark} = await createSnapshotTransaction(lc, upstreamURI, db, slot));
39
- const { tableSpec, backfill } = await validateSchema(tx, publications, bf, watermark);
90
+ await afterSnapshotForTesting?.();
91
+ const { tableSpec, backfill, progress } = await validateSchema(lc, tx, publications, bf, watermark);
40
92
  const { relation, columns } = backfill;
41
93
  const cols = [...relation.rowKey.columns, ...columns];
42
- const stmts = makeDownloadStatements(tableSpec, cols);
94
+ const order = progress.resumable && progress.start ? { after: `ctid > '${progressMarkToCtid(progress.start.progressMark)}'::tid` } : void 0;
95
+ const stmts = makeDownloadStatements(tableSpec, cols, void 0, void 0, [...cols.map((col) => id(col)), CTID_SELECT], order);
96
+ if (progress.start) lc.info?.(`resuming backfill from ${progress.start.progressMark} (timeline ${progress.timeline})`);
43
97
  if (textCopy) {
44
98
  const types = await getTypeParsers(db, { returnJsonAsString: true });
45
- yield* stream(lc, tx, backfill, stmts, `COPY (${stmts.select}) TO STDOUT`, new TsvParser(), cols.map((col) => {
99
+ yield* stream(lc, tx, backfill, progress, stmts, `COPY (${stmts.select}) TO STDOUT`, new TsvParser(), cols.map((col) => {
46
100
  const parser = types.getTypeParser(tableSpec.columns[col].typeOID);
47
101
  return (text) => parser(text);
48
- }), flushThresholdBytes);
102
+ }), (text) => text, flushThresholdBytes);
49
103
  } else {
50
- const binaryStmts = makeDownloadStatements(tableSpec, cols, void 0, void 0, makeBinarySelectExprs(tableSpec, cols));
51
- yield* stream(lc, tx, backfill, stmts, `COPY (${binaryStmts.select}) TO STDOUT WITH (FORMAT binary)`, new BinaryCopyParser(), cols.map((col) => {
104
+ const binaryStmts = makeDownloadStatements(tableSpec, cols, void 0, void 0, [...makeBinarySelectExprs(tableSpec, cols), CTID_SELECT], order);
105
+ yield* stream(lc, tx, backfill, progress, stmts, `COPY (${binaryStmts.select}) TO STDOUT WITH (FORMAT binary)`, new BinaryCopyParser(), cols.map((col) => {
52
106
  const spec = tableSpec.columns[col];
53
107
  const decoder = hasBinaryDecoder(spec) ? makeBinaryDecoder(spec) : textCastDecoder;
54
108
  return (buf) => decoder(buf);
55
- }), flushThresholdBytes);
109
+ }), (buf) => buf.toString("utf8"), flushThresholdBytes);
56
110
  }
111
+ completed = true;
57
112
  } catch (e) {
58
113
  if (e instanceof postgres.PostgresError && (e.code === PG_UNDEFINED_TABLE || e.code === PG_UNDEFINED_COLUMN)) throw new SchemaIncompatibilityError(bf, String(e), { cause: e });
59
114
  throw e;
60
115
  } finally {
61
116
  tx?.setDone();
62
- db.end().catch((e) => lc.warn?.(`error closing backfill connection`, e));
117
+ if (completed) {
118
+ await tx?.done();
119
+ await db.end();
120
+ } else db.end({ timeout: 5 }).catch((e) => lc.warn?.(`error closing backfill connection`, e));
63
121
  }
64
122
  }
65
- async function* stream(lc, tx, backfill, { getTotalRows, getTotalBytes }, copyCommand, parser, decoders, flushThresholdBytes) {
123
+ async function* stream(lc, tx, backfill, { timeline, resumable, start: startMark }, { getTotalRows, getTotalBytes }, copyCommand, parser, decoders, ctidDecoder, flushThresholdBytes) {
66
124
  assert(!SAMPLE_OR_LIMIT_RE.test(copyCommand), `backfill COPY must not sample or limit: ${copyCommand}`);
67
125
  const start = performance.now();
68
126
  const [rows, bytes] = await tx.processReadTask((sql) => Promise.all([sql.unsafe(getTotalRows), sql.unsafe(getTotalBytes)]));
@@ -76,6 +134,7 @@ async function* stream(lc, tx, backfill, { getTotalRows, getTotalBytes }, copyCo
76
134
  const chunks = new Queue();
77
135
  const acks = new Queue();
78
136
  const copyDone = tx.processReadTask(async (sql) => {
137
+ for (const setting of PHYSICAL_ORDER_SETTINGS) await sql.unsafe(`SET LOCAL ${setting}`);
79
138
  const readable = await sql.unsafe(copyCommand).readable();
80
139
  for await (const chunk of readable) {
81
140
  chunks.enqueue(chunk);
@@ -91,14 +150,26 @@ async function* stream(lc, tx, backfill, { getTotalRows, getTotalBytes }, copyCo
91
150
  const logFlushed = () => {
92
151
  lc.debug?.(`Flushed ${rowValues.length} rows, ${bufferedBytes} bytes (total: rows=${status.rows}, msgs=${totalMsgs}, bytes=${totalBytes})`);
93
152
  };
153
+ let current = startMark;
154
+ let previous = startMark;
155
+ const markOf = (progressMark) => ({
156
+ progressMark,
157
+ timeline
158
+ });
159
+ const numCols = decoders.length + 1;
94
160
  let row = Array.from({ length: decoders.length });
95
161
  let col = 0;
96
162
  for (;;) {
97
163
  const chunk = await chunks.dequeue();
98
164
  if (chunk === "done") break;
99
165
  for (const field of parser.parse(chunk)) {
100
- row[col] = field === null ? null : decoders[col](field);
101
- if (++col === decoders.length) {
166
+ if (col < decoders.length) row[col] = field === null ? null : decoders[col](field);
167
+ else {
168
+ const mark = resumable ? ctidToProgressMark(ctidDecoder(field)) : rowCountMark(status.rows + 1);
169
+ if (current !== void 0 && mark <= current.progressMark) throw new Error(`backfill rows are not in ctid order (${mark} after ${current.progressMark})`);
170
+ current = markOf(mark);
171
+ }
172
+ if (++col === numCols) {
102
173
  rowValues.push(row);
103
174
  status.rows++;
104
175
  row = Array.from({ length: decoders.length });
@@ -107,16 +178,18 @@ async function* stream(lc, tx, backfill, { getTotalRows, getTotalBytes }, copyCo
107
178
  }
108
179
  bufferedBytes += chunk.byteLength;
109
180
  totalBytes += chunk.byteLength;
110
- if (bufferedBytes >= flushThresholdBytes) {
181
+ if (bufferedBytes >= flushThresholdBytes && rowValues.length > 0) {
111
182
  yield {
112
183
  message: {
113
184
  tag: "backfill",
114
185
  ...backfill,
115
186
  rowValues,
116
- status
187
+ status,
188
+ progressMarks: progressMarks(previous, must(current))
117
189
  },
118
190
  byteSize: bufferedBytes
119
191
  };
192
+ previous = current;
120
193
  totalMsgs++;
121
194
  logFlushed();
122
195
  rowValues = [];
@@ -131,10 +204,12 @@ async function* stream(lc, tx, backfill, { getTotalRows, getTotalBytes }, copyCo
131
204
  tag: "backfill",
132
205
  ...backfill,
133
206
  rowValues,
134
- status
207
+ status,
208
+ progressMarks: progressMarks(previous, must(current))
135
209
  },
136
210
  byteSize: bufferedBytes
137
211
  };
212
+ previous = current;
138
213
  totalMsgs++;
139
214
  logFlushed();
140
215
  }
@@ -142,7 +217,8 @@ async function* stream(lc, tx, backfill, { getTotalRows, getTotalBytes }, copyCo
142
217
  message: {
143
218
  tag: "backfill-completed",
144
219
  ...backfill,
145
- status
220
+ status,
221
+ progressMarks: previous ? { previous } : {}
146
222
  },
147
223
  byteSize: 0
148
224
  };
@@ -167,7 +243,8 @@ async function createSnapshotTransaction(lc, upstreamURI, db, slotNamePrefix) {
167
243
  try {
168
244
  const { snapshot_name: snapshot, consistent_point: lsn } = await createReplicationSlot(lc, replicationSession, {
169
245
  slotName,
170
- temporary: true
246
+ temporary: true,
247
+ diagnosticsDB: db
171
248
  });
172
249
  const { init, imported } = importSnapshot(snapshot);
173
250
  const tx = new TransactionPool(lc, {
@@ -182,10 +259,10 @@ async function createSnapshotTransaction(lc, upstreamURI, db, slotNamePrefix) {
182
259
  watermark
183
260
  };
184
261
  } finally {
185
- await replicationSession.end();
262
+ await replicationSession.end({ timeout: 5 });
186
263
  }
187
264
  }
188
- function validateSchema(tx, publications, bf, watermark) {
265
+ function validateSchema(lc, tx, publications, bf, watermark) {
189
266
  return tx.processReadTask(async (sql) => {
190
267
  const { tables } = await getPublicationInfo(sql, publications);
191
268
  const spec = tables.find((spec) => spec.schema === bf.table.schema && spec.name === bf.table.name);
@@ -194,7 +271,7 @@ function validateSchema(tx, publications, bf, watermark) {
194
271
  if (spec.schemaOID !== tableMeta.schemaOID) throw new SchemaIncompatibilityError(bf, `Schema no longer corresponds to the original schema`);
195
272
  if (spec.oid !== tableMeta.relationOID) throw new SchemaIncompatibilityError(bf, `Table no longer corresponds to the original table`);
196
273
  if (!equals(new Set(Object.keys(tableMeta.rowKey)), new Set(spec.replicaIdentityColumns))) throw new SchemaIncompatibilityError(bf, "Row key (e.g. PRIMARY KEY or INDEX) has changed");
197
- const allCols = [...Object.entries(tableMeta.rowKey), ...Object.entries(bf.columns)];
274
+ const allCols = [...Object.entries(tableMeta.rowKey), ...Object.entries(bf.columns).map(([col, { id }]) => [col, id])];
198
275
  for (const [col, val] of allCols) {
199
276
  const colSpec = spec.columns[col];
200
277
  if (!colSpec) throw new SchemaIncompatibilityError(bf, `Column ${col} has been renamed or dropped`);
@@ -210,10 +287,125 @@ function validateSchema(tx, publications, bf, watermark) {
210
287
  },
211
288
  columns: Object.keys(bf.columns).filter((col) => !(col in tableMeta.rowKey)),
212
289
  watermark
213
- }
290
+ },
291
+ progress: await getProgress(lc, sql, spec.oid, bf)
214
292
  };
215
293
  });
216
294
  }
295
+ /**
296
+ * Determines the timeline of the table's progress marks (as of the snapshot),
297
+ * and whether the backfill can be resumed from the requested progress.
298
+ *
299
+ * The table is locked (in ACCESS SHARE mode, as the COPY would, for the rest
300
+ * of the transaction) so that its storage cannot be rewritten (by `VACUUM
301
+ * FULL`, `CLUSTER`, `TRUNCATE`, or a rewriting `ALTER TABLE`, all of which
302
+ * require ACCESS EXCLUSIVE) between reading the timeline and the COPY. Note
303
+ * that `pg_relation_filenode()` reflects the table's current storage (only
304
+ * refreshed upon acquiring a lock), whereas `pg_class.relfilenode` is read at
305
+ * the transaction snapshot. If they differ, the storage was rewritten after the
306
+ * snapshot, and the COPY would scan the new storage with the old snapshot,
307
+ * which is not MVCC-safe for all rewrites (e.g. the table appears empty after
308
+ * a rewriting `ALTER TABLE`). The backfill is then retried at a new snapshot.
309
+ */
310
+ async function getProgress(lc, sql, relationOID, bf) {
311
+ const table = `${id(bf.table.schema)}.${id(bf.table.name)}`;
312
+ await sql.unsafe(`LOCK TABLE ${table} IN ACCESS SHARE MODE`);
313
+ const [{ lockedOID, relkind, snapshotFilenode, filenode }] = await sql`
314
+ SELECT to_regclass(${table})::oid::int8 AS "lockedOID",
315
+ relkind,
316
+ relfilenode::text AS "snapshotFilenode",
317
+ pg_relation_filenode(oid)::text AS filenode
318
+ FROM pg_class WHERE oid = ${relationOID}`;
319
+ if (Number(lockedOID) !== relationOID) throw new SchemaIncompatibilityError(bf, `Table has been renamed or replaced`);
320
+ if (relkind !== "r" || filenode === null) return {
321
+ timeline: `${relkind}:${randomCharacters(12)}`,
322
+ resumable: false,
323
+ start: void 0
324
+ };
325
+ if (filenode !== snapshotFilenode) throw new Error(`${bf.table.schema}.${bf.table.name} was rewritten after the backfill snapshot (relfilenode ${snapshotFilenode} => ${filenode})`);
326
+ const timeline = filenode;
327
+ const requested = resumePoint(bf);
328
+ if (requested && requested.timeline !== timeline) {
329
+ lc.info?.(`restarting backfill from scratch: the requested progress is on timeline ${requested.timeline} but the table is on ${timeline}`);
330
+ return {
331
+ timeline,
332
+ resumable: true,
333
+ start: void 0
334
+ };
335
+ }
336
+ if (requested && !await canResume(sql, relationOID, bf)) {
337
+ lc.info?.(`restarting backfill from scratch: the table has TOASTed values and backfilling columns [${Object.keys(bf.columns).join(",")}] are TOAST-able`);
338
+ return {
339
+ timeline,
340
+ resumable: true,
341
+ start: void 0
342
+ };
343
+ }
344
+ return {
345
+ timeline,
346
+ resumable: true,
347
+ start: requested
348
+ };
349
+ }
350
+ /**
351
+ * Whether resuming a backfill (in a new snapshot) is guaranteed to deliver
352
+ * the values of every row that the preceding snapshot(s) had not reached.
353
+ *
354
+ * Within a single snapshot, every row is scanned exactly once, since the
355
+ * version visible to the snapshot stays in place while it is held. Across
356
+ * snapshots, however, a row that had not yet been reached (i.e. beyond the
357
+ * resume mark `M`) can be updated between the snapshots, with its new
358
+ * version placed at or before `M` (a non-HOT update into free space in an
359
+ * earlier page, or a HOT update into a lower line pointer of `M`'s page).
360
+ * Neither snapshot then scans the row, and it is only delivered by the
361
+ * replication stream. The stream's UPDATE contains the full row, _except_
362
+ * for unchanged values stored out-of-line in TOAST, which pgoutput omits
363
+ * (unless the table has REPLICA IDENTITY FULL). A backfilling column with
364
+ * such a value would be published without it.
365
+ *
366
+ * Resuming is therefore only done if no backfilling column can be TOASTed
367
+ * (i.e. all have `attstorage = 'p'`, as for fixed-width types), or if the
368
+ * table has no TOAST data. The latter is safe because an omitted value must
369
+ * still be in the TOAST relation at the new snapshot (unless its row has since
370
+ * been deleted, which the replication stream does deliver), and conservative
371
+ * because the TOAST relation does not shrink to empty without a heap rewrite,
372
+ * which changes the timeline.
373
+ *
374
+ * Potential optimization for TOAST-able backfills: have the resumed run also
375
+ * deliver the rows at or before `M` that were modified since the snapshot of
376
+ * the run that started the backfill from scratch. That run's snapshot `xmin`
377
+ * (`T_origin`, as an xid8) would be encoded in the timeline, i.e.
378
+ * `timeline = "<relfilenode>:<T_origin>"`, and carried over (rather than
379
+ * replaced) by resumed runs, so that:
380
+ * * Within a chain of runs, every row version with `xmin < T_origin` stayed
381
+ * in place across all of the runs' snapshots and was therefore scanned
382
+ * exactly once, and all other rows are re-delivered by the resumed run
383
+ * (`ctid > M OR xmin >= T_origin`).
384
+ * * Continuations from a different chain (i.e. with a newer `T_origin`) are
385
+ * not accepted by subscribers, and requests from different chains are
386
+ * merged into a backfill from scratch, as the timelines differ. Note that
387
+ * using the _latest_ `T` would be incorrect: rows that moved before `M`
388
+ * between the earlier snapshots would never be re-delivered.
389
+ * The resumed run would scan the whole table (but only deliver the modified
390
+ * rows), comparing the 32-bit `xmin` with `T_origin` modulo 2^32, which
391
+ * requires falling back to a backfill from scratch once the current xid is
392
+ * 2^31 or more past `T_origin` (i.e. wraparound). This also relies on the
393
+ * `xmin` system column returning the raw xmin of frozen tuples, which should
394
+ * be verified.
395
+ */
396
+ async function canResume(sql, relationOID, bf) {
397
+ const [{ toastable, toasted }] = await sql`
398
+ SELECT
399
+ EXISTS (
400
+ SELECT 1 FROM pg_attribute
401
+ WHERE attrelid = ${relationOID}
402
+ AND attname IN ${sql(Object.keys(bf.columns))}
403
+ AND attstorage <> 'p'
404
+ ) AS toastable,
405
+ reltoastrelid <> 0 AND pg_relation_size(reltoastrelid) > 0 AS toasted
406
+ FROM pg_class WHERE oid = ${relationOID}`;
407
+ return !toastable || !toasted;
408
+ }
217
409
  //#endregion
218
410
  export { streamBackfill };
219
411