@rocicorp/zero 1.9.1-canary.1 → 1.10.0-canary.1

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 (344) hide show
  1. package/out/analyze-query/src/analyze-cli.js +2 -2
  2. package/out/analyze-query/src/analyze-cli.js.map +1 -1
  3. package/out/replicache/src/db/commit.js +1 -4
  4. package/out/replicache/src/db/commit.js.map +1 -1
  5. package/out/replicache/src/db/read.d.ts +1 -0
  6. package/out/replicache/src/db/read.d.ts.map +1 -1
  7. package/out/replicache/src/db/read.js +1 -4
  8. package/out/replicache/src/db/read.js.map +1 -1
  9. package/out/replicache/src/db/write.d.ts +2 -1
  10. package/out/replicache/src/db/write.d.ts.map +1 -1
  11. package/out/replicache/src/db/write.js +4 -51
  12. package/out/replicache/src/db/write.js.map +1 -1
  13. package/out/replicache/src/persist/clients.d.ts +1 -0
  14. package/out/replicache/src/persist/clients.d.ts.map +1 -1
  15. package/out/replicache/src/persist/clients.js +4 -31
  16. package/out/replicache/src/persist/clients.js.map +1 -1
  17. package/out/replicache/src/process-env.d.ts +28 -0
  18. package/out/replicache/src/process-env.d.ts.map +1 -0
  19. package/out/replicache/src/replicache-impl.d.ts.map +1 -1
  20. package/out/replicache/src/replicache-impl.js.map +1 -1
  21. package/out/replicache/src/scan-iterator.js +2 -14
  22. package/out/replicache/src/scan-iterator.js.map +1 -1
  23. package/out/replicache/src/subscriptions.d.ts +1 -0
  24. package/out/replicache/src/subscriptions.d.ts.map +1 -1
  25. package/out/replicache/src/subscriptions.js +2 -10
  26. package/out/replicache/src/subscriptions.js.map +1 -1
  27. package/out/replicache/src/transactions.d.ts +1 -0
  28. package/out/replicache/src/transactions.d.ts.map +1 -1
  29. package/out/replicache/src/transactions.js +2 -4
  30. package/out/replicache/src/transactions.js.map +1 -1
  31. package/out/zero/package.js +2 -2
  32. package/out/zero/package.js.map +1 -1
  33. package/out/zero-cache/src/config/normalize.d.ts +1 -0
  34. package/out/zero-cache/src/config/normalize.d.ts.map +1 -1
  35. package/out/zero-cache/src/config/normalize.js +10 -1
  36. package/out/zero-cache/src/config/normalize.js.map +1 -1
  37. package/out/zero-cache/src/config/zero-config.d.ts +43 -1
  38. package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
  39. package/out/zero-cache/src/config/zero-config.js +139 -20
  40. package/out/zero-cache/src/config/zero-config.js.map +1 -1
  41. package/out/zero-cache/src/db/migration.js +1 -1
  42. package/out/zero-cache/src/observability/metrics.d.ts +5 -0
  43. package/out/zero-cache/src/observability/metrics.d.ts.map +1 -1
  44. package/out/zero-cache/src/observability/metrics.js +15 -1
  45. package/out/zero-cache/src/observability/metrics.js.map +1 -1
  46. package/out/zero-cache/src/server/backup-watermark-poller.js +31 -0
  47. package/out/zero-cache/src/server/backup-watermark-poller.js.map +1 -0
  48. package/out/zero-cache/src/server/change-streamer.d.ts.map +1 -1
  49. package/out/zero-cache/src/server/change-streamer.js +90 -30
  50. package/out/zero-cache/src/server/change-streamer.js.map +1 -1
  51. package/out/zero-cache/src/server/main.d.ts.map +1 -1
  52. package/out/zero-cache/src/server/main.js +5 -15
  53. package/out/zero-cache/src/server/main.js.map +1 -1
  54. package/out/zero-cache/src/server/replicator.d.ts.map +1 -1
  55. package/out/zero-cache/src/server/replicator.js +46 -3
  56. package/out/zero-cache/src/server/replicator.js.map +1 -1
  57. package/out/zero-cache/src/server/runner/run-worker.js +2 -1
  58. package/out/zero-cache/src/server/runner/run-worker.js.map +1 -1
  59. package/out/zero-cache/src/server/worker-urls.d.ts +1 -1
  60. package/out/zero-cache/src/server/worker-urls.js +2 -2
  61. package/out/zero-cache/src/server/worker-urls.js.map +1 -1
  62. package/out/zero-cache/src/services/change-source/change-source.d.ts +4 -2
  63. package/out/zero-cache/src/services/change-source/change-source.d.ts.map +1 -1
  64. package/out/zero-cache/src/services/change-source/common/replica-restore.d.ts +35 -0
  65. package/out/zero-cache/src/services/change-source/common/replica-restore.d.ts.map +1 -0
  66. package/out/zero-cache/src/services/change-source/common/replica-restore.js +34 -0
  67. package/out/zero-cache/src/services/change-source/common/replica-restore.js.map +1 -0
  68. package/out/zero-cache/src/services/change-source/common/replica-schema.d.ts +2 -0
  69. package/out/zero-cache/src/services/change-source/common/replica-schema.d.ts.map +1 -1
  70. package/out/zero-cache/src/services/change-source/common/replica-schema.js +73 -1
  71. package/out/zero-cache/src/services/change-source/common/replica-schema.js.map +1 -1
  72. package/out/zero-cache/src/services/change-source/custom/change-source.d.ts +2 -6
  73. package/out/zero-cache/src/services/change-source/custom/change-source.d.ts.map +1 -1
  74. package/out/zero-cache/src/services/change-source/custom/change-source.js +16 -7
  75. package/out/zero-cache/src/services/change-source/custom/change-source.js.map +1 -1
  76. package/out/zero-cache/src/services/change-source/pg/backfill-stream.js +4 -7
  77. package/out/zero-cache/src/services/change-source/pg/backfill-stream.js.map +1 -1
  78. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts +7 -7
  79. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts.map +1 -1
  80. package/out/zero-cache/src/services/change-source/pg/change-source.js +75 -23
  81. package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
  82. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts +9 -1
  83. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts.map +1 -1
  84. package/out/zero-cache/src/services/change-source/pg/initial-sync.js +34 -4
  85. package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
  86. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js +1 -1
  87. package/out/zero-cache/src/services/change-source/pg/replication-slots.d.ts +4 -2
  88. package/out/zero-cache/src/services/change-source/pg/replication-slots.d.ts.map +1 -1
  89. package/out/zero-cache/src/services/change-source/pg/replication-slots.js +7 -4
  90. package/out/zero-cache/src/services/change-source/pg/replication-slots.js.map +1 -1
  91. package/out/zero-cache/src/services/change-source/pg/schema/init.d.ts +0 -5
  92. package/out/zero-cache/src/services/change-source/pg/schema/init.d.ts.map +1 -1
  93. package/out/zero-cache/src/services/change-source/pg/schema/init.js +29 -41
  94. package/out/zero-cache/src/services/change-source/pg/schema/init.js.map +1 -1
  95. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts +35 -16
  96. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts.map +1 -1
  97. package/out/zero-cache/src/services/change-source/pg/schema/shard.js +77 -7
  98. package/out/zero-cache/src/services/change-source/pg/schema/shard.js.map +1 -1
  99. package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts +1 -1
  100. package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts.map +1 -1
  101. package/out/zero-cache/src/services/change-source/protocol/current/data.js +1 -12
  102. package/out/zero-cache/src/services/change-source/protocol/current/data.js.map +1 -1
  103. package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts +3 -3
  104. package/out/zero-cache/src/services/change-source/protocol/current/schema-change-tags.d.ts +6 -0
  105. package/out/zero-cache/src/services/change-source/protocol/current/schema-change-tags.d.ts.map +1 -0
  106. package/out/zero-cache/src/services/change-source/protocol/current/schema-change-tags.js +21 -0
  107. package/out/zero-cache/src/services/change-source/protocol/current/schema-change-tags.js.map +1 -0
  108. package/out/zero-cache/src/services/change-streamer/backup-cleanup-monitor-factory.d.ts +5 -6
  109. package/out/zero-cache/src/services/change-streamer/backup-cleanup-monitor-factory.d.ts.map +1 -1
  110. package/out/zero-cache/src/services/change-streamer/backup-cleanup-monitor-factory.js +32 -9
  111. package/out/zero-cache/src/services/change-streamer/backup-cleanup-monitor-factory.js.map +1 -1
  112. package/out/zero-cache/src/services/change-streamer/backup-monitor.d.ts +15 -5
  113. package/out/zero-cache/src/services/change-streamer/backup-monitor.d.ts.map +1 -1
  114. package/out/zero-cache/src/services/change-streamer/backup-monitor.js +66 -0
  115. package/out/zero-cache/src/services/change-streamer/backup-monitor.js.map +1 -0
  116. package/out/zero-cache/src/services/change-streamer/broadcast.d.ts +68 -78
  117. package/out/zero-cache/src/services/change-streamer/broadcast.d.ts.map +1 -1
  118. package/out/zero-cache/src/services/change-streamer/broadcast.js +84 -92
  119. package/out/zero-cache/src/services/change-streamer/broadcast.js.map +1 -1
  120. package/out/zero-cache/src/services/change-streamer/change-log-codec.d.ts +19 -0
  121. package/out/zero-cache/src/services/change-streamer/change-log-codec.d.ts.map +1 -0
  122. package/out/zero-cache/src/services/change-streamer/change-log-codec.js +50 -0
  123. package/out/zero-cache/src/services/change-streamer/change-log-codec.js.map +1 -0
  124. package/out/zero-cache/src/services/change-streamer/change-log-initializer.d.ts +141 -0
  125. package/out/zero-cache/src/services/change-streamer/change-log-initializer.d.ts.map +1 -0
  126. package/out/zero-cache/src/services/change-streamer/change-log-initializer.js +270 -0
  127. package/out/zero-cache/src/services/change-streamer/change-log-initializer.js.map +1 -0
  128. package/out/zero-cache/src/services/change-streamer/change-log-transaction-hash.d.ts +19 -0
  129. package/out/zero-cache/src/services/change-streamer/change-log-transaction-hash.d.ts.map +1 -0
  130. package/out/zero-cache/src/services/change-streamer/change-log-transaction-hash.js +39 -0
  131. package/out/zero-cache/src/services/change-streamer/change-log-transaction-hash.js.map +1 -0
  132. package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts +3 -4
  133. package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts.map +1 -1
  134. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +15 -20
  135. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
  136. package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts +69 -24
  137. package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts.map +1 -1
  138. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js +330 -63
  139. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -1
  140. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts +55 -13
  141. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts.map +1 -1
  142. package/out/zero-cache/src/services/change-streamer/change-streamer.js.map +1 -1
  143. package/out/zero-cache/src/services/change-streamer/error-type-enum.d.ts +8 -0
  144. package/out/zero-cache/src/services/change-streamer/error-type-enum.d.ts.map +1 -1
  145. package/out/zero-cache/src/services/change-streamer/forwarder.d.ts +14 -3
  146. package/out/zero-cache/src/services/change-streamer/forwarder.d.ts.map +1 -1
  147. package/out/zero-cache/src/services/change-streamer/forwarder.js +41 -11
  148. package/out/zero-cache/src/services/change-streamer/forwarder.js.map +1 -1
  149. package/out/zero-cache/src/services/change-streamer/{litestream3-backup-monitor.d.ts → litestream3-prometheus-poller.d.ts} +19 -45
  150. package/out/zero-cache/src/services/change-streamer/litestream3-prometheus-poller.d.ts.map +1 -0
  151. package/out/zero-cache/src/services/change-streamer/{litestream3-backup-monitor.js → litestream3-prometheus-poller.js} +57 -171
  152. package/out/zero-cache/src/services/change-streamer/litestream3-prometheus-poller.js.map +1 -0
  153. package/out/zero-cache/src/services/change-streamer/replica-poller.d.ts +15 -0
  154. package/out/zero-cache/src/services/change-streamer/replica-poller.d.ts.map +1 -0
  155. package/out/zero-cache/src/services/change-streamer/replica-poller.js +55 -0
  156. package/out/zero-cache/src/services/change-streamer/replica-poller.js.map +1 -0
  157. package/out/zero-cache/src/services/change-streamer/schema/tables.d.ts +5 -1
  158. package/out/zero-cache/src/services/change-streamer/schema/tables.d.ts.map +1 -1
  159. package/out/zero-cache/src/services/change-streamer/schema/tables.js +2 -1
  160. package/out/zero-cache/src/services/change-streamer/schema/tables.js.map +1 -1
  161. package/out/zero-cache/src/services/change-streamer/snapshot-reservations.d.ts +14 -0
  162. package/out/zero-cache/src/services/change-streamer/snapshot-reservations.d.ts.map +1 -0
  163. package/out/zero-cache/src/services/change-streamer/snapshot-reservations.js +86 -0
  164. package/out/zero-cache/src/services/change-streamer/snapshot-reservations.js.map +1 -0
  165. package/out/zero-cache/src/services/change-streamer/snapshot.d.ts +4 -1
  166. package/out/zero-cache/src/services/change-streamer/snapshot.d.ts.map +1 -1
  167. package/out/zero-cache/src/services/change-streamer/snapshot.js +39 -14
  168. package/out/zero-cache/src/services/change-streamer/snapshot.js.map +1 -1
  169. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-catchup.d.ts +75 -0
  170. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-catchup.d.ts.map +1 -0
  171. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-catchup.js +261 -0
  172. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-catchup.js.map +1 -0
  173. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-purge-scheduler.d.ts +121 -0
  174. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-purge-scheduler.d.ts.map +1 -0
  175. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-purge-scheduler.js +391 -0
  176. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-purge-scheduler.js.map +1 -0
  177. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-reader.d.ts +62 -0
  178. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-reader.d.ts.map +1 -0
  179. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-reader.js +159 -0
  180. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-reader.js.map +1 -0
  181. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.d.ts +109 -0
  182. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.d.ts.map +1 -0
  183. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.js +258 -0
  184. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.js.map +1 -0
  185. package/out/zero-cache/src/services/change-streamer/storer.d.ts +22 -12
  186. package/out/zero-cache/src/services/change-streamer/storer.d.ts.map +1 -1
  187. package/out/zero-cache/src/services/change-streamer/storer.js +93 -117
  188. package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
  189. package/out/zero-cache/src/services/change-streamer/subscriber.d.ts +61 -10
  190. package/out/zero-cache/src/services/change-streamer/subscriber.d.ts.map +1 -1
  191. package/out/zero-cache/src/services/change-streamer/subscriber.js +101 -8
  192. package/out/zero-cache/src/services/change-streamer/subscriber.js.map +1 -1
  193. package/out/zero-cache/src/services/change-streamer/upstream-acker.d.ts +34 -0
  194. package/out/zero-cache/src/services/change-streamer/upstream-acker.d.ts.map +1 -0
  195. package/out/zero-cache/src/services/change-streamer/upstream-acker.js +86 -0
  196. package/out/zero-cache/src/services/change-streamer/upstream-acker.js.map +1 -0
  197. package/out/zero-cache/src/services/life-cycle.d.ts +1 -1
  198. package/out/zero-cache/src/services/life-cycle.d.ts.map +1 -1
  199. package/out/zero-cache/src/services/life-cycle.js +3 -2
  200. package/out/zero-cache/src/services/life-cycle.js.map +1 -1
  201. package/out/zero-cache/src/services/litestream/commands.d.ts +12 -11
  202. package/out/zero-cache/src/services/litestream/commands.d.ts.map +1 -1
  203. package/out/zero-cache/src/services/litestream/commands.js +50 -140
  204. package/out/zero-cache/src/services/litestream/commands.js.map +1 -1
  205. package/out/zero-cache/src/services/litestream/config-v5.yml +42 -0
  206. package/out/zero-cache/src/services/litestream/metrics.d.ts +4 -4
  207. package/out/zero-cache/src/services/litestream/metrics.d.ts.map +1 -1
  208. package/out/zero-cache/src/services/litestream/metrics.js +7 -10
  209. package/out/zero-cache/src/services/litestream/metrics.js.map +1 -1
  210. package/out/zero-cache/src/services/litestream/vfs-watermark-poller.d.ts +57 -0
  211. package/out/zero-cache/src/services/litestream/vfs-watermark-poller.d.ts.map +1 -0
  212. package/out/zero-cache/src/services/litestream/vfs-watermark-poller.js +137 -0
  213. package/out/zero-cache/src/services/litestream/vfs-watermark-poller.js.map +1 -0
  214. package/out/zero-cache/src/services/replicator/change-log-cookies.d.ts +169 -0
  215. package/out/zero-cache/src/services/replicator/change-log-cookies.d.ts.map +1 -0
  216. package/out/zero-cache/src/services/replicator/change-log-cookies.js +434 -0
  217. package/out/zero-cache/src/services/replicator/change-log-cookies.js.map +1 -0
  218. package/out/zero-cache/src/services/replicator/change-log-db.d.ts +358 -0
  219. package/out/zero-cache/src/services/replicator/change-log-db.d.ts.map +1 -0
  220. package/out/zero-cache/src/services/replicator/change-log-db.js +477 -0
  221. package/out/zero-cache/src/services/replicator/change-log-db.js.map +1 -0
  222. package/out/zero-cache/src/services/replicator/change-log-stream-writer.d.ts +55 -0
  223. package/out/zero-cache/src/services/replicator/change-log-stream-writer.d.ts.map +1 -0
  224. package/out/zero-cache/src/services/replicator/change-log-stream-writer.js +150 -0
  225. package/out/zero-cache/src/services/replicator/change-log-stream-writer.js.map +1 -0
  226. package/out/zero-cache/src/services/replicator/change-processor.d.ts.map +1 -1
  227. package/out/zero-cache/src/services/replicator/change-processor.js +44 -17
  228. package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
  229. package/out/zero-cache/src/services/replicator/incremental-sync.d.ts +1 -1
  230. package/out/zero-cache/src/services/replicator/incremental-sync.d.ts.map +1 -1
  231. package/out/zero-cache/src/services/replicator/incremental-sync.js +11 -4
  232. package/out/zero-cache/src/services/replicator/incremental-sync.js.map +1 -1
  233. package/out/zero-cache/src/services/replicator/replicator.d.ts +1 -1
  234. package/out/zero-cache/src/services/replicator/replicator.d.ts.map +1 -1
  235. package/out/zero-cache/src/services/replicator/replicator.js +2 -2
  236. package/out/zero-cache/src/services/replicator/replicator.js.map +1 -1
  237. package/out/zero-cache/src/services/replicator/schema/backfilling.d.ts +119 -0
  238. package/out/zero-cache/src/services/replicator/schema/backfilling.d.ts.map +1 -0
  239. package/out/zero-cache/src/services/replicator/schema/backfilling.js +214 -0
  240. package/out/zero-cache/src/services/replicator/schema/backfilling.js.map +1 -0
  241. package/out/zero-cache/src/services/replicator/schema/change-log.d.ts +3 -3
  242. package/out/zero-cache/src/services/replicator/schema/column-metadata.js +1 -1
  243. package/out/zero-cache/src/services/replicator/schema/column-metadata.js.map +1 -1
  244. package/out/zero-cache/src/services/replicator/schema/replication-state.d.ts +1 -1
  245. package/out/zero-cache/src/services/replicator/schema/replication-state.d.ts.map +1 -1
  246. package/out/zero-cache/src/services/replicator/schema/replication-state.js +9 -5
  247. package/out/zero-cache/src/services/replicator/schema/replication-state.js.map +1 -1
  248. package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.d.ts +131 -0
  249. package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.d.ts.map +1 -0
  250. package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.js +413 -0
  251. package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.js.map +1 -0
  252. package/out/zero-cache/src/services/replicator/sqlite-change-log-purger.d.ts +120 -0
  253. package/out/zero-cache/src/services/replicator/sqlite-change-log-purger.d.ts.map +1 -0
  254. package/out/zero-cache/src/services/replicator/sqlite-change-log-purger.js +283 -0
  255. package/out/zero-cache/src/services/replicator/sqlite-change-log-purger.js.map +1 -0
  256. package/out/zero-cache/src/services/replicator/write-worker.js +9 -6
  257. package/out/zero-cache/src/services/replicator/write-worker.js.map +1 -1
  258. package/out/zero-cache/src/services/run-ast.d.ts.map +1 -1
  259. package/out/zero-cache/src/services/run-ast.js +2 -1
  260. package/out/zero-cache/src/services/run-ast.js.map +1 -1
  261. package/out/zero-cache/src/services/running-state.d.ts +1 -1
  262. package/out/zero-cache/src/services/running-state.d.ts.map +1 -1
  263. package/out/zero-cache/src/services/running-state.js +1 -0
  264. package/out/zero-cache/src/services/running-state.js.map +1 -1
  265. package/out/zero-cache/src/services/view-syncer/e2e-serving-lag.d.ts +9 -0
  266. package/out/zero-cache/src/services/view-syncer/e2e-serving-lag.d.ts.map +1 -1
  267. package/out/zero-cache/src/services/view-syncer/e2e-serving-lag.js +9 -0
  268. package/out/zero-cache/src/services/view-syncer/e2e-serving-lag.js.map +1 -1
  269. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
  270. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +18 -3
  271. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
  272. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts +11 -1
  273. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
  274. package/out/zero-cache/src/services/view-syncer/view-syncer.js +48 -7
  275. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  276. package/out/zero-cache/src/types/processes.d.ts +1 -2
  277. package/out/zero-cache/src/types/processes.d.ts.map +1 -1
  278. package/out/zero-cache/src/types/processes.js +1 -25
  279. package/out/zero-cache/src/types/processes.js.map +1 -1
  280. package/out/zero-cache/src/types/streams.d.ts +10 -0
  281. package/out/zero-cache/src/types/streams.d.ts.map +1 -1
  282. package/out/zero-cache/src/types/streams.js +25 -4
  283. package/out/zero-cache/src/types/streams.js.map +1 -1
  284. package/out/zero-cache/src/workers/connection.d.ts +1 -0
  285. package/out/zero-cache/src/workers/connection.d.ts.map +1 -1
  286. package/out/zero-cache/src/workers/connection.js +25 -3
  287. package/out/zero-cache/src/workers/connection.js.map +1 -1
  288. package/out/zero-cache/src/workers/replicator.d.ts +25 -0
  289. package/out/zero-cache/src/workers/replicator.d.ts.map +1 -1
  290. package/out/zero-cache/src/workers/replicator.js +33 -1
  291. package/out/zero-cache/src/workers/replicator.js.map +1 -1
  292. package/out/zero-cache/src/workers/syncer.d.ts +12 -0
  293. package/out/zero-cache/src/workers/syncer.d.ts.map +1 -1
  294. package/out/zero-cache/src/workers/syncer.js +75 -0
  295. package/out/zero-cache/src/workers/syncer.js.map +1 -1
  296. package/out/zero-client/src/client/version.js +1 -1
  297. package/out/zero-schema/src/builder/table-builder.d.ts +23 -0
  298. package/out/zero-schema/src/builder/table-builder.d.ts.map +1 -1
  299. package/out/zero-schema/src/builder/table-builder.js +18 -0
  300. package/out/zero-schema/src/builder/table-builder.js.map +1 -1
  301. package/out/zero-types/src/schema.d.ts +11 -0
  302. package/out/zero-types/src/schema.d.ts.map +1 -1
  303. package/out/zql/src/query/query-impl.d.ts +2 -2
  304. package/out/zql/src/query/query-impl.d.ts.map +1 -1
  305. package/out/zql/src/query/query-impl.js.map +1 -1
  306. package/out/zql/src/query/query.d.ts +83 -14
  307. package/out/zql/src/query/query.d.ts.map +1 -1
  308. package/out/zql/src/query/static-query.d.ts +1 -1
  309. package/out/zql/src/query/static-query.d.ts.map +1 -1
  310. package/out/zqlite/src/resolve-scalar-subqueries.d.ts +15 -0
  311. package/out/zqlite/src/resolve-scalar-subqueries.d.ts.map +1 -1
  312. package/out/zqlite/src/resolve-scalar-subqueries.js +20 -13
  313. package/out/zqlite/src/resolve-scalar-subqueries.js.map +1 -1
  314. package/package.json +2 -2
  315. package/out/replicache/src/db/index.js +0 -91
  316. package/out/replicache/src/db/index.js.map +0 -1
  317. package/out/replicache/src/lazy.d.ts +0 -2
  318. package/out/replicache/src/lazy.d.ts.map +0 -1
  319. package/out/replicache/src/lazy.js +0 -12
  320. package/out/replicache/src/lazy.js.map +0 -1
  321. package/out/zero-cache/src/server/backup-watermark-reader.js +0 -35
  322. package/out/zero-cache/src/server/backup-watermark-reader.js.map +0 -1
  323. package/out/zero-cache/src/services/change-streamer/litestream3-backup-monitor.d.ts.map +0 -1
  324. package/out/zero-cache/src/services/change-streamer/litestream3-backup-monitor.js.map +0 -1
  325. package/out/zero-cache/src/services/change-streamer/replica-monitor.d.ts +0 -16
  326. package/out/zero-cache/src/services/change-streamer/replica-monitor.d.ts.map +0 -1
  327. package/out/zero-cache/src/services/change-streamer/replica-monitor.js +0 -54
  328. package/out/zero-cache/src/services/change-streamer/replica-monitor.js.map +0 -1
  329. package/out/zero-cache/src/services/change-streamer/vfs-backup-monitor.d.ts +0 -25
  330. package/out/zero-cache/src/services/change-streamer/vfs-backup-monitor.d.ts.map +0 -1
  331. package/out/zero-cache/src/services/change-streamer/vfs-backup-monitor.js +0 -159
  332. package/out/zero-cache/src/services/change-streamer/vfs-backup-monitor.js.map +0 -1
  333. package/out/zero-cache/src/services/litestream/vfs-watermark-reader.d.ts +0 -44
  334. package/out/zero-cache/src/services/litestream/vfs-watermark-reader.d.ts.map +0 -1
  335. package/out/zero-cache/src/services/litestream/vfs-watermark-reader.js +0 -65
  336. package/out/zero-cache/src/services/litestream/vfs-watermark-reader.js.map +0 -1
  337. package/out/zero-cache/src/services/litestream/vfs-watermark-worker-source.d.ts +0 -11
  338. package/out/zero-cache/src/services/litestream/vfs-watermark-worker-source.d.ts.map +0 -1
  339. package/out/zero-cache/src/services/litestream/vfs-watermark-worker-source.js +0 -74
  340. package/out/zero-cache/src/services/litestream/vfs-watermark-worker-source.js.map +0 -1
  341. package/out/zero-cache/src/services/litestream/vfs-watermark-worker.d.ts +0 -42
  342. package/out/zero-cache/src/services/litestream/vfs-watermark-worker.d.ts.map +0 -1
  343. package/out/zero-cache/src/services/litestream/vfs-watermark-worker.js +0 -117
  344. package/out/zero-cache/src/services/litestream/vfs-watermark-worker.js.map +0 -1
@@ -2,36 +2,81 @@ import type { LogContext } from '@rocicorp/logger';
2
2
  import type { PostgresDB } from '../../types/pg.ts';
3
3
  import type { ShardID } from '../../types/shards.ts';
4
4
  import type { ChangeSource } from '../change-source/change-source.ts';
5
- import { type ChangeStreamData } from '../change-source/protocol/current/downstream.ts';
5
+ import type { LitestreamVersion } from '../litestream/metrics.ts';
6
6
  import { type ReplicationStatusPublisher } from '../replicator/replication-status.ts';
7
7
  import type { SubscriptionState } from '../replicator/schema/replication-state.ts';
8
- import { type ChangeStreamerService } from './change-streamer.ts';
8
+ import { type ChangeStreamerService, type SubscriberContext } from './change-streamer.ts';
9
+ import { type SQLiteChangeLogCleanupGuard } from './sqlite-change-log-catchup.ts';
10
+ import { type SQLiteChangeLogPurgeSchedulerOptions } from './sqlite-change-log-purge-scheduler.ts';
11
+ import { type SQLiteChangeLogWriterOptions } from './sqlite-change-log-writer.ts';
9
12
  import { type PurgeLock, type TuningOptions as StorerOptions } from './storer.ts';
13
+ export type BackupConfig = {
14
+ backupURL: string;
15
+ litestreamVersion: LitestreamVersion;
16
+ };
17
+ export type SQLiteCatchupOptions = {
18
+ /** The change-log database, i.e. `changeLogFileName(replicaFile)`. */
19
+ changeLogFile: string;
20
+ readBatchRows: number;
21
+ barrierTimeoutMs: number;
22
+ /**
23
+ * Backstop for the change-log writer's ACK, which is what normally releases
24
+ * the barrier. Defaults to the catchup coordinator's interval.
25
+ */
26
+ barrierPollIntervalMs?: number | undefined;
27
+ /**
28
+ * Slice 11 supplies the production canary selector.
29
+ *
30
+ * It does not need to exclude backup subscribers or the change-log writer:
31
+ * eligibility checks reject both before invoking this selector. Serving a
32
+ * writer from SQLite would make it wait on its own ACK.
33
+ */
34
+ shouldUse?: ((ctx: SubscriberContext) => boolean) | undefined;
35
+ /**
36
+ * Overrides the purge scheduler's guard, for tests. When absent, the
37
+ * service supplies the scheduler's real writer-serialized guard, or the
38
+ * catchup's no-op default when purging is not configured.
39
+ */
40
+ cleanupGuard?: SQLiteChangeLogCleanupGuard | undefined;
41
+ /**
42
+ * How long the change log may be unavailable before declining to serve from
43
+ * it is reported as a warning rather than a debug line. Defaults to
44
+ * {@link DEFAULT_CHANGE_LOG_UNAVAILABLE_WARN_THRESHOLD_MS}.
45
+ */
46
+ notReadyWarnThresholdMs?: number | undefined;
47
+ };
10
48
  export type TuningOptions = StorerOptions & {
11
- flowControlConsensusPaddingSeconds: number;
49
+ flowControlConsensusTimeoutProportion: number;
50
+ flowControlSlowSubscriberGracePeriodMs?: number | undefined;
51
+ sqliteCatchup?: SQLiteCatchupOptions | undefined;
52
+ /**
53
+ * Supplied when `sqliteChangeLogMode != off`, i.e. this is the gate on the
54
+ * change-log writer. Absent, nothing writes the log.
55
+ */
56
+ sqliteChangeLogWriter?: Omit<SQLiteChangeLogWriterOptions, 'onCommit' | 'onDisabled' | 'onRebuilt'> | undefined;
57
+ /**
58
+ * Also supplied when `sqliteChangeLogMode != off`, and deliberately not
59
+ * gated on the read path: in `write` mode no reader ever opens, and this is
60
+ * the configuration the purge scheduler actually ships in. The scheduler
61
+ * runs on the writer's own connection, so with the writer absent (mode
62
+ * `off`) it is never constructed, and a leftover file on disk is left to
63
+ * the replicator's cleanup.
64
+ */
65
+ sqliteChangeLogPurge?: SQLiteChangeLogPurgeSchedulerOptions | undefined;
66
+ /**
67
+ * Supplied at `sqliteChangeLogMode >= compare`, and the gate on deriving the
68
+ * stream's initialization parameters from the replica as well as from
69
+ * Postgres. Postgres stays authoritative; the two are compared and the
70
+ * result is reported. Not a new configuration option -- the mode ladder
71
+ * carries it, because a state in which the log's buffer and its cookies were
72
+ * at different rollout stages is what invariant 15 exists to forbid.
73
+ */
74
+ sqliteChangeLogCompare?: {
75
+ replicaFile: string;
76
+ } | undefined;
12
77
  };
13
78
  /**
14
79
  * Performs initialization and schema migrations to initialize a ChangeStreamerImpl.
15
80
  */
16
- export declare function initializeStreamer(lc: LogContext, shard: ShardID, taskID: string, discoveryAddress: string, discoveryProtocol: string, changeDB: PostgresDB, changeSource: ChangeSource, replicationStatusPublisher: ReplicationStatusPublisher, subscriptionState: SubscriptionState, purgeLock: PurgeLock | null, autoReset: boolean, opts: TuningOptions, setTimeoutFn?: typeof setTimeout): Promise<ChangeStreamerService>;
17
- export type ChangeTag = ChangeStreamData[1]['tag'];
18
- /**
19
- * Internally all Downstream messages (not just commits) are given a watermark.
20
- * These are used for internal ordering for:
21
- * 1. Replaying new changes in the Storer
22
- * 2. Filtering old changes in the Subscriber
23
- *
24
- * However, only the watermark for `Commit` messages are exposed to
25
- * subscribers, as that is the only semantically correct watermark to
26
- * use for tracking a position in a replication stream.
27
- *
28
- * Additionally, the ChangeStreamData is eagerly stringified once, after which
29
- * the string is passed to the changeLog and all subscribers, eliminating
30
- * redundant stringification and reducing GC churn.
31
- */
32
- export type WatermarkedChange = [
33
- watermark: string,
34
- tag: ChangeTag,
35
- json: string
36
- ];
81
+ export declare function initializeStreamer(lc: LogContext, shard: ShardID, taskID: string, discoveryAddress: string, discoveryProtocol: string, changeDB: PostgresDB, changeSource: ChangeSource, replicationStatusPublisher: ReplicationStatusPublisher, subscriptionState: SubscriptionState, backupConfig: BackupConfig | null, purgeLock: PurgeLock | null, autoReset: boolean, opts: TuningOptions, setTimeoutFn?: typeof setTimeout): Promise<ChangeStreamerService>;
37
82
  //# sourceMappingURL=change-streamer-service.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"change-streamer-service.d.ts","sourceRoot":"","sources":["../../../../../../zero-cache/src/services/change-streamer/change-streamer-service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAWjD,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,mBAAmB,CAAC;AAClD,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,uBAAuB,CAAC;AAGnD,OAAO,KAAK,EACV,YAAY,EAEb,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAEL,KAAK,gBAAgB,EAEtB,MAAM,iDAAiD,CAAC;AACzD,OAAO,EAGL,KAAK,0BAA0B,EAChC,MAAM,qCAAqC,CAAC;AAC7C,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,2CAA2C,CAAC;AAMjF,OAAO,EACL,KAAK,qBAAqB,EAG3B,MAAM,sBAAsB,CAAC;AAS9B,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,aAAa,IAAI,aAAa,EACpC,MAAM,aAAa,CAAC;AAGrB,MAAM,MAAM,aAAa,GAAG,aAAa,GAAG;IAC1C,kCAAkC,EAAE,MAAM,CAAC;CAC5C,CAAC;AAEF;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,EAAE,EAAE,UAAU,EACd,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,MAAM,EACd,gBAAgB,EAAE,MAAM,EACxB,iBAAiB,EAAE,MAAM,EACzB,QAAQ,EAAE,UAAU,EACpB,YAAY,EAAE,YAAY,EAC1B,0BAA0B,EAAE,0BAA0B,EACtD,iBAAiB,EAAE,iBAAiB,EACpC,SAAS,EAAE,SAAS,GAAG,IAAI,EAC3B,SAAS,EAAE,OAAO,EAClB,IAAI,EAAE,aAAa,EACnB,YAAY,oBAAa,GACxB,OAAO,CAAC,qBAAqB,CAAC,CA4BhC;AAID,MAAM,MAAM,SAAS,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;AAEnD;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,SAAS,EAAE,MAAM;IACjB,GAAG,EAAE,SAAS;IACd,IAAI,EAAE,MAAM;CACb,CAAC"}
1
+ {"version":3,"file":"change-streamer-service.d.ts","sourceRoot":"","sources":["../../../../../../zero-cache/src/services/change-streamer/change-streamer-service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAWjD,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,mBAAmB,CAAC;AAClD,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,uBAAuB,CAAC;AAGnD,OAAO,KAAK,EACV,YAAY,EAEb,MAAM,mCAAmC,CAAC;AAM3C,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAGL,KAAK,0BAA0B,EAChC,MAAM,qCAAqC,CAAC;AAC7C,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,2CAA2C,CAAC;AAUjF,OAAO,EACL,KAAK,qBAAqB,EAE1B,KAAK,iBAAiB,EAEvB,MAAM,sBAAsB,CAAC;AAU9B,OAAO,EAEL,KAAK,2BAA2B,EACjC,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAGL,KAAK,oCAAoC,EAC1C,MAAM,wCAAwC,CAAC;AAEhD,OAAO,EAEL,KAAK,4BAA4B,EAClC,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,aAAa,IAAI,aAAa,EACpC,MAAM,aAAa,CAAC;AAIrB,MAAM,MAAM,YAAY,GAAG;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,iBAAiB,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,sEAAsE;IACtE,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,qBAAqB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,iBAAiB,KAAK,OAAO,CAAC,GAAG,SAAS,CAAC;IAC9D;;;;OAIG;IACH,YAAY,CAAC,EAAE,2BAA2B,GAAG,SAAS,CAAC;IACvD;;;;OAIG;IACH,uBAAuB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC9C,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,aAAa,GAAG;IAC1C,qCAAqC,EAAE,MAAM,CAAC;IAC9C,sCAAsC,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5D,aAAa,CAAC,EAAE,oBAAoB,GAAG,SAAS,CAAC;IACjD;;;OAGG;IACH,qBAAqB,CAAC,EAClB,IAAI,CACF,4BAA4B,EAC5B,UAAU,GAAG,YAAY,GAAG,WAAW,CACxC,GACD,SAAS,CAAC;IACd;;;;;;;OAOG;IACH,oBAAoB,CAAC,EAAE,oCAAoC,GAAG,SAAS,CAAC;IACxE;;;;;;;OAOG;IACH,sBAAsB,CAAC,EAAE;QAAC,WAAW,EAAE,MAAM,CAAA;KAAC,GAAG,SAAS,CAAC;CAC5D,CAAC;AAEF;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,EAAE,EAAE,UAAU,EACd,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,MAAM,EACd,gBAAgB,EAAE,MAAM,EACxB,iBAAiB,EAAE,MAAM,EACzB,QAAQ,EAAE,UAAU,EACpB,YAAY,EAAE,YAAY,EAC1B,0BAA0B,EAAE,0BAA0B,EACtD,iBAAiB,EAAE,iBAAiB,EACpC,YAAY,EAAE,YAAY,GAAG,IAAI,EACjC,SAAS,EAAE,SAAS,GAAG,IAAI,EAC3B,SAAS,EAAE,OAAO,EAClB,IAAI,EAAE,aAAa,EACnB,YAAY,oBAAa,GACxB,OAAO,CAAC,qBAAqB,CAAC,CA4BhC"}
@@ -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,15 +314,19 @@ 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 {
324
+ if (unflushedBytes < flushBytesThreshold) {
325
+ this.#forwarder.forward(entry);
326
+ this.#recordForwardedTransactionBoundary(type, entry[0]);
327
+ } else {
258
328
  const forwarded = this.#forwarder.forwardWithFlowControl(entry);
329
+ this.#recordForwardedTransactionBoundary(type, entry[0]);
259
330
  await stream.changes.doneOr(forwarded);
260
331
  unflushedBytes = 0;
261
332
  }
@@ -272,11 +343,14 @@ var ChangeStreamerImpl = class {
272
343
  if (watermark) {
273
344
  this.#lc.warn?.(`aborting interrupted transaction ${watermark}`);
274
345
  this.#storer.abort();
346
+ this.#changeLogWriter?.abort();
347
+ this.#purgeScheduler?.onWriterIdle();
275
348
  this.#forwarder.forward([
276
349
  watermark,
277
350
  "rollback",
278
351
  ROLLBACK_JSON
279
352
  ]);
353
+ this.#recordForwardedTransactionBoundary("rollback", watermark);
280
354
  }
281
355
  await Promise.all([
282
356
  this.#storer.stop(),
@@ -302,27 +376,88 @@ var ChangeStreamerImpl = class {
302
376
  default: unreachable(tag);
303
377
  }
304
378
  }
305
- subscribe(ctx) {
379
+ async subscribe(ctx) {
306
380
  const { protocolVersion, id, mode, replicaVersion, watermark } = ctx;
307
381
  if (mode === "serving") this.#serving.resolve();
308
- const downstream = Subscription.create({ cleanup: () => this.#forwarder.remove(subscriber) });
309
- 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
+ };
310
390
  if (replicaVersion !== this.#replicaVersion) {
311
- this.#lc.warn?.(`rejecting subscriber at replica version ${replicaVersion}`);
391
+ lc.warn?.(`rejecting subscriber at replica version ${replicaVersion}`);
312
392
  subscriber.close(1, `current replica version is ${this.#replicaVersion} (requested ${replicaVersion})`);
313
393
  } else {
314
- this.#lc.debug?.(`adding subscriber ${subscriber.id}`);
315
- this.#forwarder.add(subscriber);
316
- 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.`);
317
432
  }
318
- return Promise.resolve(downstream);
319
433
  }
320
- scheduleCleanup(watermark) {
321
- const origSize = this.#initialWatermarks.size;
322
- this.#initialWatermarks.add(watermark);
323
- 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);
324
446
  }
325
- async getChangeLogState() {
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);
459
+ }
460
+ async #getChangeLogState() {
326
461
  const minWatermark = await this.#storer.getMinWatermarkForCatchup();
327
462
  if (!minWatermark) this.#lc.warn?.(`Unexpected empty changeLog. Resync if "Local replica watermark" errors arise`);
328
463
  return {
@@ -330,44 +465,176 @@ var ChangeStreamerImpl = class {
330
465
  minWatermark: minWatermark ?? this.#replicaVersion
331
466
  };
332
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
+ }
333
563
  /**
334
- * Makes a best effort to purge the change log. In the event of a database
335
- * error, exceptions will be logged and swallowed, so this method is safe
336
- * 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.
337
567
  */
338
- async #purgeOldChanges() {
339
- const initial = [...this.#initialWatermarks];
340
- if (initial.length === 0) {
341
- 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`);
342
582
  return;
343
583
  }
344
- const current = [...this.#forwarder.getAcks()];
345
- if (current.length === 0) {
346
- 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`);
347
586
  return;
348
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;
349
606
  try {
350
- const earliestInitial = min(...initial);
351
- const earliestCurrent = min(...current);
352
- if (earliestCurrent < earliestInitial) this.#lc.info?.(`At least one client is behind backup (${earliestCurrent} < ${earliestInitial})`);
353
- else {
354
- this.#lc.info?.(`Purging changes before ${earliestInitial} ...`);
355
- const start = performance.now();
356
- const deleted = await this.#storer.purgeRecordsBefore(earliestInitial);
357
- const elapsed = (performance.now() - start).toFixed(2);
358
- this.#lc.info?.(`Purged ${deleted} changes before ${earliestInitial} (${elapsed} ms)`);
359
- 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;
360
612
  }
361
613
  } catch (e) {
362
- this.#lc.warn?.(`error purging change log`, e);
363
- } finally {
364
- 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;
365
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;
366
626
  }
367
- async stop(err) {
368
- this.#state.stop(this.#lc, err);
369
- this.#stream?.changes.cancel();
370
- await Promise.allSettled([this.#storer.stop(), 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;