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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (408) hide show
  1. package/out/replicache/src/db/commit.js +1 -4
  2. package/out/replicache/src/db/commit.js.map +1 -1
  3. package/out/replicache/src/db/read.d.ts +1 -0
  4. package/out/replicache/src/db/read.d.ts.map +1 -1
  5. package/out/replicache/src/db/read.js +1 -4
  6. package/out/replicache/src/db/read.js.map +1 -1
  7. package/out/replicache/src/db/write.d.ts +2 -1
  8. package/out/replicache/src/db/write.d.ts.map +1 -1
  9. package/out/replicache/src/db/write.js +4 -51
  10. package/out/replicache/src/db/write.js.map +1 -1
  11. package/out/replicache/src/persist/clients.d.ts +1 -0
  12. package/out/replicache/src/persist/clients.d.ts.map +1 -1
  13. package/out/replicache/src/persist/clients.js +4 -31
  14. package/out/replicache/src/persist/clients.js.map +1 -1
  15. package/out/replicache/src/process-env.d.ts +28 -0
  16. package/out/replicache/src/process-env.d.ts.map +1 -0
  17. package/out/replicache/src/replicache-impl.d.ts.map +1 -1
  18. package/out/replicache/src/replicache-impl.js.map +1 -1
  19. package/out/replicache/src/scan-iterator.js +2 -14
  20. package/out/replicache/src/scan-iterator.js.map +1 -1
  21. package/out/replicache/src/subscriptions.d.ts +1 -0
  22. package/out/replicache/src/subscriptions.d.ts.map +1 -1
  23. package/out/replicache/src/subscriptions.js +2 -10
  24. package/out/replicache/src/subscriptions.js.map +1 -1
  25. package/out/replicache/src/transactions.d.ts +1 -0
  26. package/out/replicache/src/transactions.d.ts.map +1 -1
  27. package/out/replicache/src/transactions.js +2 -4
  28. package/out/replicache/src/transactions.js.map +1 -1
  29. package/out/z2s/src/compiler.d.ts.map +1 -1
  30. package/out/z2s/src/compiler.js +1 -22
  31. package/out/z2s/src/compiler.js.map +1 -1
  32. package/out/zero/package.js +3 -3
  33. package/out/zero/package.js.map +1 -1
  34. package/out/zero-cache/src/config/normalize.d.ts +1 -0
  35. package/out/zero-cache/src/config/normalize.d.ts.map +1 -1
  36. package/out/zero-cache/src/config/normalize.js +10 -1
  37. package/out/zero-cache/src/config/normalize.js.map +1 -1
  38. package/out/zero-cache/src/config/zero-config.d.ts +52 -1
  39. package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
  40. package/out/zero-cache/src/config/zero-config.js +171 -22
  41. package/out/zero-cache/src/config/zero-config.js.map +1 -1
  42. package/out/zero-cache/src/custom/fetch.js +1 -1
  43. package/out/zero-cache/src/custom/fetch.js.map +1 -1
  44. package/out/zero-cache/src/db/delete-lite-db.js +2 -1
  45. package/out/zero-cache/src/db/delete-lite-db.js.map +1 -1
  46. package/out/zero-cache/src/db/migration-lite.d.ts.map +1 -1
  47. package/out/zero-cache/src/db/migration-lite.js +5 -2
  48. package/out/zero-cache/src/db/migration-lite.js.map +1 -1
  49. package/out/zero-cache/src/db/migration.d.ts.map +1 -1
  50. package/out/zero-cache/src/db/migration.js +4 -2
  51. package/out/zero-cache/src/db/migration.js.map +1 -1
  52. package/out/zero-cache/src/db/sqlite-corruption.d.ts +3 -2
  53. package/out/zero-cache/src/db/sqlite-corruption.d.ts.map +1 -1
  54. package/out/zero-cache/src/db/sqlite-corruption.js +13 -8
  55. package/out/zero-cache/src/db/sqlite-corruption.js.map +1 -1
  56. package/out/zero-cache/src/observability/metrics.d.ts +6 -1
  57. package/out/zero-cache/src/observability/metrics.d.ts.map +1 -1
  58. package/out/zero-cache/src/observability/metrics.js +20 -2
  59. package/out/zero-cache/src/observability/metrics.js.map +1 -1
  60. package/out/zero-cache/src/server/backup-watermark-poller.js +31 -0
  61. package/out/zero-cache/src/server/backup-watermark-poller.js.map +1 -0
  62. package/out/zero-cache/src/server/change-streamer.d.ts.map +1 -1
  63. package/out/zero-cache/src/server/change-streamer.js +91 -31
  64. package/out/zero-cache/src/server/change-streamer.js.map +1 -1
  65. package/out/zero-cache/src/server/main.d.ts.map +1 -1
  66. package/out/zero-cache/src/server/main.js +6 -16
  67. package/out/zero-cache/src/server/main.js.map +1 -1
  68. package/out/zero-cache/src/server/replicator.d.ts.map +1 -1
  69. package/out/zero-cache/src/server/replicator.js +48 -5
  70. package/out/zero-cache/src/server/replicator.js.map +1 -1
  71. package/out/zero-cache/src/server/runner/run-worker.js +2 -1
  72. package/out/zero-cache/src/server/runner/run-worker.js.map +1 -1
  73. package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
  74. package/out/zero-cache/src/server/syncer.js +1 -1
  75. package/out/zero-cache/src/server/syncer.js.map +1 -1
  76. package/out/zero-cache/src/server/worker-urls.d.ts +1 -1
  77. package/out/zero-cache/src/server/worker-urls.js +2 -2
  78. package/out/zero-cache/src/server/worker-urls.js.map +1 -1
  79. package/out/zero-cache/src/services/change-source/change-source.d.ts +4 -2
  80. package/out/zero-cache/src/services/change-source/change-source.d.ts.map +1 -1
  81. package/out/zero-cache/src/services/change-source/common/replica-restore.d.ts +35 -0
  82. package/out/zero-cache/src/services/change-source/common/replica-restore.d.ts.map +1 -0
  83. package/out/zero-cache/src/services/change-source/common/replica-restore.js +34 -0
  84. package/out/zero-cache/src/services/change-source/common/replica-restore.js.map +1 -0
  85. package/out/zero-cache/src/services/change-source/common/replica-schema.d.ts +2 -0
  86. package/out/zero-cache/src/services/change-source/common/replica-schema.d.ts.map +1 -1
  87. package/out/zero-cache/src/services/change-source/common/replica-schema.js +73 -1
  88. package/out/zero-cache/src/services/change-source/common/replica-schema.js.map +1 -1
  89. package/out/zero-cache/src/services/change-source/custom/change-source.d.ts +2 -6
  90. package/out/zero-cache/src/services/change-source/custom/change-source.d.ts.map +1 -1
  91. package/out/zero-cache/src/services/change-source/custom/change-source.js +14 -5
  92. package/out/zero-cache/src/services/change-source/custom/change-source.js.map +1 -1
  93. package/out/zero-cache/src/services/change-source/pg/backfill-stream.js +4 -7
  94. package/out/zero-cache/src/services/change-source/pg/backfill-stream.js.map +1 -1
  95. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts +7 -7
  96. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts.map +1 -1
  97. package/out/zero-cache/src/services/change-source/pg/change-source.js +82 -25
  98. package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
  99. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts +9 -1
  100. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts.map +1 -1
  101. package/out/zero-cache/src/services/change-source/pg/initial-sync.js +12 -4
  102. package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
  103. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.d.ts +45 -2
  104. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.d.ts.map +1 -1
  105. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js +59 -8
  106. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js.map +1 -1
  107. package/out/zero-cache/src/services/change-source/pg/replication-slots.d.ts +4 -2
  108. package/out/zero-cache/src/services/change-source/pg/replication-slots.d.ts.map +1 -1
  109. package/out/zero-cache/src/services/change-source/pg/replication-slots.js +7 -4
  110. package/out/zero-cache/src/services/change-source/pg/replication-slots.js.map +1 -1
  111. package/out/zero-cache/src/services/change-source/pg/schema/init.d.ts +0 -5
  112. package/out/zero-cache/src/services/change-source/pg/schema/init.d.ts.map +1 -1
  113. package/out/zero-cache/src/services/change-source/pg/schema/init.js +29 -41
  114. package/out/zero-cache/src/services/change-source/pg/schema/init.js.map +1 -1
  115. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts +35 -16
  116. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts.map +1 -1
  117. package/out/zero-cache/src/services/change-source/pg/schema/shard.js +77 -7
  118. package/out/zero-cache/src/services/change-source/pg/schema/shard.js.map +1 -1
  119. package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts +2 -1
  120. package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts.map +1 -1
  121. package/out/zero-cache/src/services/change-source/protocol/current/data.js +5 -13
  122. package/out/zero-cache/src/services/change-source/protocol/current/data.js.map +1 -1
  123. package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts +6 -3
  124. package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts.map +1 -1
  125. package/out/zero-cache/src/services/change-source/protocol/current/schema-change-tags.d.ts +6 -0
  126. package/out/zero-cache/src/services/change-source/protocol/current/schema-change-tags.d.ts.map +1 -0
  127. package/out/zero-cache/src/services/change-source/protocol/current/schema-change-tags.js +21 -0
  128. package/out/zero-cache/src/services/change-source/protocol/current/schema-change-tags.js.map +1 -0
  129. package/out/zero-cache/src/services/change-source/protocol/current/status.d.ts +1 -0
  130. package/out/zero-cache/src/services/change-source/protocol/current/status.d.ts.map +1 -1
  131. package/out/zero-cache/src/services/change-source/protocol/current/upstream.d.ts +1 -0
  132. package/out/zero-cache/src/services/change-source/protocol/current/upstream.d.ts.map +1 -1
  133. package/out/zero-cache/src/services/change-streamer/backup-cleanup-monitor-factory.d.ts +5 -6
  134. package/out/zero-cache/src/services/change-streamer/backup-cleanup-monitor-factory.d.ts.map +1 -1
  135. package/out/zero-cache/src/services/change-streamer/backup-cleanup-monitor-factory.js +32 -9
  136. package/out/zero-cache/src/services/change-streamer/backup-cleanup-monitor-factory.js.map +1 -1
  137. package/out/zero-cache/src/services/change-streamer/backup-monitor.d.ts +15 -5
  138. package/out/zero-cache/src/services/change-streamer/backup-monitor.d.ts.map +1 -1
  139. package/out/zero-cache/src/services/change-streamer/backup-monitor.js +66 -0
  140. package/out/zero-cache/src/services/change-streamer/backup-monitor.js.map +1 -0
  141. package/out/zero-cache/src/services/change-streamer/broadcast.d.ts +68 -78
  142. package/out/zero-cache/src/services/change-streamer/broadcast.d.ts.map +1 -1
  143. package/out/zero-cache/src/services/change-streamer/broadcast.js +84 -92
  144. package/out/zero-cache/src/services/change-streamer/broadcast.js.map +1 -1
  145. package/out/zero-cache/src/services/change-streamer/change-log-codec.d.ts +19 -0
  146. package/out/zero-cache/src/services/change-streamer/change-log-codec.d.ts.map +1 -0
  147. package/out/zero-cache/src/services/change-streamer/change-log-codec.js +50 -0
  148. package/out/zero-cache/src/services/change-streamer/change-log-codec.js.map +1 -0
  149. package/out/zero-cache/src/services/change-streamer/change-log-initializer.d.ts +141 -0
  150. package/out/zero-cache/src/services/change-streamer/change-log-initializer.d.ts.map +1 -0
  151. package/out/zero-cache/src/services/change-streamer/change-log-initializer.js +270 -0
  152. package/out/zero-cache/src/services/change-streamer/change-log-initializer.js.map +1 -0
  153. package/out/zero-cache/src/services/change-streamer/change-log-transaction-hash.d.ts +19 -0
  154. package/out/zero-cache/src/services/change-streamer/change-log-transaction-hash.d.ts.map +1 -0
  155. package/out/zero-cache/src/services/change-streamer/change-log-transaction-hash.js +39 -0
  156. package/out/zero-cache/src/services/change-streamer/change-log-transaction-hash.js.map +1 -0
  157. package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts +3 -4
  158. package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts.map +1 -1
  159. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +12 -17
  160. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
  161. package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts +69 -24
  162. package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts.map +1 -1
  163. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js +333 -66
  164. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -1
  165. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts +56 -13
  166. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts.map +1 -1
  167. package/out/zero-cache/src/services/change-streamer/change-streamer.js.map +1 -1
  168. package/out/zero-cache/src/services/change-streamer/error-type-enum.d.ts +8 -0
  169. package/out/zero-cache/src/services/change-streamer/error-type-enum.d.ts.map +1 -1
  170. package/out/zero-cache/src/services/change-streamer/forwarder.d.ts +14 -3
  171. package/out/zero-cache/src/services/change-streamer/forwarder.d.ts.map +1 -1
  172. package/out/zero-cache/src/services/change-streamer/forwarder.js +41 -11
  173. package/out/zero-cache/src/services/change-streamer/forwarder.js.map +1 -1
  174. package/out/zero-cache/src/services/change-streamer/{litestream3-backup-monitor.d.ts → litestream3-prometheus-poller.d.ts} +19 -45
  175. package/out/zero-cache/src/services/change-streamer/litestream3-prometheus-poller.d.ts.map +1 -0
  176. package/out/zero-cache/src/services/change-streamer/{litestream3-backup-monitor.js → litestream3-prometheus-poller.js} +57 -171
  177. package/out/zero-cache/src/services/change-streamer/litestream3-prometheus-poller.js.map +1 -0
  178. package/out/zero-cache/src/services/change-streamer/replica-poller.d.ts +15 -0
  179. package/out/zero-cache/src/services/change-streamer/replica-poller.d.ts.map +1 -0
  180. package/out/zero-cache/src/services/change-streamer/replica-poller.js +55 -0
  181. package/out/zero-cache/src/services/change-streamer/replica-poller.js.map +1 -0
  182. package/out/zero-cache/src/services/change-streamer/schema/tables.d.ts +5 -1
  183. package/out/zero-cache/src/services/change-streamer/schema/tables.d.ts.map +1 -1
  184. package/out/zero-cache/src/services/change-streamer/schema/tables.js +2 -1
  185. package/out/zero-cache/src/services/change-streamer/schema/tables.js.map +1 -1
  186. package/out/zero-cache/src/services/change-streamer/snapshot-reservations.d.ts +14 -0
  187. package/out/zero-cache/src/services/change-streamer/snapshot-reservations.d.ts.map +1 -0
  188. package/out/zero-cache/src/services/change-streamer/snapshot-reservations.js +86 -0
  189. package/out/zero-cache/src/services/change-streamer/snapshot-reservations.js.map +1 -0
  190. package/out/zero-cache/src/services/change-streamer/snapshot.d.ts +4 -1
  191. package/out/zero-cache/src/services/change-streamer/snapshot.d.ts.map +1 -1
  192. package/out/zero-cache/src/services/change-streamer/snapshot.js +39 -14
  193. package/out/zero-cache/src/services/change-streamer/snapshot.js.map +1 -1
  194. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-catchup.d.ts +75 -0
  195. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-catchup.d.ts.map +1 -0
  196. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-catchup.js +261 -0
  197. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-catchup.js.map +1 -0
  198. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-purge-scheduler.d.ts +121 -0
  199. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-purge-scheduler.d.ts.map +1 -0
  200. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-purge-scheduler.js +391 -0
  201. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-purge-scheduler.js.map +1 -0
  202. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-reader.d.ts +62 -0
  203. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-reader.d.ts.map +1 -0
  204. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-reader.js +159 -0
  205. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-reader.js.map +1 -0
  206. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.d.ts +109 -0
  207. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.d.ts.map +1 -0
  208. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.js +258 -0
  209. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.js.map +1 -0
  210. package/out/zero-cache/src/services/change-streamer/storer.d.ts +28 -12
  211. package/out/zero-cache/src/services/change-streamer/storer.d.ts.map +1 -1
  212. package/out/zero-cache/src/services/change-streamer/storer.js +116 -121
  213. package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
  214. package/out/zero-cache/src/services/change-streamer/subscriber.d.ts +61 -10
  215. package/out/zero-cache/src/services/change-streamer/subscriber.d.ts.map +1 -1
  216. package/out/zero-cache/src/services/change-streamer/subscriber.js +101 -8
  217. package/out/zero-cache/src/services/change-streamer/subscriber.js.map +1 -1
  218. package/out/zero-cache/src/services/change-streamer/upstream-acker.d.ts +34 -0
  219. package/out/zero-cache/src/services/change-streamer/upstream-acker.d.ts.map +1 -0
  220. package/out/zero-cache/src/services/change-streamer/upstream-acker.js +86 -0
  221. package/out/zero-cache/src/services/change-streamer/upstream-acker.js.map +1 -0
  222. package/out/zero-cache/src/services/life-cycle.d.ts +1 -1
  223. package/out/zero-cache/src/services/life-cycle.d.ts.map +1 -1
  224. package/out/zero-cache/src/services/life-cycle.js +4 -3
  225. package/out/zero-cache/src/services/life-cycle.js.map +1 -1
  226. package/out/zero-cache/src/services/litestream/commands.d.ts +12 -11
  227. package/out/zero-cache/src/services/litestream/commands.d.ts.map +1 -1
  228. package/out/zero-cache/src/services/litestream/commands.js +107 -148
  229. package/out/zero-cache/src/services/litestream/commands.js.map +1 -1
  230. package/out/zero-cache/src/services/litestream/config-v5.yml +42 -0
  231. package/out/zero-cache/src/services/litestream/config.yml +3 -2
  232. package/out/zero-cache/src/services/litestream/metrics.d.ts +4 -4
  233. package/out/zero-cache/src/services/litestream/metrics.d.ts.map +1 -1
  234. package/out/zero-cache/src/services/litestream/metrics.js +7 -10
  235. package/out/zero-cache/src/services/litestream/metrics.js.map +1 -1
  236. package/out/zero-cache/src/services/litestream/vfs-watermark-poller.d.ts +57 -0
  237. package/out/zero-cache/src/services/litestream/vfs-watermark-poller.d.ts.map +1 -0
  238. package/out/zero-cache/src/services/litestream/vfs-watermark-poller.js +137 -0
  239. package/out/zero-cache/src/services/litestream/vfs-watermark-poller.js.map +1 -0
  240. package/out/zero-cache/src/services/mutagen/mutagen.d.ts.map +1 -1
  241. package/out/zero-cache/src/services/mutagen/mutagen.js +4 -1
  242. package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -1
  243. package/out/zero-cache/src/services/replicator/change-log-cookies.d.ts +169 -0
  244. package/out/zero-cache/src/services/replicator/change-log-cookies.d.ts.map +1 -0
  245. package/out/zero-cache/src/services/replicator/change-log-cookies.js +434 -0
  246. package/out/zero-cache/src/services/replicator/change-log-cookies.js.map +1 -0
  247. package/out/zero-cache/src/services/replicator/change-log-db.d.ts +358 -0
  248. package/out/zero-cache/src/services/replicator/change-log-db.d.ts.map +1 -0
  249. package/out/zero-cache/src/services/replicator/change-log-db.js +477 -0
  250. package/out/zero-cache/src/services/replicator/change-log-db.js.map +1 -0
  251. package/out/zero-cache/src/services/replicator/change-log-stream-writer.d.ts +55 -0
  252. package/out/zero-cache/src/services/replicator/change-log-stream-writer.d.ts.map +1 -0
  253. package/out/zero-cache/src/services/replicator/change-log-stream-writer.js +150 -0
  254. package/out/zero-cache/src/services/replicator/change-log-stream-writer.js.map +1 -0
  255. package/out/zero-cache/src/services/replicator/change-processor.d.ts +6 -0
  256. package/out/zero-cache/src/services/replicator/change-processor.d.ts.map +1 -1
  257. package/out/zero-cache/src/services/replicator/change-processor.js +70 -25
  258. package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
  259. package/out/zero-cache/src/services/replicator/incremental-sync.d.ts +1 -1
  260. package/out/zero-cache/src/services/replicator/incremental-sync.d.ts.map +1 -1
  261. package/out/zero-cache/src/services/replicator/incremental-sync.js +19 -6
  262. package/out/zero-cache/src/services/replicator/incremental-sync.js.map +1 -1
  263. package/out/zero-cache/src/services/replicator/notifier.d.ts +0 -22
  264. package/out/zero-cache/src/services/replicator/notifier.d.ts.map +1 -1
  265. package/out/zero-cache/src/services/replicator/notifier.js +7 -1
  266. package/out/zero-cache/src/services/replicator/notifier.js.map +1 -1
  267. package/out/zero-cache/src/services/replicator/replicator.d.ts +17 -2
  268. package/out/zero-cache/src/services/replicator/replicator.d.ts.map +1 -1
  269. package/out/zero-cache/src/services/replicator/replicator.js +9 -3
  270. package/out/zero-cache/src/services/replicator/replicator.js.map +1 -1
  271. package/out/zero-cache/src/services/replicator/reporter/recorder.d.ts +27 -0
  272. package/out/zero-cache/src/services/replicator/reporter/recorder.d.ts.map +1 -1
  273. package/out/zero-cache/src/services/replicator/reporter/recorder.js +32 -0
  274. package/out/zero-cache/src/services/replicator/reporter/recorder.js.map +1 -1
  275. package/out/zero-cache/src/services/replicator/reporter/report-schema.d.ts +1 -1
  276. package/out/zero-cache/src/services/replicator/schema/backfilling.d.ts +119 -0
  277. package/out/zero-cache/src/services/replicator/schema/backfilling.d.ts.map +1 -0
  278. package/out/zero-cache/src/services/replicator/schema/backfilling.js +214 -0
  279. package/out/zero-cache/src/services/replicator/schema/backfilling.js.map +1 -0
  280. package/out/zero-cache/src/services/replicator/schema/change-log.d.ts +3 -3
  281. package/out/zero-cache/src/services/replicator/schema/column-metadata.js +1 -1
  282. package/out/zero-cache/src/services/replicator/schema/column-metadata.js.map +1 -1
  283. package/out/zero-cache/src/services/replicator/schema/replication-state.d.ts +1 -1
  284. package/out/zero-cache/src/services/replicator/schema/replication-state.d.ts.map +1 -1
  285. package/out/zero-cache/src/services/replicator/schema/replication-state.js +9 -5
  286. package/out/zero-cache/src/services/replicator/schema/replication-state.js.map +1 -1
  287. package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.d.ts +131 -0
  288. package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.d.ts.map +1 -0
  289. package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.js +413 -0
  290. package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.js.map +1 -0
  291. package/out/zero-cache/src/services/replicator/sqlite-change-log-purger.d.ts +120 -0
  292. package/out/zero-cache/src/services/replicator/sqlite-change-log-purger.d.ts.map +1 -0
  293. package/out/zero-cache/src/services/replicator/sqlite-change-log-purger.js +283 -0
  294. package/out/zero-cache/src/services/replicator/sqlite-change-log-purger.js.map +1 -0
  295. package/out/zero-cache/src/services/replicator/write-worker.js +23 -12
  296. package/out/zero-cache/src/services/replicator/write-worker.js.map +1 -1
  297. package/out/zero-cache/src/services/run-ast.d.ts.map +1 -1
  298. package/out/zero-cache/src/services/run-ast.js +2 -1
  299. package/out/zero-cache/src/services/run-ast.js.map +1 -1
  300. package/out/zero-cache/src/services/running-state.d.ts +1 -1
  301. package/out/zero-cache/src/services/running-state.d.ts.map +1 -1
  302. package/out/zero-cache/src/services/running-state.js +1 -0
  303. package/out/zero-cache/src/services/running-state.js.map +1 -1
  304. package/out/zero-cache/src/services/view-syncer/e2e-serving-lag.d.ts +53 -0
  305. package/out/zero-cache/src/services/view-syncer/e2e-serving-lag.d.ts.map +1 -0
  306. package/out/zero-cache/src/services/view-syncer/e2e-serving-lag.js +68 -0
  307. package/out/zero-cache/src/services/view-syncer/e2e-serving-lag.js.map +1 -0
  308. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
  309. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +18 -3
  310. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
  311. package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts.map +1 -1
  312. package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
  313. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts +11 -1
  314. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
  315. package/out/zero-cache/src/services/view-syncer/view-syncer.js +64 -6
  316. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  317. package/out/zero-cache/src/types/processes.d.ts +1 -2
  318. package/out/zero-cache/src/types/processes.d.ts.map +1 -1
  319. package/out/zero-cache/src/types/processes.js +1 -25
  320. package/out/zero-cache/src/types/processes.js.map +1 -1
  321. package/out/zero-cache/src/types/streams.d.ts +21 -0
  322. package/out/zero-cache/src/types/streams.d.ts.map +1 -1
  323. package/out/zero-cache/src/types/streams.js +25 -4
  324. package/out/zero-cache/src/types/streams.js.map +1 -1
  325. package/out/zero-cache/src/types/subscription.d.ts +11 -0
  326. package/out/zero-cache/src/types/subscription.d.ts.map +1 -1
  327. package/out/zero-cache/src/types/subscription.js +27 -0
  328. package/out/zero-cache/src/types/subscription.js.map +1 -1
  329. package/out/zero-cache/src/workers/connection.d.ts +1 -0
  330. package/out/zero-cache/src/workers/connection.d.ts.map +1 -1
  331. package/out/zero-cache/src/workers/connection.js +24 -2
  332. package/out/zero-cache/src/workers/connection.js.map +1 -1
  333. package/out/zero-cache/src/workers/replicator.d.ts +25 -0
  334. package/out/zero-cache/src/workers/replicator.d.ts.map +1 -1
  335. package/out/zero-cache/src/workers/replicator.js +33 -1
  336. package/out/zero-cache/src/workers/replicator.js.map +1 -1
  337. package/out/zero-cache/src/workers/syncer.d.ts +12 -0
  338. package/out/zero-cache/src/workers/syncer.d.ts.map +1 -1
  339. package/out/zero-cache/src/workers/syncer.js +75 -0
  340. package/out/zero-cache/src/workers/syncer.js.map +1 -1
  341. package/out/zero-client/src/client/version.js +1 -1
  342. package/out/zero-client/src/client/zero.d.ts +6 -7
  343. package/out/zero-client/src/client/zero.d.ts.map +1 -1
  344. package/out/zero-client/src/client/zero.js +156 -101
  345. package/out/zero-client/src/client/zero.js.map +1 -1
  346. package/out/zero-schema/src/builder/table-builder.d.ts +23 -0
  347. package/out/zero-schema/src/builder/table-builder.d.ts.map +1 -1
  348. package/out/zero-schema/src/builder/table-builder.js +18 -0
  349. package/out/zero-schema/src/builder/table-builder.js.map +1 -1
  350. package/out/zero-server/src/custom.js +10 -3
  351. package/out/zero-server/src/custom.js.map +1 -1
  352. package/out/zero-server/src/schema.d.ts +8 -0
  353. package/out/zero-server/src/schema.d.ts.map +1 -1
  354. package/out/zero-server/src/schema.js +63 -24
  355. package/out/zero-server/src/schema.js.map +1 -1
  356. package/out/zero-types/src/schema.d.ts +11 -0
  357. package/out/zero-types/src/schema.d.ts.map +1 -1
  358. package/out/zql/src/mutate/crud.d.ts +10 -8
  359. package/out/zql/src/mutate/crud.d.ts.map +1 -1
  360. package/out/zql/src/mutate/crud.js.map +1 -1
  361. package/out/zql/src/query/query-delegate-base.d.ts.map +1 -1
  362. package/out/zql/src/query/query-delegate-base.js +5 -1
  363. package/out/zql/src/query/query-delegate-base.js.map +1 -1
  364. package/out/zql/src/query/query-impl.d.ts +2 -2
  365. package/out/zql/src/query/query-impl.d.ts.map +1 -1
  366. package/out/zql/src/query/query-impl.js.map +1 -1
  367. package/out/zql/src/query/query.d.ts +83 -14
  368. package/out/zql/src/query/query.d.ts.map +1 -1
  369. package/out/zql/src/query/static-query.d.ts +1 -1
  370. package/out/zql/src/query/static-query.d.ts.map +1 -1
  371. package/out/zqlite/src/db.js +2 -2
  372. package/out/zqlite/src/resolve-scalar-subqueries.d.ts +15 -0
  373. package/out/zqlite/src/resolve-scalar-subqueries.d.ts.map +1 -1
  374. package/out/zqlite/src/resolve-scalar-subqueries.js +33 -14
  375. package/out/zqlite/src/resolve-scalar-subqueries.js.map +1 -1
  376. package/out/zqlite/src/sqlite-cost-model.js +5 -5
  377. package/out/zqlite/src/table-source.js +3 -3
  378. package/package.json +3 -3
  379. package/out/replicache/src/db/index.js +0 -91
  380. package/out/replicache/src/db/index.js.map +0 -1
  381. package/out/replicache/src/lazy.d.ts +0 -2
  382. package/out/replicache/src/lazy.d.ts.map +0 -1
  383. package/out/replicache/src/lazy.js +0 -12
  384. package/out/replicache/src/lazy.js.map +0 -1
  385. package/out/zero-cache/src/server/backup-watermark-reader.js +0 -35
  386. package/out/zero-cache/src/server/backup-watermark-reader.js.map +0 -1
  387. package/out/zero-cache/src/services/change-streamer/litestream3-backup-monitor.d.ts.map +0 -1
  388. package/out/zero-cache/src/services/change-streamer/litestream3-backup-monitor.js.map +0 -1
  389. package/out/zero-cache/src/services/change-streamer/replica-monitor.d.ts +0 -16
  390. package/out/zero-cache/src/services/change-streamer/replica-monitor.d.ts.map +0 -1
  391. package/out/zero-cache/src/services/change-streamer/replica-monitor.js +0 -54
  392. package/out/zero-cache/src/services/change-streamer/replica-monitor.js.map +0 -1
  393. package/out/zero-cache/src/services/change-streamer/vfs-backup-monitor.d.ts +0 -25
  394. package/out/zero-cache/src/services/change-streamer/vfs-backup-monitor.d.ts.map +0 -1
  395. package/out/zero-cache/src/services/change-streamer/vfs-backup-monitor.js +0 -159
  396. package/out/zero-cache/src/services/change-streamer/vfs-backup-monitor.js.map +0 -1
  397. package/out/zero-cache/src/services/litestream/vfs-watermark-reader.d.ts +0 -44
  398. package/out/zero-cache/src/services/litestream/vfs-watermark-reader.d.ts.map +0 -1
  399. package/out/zero-cache/src/services/litestream/vfs-watermark-reader.js +0 -65
  400. package/out/zero-cache/src/services/litestream/vfs-watermark-reader.js.map +0 -1
  401. package/out/zero-cache/src/services/litestream/vfs-watermark-worker-source.d.ts +0 -11
  402. package/out/zero-cache/src/services/litestream/vfs-watermark-worker-source.d.ts.map +0 -1
  403. package/out/zero-cache/src/services/litestream/vfs-watermark-worker-source.js +0 -74
  404. package/out/zero-cache/src/services/litestream/vfs-watermark-worker-source.js.map +0 -1
  405. package/out/zero-cache/src/services/litestream/vfs-watermark-worker.d.ts +0 -42
  406. package/out/zero-cache/src/services/litestream/vfs-watermark-worker.d.ts.map +0 -1
  407. package/out/zero-cache/src/services/litestream/vfs-watermark-worker.js +0 -117
  408. package/out/zero-cache/src/services/litestream/vfs-watermark-worker.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"replication-state.d.ts","sourceRoot":"","sources":["../../../../../../../zero-cache/src/services/replicator/schema/replication-state.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAGL,KAAK,UAAU,EAChB,MAAM,0CAA0C,CAAC;AAClD,OAAO,KAAK,CAAC,MAAM,qCAAqC,CAAC;AACzD,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,iCAAiC,CAAC;AAC9D,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,2BAA2B,CAAC;AAG/D,OAAO,EAAC,wBAAwB,EAAC,MAAM,gBAAgB,CAAC;AAGxD,OAAO,EAAC,wBAAwB,EAAC,CAAC;AAElC,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAC;AAMzD,eAAO,MAAM,2BAA2B,iKAKvC,CAAC;AA0CF,QAAA,MAAM,uBAAuB;;;;EASxB,CAAC;AAEN,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE,QAAA,MAAM,iCAAiC;;;;;EAclC,CAAC;AAEN,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAC/C,OAAO,iCAAiC,CACzC,CAAC;AAEF,QAAA,MAAM,sBAAsB;;aAE1B,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE,wBAAgB,oBAAoB,CAClC,EAAE,EAAE,QAAQ,EACZ,YAAY,EAAE,MAAM,EAAE,EACtB,SAAS,EAAE,MAAM,EACjB,kBAAkB,GAAE,UAAe,EACnC,YAAY,UAAO,QAoBpB;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,EAAE,EAAE,QAAQ,QAExD;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,QAM5D;AAED,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,QAAQ;;;IAY9C;AAED,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,eAAe,GAAG,iBAAiB,CAQ3E;AAED,wBAAgB,8BAA8B,CAC5C,EAAE,EAAE,eAAe,GAClB,2BAA2B,CAS7B;AAED,wBAAgB,0BAA0B,CACxC,EAAE,EAAE,eAAe,EACnB,SAAS,EAAE,MAAM,QAQlB;AAED,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,eAAe,GAAG,gBAAgB,CAGzE"}
1
+ {"version":3,"file":"replication-state.d.ts","sourceRoot":"","sources":["../../../../../../../zero-cache/src/services/replicator/schema/replication-state.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAGL,KAAK,UAAU,EAChB,MAAM,0CAA0C,CAAC;AAClD,OAAO,KAAK,CAAC,MAAM,qCAAqC,CAAC;AACzD,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,iCAAiC,CAAC;AAC9D,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,2BAA2B,CAAC;AAI/D,OAAO,EAAC,wBAAwB,EAAC,MAAM,gBAAgB,CAAC;AAGxD,OAAO,EAAC,wBAAwB,EAAC,CAAC;AAElC,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAC;AAMzD,eAAO,MAAM,2BAA2B,iKAKvC,CAAC;AA2CF,QAAA,MAAM,uBAAuB;;;;EASxB,CAAC;AAEN,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE,QAAA,MAAM,iCAAiC;;;;;EAclC,CAAC;AAEN,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAC/C,OAAO,iCAAiC,CACzC,CAAC;AAEF,QAAA,MAAM,sBAAsB;;aAE1B,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE,wBAAgB,oBAAoB,CAClC,EAAE,EAAE,QAAQ,EACZ,YAAY,EAAE,MAAM,EAAE,EACtB,SAAS,EAAE,MAAM,EACjB,kBAAkB,GAAE,UAAe,EACnC,YAAY,UAAO,QAoBpB;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,EAAE,EAAE,QAAQ,QAExD;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,QAM5D;AAED,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,QAAQ;;;IAY9C;AAED,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,eAAe,GAAG,iBAAiB,CAQ3E;AAED,wBAAgB,8BAA8B,CAC5C,EAAE,EAAE,eAAe,GAClB,2BAA2B,CAS7B;AAED,wBAAgB,0BAA0B,CACxC,EAAE,EAAE,eAAe,EACnB,SAAS,EAAE,MAAM,EACjB,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,QAkBjC;AAED,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,eAAe,GAAG,gBAAgB,CAGzE"}
@@ -3,6 +3,7 @@ import { jsonObjectSchema, stringify } from "../../../../../shared/src/bigint-js
3
3
  import "./constants.js";
4
4
  import { CREATE_COLUMN_METADATA_TABLE } from "./column-metadata.js";
5
5
  import { CREATE_TABLE_METADATA_TABLE } from "./table-metadata.js";
6
+ import { CREATE_BACKFILLING_TABLE } from "./backfilling.js";
6
7
  import { CREATE_CHANGELOG_SCHEMA } from "./change-log.js";
7
8
  //#region ../zero-cache/src/services/replicator/schema/replication-state.ts
8
9
  /**
@@ -17,7 +18,7 @@ var CREATE_RUNTIME_EVENTS_TABLE = `
17
18
  timestamp TEXT NOT NULL DEFAULT (current_timestamp)
18
19
  );
19
20
  `;
20
- var CREATE_REPLICATION_STATE_SCHEMA = "\n CREATE TABLE \"_zero.replicationConfig\" (\n replicaVersion TEXT NOT NULL,\n publications TEXT NOT NULL,\n initialSyncContext TEXT DEFAULT '{}',\n lock INTEGER PRIMARY KEY DEFAULT 1 CHECK (lock=1)\n );\n \n CREATE TABLE \"_zero.replicationState\" (\n stateVersion TEXT NOT NULL,\n writeTimeMs INTEGER,\n lock INTEGER PRIMARY KEY DEFAULT 1 CHECK (lock=1)\n );\n " + CREATE_CHANGELOG_SCHEMA + CREATE_RUNTIME_EVENTS_TABLE + CREATE_COLUMN_METADATA_TABLE + CREATE_TABLE_METADATA_TABLE;
21
+ var CREATE_REPLICATION_STATE_SCHEMA = "\n CREATE TABLE \"_zero.replicationConfig\" (\n replicaVersion TEXT NOT NULL,\n publications TEXT NOT NULL,\n initialSyncContext TEXT DEFAULT '{}',\n lock INTEGER PRIMARY KEY DEFAULT 1 CHECK (lock=1)\n );\n \n CREATE TABLE \"_zero.replicationState\" (\n stateVersion TEXT NOT NULL,\n writeTimeMs INTEGER NOT NULL,\n lock INTEGER PRIMARY KEY DEFAULT 1 CHECK (lock=1)\n );\n " + CREATE_CHANGELOG_SCHEMA + CREATE_RUNTIME_EVENTS_TABLE + CREATE_COLUMN_METADATA_TABLE + CREATE_TABLE_METADATA_TABLE + CREATE_BACKFILLING_TABLE;
21
22
  var stringArray = valita_exports.array(valita_exports.string());
22
23
  var subscriptionStateSchema = valita_exports.object({
23
24
  replicaVersion: valita_exports.string(),
@@ -88,10 +89,13 @@ function getSubscriptionStateAndContext(db) {
88
89
  ON c.lock = s.lock
89
90
  `), subscriptionStateAndContextSchema);
90
91
  }
91
- function updateReplicationWatermark(db, watermark) {
92
- db.run(`
93
- UPDATE "_zero.replicationState"
94
- SET stateVersion=?, writeTimeMs=unixepoch('subsec') * 1000`, watermark);
92
+ function updateReplicationWatermark(db, watermark, writeTimeMs) {
93
+ if (writeTimeMs === void 0) db.run(`
94
+ UPDATE "_zero.replicationState"
95
+ SET stateVersion=?, writeTimeMs=unixepoch('subsec') * 1000`, watermark);
96
+ else db.run(`
97
+ UPDATE "_zero.replicationState"
98
+ SET stateVersion=?, writeTimeMs=?`, watermark, writeTimeMs);
95
99
  }
96
100
  function getReplicationState(db) {
97
101
  return parse(db.get(`SELECT stateVersion FROM "_zero.replicationState"`), replicationStateSchema);
@@ -1 +1 @@
1
- {"version":3,"file":"replication-state.js","names":[],"sources":["../../../../../../../zero-cache/src/services/replicator/schema/replication-state.ts"],"sourcesContent":["/**\n * Replication metadata, used for incremental view maintenance and catchup.\n *\n * These tables are created atomically in {@link setupReplicationTables}\n * after the logical replication handoff when initial data synchronization has completed.\n */\n\nimport {\n jsonObjectSchema,\n stringify,\n type JSONObject,\n} from '../../../../../shared/src/bigint-json.ts';\nimport * as v from '../../../../../shared/src/valita.ts';\nimport type {Database} from '../../../../../zqlite/src/db.ts';\nimport type {StatementRunner} from '../../../db/statements.ts';\nimport {CREATE_CHANGELOG_SCHEMA} from './change-log.ts';\nimport {CREATE_COLUMN_METADATA_TABLE} from './column-metadata.ts';\nimport {ZERO_VERSION_COLUMN_NAME} from './constants.ts';\nimport {CREATE_TABLE_METADATA_TABLE} from './table-metadata.ts';\n\nexport {ZERO_VERSION_COLUMN_NAME};\n\nexport type RuntimeEvent = 'sync' | 'upgrade' | 'vacuum';\n\n// event : The RuntimeEvent. Only one row per event is tracked.\n// Inserting an event will REPLACE any row for the same event.\n// timestamp : SQLite timestamp string, e.g. \"2024-04-12 11:37:46\".\n// Append a `Z` when parsing with `new Date(...)`;\nexport const CREATE_RUNTIME_EVENTS_TABLE = `\n CREATE TABLE \"_zero.runtimeEvents\" (\n event TEXT PRIMARY KEY ON CONFLICT REPLACE,\n timestamp TEXT NOT NULL DEFAULT (current_timestamp)\n );\n`;\n\nconst CREATE_REPLICATION_STATE_SCHEMA =\n // replicaVersion : A value identifying the version at which the initial sync happened, i.e.\n // the version at which all rows were copied, and to `_0_version` was set.\n // This value is used to distinguish data from other replicas (e.g. if a\n // replica is reset or if there are ever multiple replicas).\n // publications : JSON stringified array of publication names\n // initialSyncContext : Metadata related to the context of when and how the replica was initially\n // synced. This corresponds with the same column stored in upstream and is\n // used for debugging replica version mismatches, which can arise from a number\n // of misconfigurations, such as dueling replication-managers, or restores of\n // stale litestream backups.\n // lock : Auto-magic column for enforcing single-row semantics.\n /*sql*/ `\n CREATE TABLE \"_zero.replicationConfig\" (\n replicaVersion TEXT NOT NULL,\n publications TEXT NOT NULL,\n initialSyncContext TEXT DEFAULT '{}',\n lock INTEGER PRIMARY KEY DEFAULT 1 CHECK (lock=1)\n );\n ` +\n // stateVersion : The latest version replicated from upstream, starting with the initial\n // `replicaVersion` and moving forward to each subsequent commit watermark\n // (e.g. corresponding to a Postgres LSN). Versions are represented as\n // lexicographically sortable watermarks (e.g. LexiVersions).\n // writeTimeMs : The millisecond epoch at which this version was written to the replica.\n //\n /*sql*/ `\n CREATE TABLE \"_zero.replicationState\" (\n stateVersion TEXT NOT NULL,\n writeTimeMs INTEGER,\n lock INTEGER PRIMARY KEY DEFAULT 1 CHECK (lock=1)\n );\n ` +\n CREATE_CHANGELOG_SCHEMA +\n CREATE_RUNTIME_EVENTS_TABLE +\n CREATE_COLUMN_METADATA_TABLE +\n CREATE_TABLE_METADATA_TABLE;\n\nconst stringArray = v.array(v.string());\n\nconst subscriptionStateSchema = v\n .object({\n replicaVersion: v.string(),\n publications: v.string(),\n watermark: v.string(),\n })\n .map(s => ({\n ...s,\n publications: v.parse(JSON.parse(s.publications), stringArray),\n }));\n\nexport type SubscriptionState = v.Infer<typeof subscriptionStateSchema>;\n\nconst subscriptionStateAndContextSchema = v\n .object({\n replicaVersion: v.string(),\n publications: v.string(),\n initialSyncContext: v.string(),\n watermark: v.string(),\n })\n .map(s => ({\n ...s,\n publications: v.parse(JSON.parse(s.publications), stringArray),\n initialSyncContext: v.parse(\n JSON.parse(s.initialSyncContext),\n jsonObjectSchema,\n ),\n }));\n\nexport type SubscriptionStateAndContext = v.Infer<\n typeof subscriptionStateAndContextSchema\n>;\n\nconst replicationStateSchema = v.object({\n stateVersion: v.string(),\n});\n\nexport type ReplicationState = v.Infer<typeof replicationStateSchema>;\n\nexport function initReplicationState(\n db: Database,\n publications: string[],\n watermark: string,\n initialSyncContext: JSONObject = {},\n createTables = true,\n) {\n if (createTables) {\n createReplicationStateTables(db);\n }\n db.prepare(\n `\n INSERT INTO \"_zero.replicationConfig\" \n (replicaVersion, publications, initialSyncContext) VALUES (?, ?, ?)\n `,\n ).run(\n watermark,\n JSON.stringify(publications.sort()),\n stringify(initialSyncContext),\n );\n db.prepare(/*sql*/ `\n INSERT INTO \"_zero.replicationState\" (stateVersion, writeTimeMs) \n VALUES (?, unixepoch('subsec') * 1000)\n `).run(watermark);\n recordEvent(db, 'sync');\n}\n\n/**\n * Exposed as a separate function for the custom change source,\n * which needs the tables to be created in order to construct\n * ChangeProcessor before it knows the initial watermark.\n */\nexport function createReplicationStateTables(db: Database) {\n db.exec(CREATE_REPLICATION_STATE_SCHEMA);\n}\n\nexport function recordEvent(db: Database, event: RuntimeEvent) {\n db.prepare(\n `\n INSERT INTO \"_zero.runtimeEvents\" (event) VALUES (?) \n `,\n ).run(event);\n}\n\nexport function getAscendingEvents(db: Database) {\n const result = db\n .prepare(\n `SELECT event, timestamp FROM \"_zero.runtimeEvents\" \n ORDER BY timestamp ASC\n `,\n )\n .all<{event: string; timestamp: string}>();\n return result.map(({event, timestamp}) => ({\n event,\n timestamp: new Date(timestamp + 'Z'),\n }));\n}\n\nexport function getSubscriptionState(db: StatementRunner): SubscriptionState {\n const result = db.get(/*sql*/ `\n SELECT c.replicaVersion, c.publications, s.stateVersion as watermark\n FROM \"_zero.replicationConfig\" as c\n JOIN \"_zero.replicationState\" as s\n ON c.lock = s.lock\n `);\n return v.parse(result, subscriptionStateSchema);\n}\n\nexport function getSubscriptionStateAndContext(\n db: StatementRunner,\n): SubscriptionStateAndContext {\n const result = db.get(/*sql*/ `\n SELECT c.replicaVersion, c.publications, c.initialSyncContext,\n s.stateVersion as watermark\n FROM \"_zero.replicationConfig\" as c\n JOIN \"_zero.replicationState\" as s\n ON c.lock = s.lock\n `);\n return v.parse(result, subscriptionStateAndContextSchema);\n}\n\nexport function updateReplicationWatermark(\n db: StatementRunner,\n watermark: string,\n) {\n db.run(\n /*sql*/ `\n UPDATE \"_zero.replicationState\" \n SET stateVersion=?, writeTimeMs=unixepoch('subsec') * 1000`,\n watermark,\n );\n}\n\nexport function getReplicationState(db: StatementRunner): ReplicationState {\n const result = db.get(`SELECT stateVersion FROM \"_zero.replicationState\"`);\n return v.parse(result, replicationStateSchema);\n}\n"],"mappings":";;;;;;;;;;;;;AA4BA,IAAa,8BAA8B;;;;;;AAO3C,IAAM,kCAYI,4YAqBR,0BACA,8BACA,+BACA;AAEF,IAAM,cAAc,eAAE,MAAM,eAAE,OAAO,CAAC;AAEtC,IAAM,0BAA0B,eAC7B,OAAO;CACN,gBAAgB,eAAE,OAAO;CACzB,cAAc,eAAE,OAAO;CACvB,WAAW,eAAE,OAAO;AACtB,CAAC,EACA,KAAI,OAAM;CACT,GAAG;CACH,cAAc,MAAQ,KAAK,MAAM,EAAE,YAAY,GAAG,WAAW;AAC/D,EAAE;AAIJ,IAAM,oCAAoC,eACvC,OAAO;CACN,gBAAgB,eAAE,OAAO;CACzB,cAAc,eAAE,OAAO;CACvB,oBAAoB,eAAE,OAAO;CAC7B,WAAW,eAAE,OAAO;AACtB,CAAC,EACA,KAAI,OAAM;CACT,GAAG;CACH,cAAc,MAAQ,KAAK,MAAM,EAAE,YAAY,GAAG,WAAW;CAC7D,oBAAoB,MAClB,KAAK,MAAM,EAAE,kBAAkB,GAC/B,gBACF;AACF,EAAE;AAMJ,IAAM,yBAAyB,eAAE,OAAO,EACtC,cAAc,eAAE,OAAO,EACzB,CAAC;AAID,SAAgB,qBACd,IACA,cACA,WACA,qBAAiC,CAAC,GAClC,eAAe,MACf;CACA,IAAI,cACF,6BAA6B,EAAE;CAEjC,GAAG,QACD;;;KAIF,EAAE,IACA,WACA,KAAK,UAAU,aAAa,KAAK,CAAC,GAClC,UAAU,kBAAkB,CAC9B;CACA,GAAG,QAAgB;;;KAGhB,EAAE,IAAI,SAAS;CAClB,YAAY,IAAI,MAAM;AACxB;;;;;;AAOA,SAAgB,6BAA6B,IAAc;CACzD,GAAG,KAAK,+BAA+B;AACzC;AAEA,SAAgB,YAAY,IAAc,OAAqB;CAC7D,GAAG,QACD;;KAGF,EAAE,IAAI,KAAK;AACb;AAEA,SAAgB,mBAAmB,IAAc;CAQ/C,OAPe,GACZ,QACC;;KAGF,EACC,IACI,EAAO,KAAK,EAAC,OAAO,iBAAgB;EACzC;EACA,2BAAW,IAAI,KAAK,YAAY,GAAG;CACrC,EAAE;AACJ;AAEA,SAAgB,qBAAqB,IAAwC;CAO3E,OAAO,MANQ,GAAG,IAAY;;;;;KAMf,GAAQ,uBAAuB;AAChD;AAEA,SAAgB,+BACd,IAC6B;CAQ7B,OAAO,MAPQ,GAAG,IAAY;;;;;;KAOf,GAAQ,iCAAiC;AAC1D;AAEA,SAAgB,2BACd,IACA,WACA;CACA,GAAG,IACO;;mEAGR,SACF;AACF;AAEA,SAAgB,oBAAoB,IAAuC;CAEzE,OAAO,MADQ,GAAG,IAAI,mDACP,GAAQ,sBAAsB;AAC/C"}
1
+ {"version":3,"file":"replication-state.js","names":[],"sources":["../../../../../../../zero-cache/src/services/replicator/schema/replication-state.ts"],"sourcesContent":["/**\n * Replication metadata, used for incremental view maintenance and catchup.\n *\n * These tables are created atomically in {@link setupReplicationTables}\n * after the logical replication handoff when initial data synchronization has completed.\n */\n\nimport {\n jsonObjectSchema,\n stringify,\n type JSONObject,\n} from '../../../../../shared/src/bigint-json.ts';\nimport * as v from '../../../../../shared/src/valita.ts';\nimport type {Database} from '../../../../../zqlite/src/db.ts';\nimport type {StatementRunner} from '../../../db/statements.ts';\nimport {CREATE_BACKFILLING_TABLE} from './backfilling.ts';\nimport {CREATE_CHANGELOG_SCHEMA} from './change-log.ts';\nimport {CREATE_COLUMN_METADATA_TABLE} from './column-metadata.ts';\nimport {ZERO_VERSION_COLUMN_NAME} from './constants.ts';\nimport {CREATE_TABLE_METADATA_TABLE} from './table-metadata.ts';\n\nexport {ZERO_VERSION_COLUMN_NAME};\n\nexport type RuntimeEvent = 'sync' | 'upgrade' | 'vacuum';\n\n// event : The RuntimeEvent. Only one row per event is tracked.\n// Inserting an event will REPLACE any row for the same event.\n// timestamp : SQLite timestamp string, e.g. \"2024-04-12 11:37:46\".\n// Append a `Z` when parsing with `new Date(...)`;\nexport const CREATE_RUNTIME_EVENTS_TABLE = `\n CREATE TABLE \"_zero.runtimeEvents\" (\n event TEXT PRIMARY KEY ON CONFLICT REPLACE,\n timestamp TEXT NOT NULL DEFAULT (current_timestamp)\n );\n`;\n\nconst CREATE_REPLICATION_STATE_SCHEMA =\n // replicaVersion : A value identifying the version at which the initial sync happened, i.e.\n // the version at which all rows were copied, and to `_0_version` was set.\n // This value is used to distinguish data from other replicas (e.g. if a\n // replica is reset or if there are ever multiple replicas).\n // publications : JSON stringified array of publication names\n // initialSyncContext : Metadata related to the context of when and how the replica was initially\n // synced. This corresponds with the same column stored in upstream and is\n // used for debugging replica version mismatches, which can arise from a number\n // of misconfigurations, such as dueling replication-managers, or restores of\n // stale litestream backups.\n // lock : Auto-magic column for enforcing single-row semantics.\n /*sql*/ `\n CREATE TABLE \"_zero.replicationConfig\" (\n replicaVersion TEXT NOT NULL,\n publications TEXT NOT NULL,\n initialSyncContext TEXT DEFAULT '{}',\n lock INTEGER PRIMARY KEY DEFAULT 1 CHECK (lock=1)\n );\n ` +\n // stateVersion : The latest version replicated from upstream, starting with the initial\n // `replicaVersion` and moving forward to each subsequent commit watermark\n // (e.g. corresponding to a Postgres LSN). Versions are represented as\n // lexicographically sortable watermarks (e.g. LexiVersions).\n // writeTimeMs : The millisecond epoch at which this version was written to the replica.\n //\n /*sql*/ `\n CREATE TABLE \"_zero.replicationState\" (\n stateVersion TEXT NOT NULL,\n writeTimeMs INTEGER NOT NULL,\n lock INTEGER PRIMARY KEY DEFAULT 1 CHECK (lock=1)\n );\n ` +\n CREATE_CHANGELOG_SCHEMA +\n CREATE_RUNTIME_EVENTS_TABLE +\n CREATE_COLUMN_METADATA_TABLE +\n CREATE_TABLE_METADATA_TABLE +\n CREATE_BACKFILLING_TABLE;\n\nconst stringArray = v.array(v.string());\n\nconst subscriptionStateSchema = v\n .object({\n replicaVersion: v.string(),\n publications: v.string(),\n watermark: v.string(),\n })\n .map(s => ({\n ...s,\n publications: v.parse(JSON.parse(s.publications), stringArray),\n }));\n\nexport type SubscriptionState = v.Infer<typeof subscriptionStateSchema>;\n\nconst subscriptionStateAndContextSchema = v\n .object({\n replicaVersion: v.string(),\n publications: v.string(),\n initialSyncContext: v.string(),\n watermark: v.string(),\n })\n .map(s => ({\n ...s,\n publications: v.parse(JSON.parse(s.publications), stringArray),\n initialSyncContext: v.parse(\n JSON.parse(s.initialSyncContext),\n jsonObjectSchema,\n ),\n }));\n\nexport type SubscriptionStateAndContext = v.Infer<\n typeof subscriptionStateAndContextSchema\n>;\n\nconst replicationStateSchema = v.object({\n stateVersion: v.string(),\n});\n\nexport type ReplicationState = v.Infer<typeof replicationStateSchema>;\n\nexport function initReplicationState(\n db: Database,\n publications: string[],\n watermark: string,\n initialSyncContext: JSONObject = {},\n createTables = true,\n) {\n if (createTables) {\n createReplicationStateTables(db);\n }\n db.prepare(\n `\n INSERT INTO \"_zero.replicationConfig\" \n (replicaVersion, publications, initialSyncContext) VALUES (?, ?, ?)\n `,\n ).run(\n watermark,\n JSON.stringify(publications.sort()),\n stringify(initialSyncContext),\n );\n db.prepare(/*sql*/ `\n INSERT INTO \"_zero.replicationState\" (stateVersion, writeTimeMs) \n VALUES (?, unixepoch('subsec') * 1000)\n `).run(watermark);\n recordEvent(db, 'sync');\n}\n\n/**\n * Exposed as a separate function for the custom change source,\n * which needs the tables to be created in order to construct\n * ChangeProcessor before it knows the initial watermark.\n */\nexport function createReplicationStateTables(db: Database) {\n db.exec(CREATE_REPLICATION_STATE_SCHEMA);\n}\n\nexport function recordEvent(db: Database, event: RuntimeEvent) {\n db.prepare(\n `\n INSERT INTO \"_zero.runtimeEvents\" (event) VALUES (?) \n `,\n ).run(event);\n}\n\nexport function getAscendingEvents(db: Database) {\n const result = db\n .prepare(\n `SELECT event, timestamp FROM \"_zero.runtimeEvents\" \n ORDER BY timestamp ASC\n `,\n )\n .all<{event: string; timestamp: string}>();\n return result.map(({event, timestamp}) => ({\n event,\n timestamp: new Date(timestamp + 'Z'),\n }));\n}\n\nexport function getSubscriptionState(db: StatementRunner): SubscriptionState {\n const result = db.get(/*sql*/ `\n SELECT c.replicaVersion, c.publications, s.stateVersion as watermark\n FROM \"_zero.replicationConfig\" as c\n JOIN \"_zero.replicationState\" as s\n ON c.lock = s.lock\n `);\n return v.parse(result, subscriptionStateSchema);\n}\n\nexport function getSubscriptionStateAndContext(\n db: StatementRunner,\n): SubscriptionStateAndContext {\n const result = db.get(/*sql*/ `\n SELECT c.replicaVersion, c.publications, c.initialSyncContext,\n s.stateVersion as watermark\n FROM \"_zero.replicationConfig\" as c\n JOIN \"_zero.replicationState\" as s\n ON c.lock = s.lock\n `);\n return v.parse(result, subscriptionStateAndContextSchema);\n}\n\nexport function updateReplicationWatermark(\n db: StatementRunner,\n watermark: string,\n writeTimeMs?: number | undefined,\n) {\n if (writeTimeMs === undefined) {\n db.run(\n /*sql*/ `\n UPDATE \"_zero.replicationState\"\n SET stateVersion=?, writeTimeMs=unixepoch('subsec') * 1000`,\n watermark,\n );\n } else {\n db.run(\n /*sql*/ `\n UPDATE \"_zero.replicationState\"\n SET stateVersion=?, writeTimeMs=?`,\n watermark,\n writeTimeMs,\n );\n }\n}\n\nexport function getReplicationState(db: StatementRunner): ReplicationState {\n const result = db.get(`SELECT stateVersion FROM \"_zero.replicationState\"`);\n return v.parse(result, replicationStateSchema);\n}\n"],"mappings":";;;;;;;;;;;;;;AA6BA,IAAa,8BAA8B;;;;;;AAO3C,IAAM,kCAYI,qZAqBR,0BACA,8BACA,+BACA,8BACA;AAEF,IAAM,cAAc,eAAE,MAAM,eAAE,OAAO,CAAC;AAEtC,IAAM,0BAA0B,eAC7B,OAAO;CACN,gBAAgB,eAAE,OAAO;CACzB,cAAc,eAAE,OAAO;CACvB,WAAW,eAAE,OAAO;AACtB,CAAC,EACA,KAAI,OAAM;CACT,GAAG;CACH,cAAc,MAAQ,KAAK,MAAM,EAAE,YAAY,GAAG,WAAW;AAC/D,EAAE;AAIJ,IAAM,oCAAoC,eACvC,OAAO;CACN,gBAAgB,eAAE,OAAO;CACzB,cAAc,eAAE,OAAO;CACvB,oBAAoB,eAAE,OAAO;CAC7B,WAAW,eAAE,OAAO;AACtB,CAAC,EACA,KAAI,OAAM;CACT,GAAG;CACH,cAAc,MAAQ,KAAK,MAAM,EAAE,YAAY,GAAG,WAAW;CAC7D,oBAAoB,MAClB,KAAK,MAAM,EAAE,kBAAkB,GAC/B,gBACF;AACF,EAAE;AAMJ,IAAM,yBAAyB,eAAE,OAAO,EACtC,cAAc,eAAE,OAAO,EACzB,CAAC;AAID,SAAgB,qBACd,IACA,cACA,WACA,qBAAiC,CAAC,GAClC,eAAe,MACf;CACA,IAAI,cACF,6BAA6B,EAAE;CAEjC,GAAG,QACD;;;KAIF,EAAE,IACA,WACA,KAAK,UAAU,aAAa,KAAK,CAAC,GAClC,UAAU,kBAAkB,CAC9B;CACA,GAAG,QAAgB;;;KAGhB,EAAE,IAAI,SAAS;CAClB,YAAY,IAAI,MAAM;AACxB;;;;;;AAOA,SAAgB,6BAA6B,IAAc;CACzD,GAAG,KAAK,+BAA+B;AACzC;AAEA,SAAgB,YAAY,IAAc,OAAqB;CAC7D,GAAG,QACD;;KAGF,EAAE,IAAI,KAAK;AACb;AAEA,SAAgB,mBAAmB,IAAc;CAQ/C,OAPe,GACZ,QACC;;KAGF,EACC,IACI,EAAO,KAAK,EAAC,OAAO,iBAAgB;EACzC;EACA,2BAAW,IAAI,KAAK,YAAY,GAAG;CACrC,EAAE;AACJ;AAEA,SAAgB,qBAAqB,IAAwC;CAO3E,OAAO,MANQ,GAAG,IAAY;;;;;KAMf,GAAQ,uBAAuB;AAChD;AAEA,SAAgB,+BACd,IAC6B;CAQ7B,OAAO,MAPQ,GAAG,IAAY;;;;;;KAOf,GAAQ,iCAAiC;AAC1D;AAEA,SAAgB,2BACd,IACA,WACA,aACA;CACA,IAAI,gBAAgB,KAAA,GAClB,GAAG,IACO;;qEAGR,SACF;MAEA,GAAG,IACO;;4CAGR,WACA,WACF;AAEJ;AAEA,SAAgB,oBAAoB,IAAuC;CAEzE,OAAO,MADQ,GAAG,IAAI,mDACP,GAAQ,sBAAsB;AAC/C"}
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Observability for the SQLite change log.
3
+ *
4
+ * Everything here now runs in the **change-streamer** process, which is where
5
+ * the writer lives. The module stays beside the rest of the change-log code
6
+ * under `services/replicator/` for the same reason `change-log-db.ts` and
7
+ * `change-log-stream-writer.ts` do: moving files would obscure the topology
8
+ * diff, and the writer's home is a property of who calls it rather than of
9
+ * where it sits. Metric names are unchanged from 7H — only their emitting
10
+ * process, and therefore their resource attributes, moved.
11
+ */
12
+ import type { LogContext } from '@rocicorp/logger';
13
+ import type { Database } from '../../../../zqlite/src/db.ts';
14
+ import type { ChangeStreamData } from '../change-source/protocol/current/downstream.ts';
15
+ import { type CookieOpTag, type CookieRowCounts } from './change-log-cookies.ts';
16
+ import { type ChangeLogMeta, type ReconcileResult } from './change-log-db.ts';
17
+ import type { ChangeLogStreamTransactionStats } from './change-log-stream-writer.ts';
18
+ /**
19
+ * Reports the reconciliation of the change-log database against the watermark
20
+ * the stream connection resumes from. This runs once per stream connection, so
21
+ * a reconnect storm is visible here as well as a restart.
22
+ *
23
+ * A wipe is not an error — it is how every abnormal change-log state is
24
+ * collapsed into a correct one — but each wipe costs the retention window, so
25
+ * every reconnecting subscriber below the head gets `too-old`. The `gap` reason
26
+ * in particular means the log neither held the resume watermark nor could be
27
+ * truncated to it, so a nonzero rate in steady state is an alert, not a
28
+ * statistic.
29
+ */
30
+ export declare function recordSQLiteChangeLogReconcile(lc: LogContext, result: ReconcileResult): void;
31
+ /**
32
+ * What the log says about itself. Nothing here reads the replica: after the
33
+ * writer moved to the change-streamer, the replica's state version is a
34
+ * consequence of this log rather than a fact about it.
35
+ */
36
+ export type SQLiteChangeLogStartupInfo = ChangeLogMeta & {
37
+ readonly headWatermark: string;
38
+ };
39
+ export type SQLiteChangeLogInfo = SQLiteChangeLogStartupInfo & {
40
+ readonly rows: number;
41
+ readonly estimatedBytes: number;
42
+ readonly cookieRows: CookieRowCounts;
43
+ };
44
+ /**
45
+ * Reads the meta row and the head. The head is an index-optimized `max()`, so
46
+ * unlike {@link getSQLiteChangeLogInfo} this does not scan the log.
47
+ *
48
+ * Call this after reconciliation, which is the only point at which the head is
49
+ * known to be the resume watermark.
50
+ */
51
+ export declare function getSQLiteChangeLogStartupInfo(changeLog: Database): SQLiteChangeLogStartupInfo;
52
+ /**
53
+ * Extends {@link getSQLiteChangeLogStartupInfo} with the retained row and
54
+ * estimated byte totals. Computing these scans the entire change-log table, so
55
+ * only call it when the totals are consumed, i.e. when the writer (and thus the
56
+ * observer) is enabled.
57
+ */
58
+ export declare function getSQLiteChangeLogInfo(changeLog: Database): SQLiteChangeLogInfo;
59
+ export declare function logSQLiteChangeLogStartup(lc: LogContext, file: string, info: SQLiteChangeLogStartupInfo): void;
60
+ /**
61
+ * The on-disk footprint of a SQLite database: its main file plus its `-wal` and
62
+ * `-wal2` sidecars, whichever exist. `-shm` is excluded — it is a
63
+ * shared-memory index rather than retained bytes.
64
+ *
65
+ * A missing file counts as zero rather than warning. Which sidecars exist
66
+ * depends on the journal mode, and the change-log database is absent entirely
67
+ * until the writer creates it.
68
+ */
69
+ export declare function sqliteFileBytes(lc: LogContext, file: string): Promise<number>;
70
+ /** What the writer reports back for a committed transaction. */
71
+ export type ChangeLogCommit = {
72
+ readonly watermark: string;
73
+ readonly stats: ChangeLogStreamTransactionStats;
74
+ /**
75
+ * Appending the commit row and committing the log's transaction. This is the
76
+ * cost that sits on the forward path, once per upstream transaction.
77
+ */
78
+ readonly logCommitMs: number;
79
+ };
80
+ export type SQLiteChangeLogObservabilityState = {
81
+ readonly receivedHead: string;
82
+ readonly sqliteHead: string;
83
+ readonly headLag: number | undefined;
84
+ readonly rows: number;
85
+ readonly estimatedBytes: number;
86
+ readonly cookieRows: CookieRowCounts;
87
+ readonly cookieMutations: number;
88
+ readonly rollbacks: number;
89
+ readonly invariantFailures: number;
90
+ readonly hashMatches: number;
91
+ readonly hashMismatches: number;
92
+ readonly hashUnpaired: number;
93
+ };
94
+ /**
95
+ * Records writer metrics in the change-streamer process. State changes only
96
+ * after the corresponding write succeeds, except receivedHead, which advances
97
+ * when a commit message arrives so that transient lag behind the log is
98
+ * observable.
99
+ */
100
+ export declare class SQLiteChangeLogObserver {
101
+ #private;
102
+ constructor(lc: LogContext, info: SQLiteChangeLogInfo);
103
+ /**
104
+ * Called as each message arrives, before it is written. Hashes the *received*
105
+ * stream, which is compared against the hash the writer computes over what it
106
+ * *stored*.
107
+ */
108
+ messageReceived(data: ChangeStreamData, json: string): void;
109
+ /** Called after the message has been written to the log. */
110
+ messageProcessed(data: ChangeStreamData, commit: ChangeLogCommit | null, durationMs: number): void;
111
+ messageFailed(data: ChangeStreamData, error: unknown, durationMs: number): void;
112
+ /**
113
+ * A committed transaction folded schema changes into the cookie jar. Reported
114
+ * separately from {@link messageProcessed} because it costs a read of the
115
+ * cookie tables, which is only worth taking when they actually moved.
116
+ */
117
+ cookiesMutated(ops: readonly CookieOpTag[], rows: CookieRowCounts): void;
118
+ /**
119
+ * A missed truncate-above surfaces as a constraint violation on the writer's
120
+ * plain `INSERT`, which the fail-soft policy would otherwise absorb quietly.
121
+ * Classifying it as an invariant failure is what keeps a reconciliation bug
122
+ * from looking like a lost cache.
123
+ */
124
+ invariantFailure(message: string, details?: Record<string, unknown>): void;
125
+ /** The source interrupted the stream mid-transaction. */
126
+ abort(): void;
127
+ /** Reconciliation moved the head, so the observer's totals are restated. */
128
+ reconciled(info: SQLiteChangeLogInfo): void;
129
+ state(): SQLiteChangeLogObservabilityState;
130
+ }
131
+ //# sourceMappingURL=sqlite-change-log-observability.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite-change-log-observability.d.ts","sourceRoot":"","sources":["../../../../../../zero-cache/src/services/replicator/sqlite-change-log-observability.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAEjD,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,8BAA8B,CAAC;AAQ3D,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,iDAAiD,CAAC;AAGtF,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,eAAe,EACrB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAIL,KAAK,aAAa,EAClB,KAAK,eAAe,EACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAC,+BAA+B,EAAC,MAAM,+BAA+B,CAAC;AAEnF;;;;;;;;;;;GAWG;AACH,wBAAgB,8BAA8B,CAC5C,EAAE,EAAE,UAAU,EACd,MAAM,EAAE,eAAe,GACtB,IAAI,CAsCN;AAED;;;;GAIG;AACH,MAAM,MAAM,0BAA0B,GAAG,aAAa,GAAG;IACvD,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,0BAA0B,GAAG;IAC7D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,UAAU,EAAE,eAAe,CAAC;CACtC,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAC3C,SAAS,EAAE,QAAQ,GAClB,0BAA0B,CAO5B;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,QAAQ,GAClB,mBAAmB,CAgBrB;AAED,wBAAgB,yBAAyB,CACvC,EAAE,EAAE,UAAU,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,0BAA0B,GAC/B,IAAI,CAaN;AAED;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CACnC,EAAE,EAAE,UAAU,EACd,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,CAAC,CAcjB;AAED,gEAAgE;AAChE,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,+BAA+B,CAAC;IAChD;;;OAGG;IACH,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,iCAAiC,GAAG;IAC9C,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,UAAU,EAAE,eAAe,CAAC;IACrC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B,CAAC;AAIF;;;;;GAKG;AACH,qBAAa,uBAAuB;;gBAuEtB,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,mBAAmB;IAsDrD;;;;OAIG;IACH,eAAe,CAAC,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAwD3D,4DAA4D;IAC5D,gBAAgB,CACd,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,eAAe,GAAG,IAAI,EAC9B,UAAU,EAAE,MAAM,GACjB,IAAI;IAiEP,aAAa,CACX,IAAI,EAAE,gBAAgB,EACtB,KAAK,EAAE,OAAO,EACd,UAAU,EAAE,MAAM,GACjB,IAAI;IAsBP;;;;OAIG;IACH,cAAc,CAAC,GAAG,EAAE,SAAS,WAAW,EAAE,EAAE,IAAI,EAAE,eAAe,GAAG,IAAI;IAQxE;;;;;OAKG;IACH,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI1E,yDAAyD;IACzD,KAAK,IAAI,IAAI;IAQb,4EAA4E;IAC5E,UAAU,CAAC,IAAI,EAAE,mBAAmB,GAAG,IAAI;IAU3C,KAAK,IAAI,iCAAiC;CA0E3C"}
@@ -0,0 +1,413 @@
1
+ import { unreachable } from "../../../../shared/src/asserts.js";
2
+ import { getOrCreateCounter, getOrCreateGauge, getOrCreateLatencyHistogram, getOrCreateValueHistogram } from "../../observability/metrics.js";
3
+ import { readCookieRowCounts } from "./change-log-cookies.js";
4
+ import { versionFromLexi } from "../../types/lexi-version.js";
5
+ import { CHANGE_LOG_STREAM_TABLE, readChangeLogHead, readChangeLogMeta } from "./change-log-db.js";
6
+ import { extractChangeSubstring } from "../change-streamer/change-log-codec.js";
7
+ import { ChangeLogTransactionHasher } from "../change-streamer/change-log-transaction-hash.js";
8
+ import { stat } from "node:fs/promises";
9
+ //#region ../zero-cache/src/services/replicator/sqlite-change-log-observability.ts
10
+ /**
11
+ * Observability for the SQLite change log.
12
+ *
13
+ * Everything here now runs in the **change-streamer** process, which is where
14
+ * the writer lives. The module stays beside the rest of the change-log code
15
+ * under `services/replicator/` for the same reason `change-log-db.ts` and
16
+ * `change-log-stream-writer.ts` do: moving files would obscure the topology
17
+ * diff, and the writer's home is a property of who calls it rather than of
18
+ * where it sits. Metric names are unchanged from 7H — only their emitting
19
+ * process, and therefore their resource attributes, moved.
20
+ */
21
+ /**
22
+ * Reports the reconciliation of the change-log database against the watermark
23
+ * the stream connection resumes from. This runs once per stream connection, so
24
+ * a reconnect storm is visible here as well as a restart.
25
+ *
26
+ * A wipe is not an error — it is how every abnormal change-log state is
27
+ * collapsed into a correct one — but each wipe costs the retention window, so
28
+ * every reconnecting subscriber below the head gets `too-old`. The `gap` reason
29
+ * in particular means the log neither held the resume watermark nor could be
30
+ * truncated to it, so a nonzero rate in steady state is an alert, not a
31
+ * statistic.
32
+ */
33
+ function recordSQLiteChangeLogReconcile(lc, result) {
34
+ switch (result.action) {
35
+ case "truncated":
36
+ getOrCreateCounter("replica", "sqlite_change_log.reconcile_truncated_rows", "Phantom change-log rows removed at reconciliation, i.e. rows above the watermark the change stream resumed from.").add(result.rows);
37
+ break;
38
+ case "reseeded":
39
+ getOrCreateCounter("replica", "sqlite_change_log.reconcile_wipes", "Change-log wipes at reconciliation, by reason. Each one resets the retention window, so subscribers below the head get `too-old`.").add(1, { reason: result.reason });
40
+ break;
41
+ case "none": break;
42
+ default: unreachable(result);
43
+ }
44
+ if (result.cookiesStale) getOrCreateCounter("replica", "sqlite_change_log.cookie_reseed", "Change-log cookie sets invalidated at reconciliation, by the reconcile action that invalidated them.").add(1, { action: result.action });
45
+ lc.debug?.("SQLite change-log reconciliation", { sqliteChangeLogReconcile: result });
46
+ }
47
+ /**
48
+ * Reads the meta row and the head. The head is an index-optimized `max()`, so
49
+ * unlike {@link getSQLiteChangeLogInfo} this does not scan the log.
50
+ *
51
+ * Call this after reconciliation, which is the only point at which the head is
52
+ * known to be the resume watermark.
53
+ */
54
+ function getSQLiteChangeLogStartupInfo(changeLog) {
55
+ const meta = readChangeLogMeta(changeLog);
56
+ const head = readChangeLogHead(changeLog);
57
+ if (head === null) throw new Error("the SQLite change log must contain its seed transaction");
58
+ return {
59
+ ...meta,
60
+ headWatermark: head
61
+ };
62
+ }
63
+ /**
64
+ * Extends {@link getSQLiteChangeLogStartupInfo} with the retained row and
65
+ * estimated byte totals. Computing these scans the entire change-log table, so
66
+ * only call it when the totals are consumed, i.e. when the writer (and thus the
67
+ * observer) is enabled.
68
+ */
69
+ function getSQLiteChangeLogInfo(changeLog) {
70
+ const startup = getSQLiteChangeLogStartupInfo(changeLog);
71
+ const aggregate = changeLog.prepare(`
72
+ SELECT count(*) AS "rows",
73
+ coalesce(sum("estimatedBytes"), 0) AS "estimatedBytes"
74
+ FROM "${CHANGE_LOG_STREAM_TABLE}"
75
+ `).get();
76
+ return {
77
+ ...startup,
78
+ rows: aggregate.rows,
79
+ estimatedBytes: aggregate.estimatedBytes,
80
+ cookieRows: readCookieRowCounts(changeLog)
81
+ };
82
+ }
83
+ function logSQLiteChangeLogStartup(lc, file, info) {
84
+ lc.info?.("SQLite change-log startup", { sqliteChangeLog: {
85
+ file,
86
+ epoch: info.epoch,
87
+ generation: info.generation,
88
+ replicaID: info.replicaID,
89
+ schemaVersion: info.schemaVersion,
90
+ seedWatermark: info.seedWatermark,
91
+ seededAtMs: info.seededAtMs,
92
+ headWatermark: info.headWatermark
93
+ } });
94
+ }
95
+ /**
96
+ * The on-disk footprint of a SQLite database: its main file plus its `-wal` and
97
+ * `-wal2` sidecars, whichever exist. `-shm` is excluded — it is a
98
+ * shared-memory index rather than retained bytes.
99
+ *
100
+ * A missing file counts as zero rather than warning. Which sidecars exist
101
+ * depends on the journal mode, and the change-log database is absent entirely
102
+ * until the writer creates it.
103
+ */
104
+ async function sqliteFileBytes(lc, file) {
105
+ return (await Promise.all([
106
+ file,
107
+ `${file}-wal`,
108
+ `${file}-wal2`
109
+ ].map(async (path) => {
110
+ try {
111
+ return (await stat(path)).size;
112
+ } catch (e) {
113
+ if (e.code !== "ENOENT") lc.warn?.(`unable to stat ${path} for size metrics`, e);
114
+ return 0;
115
+ }
116
+ }))).reduce((total, size) => total + size, 0);
117
+ }
118
+ var TRANSACTION_ROW_BUCKETS = [
119
+ 2,
120
+ 3,
121
+ 5,
122
+ 10,
123
+ 25,
124
+ 50,
125
+ 100,
126
+ 250,
127
+ 1e3,
128
+ 5e3
129
+ ];
130
+ /**
131
+ * Records writer metrics in the change-streamer process. State changes only
132
+ * after the corresponding write succeeds, except receivedHead, which advances
133
+ * when a commit message arrives so that transient lag behind the log is
134
+ * observable.
135
+ */
136
+ var SQLiteChangeLogObserver = class {
137
+ #lc;
138
+ #messageProcessing = getOrCreateLatencyHistogram("replica", "sqlite_change_log.message_processing_duration", "Time to write a replication message to the SQLite change log.");
139
+ #logCommitDuration = getOrCreateLatencyHistogram("replica", "sqlite_change_log.log_commit_duration", "Time to append the commit row to the SQLite change log and commit its transaction. This is on the forward path: it precedes the forward of that transaction's commit message.");
140
+ #transactionRows = getOrCreateValueHistogram("replica", "sqlite_change_log.transaction_rows", {
141
+ description: "Rows stored per committed SQLite change-log transaction.",
142
+ unit: "{row}",
143
+ bucketBoundaries: TRANSACTION_ROW_BUCKETS
144
+ });
145
+ #rollbackCounter = getOrCreateCounter("replica", "sqlite_change_log.rollbacks", "SQLite change-log transactions rolled back before commit.");
146
+ #invariantFailureCounter = getOrCreateCounter("replica", "sqlite_change_log.invariant_failures", "Detected SQLite change-log writer invariant failures.");
147
+ #hashComparisonCounter = getOrCreateCounter("replica", "sqlite_change_log.hash_comparisons", "Ephemeral transaction hash comparisons between the received change stream and SQLite change-log writes.");
148
+ #hashUnpairedCounter = getOrCreateCounter("replica", "sqlite_change_log.hash_unpaired", "Committed change-log transactions without both ephemeral hashes available for comparison.");
149
+ #cookieMutationCounter = getOrCreateCounter("replica", "sqlite_change_log.cookie_mutations", "Change-log cookie mutations folded from schema changes, by operation.");
150
+ #receivedHead;
151
+ #sqliteHead;
152
+ #rows;
153
+ #estimatedBytes;
154
+ #cookieRows;
155
+ #cookieMutations = 0;
156
+ #transactionWatermark;
157
+ #sourceHasher;
158
+ #sourcePos = 0;
159
+ #sourceCommitHash;
160
+ #rollbacks = 0;
161
+ #invariantFailures = 0;
162
+ #hashMatches = 0;
163
+ #hashMismatches = 0;
164
+ #hashUnpaired = 0;
165
+ constructor(lc, info) {
166
+ this.#lc = lc.withContext("component", "sqlite-change-log-observer");
167
+ this.#receivedHead = info.headWatermark;
168
+ this.#sqliteHead = info.headWatermark;
169
+ this.#rows = info.rows;
170
+ this.#estimatedBytes = info.estimatedBytes;
171
+ this.#cookieRows = info.cookieRows;
172
+ getOrCreateGauge("replica", "sqlite_change_log.rows", "Rows retained in the SQLite change log.").addCallback((result) => result.observe(this.#rows));
173
+ getOrCreateGauge("replica", "sqlite_change_log.cookie_rows", "Cookie rows retained in the SQLite change log, by cookie table.").addCallback((result) => {
174
+ result.observe(this.#cookieRows.tableMetadata, { table: "tableMetadata" });
175
+ result.observe(this.#cookieRows.backfilling, { table: "backfilling" });
176
+ });
177
+ getOrCreateGauge("replica", "sqlite_change_log.retained_bytes", {
178
+ description: "Estimated UTF-8 payload bytes retained in the SQLite change log.",
179
+ unit: "By"
180
+ }).addCallback((result) => result.observe(this.#estimatedBytes));
181
+ getOrCreateGauge("replica", "sqlite_change_log.head", "SQLite change-log head converted from its lexicographic watermark.").addCallback((result) => {
182
+ const head = watermarkValue(this.#sqliteHead);
183
+ if (head !== void 0) result.observe(head);
184
+ });
185
+ getOrCreateGauge("replica", "sqlite_change_log.head_lag", "Distance from the latest received commit to the SQLite change-log head. The log commits before the forward, so this is zero except within a transaction.").addCallback((result) => {
186
+ const lag = watermarkDistance(this.#receivedHead, this.#sqliteHead);
187
+ if (lag !== void 0) result.observe(lag);
188
+ });
189
+ }
190
+ /**
191
+ * Called as each message arrives, before it is written. Hashes the *received*
192
+ * stream, which is compared against the hash the writer computes over what it
193
+ * *stored*.
194
+ */
195
+ messageReceived(data, json) {
196
+ const tag = data[1].tag;
197
+ if (data[0] === "begin") {
198
+ if (this.#sourceHasher !== void 0) this.#invariantFailure("Received change-log begin while a source hash is already open", { receivedWatermark: data[2].commitWatermark });
199
+ const watermark = data[2].commitWatermark;
200
+ this.#sourceHasher = new ChangeLogTransactionHasher();
201
+ this.#sourcePos = 0;
202
+ this.#sourceCommitHash = void 0;
203
+ this.#sourceHasher.add({
204
+ watermark,
205
+ pos: this.#sourcePos,
206
+ tag,
207
+ change: extractChangeSubstring(json, tag),
208
+ precommit: null
209
+ });
210
+ return;
211
+ }
212
+ if (tag === "rollback") {
213
+ this.#resetSourceHash();
214
+ return;
215
+ }
216
+ if (data[0] === "commit") this.#receivedHead = data[2].watermark;
217
+ const watermark = this.#transactionWatermark;
218
+ if (this.#sourceHasher === void 0 || watermark === void 0) {
219
+ this.#invariantFailure("Received change-log message without an observed transaction", { tag });
220
+ return;
221
+ }
222
+ const commitWatermark = data[0] === "commit" ? data[2].watermark : watermark;
223
+ this.#sourceHasher.add({
224
+ watermark: commitWatermark,
225
+ pos: ++this.#sourcePos,
226
+ tag,
227
+ change: extractChangeSubstring(json, tag),
228
+ precommit: data[0] === "commit" ? watermark : null
229
+ });
230
+ if (data[0] === "commit") {
231
+ this.#sourceCommitHash = this.#sourceHasher.digest();
232
+ this.#sourceHasher = void 0;
233
+ }
234
+ }
235
+ /** Called after the message has been written to the log. */
236
+ messageProcessed(data, commit, durationMs) {
237
+ const tag = data[1].tag;
238
+ this.#messageProcessing.recordMs(durationMs, {
239
+ tag,
240
+ outcome: "success"
241
+ });
242
+ if (data[0] === "begin") {
243
+ if (this.#transactionWatermark !== void 0) this.#invariantFailure("SQLite change-log transaction already open", {
244
+ openWatermark: this.#transactionWatermark,
245
+ receivedWatermark: data[2].commitWatermark
246
+ });
247
+ this.#transactionWatermark = data[2].commitWatermark;
248
+ return;
249
+ }
250
+ if (tag === "rollback") {
251
+ this.#recordRollback("upstream");
252
+ this.#transactionWatermark = void 0;
253
+ this.#resetSourceHash();
254
+ return;
255
+ }
256
+ if (data[0] !== "commit") return;
257
+ const watermark = data[2].watermark;
258
+ if (commit !== null) this.#logCommitDuration.recordMs(commit.logCommitMs);
259
+ if (this.#transactionWatermark !== watermark) this.#invariantFailure("SQLite change-log commit does not match the observed begin", {
260
+ openWatermark: this.#transactionWatermark,
261
+ commitWatermark: watermark
262
+ });
263
+ if (commit === null) {
264
+ this.#invariantFailure("SQLite change-log commit result is missing writer statistics", { commitWatermark: watermark });
265
+ this.#recordUnpaired(watermark, "missing-sqlite-hash");
266
+ } else {
267
+ if (commit.watermark !== watermark) this.#invariantFailure("SQLite change-log commit result has an unexpected watermark", {
268
+ commitWatermark: watermark,
269
+ resultWatermark: commit.watermark
270
+ });
271
+ this.#rows += commit.stats.rows;
272
+ this.#estimatedBytes += commit.stats.estimatedBytes;
273
+ this.#transactionRows.record(commit.stats.rows);
274
+ this.#compareHashes(watermark, this.#sourceCommitHash, commit.stats.hash);
275
+ }
276
+ if (watermark < this.#sqliteHead) this.#invariantFailure("SQLite change-log head regressed", {
277
+ previousHead: this.#sqliteHead,
278
+ commitWatermark: watermark
279
+ });
280
+ this.#sqliteHead = watermark;
281
+ this.#transactionWatermark = void 0;
282
+ this.#resetSourceHash();
283
+ }
284
+ messageFailed(data, error, durationMs) {
285
+ const tag = data[1].tag;
286
+ this.#messageProcessing.recordMs(durationMs, {
287
+ tag,
288
+ outcome: "error"
289
+ });
290
+ if (data[0] === "commit") this.#recordUnpaired(data[2].watermark, "sqlite-commit-failed");
291
+ if (error instanceof Error && error.name === "ChangeLogStreamInvariantError") this.#invariantFailure(error.message);
292
+ if (this.#transactionWatermark !== void 0 || data[0] === "begin") this.#recordRollback("processing-error");
293
+ this.#transactionWatermark = void 0;
294
+ this.#resetSourceHash();
295
+ }
296
+ /**
297
+ * A committed transaction folded schema changes into the cookie jar. Reported
298
+ * separately from {@link messageProcessed} because it costs a read of the
299
+ * cookie tables, which is only worth taking when they actually moved.
300
+ */
301
+ cookiesMutated(ops, rows) {
302
+ for (const op of ops) {
303
+ this.#cookieMutations++;
304
+ this.#cookieMutationCounter.add(1, { op });
305
+ }
306
+ this.#cookieRows = rows;
307
+ }
308
+ /**
309
+ * A missed truncate-above surfaces as a constraint violation on the writer's
310
+ * plain `INSERT`, which the fail-soft policy would otherwise absorb quietly.
311
+ * Classifying it as an invariant failure is what keeps a reconciliation bug
312
+ * from looking like a lost cache.
313
+ */
314
+ invariantFailure(message, details) {
315
+ this.#invariantFailure(message, details);
316
+ }
317
+ /** The source interrupted the stream mid-transaction. */
318
+ abort() {
319
+ if (this.#transactionWatermark !== void 0) {
320
+ this.#recordRollback("source-interruption");
321
+ this.#transactionWatermark = void 0;
322
+ }
323
+ this.#resetSourceHash();
324
+ }
325
+ /** Reconciliation moved the head, so the observer's totals are restated. */
326
+ reconciled(info) {
327
+ this.#receivedHead = info.headWatermark;
328
+ this.#sqliteHead = info.headWatermark;
329
+ this.#rows = info.rows;
330
+ this.#estimatedBytes = info.estimatedBytes;
331
+ this.#cookieRows = info.cookieRows;
332
+ this.#transactionWatermark = void 0;
333
+ this.#resetSourceHash();
334
+ }
335
+ state() {
336
+ return {
337
+ receivedHead: this.#receivedHead,
338
+ sqliteHead: this.#sqliteHead,
339
+ headLag: watermarkDistance(this.#receivedHead, this.#sqliteHead),
340
+ rows: this.#rows,
341
+ estimatedBytes: this.#estimatedBytes,
342
+ cookieRows: this.#cookieRows,
343
+ cookieMutations: this.#cookieMutations,
344
+ rollbacks: this.#rollbacks,
345
+ invariantFailures: this.#invariantFailures,
346
+ hashMatches: this.#hashMatches,
347
+ hashMismatches: this.#hashMismatches,
348
+ hashUnpaired: this.#hashUnpaired
349
+ };
350
+ }
351
+ #recordRollback(reason) {
352
+ this.#rollbacks++;
353
+ this.#rollbackCounter.add(1, { reason });
354
+ }
355
+ #invariantFailure(message, details) {
356
+ this.#invariantFailures++;
357
+ this.#invariantFailureCounter.add(1);
358
+ this.#lc.error?.(message, details);
359
+ }
360
+ #compareHashes(watermark, sourceHash, sqliteHash) {
361
+ if (sourceHash === void 0) {
362
+ this.#recordUnpaired(watermark, "missing-source-hash");
363
+ return;
364
+ }
365
+ if (sourceHash === sqliteHash) {
366
+ this.#hashMatches++;
367
+ this.#hashComparisonCounter.add(1, { outcome: "match" });
368
+ return;
369
+ }
370
+ this.#hashMismatches++;
371
+ this.#hashComparisonCounter.add(1, { outcome: "mismatch" });
372
+ this.#lc.error?.("SQLite change-log transaction hash mismatch", { sqliteChangeLogHashComparison: {
373
+ watermark,
374
+ sourceHash: sourceHash.slice(0, 16),
375
+ sqliteHash: sqliteHash.slice(0, 16)
376
+ } });
377
+ }
378
+ #recordUnpaired(watermark, reason) {
379
+ this.#hashUnpaired++;
380
+ this.#hashUnpairedCounter.add(1, { reason });
381
+ this.#lc.warn?.("SQLite change-log transaction hash was not compared", { sqliteChangeLogHashComparison: {
382
+ watermark,
383
+ reason
384
+ } });
385
+ }
386
+ #resetSourceHash() {
387
+ this.#sourceHasher = void 0;
388
+ this.#sourcePos = 0;
389
+ this.#sourceCommitHash = void 0;
390
+ }
391
+ };
392
+ function watermarkValue(watermark) {
393
+ try {
394
+ const value = Number(versionFromLexi(watermark));
395
+ return Number.isFinite(value) ? value : void 0;
396
+ } catch {
397
+ return;
398
+ }
399
+ }
400
+ function watermarkDistance(receivedHead, sqliteHead) {
401
+ if (receivedHead <= sqliteHead) return 0;
402
+ try {
403
+ const distance = versionFromLexi(receivedHead) - versionFromLexi(sqliteHead);
404
+ const value = Number(distance);
405
+ return Number.isFinite(value) ? value : void 0;
406
+ } catch {
407
+ return;
408
+ }
409
+ }
410
+ //#endregion
411
+ export { SQLiteChangeLogObserver, getSQLiteChangeLogInfo, logSQLiteChangeLogStartup, recordSQLiteChangeLogReconcile, sqliteFileBytes };
412
+
413
+ //# sourceMappingURL=sqlite-change-log-observability.js.map