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

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 (484) 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/shared/src/promise-race.d.ts +14 -0
  30. package/out/shared/src/promise-race.d.ts.map +1 -1
  31. package/out/shared/src/promise-race.js +32 -1
  32. package/out/shared/src/promise-race.js.map +1 -1
  33. package/out/z2s/src/compiler.d.ts.map +1 -1
  34. package/out/z2s/src/compiler.js +1 -22
  35. package/out/z2s/src/compiler.js.map +1 -1
  36. package/out/zero/package.js +3 -3
  37. package/out/zero/package.js.map +1 -1
  38. package/out/zero-cache/src/auth/write-authorizer.d.ts.map +1 -1
  39. package/out/zero-cache/src/auth/write-authorizer.js +8 -1
  40. package/out/zero-cache/src/auth/write-authorizer.js.map +1 -1
  41. package/out/zero-cache/src/config/normalize.d.ts +6 -0
  42. package/out/zero-cache/src/config/normalize.d.ts.map +1 -1
  43. package/out/zero-cache/src/config/normalize.js +24 -2
  44. package/out/zero-cache/src/config/normalize.js.map +1 -1
  45. package/out/zero-cache/src/config/zero-config.d.ts +65 -4
  46. package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
  47. package/out/zero-cache/src/config/zero-config.js +202 -35
  48. package/out/zero-cache/src/config/zero-config.js.map +1 -1
  49. package/out/zero-cache/src/custom/fetch.js +1 -1
  50. package/out/zero-cache/src/custom/fetch.js.map +1 -1
  51. package/out/zero-cache/src/db/delete-lite-db.js +2 -1
  52. package/out/zero-cache/src/db/delete-lite-db.js.map +1 -1
  53. package/out/zero-cache/src/db/migration-lite.d.ts.map +1 -1
  54. package/out/zero-cache/src/db/migration-lite.js +10 -5
  55. package/out/zero-cache/src/db/migration-lite.js.map +1 -1
  56. package/out/zero-cache/src/db/migration.d.ts.map +1 -1
  57. package/out/zero-cache/src/db/migration.js +4 -2
  58. package/out/zero-cache/src/db/migration.js.map +1 -1
  59. package/out/zero-cache/src/db/sqlite-corruption.d.ts +3 -2
  60. package/out/zero-cache/src/db/sqlite-corruption.d.ts.map +1 -1
  61. package/out/zero-cache/src/db/sqlite-corruption.js +13 -8
  62. package/out/zero-cache/src/db/sqlite-corruption.js.map +1 -1
  63. package/out/zero-cache/src/db/transaction-pool.d.ts +5 -15
  64. package/out/zero-cache/src/db/transaction-pool.d.ts.map +1 -1
  65. package/out/zero-cache/src/db/transaction-pool.js +8 -72
  66. package/out/zero-cache/src/db/transaction-pool.js.map +1 -1
  67. package/out/zero-cache/src/observability/metrics.d.ts +6 -1
  68. package/out/zero-cache/src/observability/metrics.d.ts.map +1 -1
  69. package/out/zero-cache/src/observability/metrics.js +20 -2
  70. package/out/zero-cache/src/observability/metrics.js.map +1 -1
  71. package/out/zero-cache/src/server/change-streamer.d.ts.map +1 -1
  72. package/out/zero-cache/src/server/change-streamer.js +105 -34
  73. package/out/zero-cache/src/server/change-streamer.js.map +1 -1
  74. package/out/zero-cache/src/server/main.d.ts.map +1 -1
  75. package/out/zero-cache/src/server/main.js +8 -18
  76. package/out/zero-cache/src/server/main.js.map +1 -1
  77. package/out/zero-cache/src/server/replicator.d.ts.map +1 -1
  78. package/out/zero-cache/src/server/replicator.js +48 -5
  79. package/out/zero-cache/src/server/replicator.js.map +1 -1
  80. package/out/zero-cache/src/server/runner/run-worker.js +3 -2
  81. package/out/zero-cache/src/server/runner/run-worker.js.map +1 -1
  82. package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
  83. package/out/zero-cache/src/server/syncer.js +1 -1
  84. package/out/zero-cache/src/server/syncer.js.map +1 -1
  85. package/out/zero-cache/src/server/worker-urls.d.ts +0 -1
  86. package/out/zero-cache/src/server/worker-urls.d.ts.map +1 -1
  87. package/out/zero-cache/src/server/worker-urls.js +1 -2
  88. package/out/zero-cache/src/server/worker-urls.js.map +1 -1
  89. package/out/zero-cache/src/services/change-source/change-source.d.ts +4 -2
  90. package/out/zero-cache/src/services/change-source/change-source.d.ts.map +1 -1
  91. package/out/zero-cache/src/services/change-source/common/replica-restore.d.ts +35 -0
  92. package/out/zero-cache/src/services/change-source/common/replica-restore.d.ts.map +1 -0
  93. package/out/zero-cache/src/services/change-source/common/replica-restore.js +34 -0
  94. package/out/zero-cache/src/services/change-source/common/replica-restore.js.map +1 -0
  95. package/out/zero-cache/src/services/change-source/common/replica-schema.d.ts +2 -0
  96. package/out/zero-cache/src/services/change-source/common/replica-schema.d.ts.map +1 -1
  97. package/out/zero-cache/src/services/change-source/common/replica-schema.js +81 -3
  98. package/out/zero-cache/src/services/change-source/common/replica-schema.js.map +1 -1
  99. package/out/zero-cache/src/services/change-source/custom/change-source.d.ts +2 -6
  100. package/out/zero-cache/src/services/change-source/custom/change-source.d.ts.map +1 -1
  101. package/out/zero-cache/src/services/change-source/custom/change-source.js +14 -5
  102. package/out/zero-cache/src/services/change-source/custom/change-source.js.map +1 -1
  103. package/out/zero-cache/src/services/change-source/pg/backfill-stream.d.ts.map +1 -1
  104. package/out/zero-cache/src/services/change-source/pg/backfill-stream.js +22 -11
  105. package/out/zero-cache/src/services/change-source/pg/backfill-stream.js.map +1 -1
  106. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts +7 -7
  107. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts.map +1 -1
  108. package/out/zero-cache/src/services/change-source/pg/change-source.js +90 -31
  109. package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
  110. package/out/zero-cache/src/services/change-source/pg/decommission.d.ts.map +1 -1
  111. package/out/zero-cache/src/services/change-source/pg/decommission.js +20 -11
  112. package/out/zero-cache/src/services/change-source/pg/decommission.js.map +1 -1
  113. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts +9 -1
  114. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts.map +1 -1
  115. package/out/zero-cache/src/services/change-source/pg/initial-sync.js +61 -76
  116. package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
  117. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.d.ts +65 -2
  118. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.d.ts.map +1 -1
  119. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js +101 -10
  120. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js.map +1 -1
  121. package/out/zero-cache/src/services/change-source/pg/replication-slots.d.ts +27 -2
  122. package/out/zero-cache/src/services/change-source/pg/replication-slots.d.ts.map +1 -1
  123. package/out/zero-cache/src/services/change-source/pg/replication-slots.js +41 -8
  124. package/out/zero-cache/src/services/change-source/pg/replication-slots.js.map +1 -1
  125. package/out/zero-cache/src/services/change-source/pg/schema/init.d.ts +0 -5
  126. package/out/zero-cache/src/services/change-source/pg/schema/init.d.ts.map +1 -1
  127. package/out/zero-cache/src/services/change-source/pg/schema/init.js +29 -41
  128. package/out/zero-cache/src/services/change-source/pg/schema/init.js.map +1 -1
  129. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts +35 -16
  130. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts.map +1 -1
  131. package/out/zero-cache/src/services/change-source/pg/schema/shard.js +77 -7
  132. package/out/zero-cache/src/services/change-source/pg/schema/shard.js.map +1 -1
  133. package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts +2 -1
  134. package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts.map +1 -1
  135. package/out/zero-cache/src/services/change-source/protocol/current/data.js +5 -13
  136. package/out/zero-cache/src/services/change-source/protocol/current/data.js.map +1 -1
  137. package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts +6 -3
  138. package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts.map +1 -1
  139. package/out/zero-cache/src/services/change-source/protocol/current/schema-change-tags.d.ts +6 -0
  140. package/out/zero-cache/src/services/change-source/protocol/current/schema-change-tags.d.ts.map +1 -0
  141. package/out/zero-cache/src/services/change-source/protocol/current/schema-change-tags.js +21 -0
  142. package/out/zero-cache/src/services/change-source/protocol/current/schema-change-tags.js.map +1 -0
  143. package/out/zero-cache/src/services/change-source/protocol/current/status.d.ts +1 -0
  144. package/out/zero-cache/src/services/change-source/protocol/current/status.d.ts.map +1 -1
  145. package/out/zero-cache/src/services/change-source/protocol/current/upstream.d.ts +1 -0
  146. package/out/zero-cache/src/services/change-source/protocol/current/upstream.d.ts.map +1 -1
  147. package/out/zero-cache/src/services/change-streamer/backup-cleanup-monitor-factory.d.ts +3 -7
  148. package/out/zero-cache/src/services/change-streamer/backup-cleanup-monitor-factory.d.ts.map +1 -1
  149. package/out/zero-cache/src/services/change-streamer/backup-cleanup-monitor-factory.js +26 -10
  150. package/out/zero-cache/src/services/change-streamer/backup-cleanup-monitor-factory.js.map +1 -1
  151. package/out/zero-cache/src/services/change-streamer/backup-monitor.d.ts +15 -5
  152. package/out/zero-cache/src/services/change-streamer/backup-monitor.d.ts.map +1 -1
  153. package/out/zero-cache/src/services/change-streamer/backup-monitor.js +71 -0
  154. package/out/zero-cache/src/services/change-streamer/backup-monitor.js.map +1 -0
  155. package/out/zero-cache/src/services/change-streamer/broadcast.d.ts +68 -78
  156. package/out/zero-cache/src/services/change-streamer/broadcast.d.ts.map +1 -1
  157. package/out/zero-cache/src/services/change-streamer/broadcast.js +84 -92
  158. package/out/zero-cache/src/services/change-streamer/broadcast.js.map +1 -1
  159. package/out/zero-cache/src/services/change-streamer/change-log-codec.d.ts +19 -0
  160. package/out/zero-cache/src/services/change-streamer/change-log-codec.d.ts.map +1 -0
  161. package/out/zero-cache/src/services/change-streamer/change-log-codec.js +50 -0
  162. package/out/zero-cache/src/services/change-streamer/change-log-codec.js.map +1 -0
  163. package/out/zero-cache/src/services/change-streamer/change-log-compare-digest.d.ts +34 -0
  164. package/out/zero-cache/src/services/change-streamer/change-log-compare-digest.d.ts.map +1 -0
  165. package/out/zero-cache/src/services/change-streamer/change-log-compare-digest.js +67 -0
  166. package/out/zero-cache/src/services/change-streamer/change-log-compare-digest.js.map +1 -0
  167. package/out/zero-cache/src/services/change-streamer/change-log-initializer.d.ts +141 -0
  168. package/out/zero-cache/src/services/change-streamer/change-log-initializer.d.ts.map +1 -0
  169. package/out/zero-cache/src/services/change-streamer/change-log-initializer.js +270 -0
  170. package/out/zero-cache/src/services/change-streamer/change-log-initializer.js.map +1 -0
  171. package/out/zero-cache/src/services/change-streamer/change-log-transaction-hash.d.ts +19 -0
  172. package/out/zero-cache/src/services/change-streamer/change-log-transaction-hash.d.ts.map +1 -0
  173. package/out/zero-cache/src/services/change-streamer/change-log-transaction-hash.js +39 -0
  174. package/out/zero-cache/src/services/change-streamer/change-log-transaction-hash.js.map +1 -0
  175. package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts +5 -8
  176. package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts.map +1 -1
  177. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +20 -19
  178. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
  179. package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts +90 -24
  180. package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts.map +1 -1
  181. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js +456 -66
  182. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -1
  183. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts +50 -13
  184. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts.map +1 -1
  185. package/out/zero-cache/src/services/change-streamer/change-streamer.js.map +1 -1
  186. package/out/zero-cache/src/services/change-streamer/error-type-enum.d.ts +8 -0
  187. package/out/zero-cache/src/services/change-streamer/error-type-enum.d.ts.map +1 -1
  188. package/out/zero-cache/src/services/change-streamer/forwarder.d.ts +14 -3
  189. package/out/zero-cache/src/services/change-streamer/forwarder.d.ts.map +1 -1
  190. package/out/zero-cache/src/services/change-streamer/forwarder.js +42 -12
  191. package/out/zero-cache/src/services/change-streamer/forwarder.js.map +1 -1
  192. package/out/zero-cache/src/services/change-streamer/{litestream3-backup-monitor.d.ts → litestream3-prometheus-poller.d.ts} +19 -45
  193. package/out/zero-cache/src/services/change-streamer/litestream3-prometheus-poller.d.ts.map +1 -0
  194. package/out/zero-cache/src/services/change-streamer/{litestream3-backup-monitor.js → litestream3-prometheus-poller.js} +68 -176
  195. package/out/zero-cache/src/services/change-streamer/litestream3-prometheus-poller.js.map +1 -0
  196. package/out/zero-cache/src/services/change-streamer/replica-poller.d.ts +15 -0
  197. package/out/zero-cache/src/services/change-streamer/replica-poller.d.ts.map +1 -0
  198. package/out/zero-cache/src/services/change-streamer/replica-poller.js +55 -0
  199. package/out/zero-cache/src/services/change-streamer/replica-poller.js.map +1 -0
  200. package/out/zero-cache/src/services/change-streamer/schema/tables.d.ts +5 -1
  201. package/out/zero-cache/src/services/change-streamer/schema/tables.d.ts.map +1 -1
  202. package/out/zero-cache/src/services/change-streamer/schema/tables.js +2 -1
  203. package/out/zero-cache/src/services/change-streamer/schema/tables.js.map +1 -1
  204. package/out/zero-cache/src/services/change-streamer/shard-sampling.d.ts +11 -0
  205. package/out/zero-cache/src/services/change-streamer/shard-sampling.d.ts.map +1 -0
  206. package/out/zero-cache/src/services/change-streamer/shard-sampling.js +19 -0
  207. package/out/zero-cache/src/services/change-streamer/shard-sampling.js.map +1 -0
  208. package/out/zero-cache/src/services/change-streamer/snapshot-reservations.d.ts +24 -0
  209. package/out/zero-cache/src/services/change-streamer/snapshot-reservations.d.ts.map +1 -0
  210. package/out/zero-cache/src/services/change-streamer/snapshot-reservations.js +119 -0
  211. package/out/zero-cache/src/services/change-streamer/snapshot-reservations.js.map +1 -0
  212. package/out/zero-cache/src/services/change-streamer/snapshot.d.ts +4 -1
  213. package/out/zero-cache/src/services/change-streamer/snapshot.d.ts.map +1 -1
  214. package/out/zero-cache/src/services/change-streamer/snapshot.js +39 -14
  215. package/out/zero-cache/src/services/change-streamer/snapshot.js.map +1 -1
  216. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-catchup.d.ts +99 -0
  217. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-catchup.d.ts.map +1 -0
  218. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-catchup.js +344 -0
  219. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-catchup.js.map +1 -0
  220. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-comparator.d.ts +83 -0
  221. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-comparator.d.ts.map +1 -0
  222. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-comparator.js +417 -0
  223. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-comparator.js.map +1 -0
  224. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-purge-scheduler.d.ts +121 -0
  225. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-purge-scheduler.d.ts.map +1 -0
  226. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-purge-scheduler.js +391 -0
  227. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-purge-scheduler.js.map +1 -0
  228. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-read-router.d.ts +73 -0
  229. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-read-router.d.ts.map +1 -0
  230. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-read-router.js +157 -0
  231. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-read-router.js.map +1 -0
  232. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-reader.d.ts +62 -0
  233. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-reader.d.ts.map +1 -0
  234. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-reader.js +164 -0
  235. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-reader.js.map +1 -0
  236. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.d.ts +109 -0
  237. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.d.ts.map +1 -0
  238. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.js +258 -0
  239. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.js.map +1 -0
  240. package/out/zero-cache/src/services/change-streamer/storer.d.ts +85 -12
  241. package/out/zero-cache/src/services/change-streamer/storer.d.ts.map +1 -1
  242. package/out/zero-cache/src/services/change-streamer/storer.js +286 -141
  243. package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
  244. package/out/zero-cache/src/services/change-streamer/subscriber.d.ts +61 -10
  245. package/out/zero-cache/src/services/change-streamer/subscriber.d.ts.map +1 -1
  246. package/out/zero-cache/src/services/change-streamer/subscriber.js +101 -8
  247. package/out/zero-cache/src/services/change-streamer/subscriber.js.map +1 -1
  248. package/out/zero-cache/src/services/change-streamer/upstream-acker.d.ts +34 -0
  249. package/out/zero-cache/src/services/change-streamer/upstream-acker.d.ts.map +1 -0
  250. package/out/zero-cache/src/services/change-streamer/upstream-acker.js +86 -0
  251. package/out/zero-cache/src/services/change-streamer/upstream-acker.js.map +1 -0
  252. package/out/zero-cache/src/services/change-streamer/vfs-watermark-poller.d.ts +29 -0
  253. package/out/zero-cache/src/services/change-streamer/vfs-watermark-poller.d.ts.map +1 -0
  254. package/out/zero-cache/src/services/change-streamer/vfs-watermark-poller.js +154 -0
  255. package/out/zero-cache/src/services/change-streamer/vfs-watermark-poller.js.map +1 -0
  256. package/out/zero-cache/src/services/http-service.d.ts +1 -0
  257. package/out/zero-cache/src/services/http-service.d.ts.map +1 -1
  258. package/out/zero-cache/src/services/http-service.js +7 -3
  259. package/out/zero-cache/src/services/http-service.js.map +1 -1
  260. package/out/zero-cache/src/services/life-cycle.d.ts +1 -1
  261. package/out/zero-cache/src/services/life-cycle.d.ts.map +1 -1
  262. package/out/zero-cache/src/services/life-cycle.js +4 -3
  263. package/out/zero-cache/src/services/life-cycle.js.map +1 -1
  264. package/out/zero-cache/src/services/litestream/commands.d.ts +12 -11
  265. package/out/zero-cache/src/services/litestream/commands.d.ts.map +1 -1
  266. package/out/zero-cache/src/services/litestream/commands.js +115 -152
  267. package/out/zero-cache/src/services/litestream/commands.js.map +1 -1
  268. package/out/zero-cache/src/services/litestream/config-v5.yml +42 -0
  269. package/out/zero-cache/src/services/litestream/config.yml +3 -2
  270. package/out/zero-cache/src/services/litestream/metrics.d.ts +5 -4
  271. package/out/zero-cache/src/services/litestream/metrics.d.ts.map +1 -1
  272. package/out/zero-cache/src/services/litestream/metrics.js +10 -10
  273. package/out/zero-cache/src/services/litestream/metrics.js.map +1 -1
  274. package/out/zero-cache/src/services/mutagen/mutagen.d.ts.map +1 -1
  275. package/out/zero-cache/src/services/mutagen/mutagen.js +5 -2
  276. package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -1
  277. package/out/zero-cache/src/services/replicator/change-log-cookies.d.ts +169 -0
  278. package/out/zero-cache/src/services/replicator/change-log-cookies.d.ts.map +1 -0
  279. package/out/zero-cache/src/services/replicator/change-log-cookies.js +434 -0
  280. package/out/zero-cache/src/services/replicator/change-log-cookies.js.map +1 -0
  281. package/out/zero-cache/src/services/replicator/change-log-db.d.ts +368 -0
  282. package/out/zero-cache/src/services/replicator/change-log-db.d.ts.map +1 -0
  283. package/out/zero-cache/src/services/replicator/change-log-db.js +491 -0
  284. package/out/zero-cache/src/services/replicator/change-log-db.js.map +1 -0
  285. package/out/zero-cache/src/services/replicator/change-log-stream-writer.d.ts +55 -0
  286. package/out/zero-cache/src/services/replicator/change-log-stream-writer.d.ts.map +1 -0
  287. package/out/zero-cache/src/services/replicator/change-log-stream-writer.js +150 -0
  288. package/out/zero-cache/src/services/replicator/change-log-stream-writer.js.map +1 -0
  289. package/out/zero-cache/src/services/replicator/change-processor.d.ts +6 -0
  290. package/out/zero-cache/src/services/replicator/change-processor.d.ts.map +1 -1
  291. package/out/zero-cache/src/services/replicator/change-processor.js +70 -25
  292. package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
  293. package/out/zero-cache/src/services/replicator/incremental-sync.d.ts +1 -1
  294. package/out/zero-cache/src/services/replicator/incremental-sync.d.ts.map +1 -1
  295. package/out/zero-cache/src/services/replicator/incremental-sync.js +19 -6
  296. package/out/zero-cache/src/services/replicator/incremental-sync.js.map +1 -1
  297. package/out/zero-cache/src/services/replicator/notifier.d.ts +0 -22
  298. package/out/zero-cache/src/services/replicator/notifier.d.ts.map +1 -1
  299. package/out/zero-cache/src/services/replicator/notifier.js +7 -1
  300. package/out/zero-cache/src/services/replicator/notifier.js.map +1 -1
  301. package/out/zero-cache/src/services/replicator/replicator.d.ts +17 -2
  302. package/out/zero-cache/src/services/replicator/replicator.d.ts.map +1 -1
  303. package/out/zero-cache/src/services/replicator/replicator.js +9 -3
  304. package/out/zero-cache/src/services/replicator/replicator.js.map +1 -1
  305. package/out/zero-cache/src/services/replicator/reporter/recorder.d.ts +27 -0
  306. package/out/zero-cache/src/services/replicator/reporter/recorder.d.ts.map +1 -1
  307. package/out/zero-cache/src/services/replicator/reporter/recorder.js +32 -0
  308. package/out/zero-cache/src/services/replicator/reporter/recorder.js.map +1 -1
  309. package/out/zero-cache/src/services/replicator/reporter/report-schema.d.ts +1 -1
  310. package/out/zero-cache/src/services/replicator/schema/backfilling.d.ts +119 -0
  311. package/out/zero-cache/src/services/replicator/schema/backfilling.d.ts.map +1 -0
  312. package/out/zero-cache/src/services/replicator/schema/backfilling.js +214 -0
  313. package/out/zero-cache/src/services/replicator/schema/backfilling.js.map +1 -0
  314. package/out/zero-cache/src/services/replicator/schema/change-log.d.ts +3 -3
  315. package/out/zero-cache/src/services/replicator/schema/column-metadata.js +1 -1
  316. package/out/zero-cache/src/services/replicator/schema/column-metadata.js.map +1 -1
  317. package/out/zero-cache/src/services/replicator/schema/replication-state.d.ts +1 -1
  318. package/out/zero-cache/src/services/replicator/schema/replication-state.d.ts.map +1 -1
  319. package/out/zero-cache/src/services/replicator/schema/replication-state.js +9 -5
  320. package/out/zero-cache/src/services/replicator/schema/replication-state.js.map +1 -1
  321. package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.d.ts +132 -0
  322. package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.d.ts.map +1 -0
  323. package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.js +415 -0
  324. package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.js.map +1 -0
  325. package/out/zero-cache/src/services/replicator/sqlite-change-log-purger.d.ts +120 -0
  326. package/out/zero-cache/src/services/replicator/sqlite-change-log-purger.d.ts.map +1 -0
  327. package/out/zero-cache/src/services/replicator/sqlite-change-log-purger.js +283 -0
  328. package/out/zero-cache/src/services/replicator/sqlite-change-log-purger.js.map +1 -0
  329. package/out/zero-cache/src/services/replicator/write-worker.js +23 -12
  330. package/out/zero-cache/src/services/replicator/write-worker.js.map +1 -1
  331. package/out/zero-cache/src/services/run-ast.d.ts.map +1 -1
  332. package/out/zero-cache/src/services/run-ast.js +2 -1
  333. package/out/zero-cache/src/services/run-ast.js.map +1 -1
  334. package/out/zero-cache/src/services/running-state.d.ts +1 -1
  335. package/out/zero-cache/src/services/running-state.d.ts.map +1 -1
  336. package/out/zero-cache/src/services/running-state.js +1 -0
  337. package/out/zero-cache/src/services/running-state.js.map +1 -1
  338. package/out/zero-cache/src/services/view-syncer/client-handler.d.ts +3 -2
  339. package/out/zero-cache/src/services/view-syncer/client-handler.d.ts.map +1 -1
  340. package/out/zero-cache/src/services/view-syncer/client-handler.js +25 -17
  341. package/out/zero-cache/src/services/view-syncer/client-handler.js.map +1 -1
  342. package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts.map +1 -1
  343. package/out/zero-cache/src/services/view-syncer/cvr-store.js +14 -1
  344. package/out/zero-cache/src/services/view-syncer/cvr-store.js.map +1 -1
  345. package/out/zero-cache/src/services/view-syncer/e2e-serving-lag.d.ts +53 -0
  346. package/out/zero-cache/src/services/view-syncer/e2e-serving-lag.d.ts.map +1 -0
  347. package/out/zero-cache/src/services/view-syncer/e2e-serving-lag.js +68 -0
  348. package/out/zero-cache/src/services/view-syncer/e2e-serving-lag.js.map +1 -0
  349. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
  350. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +18 -3
  351. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
  352. package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts.map +1 -1
  353. package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
  354. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts +14 -4
  355. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
  356. package/out/zero-cache/src/services/view-syncer/view-syncer.js +70 -8
  357. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  358. package/out/zero-cache/src/types/downstream.d.ts +11 -0
  359. package/out/zero-cache/src/types/downstream.d.ts.map +1 -0
  360. package/out/zero-cache/src/types/pg.d.ts.map +1 -1
  361. package/out/zero-cache/src/types/pg.js +14 -4
  362. package/out/zero-cache/src/types/pg.js.map +1 -1
  363. package/out/zero-cache/src/types/poke-chunk.d.ts +18 -0
  364. package/out/zero-cache/src/types/poke-chunk.d.ts.map +1 -0
  365. package/out/zero-cache/src/types/poke-chunk.js +57 -0
  366. package/out/zero-cache/src/types/poke-chunk.js.map +1 -0
  367. package/out/zero-cache/src/types/processes.d.ts +1 -2
  368. package/out/zero-cache/src/types/processes.d.ts.map +1 -1
  369. package/out/zero-cache/src/types/processes.js +1 -28
  370. package/out/zero-cache/src/types/processes.js.map +1 -1
  371. package/out/zero-cache/src/types/streams.d.ts +16 -0
  372. package/out/zero-cache/src/types/streams.d.ts.map +1 -1
  373. package/out/zero-cache/src/types/streams.js +25 -4
  374. package/out/zero-cache/src/types/streams.js.map +1 -1
  375. package/out/zero-cache/src/types/subscription.d.ts +2 -0
  376. package/out/zero-cache/src/types/subscription.d.ts.map +1 -1
  377. package/out/zero-cache/src/types/subscription.js +6 -0
  378. package/out/zero-cache/src/types/subscription.js.map +1 -1
  379. package/out/zero-cache/src/workers/connection.d.ts +23 -4
  380. package/out/zero-cache/src/workers/connection.d.ts.map +1 -1
  381. package/out/zero-cache/src/workers/connection.js +130 -10
  382. package/out/zero-cache/src/workers/connection.js.map +1 -1
  383. package/out/zero-cache/src/workers/replicator.d.ts +25 -0
  384. package/out/zero-cache/src/workers/replicator.d.ts.map +1 -1
  385. package/out/zero-cache/src/workers/replicator.js +33 -1
  386. package/out/zero-cache/src/workers/replicator.js.map +1 -1
  387. package/out/zero-cache/src/workers/syncer.d.ts +12 -0
  388. package/out/zero-cache/src/workers/syncer.d.ts.map +1 -1
  389. package/out/zero-cache/src/workers/syncer.js +75 -0
  390. package/out/zero-cache/src/workers/syncer.js.map +1 -1
  391. package/out/zero-client/src/client/version.js +1 -1
  392. package/out/zero-client/src/client/zero-poke-handler.d.ts +7 -2
  393. package/out/zero-client/src/client/zero-poke-handler.d.ts.map +1 -1
  394. package/out/zero-client/src/client/zero-poke-handler.js +52 -2
  395. package/out/zero-client/src/client/zero-poke-handler.js.map +1 -1
  396. package/out/zero-client/src/client/zero.d.ts +6 -7
  397. package/out/zero-client/src/client/zero.d.ts.map +1 -1
  398. package/out/zero-client/src/client/zero.js +194 -107
  399. package/out/zero-client/src/client/zero.js.map +1 -1
  400. package/out/zero-protocol/src/down.d.ts +1 -1
  401. package/out/zero-protocol/src/poke.d.ts +89 -7
  402. package/out/zero-protocol/src/poke.d.ts.map +1 -1
  403. package/out/zero-protocol/src/poke.js +16 -8
  404. package/out/zero-protocol/src/poke.js.map +1 -1
  405. package/out/zero-protocol/src/protocol-version.d.ts +12 -7
  406. package/out/zero-protocol/src/protocol-version.d.ts.map +1 -1
  407. package/out/zero-protocol/src/protocol-version.js.map +1 -1
  408. package/out/zero-schema/src/builder/table-builder.d.ts +23 -0
  409. package/out/zero-schema/src/builder/table-builder.d.ts.map +1 -1
  410. package/out/zero-schema/src/builder/table-builder.js +18 -0
  411. package/out/zero-schema/src/builder/table-builder.js.map +1 -1
  412. package/out/zero-server/src/custom.js +10 -3
  413. package/out/zero-server/src/custom.js.map +1 -1
  414. package/out/zero-server/src/schema.d.ts +8 -0
  415. package/out/zero-server/src/schema.d.ts.map +1 -1
  416. package/out/zero-server/src/schema.js +63 -24
  417. package/out/zero-server/src/schema.js.map +1 -1
  418. package/out/zero-types/src/schema.d.ts +11 -0
  419. package/out/zero-types/src/schema.d.ts.map +1 -1
  420. package/out/zql/src/ivm/memory-source.d.ts +10 -2
  421. package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
  422. package/out/zql/src/ivm/memory-source.js +14 -6
  423. package/out/zql/src/ivm/memory-source.js.map +1 -1
  424. package/out/zql/src/ivm/stream.d.ts +0 -1
  425. package/out/zql/src/ivm/stream.d.ts.map +1 -1
  426. package/out/zql/src/ivm/stream.js +1 -7
  427. package/out/zql/src/ivm/stream.js.map +1 -1
  428. package/out/zql/src/ivm/union-fan-in.d.ts +1 -1
  429. package/out/zql/src/ivm/union-fan-in.d.ts.map +1 -1
  430. package/out/zql/src/ivm/union-fan-in.js +11 -2
  431. package/out/zql/src/ivm/union-fan-in.js.map +1 -1
  432. package/out/zql/src/mutate/crud.d.ts +10 -8
  433. package/out/zql/src/mutate/crud.d.ts.map +1 -1
  434. package/out/zql/src/mutate/crud.js.map +1 -1
  435. package/out/zql/src/query/query-delegate-base.d.ts.map +1 -1
  436. package/out/zql/src/query/query-delegate-base.js +5 -1
  437. package/out/zql/src/query/query-delegate-base.js.map +1 -1
  438. package/out/zql/src/query/query-impl.d.ts +2 -2
  439. package/out/zql/src/query/query-impl.d.ts.map +1 -1
  440. package/out/zql/src/query/query-impl.js.map +1 -1
  441. package/out/zql/src/query/query.d.ts +83 -14
  442. package/out/zql/src/query/query.d.ts.map +1 -1
  443. package/out/zql/src/query/static-query.d.ts +1 -1
  444. package/out/zql/src/query/static-query.d.ts.map +1 -1
  445. package/out/zqlite/src/db.js +2 -2
  446. package/out/zqlite/src/resolve-scalar-subqueries.d.ts +15 -0
  447. package/out/zqlite/src/resolve-scalar-subqueries.d.ts.map +1 -1
  448. package/out/zqlite/src/resolve-scalar-subqueries.js +33 -14
  449. package/out/zqlite/src/resolve-scalar-subqueries.js.map +1 -1
  450. package/out/zqlite/src/sqlite-cost-model.js +5 -5
  451. package/out/zqlite/src/table-source.d.ts.map +1 -1
  452. package/out/zqlite/src/table-source.js +4 -4
  453. package/out/zqlite/src/table-source.js.map +1 -1
  454. package/package.json +3 -3
  455. package/out/replicache/src/db/index.js +0 -91
  456. package/out/replicache/src/db/index.js.map +0 -1
  457. package/out/replicache/src/lazy.d.ts +0 -2
  458. package/out/replicache/src/lazy.d.ts.map +0 -1
  459. package/out/replicache/src/lazy.js +0 -12
  460. package/out/replicache/src/lazy.js.map +0 -1
  461. package/out/zero-cache/src/server/backup-watermark-reader.js +0 -35
  462. package/out/zero-cache/src/server/backup-watermark-reader.js.map +0 -1
  463. package/out/zero-cache/src/services/change-streamer/litestream3-backup-monitor.d.ts.map +0 -1
  464. package/out/zero-cache/src/services/change-streamer/litestream3-backup-monitor.js.map +0 -1
  465. package/out/zero-cache/src/services/change-streamer/replica-monitor.d.ts +0 -16
  466. package/out/zero-cache/src/services/change-streamer/replica-monitor.d.ts.map +0 -1
  467. package/out/zero-cache/src/services/change-streamer/replica-monitor.js +0 -54
  468. package/out/zero-cache/src/services/change-streamer/replica-monitor.js.map +0 -1
  469. package/out/zero-cache/src/services/change-streamer/vfs-backup-monitor.d.ts +0 -25
  470. package/out/zero-cache/src/services/change-streamer/vfs-backup-monitor.d.ts.map +0 -1
  471. package/out/zero-cache/src/services/change-streamer/vfs-backup-monitor.js +0 -159
  472. package/out/zero-cache/src/services/change-streamer/vfs-backup-monitor.js.map +0 -1
  473. package/out/zero-cache/src/services/litestream/vfs-watermark-reader.d.ts +0 -44
  474. package/out/zero-cache/src/services/litestream/vfs-watermark-reader.d.ts.map +0 -1
  475. package/out/zero-cache/src/services/litestream/vfs-watermark-reader.js +0 -65
  476. package/out/zero-cache/src/services/litestream/vfs-watermark-reader.js.map +0 -1
  477. package/out/zero-cache/src/services/litestream/vfs-watermark-worker-source.d.ts +0 -11
  478. package/out/zero-cache/src/services/litestream/vfs-watermark-worker-source.d.ts.map +0 -1
  479. package/out/zero-cache/src/services/litestream/vfs-watermark-worker-source.js +0 -74
  480. package/out/zero-cache/src/services/litestream/vfs-watermark-worker-source.js.map +0 -1
  481. package/out/zero-cache/src/services/litestream/vfs-watermark-worker.d.ts +0 -42
  482. package/out/zero-cache/src/services/litestream/vfs-watermark-worker.d.ts.map +0 -1
  483. package/out/zero-cache/src/services/litestream/vfs-watermark-worker.js +0 -117
  484. package/out/zero-cache/src/services/litestream/vfs-watermark-worker.js.map +0 -1
@@ -1,4 +1,4 @@
1
- import { assert } 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
3
  import { AbortError } from "../../../../shared/src/abort-error.js";
4
4
  import { parse, valita_exports } from "../../../../shared/src/valita.js";
@@ -8,12 +8,15 @@ import { isDataChange, isSchemaChange } from "../change-source/protocol/current/
8
8
  import "../change-source/protocol/current/downstream.js";
9
9
  import { backfillRequestSchema } from "../change-source/protocol/current/upstream.js";
10
10
  import "../change-source/protocol/current.js";
11
+ import { cookieOps } from "../replicator/change-log-cookies.js";
11
12
  import "../../types/pg.js";
12
13
  import { READONLY, READ_COMMITTED } from "../../db/mode-enum.js";
13
14
  import { runTx } from "../../db/run-transaction.js";
14
- import { AutoResetSignal, markResetRequired } from "./schema/tables.js";
15
15
  import { Queue } from "../../../../shared/src/queue.js";
16
+ import { AutoResetSignal, markResetRequired } from "./schema/tables.js";
16
17
  import { TransactionPool } from "../../db/transaction-pool.js";
18
+ import { orTimeout } from "../../types/timeout.js";
19
+ import { extractChangeSubstring, reconstructWatermarkedChange, serializeChangeStreamData } from "./change-log-codec.js";
17
20
  import { resolver } from "@rocicorp/resolver";
18
21
  import "postgres";
19
22
  import { getHeapStatistics } from "node:v8";
@@ -58,15 +61,17 @@ var Storer = class {
58
61
  #discoveryProtocol;
59
62
  #db;
60
63
  #replicaVersion;
61
- #onConsumed;
64
+ #onCommitted;
62
65
  #onFatal;
63
66
  #queue = new Queue();
64
67
  #backPressureThresholdBytes;
65
68
  #statementTimeoutMs;
66
69
  #changeLogBatchSize;
70
+ #drainTimeoutMs;
71
+ #progressMonitor;
67
72
  #approximateQueuedBytes = 0;
68
73
  #running = false;
69
- constructor(lc, shard, taskID, discoveryAddress, discoveryProtocol, db, replicaVersion, onConsumed, onFatal, { backPressureLimitHeapProportion, statementTimeoutMs, changeLogBatchSize }) {
74
+ constructor(lc, shard, taskID, discoveryAddress, discoveryProtocol, db, replicaVersion, onCommitted, onFatal, { backPressureLimitHeapProportion, statementTimeoutMs, changeLogBatchSize, drainTimeoutMs = 3e4 }) {
70
75
  this.#lc = lc.withContext("component", "change-log");
71
76
  this.#shard = shard;
72
77
  this.#taskID = taskID;
@@ -74,10 +79,12 @@ var Storer = class {
74
79
  this.#discoveryProtocol = discoveryProtocol;
75
80
  this.#db = db;
76
81
  this.#replicaVersion = replicaVersion;
77
- this.#onConsumed = onConsumed;
82
+ this.#onCommitted = onCommitted;
78
83
  this.#onFatal = onFatal;
79
84
  this.#statementTimeoutMs = statementTimeoutMs;
80
85
  this.#changeLogBatchSize = Math.max(1, changeLogBatchSize);
86
+ this.#drainTimeoutMs = drainTimeoutMs;
87
+ this.#progressMonitor = new ProgressMonitor(lc, statementTimeoutMs, onFatal);
81
88
  const heapStats = getHeapStatistics();
82
89
  this.#backPressureThresholdBytes = (heapStats.heap_size_limit - heapStats.used_heap_size) * backPressureLimitHeapProportion;
83
90
  this.#lc.info?.(`Using up to ${(this.#backPressureThresholdBytes / 1024 ** 2).toFixed(2)} MB of --max-old-space-size (~${(heapStats.heap_size_limit / 1024 ** 2).toFixed(2)} MB) to absorb upstream spikes`, { heapStats });
@@ -85,6 +92,28 @@ var Storer = class {
85
92
  #cdc(table) {
86
93
  return this.#db(`${cdcSchema(this.#shard)}.${table}`);
87
94
  }
95
+ /**
96
+ * Bounds a one-off db call (i.e. not part of the main storer loop or the
97
+ * background catchup read, which are tracked by the ProgressMonitor
98
+ * instead) with a plain timeout. This covers calls like
99
+ * {@link assumeOwnership} and {@link getStartStreamInitializationParameters}
100
+ * that are made by the caller *before* {@link run()} -- and thus before the
101
+ * ProgressMonitor's polling starts -- as well as ones made well after,
102
+ * where a continuously-polling watchdog would be overkill for a single
103
+ * bounded db round trip.
104
+ *
105
+ * Does not cancel `promise` on timeout (there is no cancellation mechanism
106
+ * for a postgres.js query); it just stops waiting for it, and swallows a
107
+ * later rejection so it doesn't surface as an unhandled rejection.
108
+ */
109
+ async #withTimeout(name, promise) {
110
+ const result = await orTimeout(promise, this.#statementTimeoutMs);
111
+ if (result === "timed-out") {
112
+ promise.catch(() => {});
113
+ throw new AbortError(`${name} did not complete within ${this.#statementTimeoutMs}ms`);
114
+ }
115
+ return result;
116
+ }
88
117
  async assumeOwnership(purgeLock) {
89
118
  const db = this.#db;
90
119
  const owner = this.#taskID;
@@ -93,40 +122,110 @@ var Storer = class {
93
122
  const addressWithProtocol = ownerProtocol === "ws" ? ownerAddress : `${ownerProtocol}://${ownerAddress}`;
94
123
  this.#lc.info?.(`assuming ownership at ${addressWithProtocol}`);
95
124
  const start = performance.now();
96
- await db`UPDATE ${this.#cdc("replicationState")} SET ${db({
125
+ await this.#withTimeout("assume-ownership", db`UPDATE ${this.#cdc("replicationState")} SET ${db({
97
126
  owner,
98
127
  ownerAddress: addressWithProtocol
99
- })}`;
128
+ })}`);
100
129
  const elapsed = (performance.now() - start).toFixed(2);
101
130
  this.#lc.info?.(`assumed ownership at ${addressWithProtocol} (${elapsed} ms)`);
102
131
  if (purgeLock) purgeLock.release();
103
132
  }
133
+ /**
134
+ * The whole of what a stream connection starts from: where to resume, what to
135
+ * ask the change source to backfill, and the raw cookie set those requests
136
+ * were derived from.
137
+ *
138
+ * All four statements run in one REPEATABLE READ transaction, so they see one
139
+ * snapshot. That is invariant 15 — the resume watermark and the cookies must
140
+ * come from the same store, read at the same position — and it is why the
141
+ * cookies are read here rather than by a second call: a cookie set paired
142
+ * with a watermark it was not folded to loses every backfill that completed
143
+ * in the interval, and those rows are not replayable from the slot.
144
+ *
145
+ * `cookies` is not `backfillRequests` in another shape. The request list is
146
+ * driven off `backfilling`, so it drops the metadata of every table with no
147
+ * in-flight backfill — correct for starting a stream, lossy as the cookie
148
+ * snapshot that the SQLite change log continues folding onto.
149
+ */
104
150
  async getStartStreamInitializationParameters() {
105
- const [[{ lastWatermark }], result] = await runTx(this.#db, (sql) => [sql`
106
- SELECT "lastWatermark" FROM ${this.#cdc("replicationState")}`, sql`
107
- SELECT
151
+ const [[{ lastWatermark }], result, tableMetadata, backfilling] = await this.#withTimeout("get-stream-params", runTx(this.#db, (sql) => [
152
+ sql`
153
+ SELECT "lastWatermark" FROM ${this.#cdc("replicationState")}`,
154
+ sql`
155
+ SELECT
108
156
  json_build_object(
109
157
  'schema', b."schema",
110
158
  'name', b."table",
111
159
  'metadata', t."metadata"
112
160
  ) as "table",
113
- json_object_agg(b."column", b."backfill")
161
+ json_object_agg(b."column", b."backfill")
114
162
  as "columns"
115
163
  FROM ${this.#cdc("backfilling")} as b
116
164
  LEFT JOIN ${this.#cdc("tableMetadata")} as t
117
165
  ON (b."schema" = t."schema" AND b."table" = t."table")
118
166
  GROUP BY b."schema", b."table", t."metadata"
119
- `], { mode: READONLY });
167
+ `,
168
+ sql`
169
+ SELECT "schema", "table", "metadata" FROM ${this.#cdc("tableMetadata")}
170
+ ORDER BY "schema" COLLATE "C", "table" COLLATE "C"`,
171
+ sql`
172
+ SELECT "schema", "table", "column", "backfill" FROM ${this.#cdc("backfilling")}
173
+ ORDER BY "schema" COLLATE "C", "table" COLLATE "C", "column" COLLATE "C"`
174
+ ], { mode: READONLY }));
120
175
  return {
121
176
  lastWatermark,
122
- backfillRequests: parse(result, backfillRequestsSchema)
177
+ backfillRequests: parse(result, backfillRequestsSchema),
178
+ cookies: {
179
+ tableMetadata: [...tableMetadata],
180
+ backfilling: [...backfilling]
181
+ }
123
182
  };
124
183
  }
125
184
  async getMinWatermarkForCatchup() {
126
- const [{ minWatermark }] = await this.#db`
127
- SELECT min(watermark) as "minWatermark" FROM ${this.#cdc("changeLog")}`;
185
+ const [{ minWatermark }] = await this.#withTimeout("get-min-watermark", this.#db`
186
+ SELECT min(watermark) as "minWatermark" FROM ${this.#cdc("changeLog")}`);
128
187
  return minWatermark;
129
188
  }
189
+ /**
190
+ * Returns the retained Postgres catchup bounds.
191
+ * `minWatermark` is the oldest transaction, or `null` for a new replica.
192
+ * `lastWatermark` is the durable head.
193
+ */
194
+ async getCatchupBounds() {
195
+ const [bounds] = await this.#withTimeout("get-catchup-bounds", this.#db`
196
+ SELECT
197
+ (SELECT min(watermark) FROM ${this.#cdc("changeLog")}) as "minWatermark",
198
+ (SELECT "lastWatermark" FROM ${this.#cdc("replicationState")}) as "lastWatermark"`);
199
+ return bounds;
200
+ }
201
+ /**
202
+ * Lists at most `limit` committed transaction watermarks in
203
+ * `(afterWatermark, throughWatermark]`, in ascending order.
204
+ */
205
+ async listCommitWatermarks(afterWatermark, throughWatermark, limit) {
206
+ return (await this.#db`
207
+ SELECT watermark FROM ${this.#cdc("changeLog")}
208
+ WHERE precommit IS NOT NULL
209
+ AND watermark > ${afterWatermark}
210
+ AND watermark <= ${throughWatermark}
211
+ ORDER BY watermark
212
+ LIMIT ${limit}`).map(({ watermark }) => watermark);
213
+ }
214
+ /**
215
+ * Reads `(afterWatermark, throughWatermark]` in stream order and bounded batches.
216
+ * This query matches the subscriber catchup query.
217
+ *
218
+ * Both queries fail when an escaped NUL reaches `change->'tag'`.
219
+ * Postgres cannot convert that value to text.
220
+ */
221
+ readCatchupRange(afterWatermark, throughWatermark, batchRows = 2e3) {
222
+ assert(Number.isSafeInteger(batchRows) && batchRows > 0, "Postgres change log batch size must be a positive safe integer");
223
+ return this.#db`
224
+ SELECT watermark, change->'tag' as tag, change::text FROM ${this.#cdc("changeLog")}
225
+ WHERE watermark > ${afterWatermark}
226
+ AND watermark <= ${throughWatermark}
227
+ ORDER BY watermark, pos`.cursor(batchRows);
228
+ }
130
229
  purgeRecordsBefore(watermark) {
131
230
  return runTx(this.#db, async (sql) => {
132
231
  await sql`
@@ -159,7 +258,7 @@ var Storer = class {
159
258
  * @returns The JSON stringified stream message to be sent downstream.
160
259
  */
161
260
  store(watermark, data) {
162
- const json = BigIntJSON.stringify(data);
261
+ const json = serializeChangeStreamData(data);
163
262
  this.#approximateQueuedBytes += json.length;
164
263
  const change = data[1];
165
264
  this.#queue.enqueue([
@@ -173,9 +272,6 @@ var Storer = class {
173
272
  abort() {
174
273
  this.#queue.enqueue(["abort"]);
175
274
  }
176
- status(s) {
177
- this.#queue.enqueue(s);
178
- }
179
275
  catchup(subscriber, mode) {
180
276
  this.#queue.enqueue(["subscriber", {
181
277
  subscriber,
@@ -192,10 +288,12 @@ var Storer = class {
192
288
  return this.#readyForMore?.promise;
193
289
  }
194
290
  #maybeReleaseBackPressure() {
195
- if (this.#readyForMore !== null && this.#approximateQueuedBytes < this.#backPressureThresholdBytes * .8) {
196
- this.#lc.info?.(`releasing back pressure with ${this.#queue.size()} queued changes (~${(this.#approximateQueuedBytes / 1024 ** 2).toFixed(2)} MB)`);
197
- this.#readyForMore.resolve();
198
- this.#readyForMore = null;
291
+ if (this.#readyForMore !== null) {
292
+ if (this.#approximateQueuedBytes < this.#backPressureThresholdBytes * .8) {
293
+ this.#lc.info?.(`releasing back pressure with ${this.#queue.size()} queued changes (~${(this.#approximateQueuedBytes / 1024 ** 2).toFixed(2)} MB)`);
294
+ this.#readyForMore.resolve();
295
+ this.#readyForMore = null;
296
+ }
199
297
  }
200
298
  }
201
299
  /**
@@ -235,6 +333,7 @@ var Storer = class {
235
333
  this.#running = true;
236
334
  this.#stopped = stopped;
237
335
  this.#lc.info?.("starting storer");
336
+ this.#progressMonitor.start();
238
337
  let err;
239
338
  try {
240
339
  await this.#processQueue();
@@ -271,9 +370,20 @@ var Storer = class {
271
370
  async #processQueue() {
272
371
  let tx = null;
273
372
  let msg;
373
+ let lastTaskDone;
374
+ const nextMessage = async () => {
375
+ lastTaskDone?.();
376
+ lastTaskDone = void 0;
377
+ const entry = await this.#queue.dequeue();
378
+ if (entry !== "stop") lastTaskDone = this.#progressMonitor.trackTask({
379
+ task: "queue-entry",
380
+ type: entry[0]
381
+ });
382
+ return entry;
383
+ };
274
384
  const catchupQueue = [];
275
385
  try {
276
- while ((msg = await this.#queue.dequeue()) !== "stop") {
386
+ while ((msg = await nextMessage()) !== "stop") {
277
387
  const [msgType] = msg;
278
388
  switch (msgType) {
279
389
  case "ready": {
@@ -287,9 +397,6 @@ var Storer = class {
287
397
  else await this.#startCatchup([subscriber]);
288
398
  continue;
289
399
  }
290
- case "status":
291
- this.#onConsumed(msg);
292
- continue;
293
400
  case "abort":
294
401
  if (tx) {
295
402
  tx.pool.abort();
@@ -306,10 +413,7 @@ var Storer = class {
306
413
  const { promise, resolve, reject } = resolver();
307
414
  promise.catch(() => {});
308
415
  tx = {
309
- pool: new TransactionPool(this.#lc.withContext("watermark", watermark), {
310
- mode: READ_COMMITTED,
311
- statementResponseTimeout: this.#statementTimeoutMs
312
- }),
416
+ pool: new TransactionPool(this.#lc.withContext("watermark", watermark), { mode: READ_COMMITTED }),
313
417
  preCommitWatermark: watermark,
314
418
  pos: 0,
315
419
  startingReplicationState: promise,
@@ -356,7 +460,7 @@ var Storer = class {
356
460
  tx.pool.setDone();
357
461
  }
358
462
  await tx.pool.done();
359
- if (tx.ack) this.#onConsumed([
463
+ if (tx.ack) this.#onCommitted([
360
464
  "commit",
361
465
  change,
362
466
  { watermark }
@@ -377,9 +481,14 @@ var Storer = class {
377
481
  }
378
482
  async #startCatchup(subs) {
379
483
  if (subs.length === 0) return;
380
- const reader = new TransactionPool(this.#lc.withContext("pool", "catchup"), { mode: READONLY });
484
+ const lc = this.#lc.withContext("pool", "catchup");
485
+ const reader = new TransactionPool(lc, { mode: READONLY });
381
486
  reader.run(this.#db);
382
487
  let lastWatermark;
488
+ const catchupSnapshotted = this.#progressMonitor.trackTask({
489
+ task: "capture-catchup-snapshot",
490
+ subscribers: subs.map(({ subscriber: s }) => s.id)
491
+ });
383
492
  try {
384
493
  [{lastWatermark}] = await reader.processReadTask((sql) => sql`
385
494
  SELECT "lastWatermark" FROM ${this.#cdc("replicationState")}
@@ -387,12 +496,22 @@ var Storer = class {
387
496
  } catch (e) {
388
497
  subs.map(({ subscriber }) => subscriber.fail(e));
389
498
  throw e;
499
+ } finally {
500
+ catchupSnapshotted();
390
501
  }
391
- Promise.all(subs.map((sub) => this.#catchup(sub, lastWatermark, reader))).finally(() => reader.setDone());
502
+ Promise.all(subs.map((sub) => this.#catchup(lc.withContext("subscriber", sub.subscriber.id), sub, lastWatermark, reader))).finally(() => reader.setDone());
392
503
  }
393
- async #catchup({ subscriber: sub, mode }, lastWatermark, reader) {
504
+ async #catchup(lc, { subscriber: sub, mode }, lastWatermark, reader) {
505
+ let entriesReceived = 0;
506
+ let catchupProgressed = this.#progressMonitor.trackTask({
507
+ task: "catchup",
508
+ subscriber: sub.id,
509
+ entriesReceived
510
+ });
394
511
  try {
512
+ lc.info?.(`starting catchup`);
395
513
  await reader.processReadTask(async (tx) => {
514
+ lc.info?.(`catching up`);
396
515
  const start = Date.now();
397
516
  let watermarkFound = sub.watermark === this.#replicaVersion;
398
517
  let count = 0;
@@ -402,100 +521,100 @@ var Storer = class {
402
521
  WHERE watermark >= ${sub.watermark}
403
522
  AND watermark <= ${lastWatermark}
404
523
  ORDER BY watermark, pos`.cursor(2e3)) {
405
- const start = performance.now();
406
- await lastBatchConsumed;
407
- const elapsed = performance.now() - start;
408
- if (lastBatchConsumed) this.#lc[elapsed > 100 ? "info" : "debug"]?.(`waited ${elapsed.toFixed(3)} ms for ${sub.id} to consume last batch of catchup entries`);
409
- for (const entry of entries) if (entry.watermark === sub.watermark) watermarkFound = true;
410
- else if (watermarkFound) {
411
- lastBatchConsumed = sub.catchup(toDownstream(entry));
412
- count++;
413
- } else if (mode === "backup") throw new AutoResetSignal(`backup replica at watermark ${sub.watermark} is behind change db: ${entry.watermark})`);
414
- else {
415
- this.#lc.warn?.(`rejecting subscriber at watermark ${sub.watermark} (earliest watermark: ${entry.watermark})`);
416
- sub.close(2, `earliest supported watermark is ${entry.watermark} (requested ${sub.watermark})`);
417
- return;
524
+ catchupProgressed();
525
+ entriesReceived += entries.length;
526
+ try {
527
+ const start = performance.now();
528
+ await lastBatchConsumed;
529
+ const elapsed = performance.now() - start;
530
+ if (lastBatchConsumed) lc[elapsed > 100 ? "info" : "debug"]?.(`waited ${elapsed.toFixed(3)} ms for ${sub.id} to consume last batch of catchup entries`);
531
+ for (const entry of entries) if (entry.watermark === sub.watermark) watermarkFound = true;
532
+ else if (watermarkFound) {
533
+ lastBatchConsumed = sub.catchup(reconstructWatermarkedChange(entry));
534
+ count++;
535
+ } else if (mode === "backup") throw new AutoResetSignal(`backup replica at watermark ${sub.watermark} is behind change db: ${entry.watermark})`);
536
+ else {
537
+ lc.warn?.(`rejecting subscriber at watermark ${sub.watermark} (earliest watermark: ${entry.watermark})`);
538
+ sub.close(2, `earliest supported watermark is ${entry.watermark} (requested ${sub.watermark})`);
539
+ return;
540
+ }
541
+ } finally {
542
+ catchupProgressed = this.#progressMonitor.trackTask({
543
+ task: "catchup",
544
+ subscriber: sub.id,
545
+ entriesReceived
546
+ });
418
547
  }
419
548
  }
549
+ catchupProgressed();
420
550
  if (watermarkFound) {
421
551
  await lastBatchConsumed;
422
- this.#lc.info?.(`caught up ${sub.id} with ${count} changes (${Date.now() - start} ms)`);
423
- } else this.#lc.warn?.(`subscriber ${sub.id} at watermark ${sub.watermark} is ahead of the latest durable watermark ${lastWatermark}; waiting for the change DB to catch up`);
552
+ lc.info?.(`caught up ${sub.id} with ${count} changes (${Date.now() - start} ms)`);
553
+ } else lc.warn?.(`subscriber ${sub.id} at watermark ${sub.watermark} is ahead of the latest durable watermark ${lastWatermark}; waiting for the change DB to catch up`);
424
554
  sub.setCaughtUp();
425
555
  });
426
556
  } catch (err) {
427
- this.#lc.error?.(`error while catching up subscriber ${sub.id}`, err);
557
+ lc.error?.(`error while catching up subscriber ${sub.id}`, err);
428
558
  if (err instanceof AutoResetSignal) {
429
559
  await markResetRequired(this.#db, this.#shard);
430
560
  this.#onFatal(err);
431
561
  }
432
562
  sub.fail(err);
563
+ } finally {
564
+ catchupProgressed();
433
565
  }
434
566
  }
435
567
  /**
436
568
  * Returns the db statements necessary to track backfill and table metadata
437
569
  * presented in the `change`, if any.
570
+ *
571
+ * This is the Postgres interpreter of {@link cookieOps}, which is also
572
+ * interpreted against the SQLite change log by `ChangeLogCookieWriter`. The
573
+ * two stores have to agree on every transition forever, and the failure mode
574
+ * if they drift is a backfill that is silently never re-requested — so the
575
+ * decision of what a schema change *means* lives in one place and only its
576
+ * transport lives here.
438
577
  */
439
578
  #trackBackfillMetadata(sql, change) {
440
- const stmts = [];
441
- switch (change.tag) {
442
- case "update-table-metadata": {
443
- const { table, new: metadata } = change;
444
- stmts.push(this.#upsertTableMetadataStmt(sql, table, metadata));
445
- break;
446
- }
447
- case "create-table": {
448
- const { spec, metadata, backfill } = change;
449
- if (metadata) stmts.push(this.#upsertTableMetadataStmt(sql, spec, metadata));
450
- if (backfill) Object.entries(backfill).forEach(([col, backfill]) => {
451
- stmts.push(this.#upsertColumnBackfillStmt(sql, spec, col, backfill));
452
- });
453
- break;
454
- }
579
+ return cookieOps(change).flatMap((op) => this.#cookieStmts(sql, op));
580
+ }
581
+ #cookieStmts(sql, op) {
582
+ switch (op.op) {
583
+ case "upsert-metadata": return [this.#upsertTableMetadataStmt(sql, op.table, op.metadata)];
584
+ case "upsert-backfill": return [this.#upsertColumnBackfillStmt(sql, op.table, op.column, op.backfill)];
455
585
  case "rename-table": {
456
- const { old } = change;
586
+ const { old } = op;
457
587
  const row = {
458
- schema: change.new.schema,
459
- table: change.new.name
588
+ schema: op.new.schema,
589
+ table: op.new.name
460
590
  };
461
- stmts.push(sql`UPDATE ${this.#cdc("tableMetadata")} SET ${sql(row)}
591
+ return [sql`UPDATE ${this.#cdc("tableMetadata")} SET ${sql(row)}
462
592
  WHERE "schema" = ${old.schema} AND "table" = ${old.name}`, sql`UPDATE ${this.#cdc("backfilling")} SET ${sql(row)}
463
- WHERE "schema" = ${old.schema} AND "table" = ${old.name}`);
464
- break;
593
+ WHERE "schema" = ${old.schema} AND "table" = ${old.name}`];
465
594
  }
466
595
  case "drop-table": {
467
- const { id: { schema, name } } = change;
468
- stmts.push(sql`DELETE FROM ${this.#cdc("tableMetadata")}
596
+ const { schema, name } = op.table;
597
+ return [sql`DELETE FROM ${this.#cdc("tableMetadata")}
469
598
  WHERE "schema" = ${schema} AND "table" = ${name}`, sql`DELETE FROM ${this.#cdc("backfilling")}
470
- WHERE "schema" = ${schema} AND "table" = ${name}`);
471
- break;
599
+ WHERE "schema" = ${schema} AND "table" = ${name}`];
472
600
  }
473
- case "add-column": {
474
- const { table, tableMetadata, column, backfill } = change;
475
- if (tableMetadata) stmts.push(this.#upsertTableMetadataStmt(sql, table, tableMetadata));
476
- if (backfill) stmts.push(this.#upsertColumnBackfillStmt(sql, table, column.name, backfill));
477
- break;
478
- }
479
- case "update-column": {
480
- const { table: { schema, name: table }, old: { name: oldName }, new: { name: newName } } = change;
481
- if (oldName !== newName) stmts.push(sql`UPDATE ${this.#cdc("backfilling")} SET "column" = ${newName}
482
- WHERE "schema" = ${schema} AND "table" = ${table} AND "column" = ${oldName}`);
483
- break;
601
+ case "rename-column": {
602
+ const { schema, name: table } = op.table;
603
+ return [sql`UPDATE ${this.#cdc("backfilling")} SET "column" = ${op.new}
604
+ WHERE "schema" = ${schema} AND "table" = ${table} AND "column" = ${op.old}`];
484
605
  }
485
606
  case "drop-column": {
486
- const { table: { schema, name }, column } = change;
487
- stmts.push(sql`DELETE FROM ${this.#cdc("backfilling")}
488
- WHERE "schema" = ${schema} AND "table" = ${name} AND "column" = ${column}`);
489
- break;
607
+ const { schema, name } = op.table;
608
+ return [sql`DELETE FROM ${this.#cdc("backfilling")}
609
+ WHERE "schema" = ${schema} AND "table" = ${name} AND "column" = ${op.column}`];
490
610
  }
491
- case "backfill-completed": {
492
- const { relation: { schema, name: table, rowKey }, columns } = change;
493
- const cols = [...rowKey.columns, ...columns];
494
- stmts.push(sql`DELETE FROM ${this.#cdc("backfilling")}
495
- WHERE "schema" = ${schema} AND "table" = ${table} AND "column" IN ${sql(cols)}`);
611
+ case "complete-backfill": {
612
+ const { schema, name: table } = op.table;
613
+ return [sql`DELETE FROM ${this.#cdc("backfilling")}
614
+ WHERE "schema" = ${schema} AND "table" = ${table} AND "column" IN ${sql([...op.columns])}`];
496
615
  }
616
+ default: unreachable(op);
497
617
  }
498
- return stmts;
499
618
  }
500
619
  #upsertTableMetadataStmt(sql, { schema, name: table }, metadata) {
501
620
  const row = {
@@ -505,7 +624,7 @@ var Storer = class {
505
624
  };
506
625
  return sql`
507
626
  INSERT INTO ${this.#cdc("tableMetadata")} ${sql(row)}
508
- ON CONFLICT ("schema", "table")
627
+ ON CONFLICT ("schema", "table")
509
628
  DO UPDATE SET ${sql(row)};
510
629
  `;
511
630
  }
@@ -518,7 +637,7 @@ var Storer = class {
518
637
  };
519
638
  return sql`
520
639
  INSERT INTO ${this.#cdc("backfilling")} ${sql(row)}
521
- ON CONFLICT ("schema", "table", "column")
640
+ ON CONFLICT ("schema", "table", "column")
522
641
  DO UPDATE SET ${sql(row)};
523
642
  `;
524
643
  }
@@ -533,54 +652,21 @@ var Storer = class {
533
652
  await promise;
534
653
  }
535
654
  }
536
- stop() {
655
+ /**
656
+ * Stops the storer and waits up to a drain timeout for entries to drain,
657
+ * throwing an exception if it doesn't drain in time, in order to abort
658
+ * the server when PG (or the connection to it) appears to be wedged.
659
+ */
660
+ async stop() {
537
661
  if (this.#running) {
662
+ this.#progressMonitor.stop();
538
663
  this.#lc.info?.(`draining ${this.#queue.size()} changeLog entries`);
664
+ this.abort();
539
665
  this.#queue.enqueue("stop");
540
666
  }
541
- return this.#stopped;
667
+ if (await orTimeout(this.#stopped, this.#drainTimeoutMs) === "timed-out") throw new AbortError(`changeLog did not drain within ${this.#drainTimeoutMs}ms`);
542
668
  }
543
669
  };
544
- /**
545
- * Extracts the stringified change message from the stringified
546
- * stream message (e.g. the second tuple element). This optimization
547
- * facilitates stringifying (and sharing the result of) the stream
548
- * message exactly once, but storing only the change message substring
549
- * in the changeLog for backwards compatibility.
550
- */
551
- function extractChangeSubstring(streamMessageJSON, tag) {
552
- switch (tag) {
553
- case "begin":
554
- case "commit": return streamMessageJSON.substring(streamMessageJSON.indexOf(",") + 1, streamMessageJSON.lastIndexOf(","));
555
- default: return streamMessageJSON.substring(streamMessageJSON.indexOf(",") + 1, streamMessageJSON.lastIndexOf("]"));
556
- }
557
- }
558
- function toDownstream(entry) {
559
- const { watermark, change } = entry;
560
- const tag = entry.tag;
561
- switch (tag) {
562
- case "begin": return [
563
- watermark,
564
- tag,
565
- `["begin",${change},{"commitWatermark":"${watermark}"}]`
566
- ];
567
- case "commit": return [
568
- watermark,
569
- tag,
570
- `["commit",${change},{"watermark":"${watermark}"}]`
571
- ];
572
- case "rollback": return [
573
- watermark,
574
- tag,
575
- `["rollback",${change}]`
576
- ];
577
- default: return [
578
- watermark,
579
- tag,
580
- `["data",${change}]`
581
- ];
582
- }
583
- }
584
670
  var PurgeLock = class {
585
671
  #lc;
586
672
  #tx;
@@ -634,6 +720,65 @@ var PurgeLocker = class {
634
720
  return new PurgeLock(this.#lc, tx, replicaVersion, watermark);
635
721
  }
636
722
  };
723
+ /**
724
+ * Periodic monitor for detecting the pathological condition in which a db
725
+ * query hangs forever because of a connection problem, such as a half-closed
726
+ * socket.
727
+ *
728
+ * Use this for db calls that recur or accumulate progress within a single
729
+ * logical operation on the main storer loop (e.g. the queue-processing loop,
730
+ * or a multi-batch catchup read), where "no progress for N ms" is the
731
+ * meaningful signal. For a one-off db call -- including ones made before
732
+ * {@link Storer.run} starts this monitor's polling -- use a plain timeout
733
+ * (see `Storer.#withTimeout`) instead.
734
+ *
735
+ * The failure handler should stop the server. The ProgressMonitor will
736
+ * assume this and stop itself after calling it.
737
+ *
738
+ * Internal to the Storer, but exported for testing.
739
+ */
740
+ var ProgressMonitor = class {
741
+ #lc;
742
+ #failureThresholdMs;
743
+ #onFailure;
744
+ #taskUpdates = /* @__PURE__ */ new Map();
745
+ #timer;
746
+ constructor(lc, failureThresholdMs, onFailure) {
747
+ this.#lc = lc.withContext("component", "storer-progress-monitor");
748
+ this.#failureThresholdMs = failureThresholdMs;
749
+ this.#onFailure = onFailure;
750
+ }
751
+ start() {
752
+ clearInterval(this.#timer);
753
+ this.#timer = setInterval(() => this.checkTaskProgress(/* @__PURE__ */ new Date()), this.#failureThresholdMs).unref();
754
+ }
755
+ checkTaskProgress(now) {
756
+ for (const [task, lastUpdate] of this.#taskUpdates.entries()) if (now.getTime() - lastUpdate.getTime() >= this.#failureThresholdMs) {
757
+ this.#lc.error?.(`Last task update was more than ${this.#failureThresholdMs}ms ago`, {
758
+ task,
759
+ lastUpdate
760
+ });
761
+ this.#onFailure(/* @__PURE__ */ new Error(`Task failed to progress for over ${this.#failureThresholdMs}ms: ${BigIntJSON.stringify(task)}`));
762
+ this.stop();
763
+ return;
764
+ }
765
+ }
766
+ /**
767
+ * Starts a task to be tracked.
768
+ *
769
+ * @return a callback to invoke when the task is done.
770
+ */
771
+ trackTask(task, now = /* @__PURE__ */ new Date()) {
772
+ this.#taskUpdates.set(task, now);
773
+ return () => {
774
+ this.#taskUpdates.delete(task);
775
+ };
776
+ }
777
+ stop() {
778
+ clearInterval(this.#timer);
779
+ this.#taskUpdates.clear();
780
+ }
781
+ };
637
782
  //#endregion
638
783
  export { PurgeLocker, Storer };
639
784