@rocicorp/zero 1.10.0-canary.0 → 1.10.0-canary.2

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 (408) hide show
  1. package/out/replicache/src/db/commit.js +1 -4
  2. package/out/replicache/src/db/commit.js.map +1 -1
  3. package/out/replicache/src/db/read.d.ts +1 -0
  4. package/out/replicache/src/db/read.d.ts.map +1 -1
  5. package/out/replicache/src/db/read.js +1 -4
  6. package/out/replicache/src/db/read.js.map +1 -1
  7. package/out/replicache/src/db/write.d.ts +2 -1
  8. package/out/replicache/src/db/write.d.ts.map +1 -1
  9. package/out/replicache/src/db/write.js +4 -51
  10. package/out/replicache/src/db/write.js.map +1 -1
  11. package/out/replicache/src/persist/clients.d.ts +1 -0
  12. package/out/replicache/src/persist/clients.d.ts.map +1 -1
  13. package/out/replicache/src/persist/clients.js +4 -31
  14. package/out/replicache/src/persist/clients.js.map +1 -1
  15. package/out/replicache/src/process-env.d.ts +28 -0
  16. package/out/replicache/src/process-env.d.ts.map +1 -0
  17. package/out/replicache/src/replicache-impl.d.ts.map +1 -1
  18. package/out/replicache/src/replicache-impl.js.map +1 -1
  19. package/out/replicache/src/scan-iterator.js +2 -14
  20. package/out/replicache/src/scan-iterator.js.map +1 -1
  21. package/out/replicache/src/subscriptions.d.ts +1 -0
  22. package/out/replicache/src/subscriptions.d.ts.map +1 -1
  23. package/out/replicache/src/subscriptions.js +2 -10
  24. package/out/replicache/src/subscriptions.js.map +1 -1
  25. package/out/replicache/src/transactions.d.ts +1 -0
  26. package/out/replicache/src/transactions.d.ts.map +1 -1
  27. package/out/replicache/src/transactions.js +2 -4
  28. package/out/replicache/src/transactions.js.map +1 -1
  29. package/out/z2s/src/compiler.d.ts.map +1 -1
  30. package/out/z2s/src/compiler.js +1 -22
  31. package/out/z2s/src/compiler.js.map +1 -1
  32. package/out/zero/package.js +3 -3
  33. package/out/zero/package.js.map +1 -1
  34. package/out/zero-cache/src/config/normalize.d.ts +1 -0
  35. package/out/zero-cache/src/config/normalize.d.ts.map +1 -1
  36. package/out/zero-cache/src/config/normalize.js +10 -1
  37. package/out/zero-cache/src/config/normalize.js.map +1 -1
  38. package/out/zero-cache/src/config/zero-config.d.ts +52 -1
  39. package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
  40. package/out/zero-cache/src/config/zero-config.js +171 -22
  41. package/out/zero-cache/src/config/zero-config.js.map +1 -1
  42. package/out/zero-cache/src/custom/fetch.js +1 -1
  43. package/out/zero-cache/src/custom/fetch.js.map +1 -1
  44. package/out/zero-cache/src/db/delete-lite-db.js +2 -1
  45. package/out/zero-cache/src/db/delete-lite-db.js.map +1 -1
  46. package/out/zero-cache/src/db/migration-lite.d.ts.map +1 -1
  47. package/out/zero-cache/src/db/migration-lite.js +5 -2
  48. package/out/zero-cache/src/db/migration-lite.js.map +1 -1
  49. package/out/zero-cache/src/db/migration.d.ts.map +1 -1
  50. package/out/zero-cache/src/db/migration.js +4 -2
  51. package/out/zero-cache/src/db/migration.js.map +1 -1
  52. package/out/zero-cache/src/db/sqlite-corruption.d.ts +3 -2
  53. package/out/zero-cache/src/db/sqlite-corruption.d.ts.map +1 -1
  54. package/out/zero-cache/src/db/sqlite-corruption.js +13 -8
  55. package/out/zero-cache/src/db/sqlite-corruption.js.map +1 -1
  56. package/out/zero-cache/src/observability/metrics.d.ts +6 -1
  57. package/out/zero-cache/src/observability/metrics.d.ts.map +1 -1
  58. package/out/zero-cache/src/observability/metrics.js +20 -2
  59. package/out/zero-cache/src/observability/metrics.js.map +1 -1
  60. package/out/zero-cache/src/server/backup-watermark-poller.js +31 -0
  61. package/out/zero-cache/src/server/backup-watermark-poller.js.map +1 -0
  62. package/out/zero-cache/src/server/change-streamer.d.ts.map +1 -1
  63. package/out/zero-cache/src/server/change-streamer.js +91 -31
  64. package/out/zero-cache/src/server/change-streamer.js.map +1 -1
  65. package/out/zero-cache/src/server/main.d.ts.map +1 -1
  66. package/out/zero-cache/src/server/main.js +6 -16
  67. package/out/zero-cache/src/server/main.js.map +1 -1
  68. package/out/zero-cache/src/server/replicator.d.ts.map +1 -1
  69. package/out/zero-cache/src/server/replicator.js +48 -5
  70. package/out/zero-cache/src/server/replicator.js.map +1 -1
  71. package/out/zero-cache/src/server/runner/run-worker.js +2 -1
  72. package/out/zero-cache/src/server/runner/run-worker.js.map +1 -1
  73. package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
  74. package/out/zero-cache/src/server/syncer.js +1 -1
  75. package/out/zero-cache/src/server/syncer.js.map +1 -1
  76. package/out/zero-cache/src/server/worker-urls.d.ts +1 -1
  77. package/out/zero-cache/src/server/worker-urls.js +2 -2
  78. package/out/zero-cache/src/server/worker-urls.js.map +1 -1
  79. package/out/zero-cache/src/services/change-source/change-source.d.ts +4 -2
  80. package/out/zero-cache/src/services/change-source/change-source.d.ts.map +1 -1
  81. package/out/zero-cache/src/services/change-source/common/replica-restore.d.ts +35 -0
  82. package/out/zero-cache/src/services/change-source/common/replica-restore.d.ts.map +1 -0
  83. package/out/zero-cache/src/services/change-source/common/replica-restore.js +34 -0
  84. package/out/zero-cache/src/services/change-source/common/replica-restore.js.map +1 -0
  85. package/out/zero-cache/src/services/change-source/common/replica-schema.d.ts +2 -0
  86. package/out/zero-cache/src/services/change-source/common/replica-schema.d.ts.map +1 -1
  87. package/out/zero-cache/src/services/change-source/common/replica-schema.js +73 -1
  88. package/out/zero-cache/src/services/change-source/common/replica-schema.js.map +1 -1
  89. package/out/zero-cache/src/services/change-source/custom/change-source.d.ts +2 -6
  90. package/out/zero-cache/src/services/change-source/custom/change-source.d.ts.map +1 -1
  91. package/out/zero-cache/src/services/change-source/custom/change-source.js +14 -5
  92. package/out/zero-cache/src/services/change-source/custom/change-source.js.map +1 -1
  93. package/out/zero-cache/src/services/change-source/pg/backfill-stream.js +4 -7
  94. package/out/zero-cache/src/services/change-source/pg/backfill-stream.js.map +1 -1
  95. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts +7 -7
  96. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts.map +1 -1
  97. package/out/zero-cache/src/services/change-source/pg/change-source.js +82 -25
  98. package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
  99. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts +9 -1
  100. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts.map +1 -1
  101. package/out/zero-cache/src/services/change-source/pg/initial-sync.js +12 -4
  102. package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
  103. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.d.ts +45 -2
  104. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.d.ts.map +1 -1
  105. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js +59 -8
  106. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js.map +1 -1
  107. package/out/zero-cache/src/services/change-source/pg/replication-slots.d.ts +4 -2
  108. package/out/zero-cache/src/services/change-source/pg/replication-slots.d.ts.map +1 -1
  109. package/out/zero-cache/src/services/change-source/pg/replication-slots.js +7 -4
  110. package/out/zero-cache/src/services/change-source/pg/replication-slots.js.map +1 -1
  111. package/out/zero-cache/src/services/change-source/pg/schema/init.d.ts +0 -5
  112. package/out/zero-cache/src/services/change-source/pg/schema/init.d.ts.map +1 -1
  113. package/out/zero-cache/src/services/change-source/pg/schema/init.js +29 -41
  114. package/out/zero-cache/src/services/change-source/pg/schema/init.js.map +1 -1
  115. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts +35 -16
  116. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts.map +1 -1
  117. package/out/zero-cache/src/services/change-source/pg/schema/shard.js +77 -7
  118. package/out/zero-cache/src/services/change-source/pg/schema/shard.js.map +1 -1
  119. package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts +2 -1
  120. package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts.map +1 -1
  121. package/out/zero-cache/src/services/change-source/protocol/current/data.js +5 -13
  122. package/out/zero-cache/src/services/change-source/protocol/current/data.js.map +1 -1
  123. package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts +6 -3
  124. package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts.map +1 -1
  125. package/out/zero-cache/src/services/change-source/protocol/current/schema-change-tags.d.ts +6 -0
  126. package/out/zero-cache/src/services/change-source/protocol/current/schema-change-tags.d.ts.map +1 -0
  127. package/out/zero-cache/src/services/change-source/protocol/current/schema-change-tags.js +21 -0
  128. package/out/zero-cache/src/services/change-source/protocol/current/schema-change-tags.js.map +1 -0
  129. package/out/zero-cache/src/services/change-source/protocol/current/status.d.ts +1 -0
  130. package/out/zero-cache/src/services/change-source/protocol/current/status.d.ts.map +1 -1
  131. package/out/zero-cache/src/services/change-source/protocol/current/upstream.d.ts +1 -0
  132. package/out/zero-cache/src/services/change-source/protocol/current/upstream.d.ts.map +1 -1
  133. package/out/zero-cache/src/services/change-streamer/backup-cleanup-monitor-factory.d.ts +5 -6
  134. package/out/zero-cache/src/services/change-streamer/backup-cleanup-monitor-factory.d.ts.map +1 -1
  135. package/out/zero-cache/src/services/change-streamer/backup-cleanup-monitor-factory.js +32 -9
  136. package/out/zero-cache/src/services/change-streamer/backup-cleanup-monitor-factory.js.map +1 -1
  137. package/out/zero-cache/src/services/change-streamer/backup-monitor.d.ts +15 -5
  138. package/out/zero-cache/src/services/change-streamer/backup-monitor.d.ts.map +1 -1
  139. package/out/zero-cache/src/services/change-streamer/backup-monitor.js +66 -0
  140. package/out/zero-cache/src/services/change-streamer/backup-monitor.js.map +1 -0
  141. package/out/zero-cache/src/services/change-streamer/broadcast.d.ts +68 -78
  142. package/out/zero-cache/src/services/change-streamer/broadcast.d.ts.map +1 -1
  143. package/out/zero-cache/src/services/change-streamer/broadcast.js +84 -92
  144. package/out/zero-cache/src/services/change-streamer/broadcast.js.map +1 -1
  145. package/out/zero-cache/src/services/change-streamer/change-log-codec.d.ts +19 -0
  146. package/out/zero-cache/src/services/change-streamer/change-log-codec.d.ts.map +1 -0
  147. package/out/zero-cache/src/services/change-streamer/change-log-codec.js +50 -0
  148. package/out/zero-cache/src/services/change-streamer/change-log-codec.js.map +1 -0
  149. package/out/zero-cache/src/services/change-streamer/change-log-initializer.d.ts +141 -0
  150. package/out/zero-cache/src/services/change-streamer/change-log-initializer.d.ts.map +1 -0
  151. package/out/zero-cache/src/services/change-streamer/change-log-initializer.js +270 -0
  152. package/out/zero-cache/src/services/change-streamer/change-log-initializer.js.map +1 -0
  153. package/out/zero-cache/src/services/change-streamer/change-log-transaction-hash.d.ts +19 -0
  154. package/out/zero-cache/src/services/change-streamer/change-log-transaction-hash.d.ts.map +1 -0
  155. package/out/zero-cache/src/services/change-streamer/change-log-transaction-hash.js +39 -0
  156. package/out/zero-cache/src/services/change-streamer/change-log-transaction-hash.js.map +1 -0
  157. package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts +3 -4
  158. package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts.map +1 -1
  159. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +12 -17
  160. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
  161. package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts +69 -24
  162. package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts.map +1 -1
  163. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js +333 -66
  164. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -1
  165. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts +56 -13
  166. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts.map +1 -1
  167. package/out/zero-cache/src/services/change-streamer/change-streamer.js.map +1 -1
  168. package/out/zero-cache/src/services/change-streamer/error-type-enum.d.ts +8 -0
  169. package/out/zero-cache/src/services/change-streamer/error-type-enum.d.ts.map +1 -1
  170. package/out/zero-cache/src/services/change-streamer/forwarder.d.ts +14 -3
  171. package/out/zero-cache/src/services/change-streamer/forwarder.d.ts.map +1 -1
  172. package/out/zero-cache/src/services/change-streamer/forwarder.js +41 -11
  173. package/out/zero-cache/src/services/change-streamer/forwarder.js.map +1 -1
  174. package/out/zero-cache/src/services/change-streamer/{litestream3-backup-monitor.d.ts → litestream3-prometheus-poller.d.ts} +19 -45
  175. package/out/zero-cache/src/services/change-streamer/litestream3-prometheus-poller.d.ts.map +1 -0
  176. package/out/zero-cache/src/services/change-streamer/{litestream3-backup-monitor.js → litestream3-prometheus-poller.js} +57 -171
  177. package/out/zero-cache/src/services/change-streamer/litestream3-prometheus-poller.js.map +1 -0
  178. package/out/zero-cache/src/services/change-streamer/replica-poller.d.ts +15 -0
  179. package/out/zero-cache/src/services/change-streamer/replica-poller.d.ts.map +1 -0
  180. package/out/zero-cache/src/services/change-streamer/replica-poller.js +55 -0
  181. package/out/zero-cache/src/services/change-streamer/replica-poller.js.map +1 -0
  182. package/out/zero-cache/src/services/change-streamer/schema/tables.d.ts +5 -1
  183. package/out/zero-cache/src/services/change-streamer/schema/tables.d.ts.map +1 -1
  184. package/out/zero-cache/src/services/change-streamer/schema/tables.js +2 -1
  185. package/out/zero-cache/src/services/change-streamer/schema/tables.js.map +1 -1
  186. package/out/zero-cache/src/services/change-streamer/snapshot-reservations.d.ts +14 -0
  187. package/out/zero-cache/src/services/change-streamer/snapshot-reservations.d.ts.map +1 -0
  188. package/out/zero-cache/src/services/change-streamer/snapshot-reservations.js +86 -0
  189. package/out/zero-cache/src/services/change-streamer/snapshot-reservations.js.map +1 -0
  190. package/out/zero-cache/src/services/change-streamer/snapshot.d.ts +4 -1
  191. package/out/zero-cache/src/services/change-streamer/snapshot.d.ts.map +1 -1
  192. package/out/zero-cache/src/services/change-streamer/snapshot.js +39 -14
  193. package/out/zero-cache/src/services/change-streamer/snapshot.js.map +1 -1
  194. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-catchup.d.ts +75 -0
  195. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-catchup.d.ts.map +1 -0
  196. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-catchup.js +261 -0
  197. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-catchup.js.map +1 -0
  198. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-purge-scheduler.d.ts +121 -0
  199. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-purge-scheduler.d.ts.map +1 -0
  200. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-purge-scheduler.js +391 -0
  201. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-purge-scheduler.js.map +1 -0
  202. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-reader.d.ts +62 -0
  203. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-reader.d.ts.map +1 -0
  204. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-reader.js +159 -0
  205. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-reader.js.map +1 -0
  206. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.d.ts +109 -0
  207. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.d.ts.map +1 -0
  208. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.js +258 -0
  209. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.js.map +1 -0
  210. package/out/zero-cache/src/services/change-streamer/storer.d.ts +28 -12
  211. package/out/zero-cache/src/services/change-streamer/storer.d.ts.map +1 -1
  212. package/out/zero-cache/src/services/change-streamer/storer.js +116 -121
  213. package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
  214. package/out/zero-cache/src/services/change-streamer/subscriber.d.ts +61 -10
  215. package/out/zero-cache/src/services/change-streamer/subscriber.d.ts.map +1 -1
  216. package/out/zero-cache/src/services/change-streamer/subscriber.js +101 -8
  217. package/out/zero-cache/src/services/change-streamer/subscriber.js.map +1 -1
  218. package/out/zero-cache/src/services/change-streamer/upstream-acker.d.ts +34 -0
  219. package/out/zero-cache/src/services/change-streamer/upstream-acker.d.ts.map +1 -0
  220. package/out/zero-cache/src/services/change-streamer/upstream-acker.js +86 -0
  221. package/out/zero-cache/src/services/change-streamer/upstream-acker.js.map +1 -0
  222. package/out/zero-cache/src/services/life-cycle.d.ts +1 -1
  223. package/out/zero-cache/src/services/life-cycle.d.ts.map +1 -1
  224. package/out/zero-cache/src/services/life-cycle.js +4 -3
  225. package/out/zero-cache/src/services/life-cycle.js.map +1 -1
  226. package/out/zero-cache/src/services/litestream/commands.d.ts +12 -11
  227. package/out/zero-cache/src/services/litestream/commands.d.ts.map +1 -1
  228. package/out/zero-cache/src/services/litestream/commands.js +107 -148
  229. package/out/zero-cache/src/services/litestream/commands.js.map +1 -1
  230. package/out/zero-cache/src/services/litestream/config-v5.yml +42 -0
  231. package/out/zero-cache/src/services/litestream/config.yml +3 -2
  232. package/out/zero-cache/src/services/litestream/metrics.d.ts +4 -4
  233. package/out/zero-cache/src/services/litestream/metrics.d.ts.map +1 -1
  234. package/out/zero-cache/src/services/litestream/metrics.js +7 -10
  235. package/out/zero-cache/src/services/litestream/metrics.js.map +1 -1
  236. package/out/zero-cache/src/services/litestream/vfs-watermark-poller.d.ts +57 -0
  237. package/out/zero-cache/src/services/litestream/vfs-watermark-poller.d.ts.map +1 -0
  238. package/out/zero-cache/src/services/litestream/vfs-watermark-poller.js +137 -0
  239. package/out/zero-cache/src/services/litestream/vfs-watermark-poller.js.map +1 -0
  240. package/out/zero-cache/src/services/mutagen/mutagen.d.ts.map +1 -1
  241. package/out/zero-cache/src/services/mutagen/mutagen.js +4 -1
  242. package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -1
  243. package/out/zero-cache/src/services/replicator/change-log-cookies.d.ts +169 -0
  244. package/out/zero-cache/src/services/replicator/change-log-cookies.d.ts.map +1 -0
  245. package/out/zero-cache/src/services/replicator/change-log-cookies.js +434 -0
  246. package/out/zero-cache/src/services/replicator/change-log-cookies.js.map +1 -0
  247. package/out/zero-cache/src/services/replicator/change-log-db.d.ts +358 -0
  248. package/out/zero-cache/src/services/replicator/change-log-db.d.ts.map +1 -0
  249. package/out/zero-cache/src/services/replicator/change-log-db.js +477 -0
  250. package/out/zero-cache/src/services/replicator/change-log-db.js.map +1 -0
  251. package/out/zero-cache/src/services/replicator/change-log-stream-writer.d.ts +55 -0
  252. package/out/zero-cache/src/services/replicator/change-log-stream-writer.d.ts.map +1 -0
  253. package/out/zero-cache/src/services/replicator/change-log-stream-writer.js +150 -0
  254. package/out/zero-cache/src/services/replicator/change-log-stream-writer.js.map +1 -0
  255. package/out/zero-cache/src/services/replicator/change-processor.d.ts +6 -0
  256. package/out/zero-cache/src/services/replicator/change-processor.d.ts.map +1 -1
  257. package/out/zero-cache/src/services/replicator/change-processor.js +70 -25
  258. package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
  259. package/out/zero-cache/src/services/replicator/incremental-sync.d.ts +1 -1
  260. package/out/zero-cache/src/services/replicator/incremental-sync.d.ts.map +1 -1
  261. package/out/zero-cache/src/services/replicator/incremental-sync.js +19 -6
  262. package/out/zero-cache/src/services/replicator/incremental-sync.js.map +1 -1
  263. package/out/zero-cache/src/services/replicator/notifier.d.ts +0 -22
  264. package/out/zero-cache/src/services/replicator/notifier.d.ts.map +1 -1
  265. package/out/zero-cache/src/services/replicator/notifier.js +7 -1
  266. package/out/zero-cache/src/services/replicator/notifier.js.map +1 -1
  267. package/out/zero-cache/src/services/replicator/replicator.d.ts +17 -2
  268. package/out/zero-cache/src/services/replicator/replicator.d.ts.map +1 -1
  269. package/out/zero-cache/src/services/replicator/replicator.js +9 -3
  270. package/out/zero-cache/src/services/replicator/replicator.js.map +1 -1
  271. package/out/zero-cache/src/services/replicator/reporter/recorder.d.ts +27 -0
  272. package/out/zero-cache/src/services/replicator/reporter/recorder.d.ts.map +1 -1
  273. package/out/zero-cache/src/services/replicator/reporter/recorder.js +32 -0
  274. package/out/zero-cache/src/services/replicator/reporter/recorder.js.map +1 -1
  275. package/out/zero-cache/src/services/replicator/reporter/report-schema.d.ts +1 -1
  276. package/out/zero-cache/src/services/replicator/schema/backfilling.d.ts +119 -0
  277. package/out/zero-cache/src/services/replicator/schema/backfilling.d.ts.map +1 -0
  278. package/out/zero-cache/src/services/replicator/schema/backfilling.js +214 -0
  279. package/out/zero-cache/src/services/replicator/schema/backfilling.js.map +1 -0
  280. package/out/zero-cache/src/services/replicator/schema/change-log.d.ts +3 -3
  281. package/out/zero-cache/src/services/replicator/schema/column-metadata.js +1 -1
  282. package/out/zero-cache/src/services/replicator/schema/column-metadata.js.map +1 -1
  283. package/out/zero-cache/src/services/replicator/schema/replication-state.d.ts +1 -1
  284. package/out/zero-cache/src/services/replicator/schema/replication-state.d.ts.map +1 -1
  285. package/out/zero-cache/src/services/replicator/schema/replication-state.js +9 -5
  286. package/out/zero-cache/src/services/replicator/schema/replication-state.js.map +1 -1
  287. package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.d.ts +131 -0
  288. package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.d.ts.map +1 -0
  289. package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.js +413 -0
  290. package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.js.map +1 -0
  291. package/out/zero-cache/src/services/replicator/sqlite-change-log-purger.d.ts +120 -0
  292. package/out/zero-cache/src/services/replicator/sqlite-change-log-purger.d.ts.map +1 -0
  293. package/out/zero-cache/src/services/replicator/sqlite-change-log-purger.js +283 -0
  294. package/out/zero-cache/src/services/replicator/sqlite-change-log-purger.js.map +1 -0
  295. package/out/zero-cache/src/services/replicator/write-worker.js +23 -12
  296. package/out/zero-cache/src/services/replicator/write-worker.js.map +1 -1
  297. package/out/zero-cache/src/services/run-ast.d.ts.map +1 -1
  298. package/out/zero-cache/src/services/run-ast.js +2 -1
  299. package/out/zero-cache/src/services/run-ast.js.map +1 -1
  300. package/out/zero-cache/src/services/running-state.d.ts +1 -1
  301. package/out/zero-cache/src/services/running-state.d.ts.map +1 -1
  302. package/out/zero-cache/src/services/running-state.js +1 -0
  303. package/out/zero-cache/src/services/running-state.js.map +1 -1
  304. package/out/zero-cache/src/services/view-syncer/e2e-serving-lag.d.ts +53 -0
  305. package/out/zero-cache/src/services/view-syncer/e2e-serving-lag.d.ts.map +1 -0
  306. package/out/zero-cache/src/services/view-syncer/e2e-serving-lag.js +68 -0
  307. package/out/zero-cache/src/services/view-syncer/e2e-serving-lag.js.map +1 -0
  308. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
  309. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +18 -3
  310. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
  311. package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts.map +1 -1
  312. package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
  313. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts +11 -1
  314. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
  315. package/out/zero-cache/src/services/view-syncer/view-syncer.js +64 -6
  316. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  317. package/out/zero-cache/src/types/processes.d.ts +1 -2
  318. package/out/zero-cache/src/types/processes.d.ts.map +1 -1
  319. package/out/zero-cache/src/types/processes.js +1 -25
  320. package/out/zero-cache/src/types/processes.js.map +1 -1
  321. package/out/zero-cache/src/types/streams.d.ts +21 -0
  322. package/out/zero-cache/src/types/streams.d.ts.map +1 -1
  323. package/out/zero-cache/src/types/streams.js +25 -4
  324. package/out/zero-cache/src/types/streams.js.map +1 -1
  325. package/out/zero-cache/src/types/subscription.d.ts +11 -0
  326. package/out/zero-cache/src/types/subscription.d.ts.map +1 -1
  327. package/out/zero-cache/src/types/subscription.js +27 -0
  328. package/out/zero-cache/src/types/subscription.js.map +1 -1
  329. package/out/zero-cache/src/workers/connection.d.ts +1 -0
  330. package/out/zero-cache/src/workers/connection.d.ts.map +1 -1
  331. package/out/zero-cache/src/workers/connection.js +24 -2
  332. package/out/zero-cache/src/workers/connection.js.map +1 -1
  333. package/out/zero-cache/src/workers/replicator.d.ts +25 -0
  334. package/out/zero-cache/src/workers/replicator.d.ts.map +1 -1
  335. package/out/zero-cache/src/workers/replicator.js +33 -1
  336. package/out/zero-cache/src/workers/replicator.js.map +1 -1
  337. package/out/zero-cache/src/workers/syncer.d.ts +12 -0
  338. package/out/zero-cache/src/workers/syncer.d.ts.map +1 -1
  339. package/out/zero-cache/src/workers/syncer.js +75 -0
  340. package/out/zero-cache/src/workers/syncer.js.map +1 -1
  341. package/out/zero-client/src/client/version.js +1 -1
  342. package/out/zero-client/src/client/zero.d.ts +6 -7
  343. package/out/zero-client/src/client/zero.d.ts.map +1 -1
  344. package/out/zero-client/src/client/zero.js +156 -101
  345. package/out/zero-client/src/client/zero.js.map +1 -1
  346. package/out/zero-schema/src/builder/table-builder.d.ts +23 -0
  347. package/out/zero-schema/src/builder/table-builder.d.ts.map +1 -1
  348. package/out/zero-schema/src/builder/table-builder.js +18 -0
  349. package/out/zero-schema/src/builder/table-builder.js.map +1 -1
  350. package/out/zero-server/src/custom.js +10 -3
  351. package/out/zero-server/src/custom.js.map +1 -1
  352. package/out/zero-server/src/schema.d.ts +8 -0
  353. package/out/zero-server/src/schema.d.ts.map +1 -1
  354. package/out/zero-server/src/schema.js +63 -24
  355. package/out/zero-server/src/schema.js.map +1 -1
  356. package/out/zero-types/src/schema.d.ts +11 -0
  357. package/out/zero-types/src/schema.d.ts.map +1 -1
  358. package/out/zql/src/mutate/crud.d.ts +10 -8
  359. package/out/zql/src/mutate/crud.d.ts.map +1 -1
  360. package/out/zql/src/mutate/crud.js.map +1 -1
  361. package/out/zql/src/query/query-delegate-base.d.ts.map +1 -1
  362. package/out/zql/src/query/query-delegate-base.js +5 -1
  363. package/out/zql/src/query/query-delegate-base.js.map +1 -1
  364. package/out/zql/src/query/query-impl.d.ts +2 -2
  365. package/out/zql/src/query/query-impl.d.ts.map +1 -1
  366. package/out/zql/src/query/query-impl.js.map +1 -1
  367. package/out/zql/src/query/query.d.ts +83 -14
  368. package/out/zql/src/query/query.d.ts.map +1 -1
  369. package/out/zql/src/query/static-query.d.ts +1 -1
  370. package/out/zql/src/query/static-query.d.ts.map +1 -1
  371. package/out/zqlite/src/db.js +2 -2
  372. package/out/zqlite/src/resolve-scalar-subqueries.d.ts +15 -0
  373. package/out/zqlite/src/resolve-scalar-subqueries.d.ts.map +1 -1
  374. package/out/zqlite/src/resolve-scalar-subqueries.js +33 -14
  375. package/out/zqlite/src/resolve-scalar-subqueries.js.map +1 -1
  376. package/out/zqlite/src/sqlite-cost-model.js +5 -5
  377. package/out/zqlite/src/table-source.js +3 -3
  378. package/package.json +3 -3
  379. package/out/replicache/src/db/index.js +0 -91
  380. package/out/replicache/src/db/index.js.map +0 -1
  381. package/out/replicache/src/lazy.d.ts +0 -2
  382. package/out/replicache/src/lazy.d.ts.map +0 -1
  383. package/out/replicache/src/lazy.js +0 -12
  384. package/out/replicache/src/lazy.js.map +0 -1
  385. package/out/zero-cache/src/server/backup-watermark-reader.js +0 -35
  386. package/out/zero-cache/src/server/backup-watermark-reader.js.map +0 -1
  387. package/out/zero-cache/src/services/change-streamer/litestream3-backup-monitor.d.ts.map +0 -1
  388. package/out/zero-cache/src/services/change-streamer/litestream3-backup-monitor.js.map +0 -1
  389. package/out/zero-cache/src/services/change-streamer/replica-monitor.d.ts +0 -16
  390. package/out/zero-cache/src/services/change-streamer/replica-monitor.d.ts.map +0 -1
  391. package/out/zero-cache/src/services/change-streamer/replica-monitor.js +0 -54
  392. package/out/zero-cache/src/services/change-streamer/replica-monitor.js.map +0 -1
  393. package/out/zero-cache/src/services/change-streamer/vfs-backup-monitor.d.ts +0 -25
  394. package/out/zero-cache/src/services/change-streamer/vfs-backup-monitor.d.ts.map +0 -1
  395. package/out/zero-cache/src/services/change-streamer/vfs-backup-monitor.js +0 -159
  396. package/out/zero-cache/src/services/change-streamer/vfs-backup-monitor.js.map +0 -1
  397. package/out/zero-cache/src/services/litestream/vfs-watermark-reader.d.ts +0 -44
  398. package/out/zero-cache/src/services/litestream/vfs-watermark-reader.d.ts.map +0 -1
  399. package/out/zero-cache/src/services/litestream/vfs-watermark-reader.js +0 -65
  400. package/out/zero-cache/src/services/litestream/vfs-watermark-reader.js.map +0 -1
  401. package/out/zero-cache/src/services/litestream/vfs-watermark-worker-source.d.ts +0 -11
  402. package/out/zero-cache/src/services/litestream/vfs-watermark-worker-source.d.ts.map +0 -1
  403. package/out/zero-cache/src/services/litestream/vfs-watermark-worker-source.js +0 -74
  404. package/out/zero-cache/src/services/litestream/vfs-watermark-worker-source.js.map +0 -1
  405. package/out/zero-cache/src/services/litestream/vfs-watermark-worker.d.ts +0 -42
  406. package/out/zero-cache/src/services/litestream/vfs-watermark-worker.d.ts.map +0 -1
  407. package/out/zero-cache/src/services/litestream/vfs-watermark-worker.js +0 -117
  408. package/out/zero-cache/src/services/litestream/vfs-watermark-worker.js.map +0 -1
@@ -1,31 +1,38 @@
1
- import { unreachable } from "../../../../shared/src/asserts.js";
1
+ import { assert, unreachable } from "../../../../shared/src/asserts.js";
2
2
  import { promiseVoid } from "../../../../shared/src/resolved-promises.js";
3
+ import { must } from "../../../../shared/src/must.js";
3
4
  import "../change-source/protocol/current/downstream.js";
4
- import { getOrCreateCounter } from "../../observability/metrics.js";
5
+ import { getOrCreateCounter, getOrCreateLatencyHistogram } from "../../observability/metrics.js";
5
6
  import { DEFAULT_MAX_RETRY_DELAY_MS, RunningState, UnrecoverableError } from "../running-state.js";
6
7
  import { min } from "../../types/lexi-version.js";
7
8
  import { publishCriticalEvent } from "../../observability/events.js";
8
- import { AutoResetSignal, ensureReplicationConfig, markResetRequired } from "./schema/tables.js";
9
9
  import { Subscription } from "../../types/subscription.js";
10
+ import { AutoResetSignal, ensureReplicationConfig, markResetRequired } from "./schema/tables.js";
10
11
  import { publishReplicationError, replicationStatusError } from "../replicator/replication-status.js";
11
12
  import "./change-streamer.js";
13
+ import { SQLiteChangeLogReader } from "./sqlite-change-log-reader.js";
14
+ import { ChangeLogInitializer, replicaInitializationSource } from "./change-log-initializer.js";
12
15
  import { Forwarder } from "./forwarder.js";
13
- import { initChangeStreamerSchema } from "./schema/init.js";
16
+ import { SnapshotReservations } from "./snapshot-reservations.js";
17
+ import { SQLiteChangeLogCatchup } from "./sqlite-change-log-catchup.js";
18
+ import { SQLiteChangeLogPurgeScheduler } from "./sqlite-change-log-purge-scheduler.js";
19
+ import { SQLiteChangeLogWriter } from "./sqlite-change-log-writer.js";
14
20
  import { Storer } from "./storer.js";
15
21
  import { Subscriber } from "./subscriber.js";
22
+ import { UpstreamAcker } from "./upstream-acker.js";
16
23
  import { resolver } from "@rocicorp/resolver";
17
24
  import { getDefaultHighWaterMark } from "node:stream";
18
25
  //#region ../zero-cache/src/services/change-streamer/change-streamer-service.ts
19
26
  /**
20
27
  * Performs initialization and schema migrations to initialize a ChangeStreamerImpl.
21
28
  */
22
- async function initializeStreamer(lc, shard, taskID, discoveryAddress, discoveryProtocol, changeDB, changeSource, replicationStatusPublisher, subscriptionState, purgeLock, autoReset, opts, setTimeoutFn = setTimeout) {
23
- await initChangeStreamerSchema(lc, changeDB, shard);
24
- await ensureReplicationConfig(lc, changeDB, subscriptionState, shard, autoReset, setTimeoutFn);
29
+ async function initializeStreamer(lc, shard, taskID, discoveryAddress, discoveryProtocol, changeDB, changeSource, replicationStatusPublisher, subscriptionState, backupConfig, purgeLock, autoReset, opts, setTimeoutFn = setTimeout) {
30
+ await ensureReplicationConfig(lc, changeDB, subscriptionState, shard, autoReset, purgeLock ?? void 0, setTimeoutFn);
25
31
  const { replicaVersion } = subscriptionState;
26
- return new ChangeStreamerImpl(lc, shard, taskID, discoveryAddress, discoveryProtocol, changeDB, replicaVersion, changeSource, replicationStatusPublisher, purgeLock, autoReset, opts, setTimeoutFn);
32
+ return new ChangeStreamerImpl(lc, shard, taskID, discoveryAddress, discoveryProtocol, changeDB, replicaVersion, changeSource, replicationStatusPublisher, backupConfig, purgeLock, autoReset, opts, setTimeoutFn);
27
33
  }
28
34
  var REPLICATION_STATUS_ERROR_DELAY_THRESHOLD_MS = 5e3;
35
+ var DEFAULT_CHANGE_LOG_UNAVAILABLE_WARN_THRESHOLD_MS = 6e4;
29
36
  /**
30
37
  * Upstream-agnostic dispatch of messages in a {@link ChangeStreamMessage} to a
31
38
  * {@link Forwarder} and {@link Storer} to execute the forward-store-ack
@@ -173,30 +180,84 @@ var ChangeStreamerImpl = class {
173
180
  #source;
174
181
  #storer;
175
182
  #forwarder;
183
+ #reservations;
176
184
  #replicationStatusPublisher;
185
+ #sqliteCatchupOptions;
186
+ #changeLogWriter;
187
+ #purgeScheduler;
188
+ #acker;
189
+ #initializer;
177
190
  #autoReset;
178
191
  #state;
179
- #initialWatermarks = /* @__PURE__ */ new Set();
180
192
  #serving = resolver();
181
193
  #txCounter = getOrCreateCounter("replication", "transactions", "Count of replicated transactions");
182
194
  #changeCounter = getOrCreateCounter("replication", "changes", "Count of replicated changes (DML or DDL statements)");
195
+ #transactionForwardDuration = getOrCreateLatencyHistogram("replication", "transaction_forward_duration", "Time from receiving a transaction's `begin` to forwarding its `commit`, i.e. the change-streamer half of forward-to-subscriber latency.");
183
196
  #latestStatus;
197
+ #latestLagReportCommitTimeMs = 0;
198
+ #backupWatermark;
199
+ #pgPurgedWatermark = "";
200
+ /**
201
+ * The floor last logged as held back by a laggard. The level-triggered
202
+ * retry re-evaluates every {@link CLEANUP_DELAY_MS}; logging only when the
203
+ * blocking floor moves keeps a stuck subscriber from emitting the same
204
+ * line indefinitely.
205
+ */
206
+ #loggedBehindWatermark;
207
+ #sqlitePurgeContinuation;
184
208
  #purgeLock;
209
+ #pgPurgeScheduled = false;
210
+ #pgPurgeRunning = false;
211
+ #sqlitePurgeScheduled = false;
212
+ #sqlitePurgeRunning = false;
185
213
  #stream;
186
- constructor(lc, shard, taskID, discoveryAddress, discoveryProtocol, changeDB, replicaVersion, source, replicationStatusPublisher, initialPurgeLock, autoReset, opts, setTimeoutFn = setTimeout) {
214
+ #sqliteCatchup;
215
+ #changeLogUnavailableSince;
216
+ #lastForwardedCommitWatermark;
217
+ #transactionForwardStartedAt;
218
+ #currentTransactionCompletion;
219
+ constructor(lc, shard, taskID, discoveryAddress, discoveryProtocol, changeDB, replicaVersion, source, replicationStatusPublisher, backupConfig, initialPurgeLock, autoReset, opts, setTimeoutFn = setTimeout) {
187
220
  this.id = `change-streamer`;
188
221
  this.#lc = lc.withContext("component", "change-streamer");
189
222
  this.#shard = shard;
190
223
  this.#changeDB = changeDB;
191
224
  this.#replicaVersion = replicaVersion;
192
225
  this.#source = source;
193
- this.#storer = new Storer(lc, shard, taskID, discoveryAddress, discoveryProtocol, changeDB, replicaVersion, (consumed) => this.#stream?.acks.push([
194
- "status",
195
- consumed[1],
196
- consumed[2]
197
- ]), (err) => this.stop(err), opts);
198
- this.#forwarder = new Forwarder(lc, { flowControlConsensusPaddingSeconds: opts.flowControlConsensusPaddingSeconds });
226
+ this.#storer = new Storer(lc, shard, taskID, discoveryAddress, discoveryProtocol, changeDB, replicaVersion, (consumed) => this.#acker.trackPgChangeLog(consumed[2].watermark), (err) => this.stop(err), opts);
227
+ this.#forwarder = new Forwarder(lc, {
228
+ flowControlConsensusTimeoutProportion: opts.flowControlConsensusTimeoutProportion,
229
+ flowControlSlowSubscriberGracePeriodMs: opts.flowControlSlowSubscriberGracePeriodMs
230
+ });
231
+ this.#reservations = backupConfig ? new SnapshotReservations(lc, backupConfig, (taskID) => this.#purgeScheduler?.resume(taskID)) : void 0;
199
232
  this.#replicationStatusPublisher = replicationStatusPublisher;
233
+ this.#changeLogWriter = opts.sqliteChangeLogWriter ? new SQLiteChangeLogWriter(lc, {
234
+ ...opts.sqliteChangeLogWriter,
235
+ onCommit: (watermark) => {
236
+ this.#sqliteCatchup?.onChangeLogCommit(watermark);
237
+ this.#purgeScheduler?.onWriterIdle();
238
+ },
239
+ onDisabled: () => this.#closeSQLiteCatchup(),
240
+ onRebuilt: () => this.#closeSQLiteCatchup()
241
+ }) : void 0;
242
+ this.#purgeScheduler = opts.sqliteChangeLogPurge && this.#changeLogWriter ? new SQLiteChangeLogPurgeScheduler(lc, () => this.#changeLogWriter?.connection, () => this.#forwarder.getAcks(), opts.sqliteChangeLogPurge) : void 0;
243
+ this.#acker = new UpstreamAcker({
244
+ trackPgChangeLog: true,
245
+ trackBackup: backupConfig?.litestreamVersion === "v5"
246
+ });
247
+ const replicaSource = opts.sqliteChangeLogCompare ? replicaInitializationSource(lc, opts.sqliteChangeLogCompare.replicaFile) : void 0;
248
+ this.#initializer = new ChangeLogInitializer(lc, {
249
+ initFromPgChangeLog: true,
250
+ initFromReplica: replicaSource !== void 0
251
+ }, {
252
+ pgChangeLog: () => this.#storer.getStartStreamInitializationParameters(),
253
+ replica: () => must(replicaSource)(),
254
+ reconcileChangeLog: (resumeFrom, seed) => resumeFrom ? this.#changeLogWriter?.reconcile(resumeFrom) : this.#changeLogWriter?.reconcileFromLog(seed),
255
+ changeLog: () => this.#changeLogWriter?.connection
256
+ });
257
+ this.#sqliteCatchupOptions = opts.sqliteCatchup ? {
258
+ ...opts.sqliteCatchup,
259
+ cleanupGuard: opts.sqliteCatchup.cleanupGuard ?? this.#purgeScheduler?.cleanupGuard
260
+ } : void 0;
200
261
  this.#purgeLock = initialPurgeLock;
201
262
  this.#autoReset = autoReset;
202
263
  this.#state = new RunningState(this.id, void 0, setTimeoutFn);
@@ -205,8 +266,11 @@ var ChangeStreamerImpl = class {
205
266
  async run() {
206
267
  this.#lc.info?.("starting change stream");
207
268
  this.#forwarder.startProgressMonitor();
208
- const lagReport = await this.#source.startLagReporter();
209
- if (lagReport) this.#latestStatus.lagReport = lagReport;
269
+ const lagReportInit = await this.#source.startLagReporter();
270
+ if (lagReportInit) {
271
+ this.#latestStatus.lagReport = { nextSendTimeMs: lagReportInit.nextSendTimeMs };
272
+ this.#latestLagReportCommitTimeMs = lagReportInit.firstCommitTimeMs;
273
+ }
210
274
  await this.#storer.assumeOwnership(this.#purgeLock);
211
275
  this.#purgeLock = null;
212
276
  const flushBytesThreshold = getDefaultHighWaterMark(false);
@@ -215,19 +279,22 @@ var ChangeStreamerImpl = class {
215
279
  let watermark = null;
216
280
  let unflushedBytes = 0;
217
281
  try {
218
- const { lastWatermark, backfillRequests } = await this.#storer.getStartStreamInitializationParameters();
282
+ const { lastWatermark, backfillRequests } = await this.#initializer.initialize();
283
+ this.#lastForwardedCommitWatermark = lastWatermark;
219
284
  const stream = await this.#source.startStream(lastWatermark, backfillRequests);
220
285
  this.#storer.run().catch((e) => stream.changes.cancel(e));
221
286
  this.#stream = stream;
222
287
  if (this.#state.resetBackoff() > REPLICATION_STATUS_ERROR_DELAY_THRESHOLD_MS) this.#replicationStatusPublisher.publish(this.#lc, "Replicating", `Replicating from ${lastWatermark}`);
223
288
  watermark = null;
289
+ this.#acker.reset(stream.acks);
224
290
  for await (const change of stream.changes) {
291
+ this.#acker.trackDownstream(change);
225
292
  const [type, msg] = change;
226
293
  switch (type) {
227
294
  case "status":
228
- if (msg.ack) this.#storer.status(change);
229
- if (msg.lagReport) {
295
+ if (msg.lagReport && msg.lagReport.lastTimings.commitTimeMs >= this.#latestLagReportCommitTimeMs) {
230
296
  this.#latestStatus.lagReport = msg.lagReport;
297
+ this.#latestLagReportCommitTimeMs = msg.lagReport.lastTimings.commitTimeMs;
231
298
  this.#forwarder.sendStatus(this.#latestStatus);
232
299
  }
233
300
  continue;
@@ -247,20 +314,25 @@ var ChangeStreamerImpl = class {
247
314
  break;
248
315
  }
249
316
  const json = this.#storer.store(watermark, change);
317
+ this.#changeLogWriter?.write(change, json);
250
318
  const entry = [
251
319
  watermark,
252
320
  change[1].tag,
253
321
  json
254
322
  ];
255
323
  unflushedBytes += json.length;
256
- if (unflushedBytes < flushBytesThreshold) this.#forwarder.forward(entry);
257
- else {
258
- await this.#forwarder.forwardWithFlowControl(entry);
324
+ if (unflushedBytes < flushBytesThreshold) {
325
+ this.#forwarder.forward(entry);
326
+ this.#recordForwardedTransactionBoundary(type, entry[0]);
327
+ } else {
328
+ const forwarded = this.#forwarder.forwardWithFlowControl(entry);
329
+ this.#recordForwardedTransactionBoundary(type, entry[0]);
330
+ await stream.changes.doneOr(forwarded);
259
331
  unflushedBytes = 0;
260
332
  }
261
333
  if (type === "commit" || type === "rollback") watermark = null;
262
334
  const readyForMore = this.#storer.readyForMore();
263
- if (readyForMore) await readyForMore;
335
+ if (readyForMore) await stream.changes.doneOr(readyForMore);
264
336
  }
265
337
  } catch (e) {
266
338
  err = e;
@@ -271,11 +343,14 @@ var ChangeStreamerImpl = class {
271
343
  if (watermark) {
272
344
  this.#lc.warn?.(`aborting interrupted transaction ${watermark}`);
273
345
  this.#storer.abort();
346
+ this.#changeLogWriter?.abort();
347
+ this.#purgeScheduler?.onWriterIdle();
274
348
  this.#forwarder.forward([
275
349
  watermark,
276
350
  "rollback",
277
351
  ROLLBACK_JSON
278
352
  ]);
353
+ this.#recordForwardedTransactionBoundary("rollback", watermark);
279
354
  }
280
355
  await Promise.all([
281
356
  this.#storer.stop(),
@@ -301,27 +376,88 @@ var ChangeStreamerImpl = class {
301
376
  default: unreachable(tag);
302
377
  }
303
378
  }
304
- subscribe(ctx) {
379
+ async subscribe(ctx) {
305
380
  const { protocolVersion, id, mode, replicaVersion, watermark } = ctx;
306
381
  if (mode === "serving") this.#serving.resolve();
307
- const downstream = Subscription.create({ cleanup: () => this.#forwarder.remove(subscriber) });
308
- const subscriber = new Subscriber(protocolVersion, id, watermark, downstream, () => this.#latestStatus);
382
+ let cleanupSubscriber = () => {};
383
+ const downstream = Subscription.create({ cleanup: () => cleanupSubscriber() });
384
+ const subscriber = new Subscriber(protocolVersion, id, watermark, downstream, () => this.#latestStatus, {});
385
+ const lc = this.#lc.withContext("subscriber", subscriber.id);
386
+ cleanupSubscriber = () => {
387
+ lc.info?.(`removing subscriber ${subscriber.id}`);
388
+ this.#forwarder.remove(subscriber);
389
+ };
309
390
  if (replicaVersion !== this.#replicaVersion) {
310
- this.#lc.warn?.(`rejecting subscriber at replica version ${replicaVersion}`);
391
+ lc.warn?.(`rejecting subscriber at replica version ${replicaVersion}`);
311
392
  subscriber.close(1, `current replica version is ${this.#replicaVersion} (requested ${replicaVersion})`);
312
393
  } else {
313
- this.#lc.debug?.(`adding subscriber ${subscriber.id}`);
314
- this.#forwarder.add(subscriber);
315
- this.#storer.catchup(subscriber, mode);
394
+ lc.info?.(`adding subscriber ${subscriber.id}`);
395
+ const sqliteCatchup = this.#selectSQLiteCatchup(ctx);
396
+ if (sqliteCatchup) {
397
+ cleanupSubscriber = () => sqliteCatchup.remove(subscriber);
398
+ await sqliteCatchup.catchup(subscriber, () => this.#captureRequiredHead());
399
+ } else {
400
+ this.#forwarder.add(subscriber);
401
+ this.#storer.catchup(subscriber, mode);
402
+ }
403
+ }
404
+ this.#reservations?.close(ctx.taskID);
405
+ return downstream;
406
+ }
407
+ async startSnapshotReservation(taskID) {
408
+ if (!this.#reservations) throw new Error("backups are not configured");
409
+ const downstream = this.#reservations.open(taskID);
410
+ try {
411
+ await (this.#purgeScheduler?.pause(taskID) ?? promiseVoid);
412
+ await this.#confirmReservations();
413
+ return downstream;
414
+ } catch (e) {
415
+ downstream.cancel();
416
+ throw e;
417
+ }
418
+ }
419
+ trackBackupWatermark(watermark) {
420
+ this.#backupWatermark = watermark;
421
+ this.#acker.trackBackup(watermark);
422
+ this.#requestSQLitePurge("deferred");
423
+ this.#maybeSchedulePGPurge();
424
+ this.#maybeScheduleSQLitePurge();
425
+ this.#confirmReservations().catch((e) => this.#lc.warn?.(`error confirming snapshot reservation`, e));
426
+ }
427
+ async #confirmReservations() {
428
+ if (this.#backupWatermark && this.#reservations?.confirmationsRequired()) {
429
+ const { replicaVersion, minWatermark } = await this.#getChangeLogState();
430
+ if (minWatermark <= this.#backupWatermark) this.#reservations?.confirm(replicaVersion, this.#backupWatermark);
431
+ else this.#lc.error?.(`change-log minWatermark ${minWatermark} is later than backupWatermark ${this.#backupWatermark}. Delaying confirmation of snapshot reservation until next backup.`);
316
432
  }
317
- return Promise.resolve(downstream);
318
433
  }
319
- scheduleCleanup(watermark) {
320
- const origSize = this.#initialWatermarks.size;
321
- this.#initialWatermarks.add(watermark);
322
- if (origSize === 0) this.#state.setTimeout(() => this.#purgeOldChanges(), CLEANUP_DELAY_MS);
434
+ #maybeSchedulePGPurge() {
435
+ const backupWatermark = this.#backupWatermark;
436
+ if (this.#pgPurgeScheduled || this.#pgPurgeRunning || backupWatermark === void 0 || this.#pgPurgedWatermark >= backupWatermark) return;
437
+ this.#pgPurgeScheduled = true;
438
+ this.#state.setTimeout(() => {
439
+ this.#pgPurgeScheduled = false;
440
+ this.#pgPurgeRunning = true;
441
+ return this.#purgePGChangeLog().finally(() => {
442
+ this.#pgPurgeRunning = false;
443
+ this.#maybeSchedulePGPurge();
444
+ });
445
+ }, CLEANUP_DELAY_MS);
446
+ }
447
+ #maybeScheduleSQLitePurge() {
448
+ if (this.#sqlitePurgeScheduled || this.#sqlitePurgeRunning || this.#backupWatermark === void 0 || this.#sqlitePurgeContinuation === void 0) return;
449
+ const delay = this.#sqlitePurgeContinuation === "immediate" ? 0 : CLEANUP_DELAY_MS;
450
+ this.#sqlitePurgeScheduled = true;
451
+ this.#state.setTimeout(() => {
452
+ this.#sqlitePurgeScheduled = false;
453
+ this.#sqlitePurgeRunning = true;
454
+ return this.#purgeSQLiteChangeLog().finally(() => {
455
+ this.#sqlitePurgeRunning = false;
456
+ this.#maybeScheduleSQLitePurge();
457
+ });
458
+ }, delay);
323
459
  }
324
- async getChangeLogState() {
460
+ async #getChangeLogState() {
325
461
  const minWatermark = await this.#storer.getMinWatermarkForCatchup();
326
462
  if (!minWatermark) this.#lc.warn?.(`Unexpected empty changeLog. Resync if "Local replica watermark" errors arise`);
327
463
  return {
@@ -329,45 +465,176 @@ var ChangeStreamerImpl = class {
329
465
  minWatermark: minWatermark ?? this.#replicaVersion
330
466
  };
331
467
  }
468
+ #getCleanupFloor() {
469
+ const backupWatermark = this.#backupWatermark;
470
+ assert(backupWatermark !== void 0, "cleanup cannot run without a backup watermark");
471
+ const current = [...this.#forwarder.getAcks(), ...this.#reservations?.getReservedWatermarks() ?? []];
472
+ return {
473
+ backupWatermark,
474
+ purgeWatermark: min(backupWatermark, ...current),
475
+ current
476
+ };
477
+ }
478
+ async #purgePGChangeLog() {
479
+ try {
480
+ const { backupWatermark, purgeWatermark, current } = this.#getCleanupFloor();
481
+ if (purgeWatermark < backupWatermark) {
482
+ if (this.#loggedBehindWatermark !== purgeWatermark) {
483
+ this.#loggedBehindWatermark = purgeWatermark;
484
+ this.#lc.info?.(`At least one client is behind backup ${backupWatermark}`, { watermarks: current });
485
+ }
486
+ } else this.#loggedBehindWatermark = void 0;
487
+ if (purgeWatermark <= this.#pgPurgedWatermark) return;
488
+ this.#lc.info?.(`Purging PG changes before ${purgeWatermark} ...`);
489
+ const start = performance.now();
490
+ const deleted = await this.#storer.purgeRecordsBefore(purgeWatermark);
491
+ const elapsed = (performance.now() - start).toFixed(2);
492
+ this.#lc.info?.(`Purged ${deleted} PG changes before ${purgeWatermark} (${elapsed} ms)`);
493
+ this.#pgPurgedWatermark = purgeWatermark;
494
+ } catch (e) {
495
+ this.#lc.warn?.(`error purging the PG change log`, e);
496
+ }
497
+ }
498
+ async #purgeSQLiteChangeLog() {
499
+ const scheduler = this.#purgeScheduler;
500
+ if (!scheduler) return;
501
+ try {
502
+ const { backupWatermark, purgeWatermark } = this.#getCleanupFloor();
503
+ this.#sqlitePurgeContinuation = void 0;
504
+ if (purgeWatermark < backupWatermark) this.#requestSQLitePurge("deferred");
505
+ const result = await scheduler.purge(purgeWatermark);
506
+ this.#requestSQLitePurge(result.continuation);
507
+ } catch (e) {
508
+ this.#requestSQLitePurge("deferred");
509
+ this.#lc.warn?.(`error purging the SQLite change log`, e);
510
+ }
511
+ }
512
+ #requestSQLitePurge(continuation) {
513
+ if (!this.#purgeScheduler || continuation === void 0) return;
514
+ if (continuation === "immediate" || this.#sqlitePurgeContinuation === void 0) this.#sqlitePurgeContinuation = continuation;
515
+ }
516
+ async stop(err) {
517
+ this.#state.stop(this.#lc, err);
518
+ this.#stream?.changes.cancel();
519
+ this.#purgeScheduler?.stop();
520
+ this.#sqliteCatchup?.close();
521
+ this.#changeLogWriter?.close();
522
+ await Promise.allSettled([this.#storer.stop(), this.#source.stop()]);
523
+ }
524
+ #recordForwardedTransactionBoundary(type, watermark) {
525
+ switch (type) {
526
+ case "begin":
527
+ assert(this.#currentTransactionCompletion === void 0, "forwarded begin while a transaction is already in progress");
528
+ this.#currentTransactionCompletion = resolver();
529
+ this.#transactionForwardStartedAt = performance.now();
530
+ break;
531
+ case "commit": {
532
+ const completion = this.#currentTransactionCompletion;
533
+ assert(completion, "forwarded commit without a pending transaction");
534
+ this.#recordTransactionForwardDuration();
535
+ this.#lastForwardedCommitWatermark = watermark;
536
+ this.#currentTransactionCompletion = void 0;
537
+ completion.resolve({
538
+ kind: "committed",
539
+ watermark
540
+ });
541
+ break;
542
+ }
543
+ case "rollback": {
544
+ const completion = this.#currentTransactionCompletion;
545
+ assert(completion, "forwarded rollback without a pending transaction");
546
+ const committed = this.#lastForwardedCommitWatermark;
547
+ assert(committed, "last forwarded commit watermark is not initialized");
548
+ this.#transactionForwardStartedAt = void 0;
549
+ this.#currentTransactionCompletion = void 0;
550
+ completion.resolve({
551
+ kind: "rolled-back",
552
+ watermark: committed
553
+ });
554
+ break;
555
+ }
556
+ }
557
+ }
558
+ #recordTransactionForwardDuration() {
559
+ const startedAt = this.#transactionForwardStartedAt;
560
+ this.#transactionForwardStartedAt = void 0;
561
+ if (startedAt !== void 0) this.#transactionForwardDuration.recordMs(performance.now() - startedAt, { sqlite_change_log: this.#changeLogWriter?.enabled ? "on" : "off" });
562
+ }
332
563
  /**
333
- * Makes a best effort to purge the change log. In the event of a database
334
- * error, exceptions will be logged and swallowed, so this method is safe
335
- * to run in a timeout.
564
+ * Closes and forgets the cached catchup coordinator, so that a later
565
+ * subscription re-opens the log from scratch rather than reading a handle
566
+ * whose file is gone.
336
567
  */
337
- async #purgeOldChanges() {
338
- const initial = [...this.#initialWatermarks];
339
- if (initial.length === 0) {
340
- this.#lc.warn?.("No initial watermarks to check for cleanup");
568
+ #closeSQLiteCatchup() {
569
+ this.#sqliteCatchup?.close();
570
+ this.#sqliteCatchup = void 0;
571
+ }
572
+ #captureRequiredHead() {
573
+ const committed = this.#lastForwardedCommitWatermark;
574
+ assert(committed, "last forwarded commit watermark is not initialized");
575
+ return this.#currentTransactionCompletion?.promise.then((completion) => completion.watermark) ?? committed;
576
+ }
577
+ #selectSQLiteCatchup(ctx) {
578
+ const opts = this.#sqliteCatchupOptions;
579
+ if (this.#lastForwardedCommitWatermark === void 0 || !opts) return;
580
+ if (ctx.mode !== "serving") {
581
+ this.#lc.info?.(`not serving backup subscriber ${ctx.id} from SQLite catchup`);
341
582
  return;
342
583
  }
343
- const current = [...this.#forwarder.getAcks()];
344
- if (current.length === 0) {
345
- this.#lc.warn?.("No subscribers to confirm cleanup");
584
+ if (ctx.logsChangeStream) {
585
+ this.#lc.warn?.(`not serving legacy change-log writer ${ctx.id} from SQLite catchup`);
346
586
  return;
347
587
  }
588
+ if (!opts.shouldUse?.(ctx)) return;
589
+ return this.#sqliteCatchup ?? this.#openSQLiteCatchup(opts, ctx);
590
+ }
591
+ /**
592
+ * Opens the change log and, if it can serve, wraps it in the coordinator that
593
+ * subsequent subscriptions reuse.
594
+ *
595
+ * The log may not exist yet -- the writer creates it at the stream loop's
596
+ * first reconcile, and deletes it when it fails soft -- or may exist without
597
+ * content, or may be unreadable. None of those can be allowed to fail a
598
+ * subscription:
599
+ * this is the last point at which PG catchup is still available -- past
600
+ * `Forwarder.add()` the subscriber is committed to SQLite -- so each declines
601
+ * here instead. Neither the failure nor the reader is retained, so a later
602
+ * subscription retries from scratch.
603
+ */
604
+ #openSQLiteCatchup(opts, ctx) {
605
+ let reader;
348
606
  try {
349
- const earliestInitial = min(...initial);
350
- const earliestCurrent = min(...current);
351
- if (earliestCurrent < earliestInitial) this.#lc.info?.(`At least one client is behind backup (${earliestCurrent} < ${earliestInitial})`);
352
- else {
353
- this.#lc.info?.(`Purging changes before ${earliestInitial} ...`);
354
- const start = performance.now();
355
- const deleted = await this.#storer.purgeRecordsBefore(earliestInitial);
356
- const elapsed = (performance.now() - start).toFixed(2);
357
- this.#lc.info?.(`Purged ${deleted} changes before ${earliestInitial} (${elapsed} ms)`);
358
- this.#initialWatermarks.delete(earliestInitial);
607
+ reader = new SQLiteChangeLogReader(this.#lc, opts.changeLogFile);
608
+ if (reader.plan(ctx.watermark).kind === "not-ready") {
609
+ reader.close();
610
+ this.#declineSQLiteCatchup(ctx, opts, `${opts.changeLogFile} has no changes to serve yet`);
611
+ return;
359
612
  }
360
613
  } catch (e) {
361
- this.#lc.warn?.(`error purging change log`, e);
362
- } finally {
363
- if (this.#initialWatermarks.size) this.#state.setTimeout(() => this.#purgeOldChanges(), CLEANUP_DELAY_MS);
614
+ reader?.close();
615
+ this.#declineSQLiteCatchup(ctx, opts, `cannot read ${opts.changeLogFile}`, e);
616
+ return;
364
617
  }
618
+ this.#changeLogUnavailableSince = void 0;
619
+ this.#sqliteCatchup = new SQLiteChangeLogCatchup(this.#lc, this.#forwarder, reader, {
620
+ batchSize: opts.readBatchRows,
621
+ barrierTimeoutMs: opts.barrierTimeoutMs,
622
+ barrierPollIntervalMs: opts.barrierPollIntervalMs,
623
+ cleanupGuard: opts.cleanupGuard
624
+ });
625
+ return this.#sqliteCatchup;
365
626
  }
366
- async stop(err) {
367
- this.#state.stop(this.#lc, err);
368
- this.#stream?.changes.cancel();
369
- await this.#storer.stop();
370
- await this.#source.stop();
627
+ /**
628
+ * Reports falling back to PG catchup, tracking how long the log has been
629
+ * unavailable so that a subscription that merely arrived before the writer's
630
+ * first reconcile does not look like an incident.
631
+ */
632
+ #declineSQLiteCatchup(ctx, opts, reason, error) {
633
+ const now = Date.now();
634
+ this.#changeLogUnavailableSince ??= now;
635
+ const unavailableMs = now - this.#changeLogUnavailableSince;
636
+ const threshold = opts.notReadyWarnThresholdMs ?? DEFAULT_CHANGE_LOG_UNAVAILABLE_WARN_THRESHOLD_MS;
637
+ this.#lc[unavailableMs >= threshold ? "warn" : "debug"]?.(`serving ${ctx.id} from PG catchup: ${reason} (unavailable for ${unavailableMs} ms)`, ...error === void 0 ? [] : [error]);
371
638
  }
372
639
  };
373
640
  var CLEANUP_DELAY_MS = DEFAULT_MAX_RETRY_DELAY_MS * 3;