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

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 (372) hide show
  1. package/out/replicache/src/btree/read.d.ts +12 -1
  2. package/out/replicache/src/btree/read.d.ts.map +1 -1
  3. package/out/replicache/src/btree/read.js +24 -12
  4. package/out/replicache/src/btree/read.js.map +1 -1
  5. package/out/replicache/src/db/write.js.map +1 -1
  6. package/out/replicache/src/kv/expo-sqlite/store.d.ts.map +1 -1
  7. package/out/replicache/src/kv/expo-sqlite/store.js +27 -4
  8. package/out/replicache/src/kv/expo-sqlite/store.js.map +1 -1
  9. package/out/replicache/src/kv/sqlite-store.d.ts +11 -0
  10. package/out/replicache/src/kv/sqlite-store.d.ts.map +1 -1
  11. package/out/replicache/src/kv/sqlite-store.js +43 -3
  12. package/out/replicache/src/kv/sqlite-store.js.map +1 -1
  13. package/out/replicache/src/replicache-impl.d.ts.map +1 -1
  14. package/out/replicache/src/replicache-impl.js +10 -0
  15. package/out/replicache/src/replicache-impl.js.map +1 -1
  16. package/out/replicache/src/transactions.d.ts.map +1 -1
  17. package/out/replicache/src/transactions.js +1 -1
  18. package/out/replicache/src/transactions.js.map +1 -1
  19. package/out/shared/src/error.d.ts +11 -0
  20. package/out/shared/src/error.d.ts.map +1 -1
  21. package/out/shared/src/error.js +35 -1
  22. package/out/shared/src/error.js.map +1 -1
  23. package/out/shared/src/hash.d.ts.map +1 -1
  24. package/out/shared/src/hash.js +105 -10
  25. package/out/shared/src/hash.js.map +1 -1
  26. package/out/shared/src/map.d.ts +7 -2
  27. package/out/shared/src/map.d.ts.map +1 -1
  28. package/out/shared/src/map.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/zero/package.js +2 -3
  34. package/out/zero/package.js.map +1 -1
  35. package/out/zero-cache/src/auth/write-authorizer.d.ts.map +1 -1
  36. package/out/zero-cache/src/auth/write-authorizer.js +8 -1
  37. package/out/zero-cache/src/auth/write-authorizer.js.map +1 -1
  38. package/out/zero-cache/src/config/normalize.d.ts +5 -0
  39. package/out/zero-cache/src/config/normalize.d.ts.map +1 -1
  40. package/out/zero-cache/src/config/normalize.js +16 -3
  41. package/out/zero-cache/src/config/normalize.js.map +1 -1
  42. package/out/zero-cache/src/config/zero-config.d.ts +36 -7
  43. package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
  44. package/out/zero-cache/src/config/zero-config.js +121 -46
  45. package/out/zero-cache/src/config/zero-config.js.map +1 -1
  46. package/out/zero-cache/src/db/create.d.ts.map +1 -1
  47. package/out/zero-cache/src/db/create.js +4 -1
  48. package/out/zero-cache/src/db/create.js.map +1 -1
  49. package/out/zero-cache/src/db/index-predicate.d.ts +4 -0
  50. package/out/zero-cache/src/db/index-predicate.d.ts.map +1 -0
  51. package/out/zero-cache/src/db/index-predicate.js +46 -0
  52. package/out/zero-cache/src/db/index-predicate.js.map +1 -0
  53. package/out/zero-cache/src/db/lite-tables.d.ts +10 -2
  54. package/out/zero-cache/src/db/lite-tables.d.ts.map +1 -1
  55. package/out/zero-cache/src/db/lite-tables.js +8 -3
  56. package/out/zero-cache/src/db/lite-tables.js.map +1 -1
  57. package/out/zero-cache/src/db/migration-lite.d.ts.map +1 -1
  58. package/out/zero-cache/src/db/migration-lite.js +5 -3
  59. package/out/zero-cache/src/db/migration-lite.js.map +1 -1
  60. package/out/zero-cache/src/db/specs.d.ts +41 -0
  61. package/out/zero-cache/src/db/specs.d.ts.map +1 -1
  62. package/out/zero-cache/src/db/specs.js +30 -3
  63. package/out/zero-cache/src/db/specs.js.map +1 -1
  64. package/out/zero-cache/src/db/transaction-pool.d.ts +5 -15
  65. package/out/zero-cache/src/db/transaction-pool.d.ts.map +1 -1
  66. package/out/zero-cache/src/db/transaction-pool.js +39 -73
  67. package/out/zero-cache/src/db/transaction-pool.js.map +1 -1
  68. package/out/zero-cache/src/server/change-streamer.d.ts.map +1 -1
  69. package/out/zero-cache/src/server/change-streamer.js +27 -15
  70. package/out/zero-cache/src/server/change-streamer.js.map +1 -1
  71. package/out/zero-cache/src/server/main.d.ts.map +1 -1
  72. package/out/zero-cache/src/server/main.js +4 -4
  73. package/out/zero-cache/src/server/main.js.map +1 -1
  74. package/out/zero-cache/src/server/replicator.d.ts.map +1 -1
  75. package/out/zero-cache/src/server/replicator.js +8 -4
  76. package/out/zero-cache/src/server/replicator.js.map +1 -1
  77. package/out/zero-cache/src/server/runner/run-worker.js +1 -1
  78. package/out/zero-cache/src/server/worker-urls.d.ts +0 -1
  79. package/out/zero-cache/src/server/worker-urls.d.ts.map +1 -1
  80. package/out/zero-cache/src/server/worker-urls.js +1 -2
  81. package/out/zero-cache/src/server/worker-urls.js.map +1 -1
  82. package/out/zero-cache/src/services/analyze.d.ts.map +1 -1
  83. package/out/zero-cache/src/services/analyze.js +1 -0
  84. package/out/zero-cache/src/services/analyze.js.map +1 -1
  85. package/out/zero-cache/src/services/change-source/common/backfill-manager.d.ts +12 -2
  86. package/out/zero-cache/src/services/change-source/common/backfill-manager.d.ts.map +1 -1
  87. package/out/zero-cache/src/services/change-source/common/backfill-manager.js +14 -3
  88. package/out/zero-cache/src/services/change-source/common/backfill-manager.js.map +1 -1
  89. package/out/zero-cache/src/services/change-source/common/replica-schema.d.ts.map +1 -1
  90. package/out/zero-cache/src/services/change-source/common/replica-schema.js +10 -41
  91. package/out/zero-cache/src/services/change-source/common/replica-schema.js.map +1 -1
  92. package/out/zero-cache/src/services/change-source/pg/backfill-stream.d.ts +3 -2
  93. package/out/zero-cache/src/services/change-source/pg/backfill-stream.d.ts.map +1 -1
  94. package/out/zero-cache/src/services/change-source/pg/backfill-stream.js +42 -16
  95. package/out/zero-cache/src/services/change-source/pg/backfill-stream.js.map +1 -1
  96. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts +34 -2
  97. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts.map +1 -1
  98. package/out/zero-cache/src/services/change-source/pg/change-source.js +47 -19
  99. package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
  100. package/out/zero-cache/src/services/change-source/pg/decommission.d.ts.map +1 -1
  101. package/out/zero-cache/src/services/change-source/pg/decommission.js +20 -11
  102. package/out/zero-cache/src/services/change-source/pg/decommission.js.map +1 -1
  103. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts +1 -0
  104. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts.map +1 -1
  105. package/out/zero-cache/src/services/change-source/pg/initial-sync.js +58 -80
  106. package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
  107. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.d.ts +20 -0
  108. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.d.ts.map +1 -1
  109. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js +43 -3
  110. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js.map +1 -1
  111. package/out/zero-cache/src/services/change-source/pg/replication-slots.d.ts +24 -1
  112. package/out/zero-cache/src/services/change-source/pg/replication-slots.d.ts.map +1 -1
  113. package/out/zero-cache/src/services/change-source/pg/replication-slots.js +35 -5
  114. package/out/zero-cache/src/services/change-source/pg/replication-slots.js.map +1 -1
  115. package/out/zero-cache/src/services/change-source/pg/schema/ddl.d.ts +1513 -229
  116. package/out/zero-cache/src/services/change-source/pg/schema/ddl.d.ts.map +1 -1
  117. package/out/zero-cache/src/services/change-source/pg/schema/ddl.js +2 -2
  118. package/out/zero-cache/src/services/change-source/pg/schema/ddl.js.map +1 -1
  119. package/out/zero-cache/src/services/change-source/pg/schema/index-predicate.d.ts +19 -0
  120. package/out/zero-cache/src/services/change-source/pg/schema/index-predicate.d.ts.map +1 -0
  121. package/out/zero-cache/src/services/change-source/pg/schema/index-predicate.js +581 -0
  122. package/out/zero-cache/src/services/change-source/pg/schema/index-predicate.js.map +1 -0
  123. package/out/zero-cache/src/services/change-source/pg/schema/init.d.ts +1 -1
  124. package/out/zero-cache/src/services/change-source/pg/schema/init.d.ts.map +1 -1
  125. package/out/zero-cache/src/services/change-source/pg/schema/init.js +15 -6
  126. package/out/zero-cache/src/services/change-source/pg/schema/init.js.map +1 -1
  127. package/out/zero-cache/src/services/change-source/pg/schema/published.d.ts +137 -20
  128. package/out/zero-cache/src/services/change-source/pg/schema/published.d.ts.map +1 -1
  129. package/out/zero-cache/src/services/change-source/pg/schema/published.js +82 -13
  130. package/out/zero-cache/src/services/change-source/pg/schema/published.js.map +1 -1
  131. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts +128 -21
  132. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts.map +1 -1
  133. package/out/zero-cache/src/services/change-source/pg/schema/shard.js +5 -5
  134. package/out/zero-cache/src/services/change-source/pg/schema/shard.js.map +1 -1
  135. package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts +2 -0
  136. package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts.map +1 -1
  137. package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts +3 -0
  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-streamer/backup-cleanup-monitor-factory.d.ts +1 -4
  140. package/out/zero-cache/src/services/change-streamer/backup-cleanup-monitor-factory.d.ts.map +1 -1
  141. package/out/zero-cache/src/services/change-streamer/backup-cleanup-monitor-factory.js +11 -18
  142. package/out/zero-cache/src/services/change-streamer/backup-cleanup-monitor-factory.js.map +1 -1
  143. package/out/zero-cache/src/services/change-streamer/backup-monitor.d.ts.map +1 -1
  144. package/out/zero-cache/src/services/change-streamer/backup-monitor.js +8 -3
  145. package/out/zero-cache/src/services/change-streamer/backup-monitor.js.map +1 -1
  146. package/out/zero-cache/src/services/change-streamer/broadcast.d.ts.map +1 -1
  147. package/out/zero-cache/src/services/change-streamer/broadcast.js +4 -1
  148. package/out/zero-cache/src/services/change-streamer/broadcast.js.map +1 -1
  149. package/out/zero-cache/src/services/change-streamer/change-log-compare-digest.d.ts +34 -0
  150. package/out/zero-cache/src/services/change-streamer/change-log-compare-digest.d.ts.map +1 -0
  151. package/out/zero-cache/src/services/change-streamer/change-log-compare-digest.js +67 -0
  152. package/out/zero-cache/src/services/change-streamer/change-log-compare-digest.js.map +1 -0
  153. package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts +2 -4
  154. package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts.map +1 -1
  155. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +8 -2
  156. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
  157. package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts +34 -13
  158. package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts.map +1 -1
  159. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js +165 -36
  160. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -1
  161. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts +4 -9
  162. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts.map +1 -1
  163. package/out/zero-cache/src/services/change-streamer/change-streamer.js.map +1 -1
  164. package/out/zero-cache/src/services/change-streamer/forwarder.d.ts.map +1 -1
  165. package/out/zero-cache/src/services/change-streamer/forwarder.js +12 -3
  166. package/out/zero-cache/src/services/change-streamer/forwarder.js.map +1 -1
  167. package/out/zero-cache/src/services/change-streamer/litestream3-prometheus-poller.d.ts.map +1 -1
  168. package/out/zero-cache/src/services/change-streamer/litestream3-prometheus-poller.js +11 -5
  169. package/out/zero-cache/src/services/change-streamer/litestream3-prometheus-poller.js.map +1 -1
  170. package/out/zero-cache/src/services/change-streamer/shard-sampling.d.ts +11 -0
  171. package/out/zero-cache/src/services/change-streamer/shard-sampling.d.ts.map +1 -0
  172. package/out/zero-cache/src/services/change-streamer/shard-sampling.js +19 -0
  173. package/out/zero-cache/src/services/change-streamer/shard-sampling.js.map +1 -0
  174. package/out/zero-cache/src/services/change-streamer/snapshot-reservations.d.ts +11 -1
  175. package/out/zero-cache/src/services/change-streamer/snapshot-reservations.d.ts.map +1 -1
  176. package/out/zero-cache/src/services/change-streamer/snapshot-reservations.js +38 -5
  177. package/out/zero-cache/src/services/change-streamer/snapshot-reservations.js.map +1 -1
  178. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-catchup.d.ts +25 -1
  179. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-catchup.d.ts.map +1 -1
  180. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-catchup.js +95 -12
  181. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-catchup.js.map +1 -1
  182. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-comparator.d.ts +83 -0
  183. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-comparator.d.ts.map +1 -0
  184. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-comparator.js +417 -0
  185. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-comparator.js.map +1 -0
  186. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-read-router.d.ts +73 -0
  187. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-read-router.d.ts.map +1 -0
  188. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-read-router.js +157 -0
  189. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-read-router.js.map +1 -0
  190. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-reader.d.ts +1 -1
  191. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-reader.d.ts.map +1 -1
  192. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-reader.js +8 -3
  193. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-reader.js.map +1 -1
  194. package/out/zero-cache/src/services/change-streamer/storer.d.ts +63 -1
  195. package/out/zero-cache/src/services/change-streamer/storer.d.ts.map +1 -1
  196. package/out/zero-cache/src/services/change-streamer/storer.js +217 -49
  197. package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
  198. package/out/zero-cache/src/services/change-streamer/subscriber.d.ts +8 -1
  199. package/out/zero-cache/src/services/change-streamer/subscriber.d.ts.map +1 -1
  200. package/out/zero-cache/src/services/change-streamer/subscriber.js +10 -1
  201. package/out/zero-cache/src/services/change-streamer/subscriber.js.map +1 -1
  202. package/out/zero-cache/src/services/change-streamer/vfs-watermark-poller.d.ts +29 -0
  203. package/out/zero-cache/src/services/change-streamer/vfs-watermark-poller.d.ts.map +1 -0
  204. package/out/zero-cache/src/services/change-streamer/vfs-watermark-poller.js +154 -0
  205. package/out/zero-cache/src/services/change-streamer/vfs-watermark-poller.js.map +1 -0
  206. package/out/zero-cache/src/services/http-service.d.ts +1 -0
  207. package/out/zero-cache/src/services/http-service.d.ts.map +1 -1
  208. package/out/zero-cache/src/services/http-service.js +7 -3
  209. package/out/zero-cache/src/services/http-service.js.map +1 -1
  210. package/out/zero-cache/src/services/litestream/commands.d.ts.map +1 -1
  211. package/out/zero-cache/src/services/litestream/commands.js +16 -7
  212. package/out/zero-cache/src/services/litestream/commands.js.map +1 -1
  213. package/out/zero-cache/src/services/litestream/config-v5.yml +15 -1
  214. package/out/zero-cache/src/services/litestream/litestream-checkpointer.js +131 -0
  215. package/out/zero-cache/src/services/litestream/litestream-checkpointer.js.map +1 -0
  216. package/out/zero-cache/src/services/litestream/litestream-controller.d.ts +70 -0
  217. package/out/zero-cache/src/services/litestream/litestream-controller.d.ts.map +1 -0
  218. package/out/zero-cache/src/services/litestream/litestream-controller.js +101 -0
  219. package/out/zero-cache/src/services/litestream/litestream-controller.js.map +1 -0
  220. package/out/zero-cache/src/services/litestream/metrics.d.ts +1 -0
  221. package/out/zero-cache/src/services/litestream/metrics.d.ts.map +1 -1
  222. package/out/zero-cache/src/services/litestream/metrics.js +4 -1
  223. package/out/zero-cache/src/services/litestream/metrics.js.map +1 -1
  224. package/out/zero-cache/src/services/mutagen/mutagen.d.ts.map +1 -1
  225. package/out/zero-cache/src/services/mutagen/mutagen.js +1 -1
  226. package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -1
  227. package/out/zero-cache/src/services/replicator/change-log-db.d.ts +10 -0
  228. package/out/zero-cache/src/services/replicator/change-log-db.d.ts.map +1 -1
  229. package/out/zero-cache/src/services/replicator/change-log-db.js +15 -1
  230. package/out/zero-cache/src/services/replicator/change-log-db.js.map +1 -1
  231. package/out/zero-cache/src/services/replicator/change-processor.d.ts.map +1 -1
  232. package/out/zero-cache/src/services/replicator/change-processor.js +18 -21
  233. package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
  234. package/out/zero-cache/src/services/replicator/incremental-sync.d.ts +1 -1
  235. package/out/zero-cache/src/services/replicator/incremental-sync.d.ts.map +1 -1
  236. package/out/zero-cache/src/services/replicator/incremental-sync.js +2 -6
  237. package/out/zero-cache/src/services/replicator/incremental-sync.js.map +1 -1
  238. package/out/zero-cache/src/services/replicator/replicator.d.ts +1 -1
  239. package/out/zero-cache/src/services/replicator/replicator.d.ts.map +1 -1
  240. package/out/zero-cache/src/services/replicator/replicator.js +2 -2
  241. package/out/zero-cache/src/services/replicator/replicator.js.map +1 -1
  242. package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.d.ts +3 -2
  243. package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.d.ts.map +1 -1
  244. package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.js +8 -6
  245. package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.js.map +1 -1
  246. package/out/zero-cache/src/services/replicator/write-worker-client.d.ts +27 -2
  247. package/out/zero-cache/src/services/replicator/write-worker-client.d.ts.map +1 -1
  248. package/out/zero-cache/src/services/replicator/write-worker-client.js +3 -2
  249. package/out/zero-cache/src/services/replicator/write-worker-client.js.map +1 -1
  250. package/out/zero-cache/src/services/replicator/write-worker.js +24 -5
  251. package/out/zero-cache/src/services/replicator/write-worker.js.map +1 -1
  252. package/out/zero-cache/src/services/view-syncer/client-handler.d.ts +3 -2
  253. package/out/zero-cache/src/services/view-syncer/client-handler.d.ts.map +1 -1
  254. package/out/zero-cache/src/services/view-syncer/client-handler.js +25 -17
  255. package/out/zero-cache/src/services/view-syncer/client-handler.js.map +1 -1
  256. package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts.map +1 -1
  257. package/out/zero-cache/src/services/view-syncer/cvr-store.js +14 -1
  258. package/out/zero-cache/src/services/view-syncer/cvr-store.js.map +1 -1
  259. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts +3 -3
  260. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
  261. package/out/zero-cache/src/services/view-syncer/view-syncer.js +6 -2
  262. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  263. package/out/zero-cache/src/types/downstream.d.ts +11 -0
  264. package/out/zero-cache/src/types/downstream.d.ts.map +1 -0
  265. package/out/zero-cache/src/types/pg.d.ts +15 -2
  266. package/out/zero-cache/src/types/pg.d.ts.map +1 -1
  267. package/out/zero-cache/src/types/pg.js +21 -8
  268. package/out/zero-cache/src/types/pg.js.map +1 -1
  269. package/out/zero-cache/src/types/poke-chunk.d.ts +18 -0
  270. package/out/zero-cache/src/types/poke-chunk.d.ts.map +1 -0
  271. package/out/zero-cache/src/types/poke-chunk.js +57 -0
  272. package/out/zero-cache/src/types/poke-chunk.js.map +1 -0
  273. package/out/zero-cache/src/types/processes.js +1 -4
  274. package/out/zero-cache/src/types/processes.js.map +1 -1
  275. package/out/zero-cache/src/types/streams.d.ts +4 -9
  276. package/out/zero-cache/src/types/streams.d.ts.map +1 -1
  277. package/out/zero-cache/src/types/streams.js.map +1 -1
  278. package/out/zero-cache/src/types/subscription.d.ts +2 -11
  279. package/out/zero-cache/src/types/subscription.d.ts.map +1 -1
  280. package/out/zero-cache/src/types/subscription.js +4 -25
  281. package/out/zero-cache/src/types/subscription.js.map +1 -1
  282. package/out/zero-cache/src/workers/connection.d.ts +22 -4
  283. package/out/zero-cache/src/workers/connection.d.ts.map +1 -1
  284. package/out/zero-cache/src/workers/connection.js +112 -14
  285. package/out/zero-cache/src/workers/connection.js.map +1 -1
  286. package/out/zero-cache/src/workers/replicator.d.ts +1 -0
  287. package/out/zero-cache/src/workers/replicator.d.ts.map +1 -1
  288. package/out/zero-cache/src/workers/replicator.js +4 -2
  289. package/out/zero-cache/src/workers/replicator.js.map +1 -1
  290. package/out/zero-client/src/client/connection-manager.d.ts.map +1 -1
  291. package/out/zero-client/src/client/connection-manager.js +46 -0
  292. package/out/zero-client/src/client/connection-manager.js.map +1 -1
  293. package/out/zero-client/src/client/context.d.ts +15 -0
  294. package/out/zero-client/src/client/context.d.ts.map +1 -1
  295. package/out/zero-client/src/client/context.js +44 -0
  296. package/out/zero-client/src/client/context.js.map +1 -1
  297. package/out/zero-client/src/client/inspector/lazy-inspector.d.ts.map +1 -1
  298. package/out/zero-client/src/client/inspector/lazy-inspector.js +19 -12
  299. package/out/zero-client/src/client/inspector/lazy-inspector.js.map +1 -1
  300. package/out/zero-client/src/client/ivm-branch.js.map +1 -1
  301. package/out/zero-client/src/client/version.js +1 -1
  302. package/out/zero-client/src/client/zero-poke-handler.d.ts +7 -2
  303. package/out/zero-client/src/client/zero-poke-handler.d.ts.map +1 -1
  304. package/out/zero-client/src/client/zero-poke-handler.js +52 -2
  305. package/out/zero-client/src/client/zero-poke-handler.js.map +1 -1
  306. package/out/zero-client/src/client/zero-rep.d.ts.map +1 -1
  307. package/out/zero-client/src/client/zero-rep.js +2 -1
  308. package/out/zero-client/src/client/zero-rep.js.map +1 -1
  309. package/out/zero-client/src/client/zero.d.ts.map +1 -1
  310. package/out/zero-client/src/client/zero.js +98 -25
  311. package/out/zero-client/src/client/zero.js.map +1 -1
  312. package/out/zero-protocol/src/custom-queries.d.ts +1 -1
  313. package/out/zero-protocol/src/down.d.ts +1 -1
  314. package/out/zero-protocol/src/error.d.ts +4 -4
  315. package/out/zero-protocol/src/inspect-down.js +1 -1
  316. package/out/zero-protocol/src/mutate-server.d.ts +2 -2
  317. package/out/zero-protocol/src/poke.d.ts +89 -7
  318. package/out/zero-protocol/src/poke.d.ts.map +1 -1
  319. package/out/zero-protocol/src/poke.js +16 -8
  320. package/out/zero-protocol/src/poke.js.map +1 -1
  321. package/out/zero-protocol/src/protocol-version.d.ts +12 -7
  322. package/out/zero-protocol/src/protocol-version.d.ts.map +1 -1
  323. package/out/zero-protocol/src/protocol-version.js.map +1 -1
  324. package/out/zero-protocol/src/push.d.ts +1 -1
  325. package/out/zero-protocol/src/query-server.d.ts +2 -2
  326. package/out/zql/src/ivm/array-view.d.ts.map +1 -1
  327. package/out/zql/src/ivm/array-view.js +5 -3
  328. package/out/zql/src/ivm/array-view.js.map +1 -1
  329. package/out/zql/src/ivm/data.d.ts.map +1 -1
  330. package/out/zql/src/ivm/data.js +8 -3
  331. package/out/zql/src/ivm/data.js.map +1 -1
  332. package/out/zql/src/ivm/deferred-input.d.ts +44 -0
  333. package/out/zql/src/ivm/deferred-input.d.ts.map +1 -0
  334. package/out/zql/src/ivm/deferred-input.js +88 -0
  335. package/out/zql/src/ivm/deferred-input.js.map +1 -0
  336. package/out/zql/src/ivm/memory-source.d.ts +10 -2
  337. package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
  338. package/out/zql/src/ivm/memory-source.js +19 -16
  339. package/out/zql/src/ivm/memory-source.js.map +1 -1
  340. package/out/zql/src/ivm/stream.d.ts +0 -1
  341. package/out/zql/src/ivm/stream.d.ts.map +1 -1
  342. package/out/zql/src/ivm/stream.js +1 -7
  343. package/out/zql/src/ivm/stream.js.map +1 -1
  344. package/out/zql/src/ivm/union-fan-in.d.ts +1 -1
  345. package/out/zql/src/ivm/union-fan-in.d.ts.map +1 -1
  346. package/out/zql/src/ivm/union-fan-in.js +11 -2
  347. package/out/zql/src/ivm/union-fan-in.js.map +1 -1
  348. package/out/zql/src/ivm/view-apply-change.js +6 -1
  349. package/out/zql/src/ivm/view-apply-change.js.map +1 -1
  350. package/out/zql/src/query/query-delegate-base.d.ts +6 -0
  351. package/out/zql/src/query/query-delegate-base.d.ts.map +1 -1
  352. package/out/zql/src/query/query-delegate-base.js +73 -10
  353. package/out/zql/src/query/query-delegate-base.js.map +1 -1
  354. package/out/zql/src/query/query-delegate.d.ts +22 -0
  355. package/out/zql/src/query/query-delegate.d.ts.map +1 -1
  356. package/out/zqlite/src/query-builder.d.ts.map +1 -1
  357. package/out/zqlite/src/query-builder.js +2 -1
  358. package/out/zqlite/src/query-builder.js.map +1 -1
  359. package/out/zqlite/src/sqlite-stat-fanout.d.ts.map +1 -1
  360. package/out/zqlite/src/sqlite-stat-fanout.js +1 -0
  361. package/out/zqlite/src/sqlite-stat-fanout.js.map +1 -1
  362. package/out/zqlite/src/table-source.d.ts +1 -1
  363. package/out/zqlite/src/table-source.d.ts.map +1 -1
  364. package/out/zqlite/src/table-source.js +3 -2
  365. package/out/zqlite/src/table-source.js.map +1 -1
  366. package/package.json +2 -3
  367. package/out/zero-cache/src/server/backup-watermark-poller.js +0 -31
  368. package/out/zero-cache/src/server/backup-watermark-poller.js.map +0 -1
  369. package/out/zero-cache/src/services/litestream/vfs-watermark-poller.d.ts +0 -57
  370. package/out/zero-cache/src/services/litestream/vfs-watermark-poller.d.ts.map +0 -1
  371. package/out/zero-cache/src/services/litestream/vfs-watermark-poller.js +0 -137
  372. package/out/zero-cache/src/services/litestream/vfs-watermark-poller.js.map +0 -1
@@ -1,3 +1,4 @@
1
+ import { assert } from "../../../../shared/src/asserts.js";
1
2
  import { must } from "../../../../shared/src/must.js";
2
3
  import { Database } from "../../../../zqlite/src/db.js";
3
4
  import { getSubscriptionState } from "./schema/replication-state.js";
@@ -6,7 +7,9 @@ import { isSQLiteCorruption, logSQLiteCorruptionDiagnostics, registerSQLiteCorru
6
7
  import { createLogContext } from "../../server/logging.js";
7
8
  import { deleteLiteDB } from "../../db/delete-lite-db.js";
8
9
  import { ChangeProcessor } from "./change-processor.js";
10
+ import { LitestreamController } from "../litestream/litestream-controller.js";
9
11
  import { applyPragmas, serializeError } from "./write-worker-client.js";
12
+ import { LitestreamCheckpointer } from "../litestream/litestream-checkpointer.js";
10
13
  import { parentPort } from "node:worker_threads";
11
14
  //#region ../zero-cache/src/services/replicator/write-worker.ts
12
15
  if (!parentPort) throw new Error("write-worker must be run as a worker thread");
@@ -19,6 +22,8 @@ function createAPI() {
19
22
  let lc;
20
23
  let replicaDbPath;
21
24
  let unregisterCorruptionDiagnosticTargets = [];
25
+ let checkpointerConfig;
26
+ let checkpointer;
22
27
  function unregisterCorruptionDiagnostics() {
23
28
  unregisterCorruptionDiagnosticTargets.forEach((unregister) => unregister());
24
29
  unregisterCorruptionDiagnosticTargets = [];
@@ -39,8 +44,14 @@ function createAPI() {
39
44
  port.postMessage({ writeError: serializeError(err) });
40
45
  });
41
46
  }
47
+ function createCheckpointer() {
48
+ if (checkpointerConfig) {
49
+ assert(lc && db && replicaDbPath, `not initialized`);
50
+ checkpointer = new LitestreamCheckpointer(lc, db, new LitestreamController(lc, replicaDbPath), checkpointerConfig);
51
+ }
52
+ }
42
53
  return {
43
- init(dbPath, cpMode, pragmas, logConfig) {
54
+ init(dbPath, cpMode, pragmas, logConfig, checkpointConfig) {
44
55
  replicaDbPath = dbPath;
45
56
  lc = createLogContext({ log: logConfig }, "write-worker");
46
57
  unregisterCorruptionDiagnostics();
@@ -53,7 +64,9 @@ function createAPI() {
53
64
  applyPragmas(db, pragmas);
54
65
  runner = new StatementRunner(db);
55
66
  mode = cpMode;
67
+ checkpointerConfig = checkpointConfig ?? void 0;
56
68
  createProcessor();
69
+ createCheckpointer();
57
70
  } catch (e) {
58
71
  handleCorruptedDb(e);
59
72
  throw e;
@@ -67,9 +80,11 @@ function createAPI() {
67
80
  throw e;
68
81
  }
69
82
  },
70
- processMessage(downstream) {
83
+ async processMessage(downstream) {
71
84
  try {
72
- return must(processor).processMessage(must(lc), downstream);
85
+ const committed = must(processor).processMessage(must(lc), downstream);
86
+ if (committed && checkpointer) await checkpointer.maybeCheckpoint();
87
+ return committed;
73
88
  } catch (e) {
74
89
  handleCorruptedDb(e);
75
90
  throw e;
@@ -77,9 +92,13 @@ function createAPI() {
77
92
  },
78
93
  abort() {
79
94
  must(processor).abort(must(lc));
95
+ checkpointer?.close();
80
96
  createProcessor();
97
+ createCheckpointer();
81
98
  },
82
99
  stop() {
100
+ checkpointer?.close();
101
+ checkpointer = void 0;
83
102
  db?.close();
84
103
  db = void 0;
85
104
  runner = void 0;
@@ -90,9 +109,9 @@ function createAPI() {
90
109
  };
91
110
  }
92
111
  var api = createAPI();
93
- port.on("message", (msg) => {
112
+ port.on("message", async (msg) => {
94
113
  try {
95
- const result = api[msg.method](...msg.args);
114
+ const result = await api[msg.method](...msg.args);
96
115
  if (msg.method !== "abort") port.postMessage({
97
116
  method: msg.method,
98
117
  result
@@ -1 +1 @@
1
- {"version":3,"file":"write-worker.js","names":[],"sources":["../../../../../../zero-cache/src/services/replicator/write-worker.ts"],"sourcesContent":["import {parentPort} from 'node:worker_threads';\nimport type {LogContext} from '@rocicorp/logger';\nimport type {LogConfig} from '../../../../shared/src/logging.ts';\nimport {must} from '../../../../shared/src/must.ts';\nimport {Database} from '../../../../zqlite/src/db.ts';\nimport {deleteLiteDB} from '../../db/delete-lite-db.ts';\nimport {\n isSQLiteCorruption,\n logSQLiteCorruptionDiagnostics,\n registerSQLiteCorruptionDiagnosticTarget,\n} from '../../db/sqlite-corruption.ts';\nimport {StatementRunner} from '../../db/statements.ts';\nimport {createLogContext} from '../../server/logging.ts';\nimport type {ChangeStreamData} from '../change-source/protocol/current/downstream.ts';\nimport {ChangeProcessor, type ChangeProcessorMode} from './change-processor.ts';\nimport {getSubscriptionState} from './schema/replication-state.ts';\nimport {\n applyPragmas,\n serializeError,\n type ArgsMap,\n type Method,\n type PragmaConfig,\n type Request,\n type Response,\n type ResultMap,\n type WriteError,\n} from './write-worker-client.ts';\n\nif (!parentPort) {\n throw new Error('write-worker must be run as a worker thread');\n}\n\nconst port = parentPort;\n\ntype API = {[M in Method]: (...args: ArgsMap[M]) => ResultMap[M]};\n\nfunction createAPI(): API {\n let db: Database | undefined;\n let runner: StatementRunner | undefined;\n let processor: ChangeProcessor | undefined;\n let mode: ChangeProcessorMode | undefined;\n let lc: LogContext | undefined;\n let replicaDbPath: string | undefined;\n let unregisterCorruptionDiagnosticTargets: (() => void)[] = [];\n\n function unregisterCorruptionDiagnostics() {\n unregisterCorruptionDiagnosticTargets.forEach(unregister => unregister());\n unregisterCorruptionDiagnosticTargets = [];\n }\n\n function handleCorruptedDb(err: unknown) {\n if (!lc || !replicaDbPath || !isSQLiteCorruption(err)) {\n return;\n }\n logSQLiteCorruptionDiagnostics(lc, 'write-worker', replicaDbPath, err);\n try {\n lc.warn?.(`deleting corrupted db at ${replicaDbPath}`);\n deleteLiteDB(replicaDbPath);\n } catch (e) {\n lc.warn?.(`error deleting corrupted db at ${replicaDbPath}`, e);\n }\n }\n\n function createProcessor() {\n processor = new ChangeProcessor(must(runner), must(mode), (_lc, err) => {\n handleCorruptedDb(err);\n port.postMessage({\n writeError: serializeError(err),\n } satisfies WriteError);\n });\n }\n\n return {\n init(\n dbPath: string,\n cpMode: ChangeProcessorMode,\n pragmas: PragmaConfig,\n logConfig: LogConfig,\n ): void {\n replicaDbPath = dbPath;\n lc = createLogContext({log: logConfig}, 'write-worker');\n unregisterCorruptionDiagnostics();\n unregisterCorruptionDiagnosticTargets.push(\n registerSQLiteCorruptionDiagnosticTarget({\n debugName: 'write-worker',\n dbPath,\n }),\n );\n try {\n db = new Database(lc, dbPath);\n applyPragmas(db, pragmas);\n runner = new StatementRunner(db);\n mode = cpMode;\n createProcessor();\n } catch (e) {\n handleCorruptedDb(e);\n throw e;\n }\n },\n\n getSubscriptionState() {\n try {\n return getSubscriptionState(must(runner));\n } catch (e) {\n handleCorruptedDb(e);\n throw e;\n }\n },\n\n processMessage(downstream: ChangeStreamData) {\n try {\n return must(processor).processMessage(must(lc), downstream);\n } catch (e) {\n handleCorruptedDb(e);\n throw e;\n }\n },\n\n abort() {\n must(processor).abort(must(lc));\n createProcessor();\n },\n\n stop() {\n db?.close();\n db = undefined;\n runner = undefined;\n processor = undefined;\n replicaDbPath = undefined;\n unregisterCorruptionDiagnostics();\n },\n };\n}\n\nconst api = createAPI();\n\nport.on('message', (msg: Request) => {\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- TS can't narrow msg.method + msg.args together\n const result = (api[msg.method] as (...args: any[]) => unknown)(\n ...msg.args,\n );\n // abort is fire-and-forget — no pending slot on the client side.\n if (msg.method !== 'abort') {\n port.postMessage({method: msg.method, result} as Response);\n }\n } catch (e) {\n if (msg.method !== 'abort') {\n port.postMessage({\n method: msg.method,\n error: serializeError(e),\n } as Response);\n }\n }\n});\n"],"mappings":";;;;;;;;;;;AA4BA,IAAI,CAAC,YACH,MAAM,IAAI,MAAM,6CAA6C;AAG/D,IAAM,OAAO;AAIb,SAAS,YAAiB;CACxB,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI,wCAAwD,CAAC;CAE7D,SAAS,kCAAkC;EACzC,sCAAsC,SAAQ,eAAc,WAAW,CAAC;EACxE,wCAAwC,CAAC;CAC3C;CAEA,SAAS,kBAAkB,KAAc;EACvC,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,mBAAmB,GAAG,GAClD;EAEF,+BAA+B,IAAI,gBAAgB,eAAe,GAAG;EACrE,IAAI;GACF,GAAG,OAAO,4BAA4B,eAAe;GACrD,aAAa,aAAa;EAC5B,SAAS,GAAG;GACV,GAAG,OAAO,kCAAkC,iBAAiB,CAAC;EAChE;CACF;CAEA,SAAS,kBAAkB;EACzB,YAAY,IAAI,gBAAgB,KAAK,MAAM,GAAG,KAAK,IAAI,IAAI,KAAK,QAAQ;GACtE,kBAAkB,GAAG;GACrB,KAAK,YAAY,EACf,YAAY,eAAe,GAAG,EAChC,CAAsB;EACxB,CAAC;CACH;CAEA,OAAO;EACL,KACE,QACA,QACA,SACA,WACM;GACN,gBAAgB;GAChB,KAAK,iBAAiB,EAAC,KAAK,UAAS,GAAG,cAAc;GACtD,gCAAgC;GAChC,sCAAsC,KACpC,yCAAyC;IACvC,WAAW;IACX;GACF,CAAC,CACH;GACA,IAAI;IACF,KAAK,IAAI,SAAS,IAAI,MAAM;IAC5B,aAAa,IAAI,OAAO;IACxB,SAAS,IAAI,gBAAgB,EAAE;IAC/B,OAAO;IACP,gBAAgB;GAClB,SAAS,GAAG;IACV,kBAAkB,CAAC;IACnB,MAAM;GACR;EACF;EAEA,uBAAuB;GACrB,IAAI;IACF,OAAO,qBAAqB,KAAK,MAAM,CAAC;GAC1C,SAAS,GAAG;IACV,kBAAkB,CAAC;IACnB,MAAM;GACR;EACF;EAEA,eAAe,YAA8B;GAC3C,IAAI;IACF,OAAO,KAAK,SAAS,EAAE,eAAe,KAAK,EAAE,GAAG,UAAU;GAC5D,SAAS,GAAG;IACV,kBAAkB,CAAC;IACnB,MAAM;GACR;EACF;EAEA,QAAQ;GACN,KAAK,SAAS,EAAE,MAAM,KAAK,EAAE,CAAC;GAC9B,gBAAgB;EAClB;EAEA,OAAO;GACL,IAAI,MAAM;GACV,KAAK,KAAA;GACL,SAAS,KAAA;GACT,YAAY,KAAA;GACZ,gBAAgB,KAAA;GAChB,gCAAgC;EAClC;CACF;AACF;AAEA,IAAM,MAAM,UAAU;AAEtB,KAAK,GAAG,YAAY,QAAiB;CACnC,IAAI;EAEF,MAAM,SAAU,IAAI,IAAI,QACtB,GAAG,IAAI,IACT;EAEA,IAAI,IAAI,WAAW,SACjB,KAAK,YAAY;GAAC,QAAQ,IAAI;GAAQ;EAAM,CAAa;CAE7D,SAAS,GAAG;EACV,IAAI,IAAI,WAAW,SACjB,KAAK,YAAY;GACf,QAAQ,IAAI;GACZ,OAAO,eAAe,CAAC;EACzB,CAAa;CAEjB;AACF,CAAC"}
1
+ {"version":3,"file":"write-worker.js","names":[],"sources":["../../../../../../zero-cache/src/services/replicator/write-worker.ts"],"sourcesContent":["import {parentPort} from 'node:worker_threads';\nimport type {LogContext} from '@rocicorp/logger';\nimport {assert} from '../../../../shared/src/asserts.ts';\nimport type {LogConfig} from '../../../../shared/src/logging.ts';\nimport {must} from '../../../../shared/src/must.ts';\nimport {Database} from '../../../../zqlite/src/db.ts';\nimport {deleteLiteDB} from '../../db/delete-lite-db.ts';\nimport {\n isSQLiteCorruption,\n logSQLiteCorruptionDiagnostics,\n registerSQLiteCorruptionDiagnosticTarget,\n} from '../../db/sqlite-corruption.ts';\nimport {StatementRunner} from '../../db/statements.ts';\nimport {createLogContext} from '../../server/logging.ts';\nimport type {ChangeStreamData} from '../change-source/protocol/current/downstream.ts';\nimport {LitestreamCheckpointer} from '../litestream/litestream-checkpointer.ts';\nimport {LitestreamController} from '../litestream/litestream-controller.ts';\nimport {ChangeProcessor, type ChangeProcessorMode} from './change-processor.ts';\nimport {getSubscriptionState} from './schema/replication-state.ts';\nimport {\n applyPragmas,\n serializeError,\n type ArgsMap,\n type ForceCheckpointConfig,\n type Method,\n type PragmaConfig,\n type Request,\n type Response,\n type ResultMap,\n type WriteError,\n} from './write-worker-client.ts';\n\nif (!parentPort) {\n throw new Error('write-worker must be run as a worker thread');\n}\n\nconst port = parentPort;\n\ntype API = {\n [M in Method]: (...args: ArgsMap[M]) => ResultMap[M] | Promise<ResultMap[M]>;\n};\n\nfunction createAPI(): API {\n let db: Database | undefined;\n let runner: StatementRunner | undefined;\n let processor: ChangeProcessor | undefined;\n let mode: ChangeProcessorMode | undefined;\n let lc: LogContext | undefined;\n let replicaDbPath: string | undefined;\n let unregisterCorruptionDiagnosticTargets: (() => void)[] = [];\n\n // Set when write-path checkpoint backpressure is enabled (backup replicator\n // on litestream v5). `undefined` disables the feature.\n let checkpointerConfig: ForceCheckpointConfig | undefined;\n let checkpointer: LitestreamCheckpointer | undefined;\n\n function unregisterCorruptionDiagnostics() {\n unregisterCorruptionDiagnosticTargets.forEach(unregister => unregister());\n unregisterCorruptionDiagnosticTargets = [];\n }\n\n function handleCorruptedDb(err: unknown) {\n if (!lc || !replicaDbPath || !isSQLiteCorruption(err)) {\n return;\n }\n logSQLiteCorruptionDiagnostics(lc, 'write-worker', replicaDbPath, err);\n try {\n lc.warn?.(`deleting corrupted db at ${replicaDbPath}`);\n deleteLiteDB(replicaDbPath);\n } catch (e) {\n lc.warn?.(`error deleting corrupted db at ${replicaDbPath}`, e);\n }\n }\n\n function createProcessor() {\n processor = new ChangeProcessor(must(runner), must(mode), (_lc, err) => {\n handleCorruptedDb(err);\n port.postMessage({\n writeError: serializeError(err),\n } satisfies WriteError);\n });\n }\n\n function createCheckpointer() {\n if (checkpointerConfig) {\n assert(lc && db && replicaDbPath, `not initialized`);\n checkpointer = new LitestreamCheckpointer(\n lc,\n db,\n new LitestreamController(lc, replicaDbPath),\n checkpointerConfig,\n );\n }\n }\n\n return {\n init(\n dbPath: string,\n cpMode: ChangeProcessorMode,\n pragmas: PragmaConfig,\n logConfig: LogConfig,\n checkpointConfig: ForceCheckpointConfig | null,\n ): void {\n replicaDbPath = dbPath;\n lc = createLogContext({log: logConfig}, 'write-worker');\n unregisterCorruptionDiagnostics();\n unregisterCorruptionDiagnosticTargets.push(\n registerSQLiteCorruptionDiagnosticTarget({\n debugName: 'write-worker',\n dbPath,\n }),\n );\n try {\n db = new Database(lc, dbPath);\n applyPragmas(db, pragmas);\n runner = new StatementRunner(db);\n mode = cpMode;\n checkpointerConfig = checkpointConfig ?? undefined;\n createProcessor();\n createCheckpointer();\n } catch (e) {\n handleCorruptedDb(e);\n throw e;\n }\n },\n\n getSubscriptionState() {\n try {\n return getSubscriptionState(must(runner));\n } catch (e) {\n handleCorruptedDb(e);\n throw e;\n }\n },\n\n async processMessage(downstream: ChangeStreamData) {\n try {\n const committed = must(processor).processMessage(must(lc), downstream);\n if (committed && checkpointer) {\n await checkpointer.maybeCheckpoint();\n }\n return committed;\n } catch (e) {\n handleCorruptedDb(e);\n throw e;\n }\n },\n\n abort() {\n must(processor).abort(must(lc));\n checkpointer?.close();\n createProcessor();\n createCheckpointer();\n },\n\n stop() {\n checkpointer?.close();\n checkpointer = undefined;\n db?.close();\n db = undefined;\n runner = undefined;\n processor = undefined;\n replicaDbPath = undefined;\n unregisterCorruptionDiagnostics();\n },\n };\n}\n\nconst api = createAPI();\n\nport.on('message', async (msg: Request) => {\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- TS can't narrow msg.method + msg.args together\n const result = await (api[msg.method] as (...args: any[]) => unknown)(\n ...msg.args,\n );\n // abort is fire-and-forget — no pending slot on the client side.\n if (msg.method !== 'abort') {\n port.postMessage({method: msg.method, result} as Response);\n }\n } catch (e) {\n if (msg.method !== 'abort') {\n port.postMessage({\n method: msg.method,\n error: serializeError(e),\n } as Response);\n }\n }\n});\n"],"mappings":"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"}
@@ -2,9 +2,9 @@ import type { LogContext } from '@rocicorp/logger';
2
2
  import type { JSONObject } from '../../../../shared/src/bigint-json.ts';
3
3
  import { type JSONObject as SafeJSONObject } from '../../../../shared/src/json.ts';
4
4
  import type { ErroredQuery } from '../../../../zero-protocol/src/custom-queries.ts';
5
- import type { Downstream } from '../../../../zero-protocol/src/down.ts';
6
5
  import { type TransformFailedBody } from '../../../../zero-protocol/src/error.ts';
7
6
  import type { InspectDownBody } from '../../../../zero-protocol/src/inspect-down.ts';
7
+ import type { ViewSyncerDownstream } from '../../types/downstream.ts';
8
8
  import { type ShardID } from '../../types/shards.ts';
9
9
  import type { Subscription } from '../../types/subscription.ts';
10
10
  import { type CVRVersion, type DelQueryPatch, type NullableCVRVersion, type PutQueryPatch, type RowID } from './schema/types.ts';
@@ -33,6 +33,7 @@ export interface PokeHandler {
33
33
  }
34
34
  /** Wraps PokeHandlers for multiple clients in a single PokeHandler. */
35
35
  export declare function startPoke(clients: ClientHandler[], tentativeVersion: CVRVersion): PokeHandler;
36
+ export declare const POKE_PART_FLUSH_THRESHOLD_CHARS: number;
36
37
  /**
37
38
  * Handles a single `ViewSyncer` connection.
38
39
  */
@@ -40,7 +41,7 @@ export declare class ClientHandler {
40
41
  #private;
41
42
  readonly clientID: string;
42
43
  readonly wsID: string;
43
- constructor(lc: LogContext, clientGroupID: string, clientID: string, wsID: string, shard: ShardID, baseCookie: string | null, downstream: Subscription<Downstream>);
44
+ constructor(lc: LogContext, clientGroupID: string, clientID: string, wsID: string, shard: ShardID, baseCookie: string | null, downstream: Subscription<ViewSyncerDownstream>);
44
45
  version(): NullableCVRVersion;
45
46
  fail(e: unknown): void;
46
47
  close(reason: string): void;
@@ -1 +1 @@
1
- {"version":3,"file":"client-handler.d.ts","sourceRoot":"","sources":["../../../../../../zero-cache/src/services/view-syncer/client-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAEjD,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,uCAAuC,CAAC;AACtE,OAAO,EAEL,KAAK,UAAU,IAAI,cAAc,EAClC,MAAM,gCAAgC,CAAC;AAIxC,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,iDAAiD,CAAC;AAGlF,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,uCAAuC,CAAC;AACtE,OAAO,EAEL,KAAK,mBAAmB,EACzB,MAAM,wCAAwC,CAAC;AAChD,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,+CAA+C,CAAC;AAgBnF,OAAO,EAAiB,KAAK,OAAO,EAAC,MAAM,uBAAuB,CAAC;AACnE,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAKL,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,KAAK,KAAK,EACX,MAAM,mBAAmB,CAAC;AAE3B,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,KAAK,CAAC;IACZ,EAAE,EAAE,KAAK,CAAC;IACV,EAAE,EAAE,KAAK,CAAC;IACV,QAAQ,EAAE,UAAU,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,KAAK,CAAC;IACZ,EAAE,EAAE,KAAK,CAAC;IACV,EAAE,EAAE,KAAK,CAAC;CACX,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG,WAAW,GAAG,cAAc,CAAC;AACpD,MAAM,MAAM,WAAW,GAAG,aAAa,GAAG,aAAa,CAAC;AAExD,MAAM,MAAM,KAAK,GAAG,WAAW,GAAG,QAAQ,CAAC;AAE3C,MAAM,MAAM,cAAc,GAAG;IAC3B,KAAK,EAAE,KAAK,CAAC;IACb,SAAS,EAAE,UAAU,CAAC;CACvB,CAAC;AAEF,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACxB,GAAG,CAAC,YAAY,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9C;AAQD,uEAAuE;AACvE,wBAAgB,SAAS,CACvB,OAAO,EAAE,aAAa,EAAE,EACxB,gBAAgB,EAAE,UAAU,GAC3B,WAAW,CAiBb;AAMD;;GAEG;AACH,qBAAa,aAAa;;IAExB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBA8BpB,EAAE,EAAE,UAAU,EACd,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,OAAO,EACd,UAAU,EAAE,MAAM,GAAG,IAAI,EACzB,UAAU,EAAE,YAAY,CAAC,UAAU,CAAC;IAatC,OAAO,IAAI,kBAAkB;IAS7B,IAAI,CAAC,CAAC,EAAE,OAAO;IAQf,KAAK,CAAC,MAAM,EAAE,MAAM;IAKpB,SAAS,CAAC,gBAAgB,EAAE,UAAU,GAAG,WAAW;IA+J9C,iBAAiB,CACrB,EAAE,EAAE,UAAU,EACd,gBAAgB,EAAE,MAAM,EAAE,EAC1B,qBAAqB,EAAE,MAAM,EAAE;IAajC,mCAAmC,CAAC,MAAM,EAAE,YAAY,EAAE;IAI1D,6BAA6B,CAAC,KAAK,EAAE,mBAAmB;IAIxD,mBAAmB,CAAC,EAAE,EAAE,UAAU,EAAE,QAAQ,EAAE,eAAe,GAAG,IAAI;CA0BrE;AA0CD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,UAAU,GAAG,cAAc,CAkB9D"}
1
+ {"version":3,"file":"client-handler.d.ts","sourceRoot":"","sources":["../../../../../../zero-cache/src/services/view-syncer/client-handler.ts"],"names":[],"mappings":"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"}
@@ -62,8 +62,11 @@ var ClientHandler = class {
62
62
  version() {
63
63
  return this.#baseVersion;
64
64
  }
65
- async #push(msg) {
66
- const { result } = this.#downstream.push(msg);
65
+ async #push(msg, serialized) {
66
+ const { result } = this.#downstream.push({
67
+ message: msg,
68
+ serialized
69
+ });
67
70
  await result;
68
71
  }
69
72
  fail(e) {
@@ -94,6 +97,7 @@ var ClientHandler = class {
94
97
  let pokeStarted = false;
95
98
  let body;
96
99
  let partCount = 0;
100
+ let serializedRowsLength = 0;
97
101
  const ensureBody = async () => {
98
102
  if (!pokeStarted) {
99
103
  await this.#push(["pokeStart", pokeStart]);
@@ -103,33 +107,29 @@ var ClientHandler = class {
103
107
  };
104
108
  const flushBody = async () => {
105
109
  if (body) {
106
- await this.#push(["pokePart", body]);
110
+ const message = ["pokePart", body];
111
+ await this.#push(message, JSON.stringify(message));
107
112
  body = void 0;
108
113
  partCount = 0;
114
+ serializedRowsLength = 0;
109
115
  }
110
116
  };
111
117
  const addPatch = async (patchToVersion) => {
112
118
  const { patch, toVersion } = patchToVersion;
113
119
  if (cmpVersions(toVersion, this.#baseVersion) <= 0) return;
114
- const body = await ensureBody();
120
+ const target = await ensureBody();
115
121
  const { type, op } = patch;
116
122
  switch (type) {
117
- case "query": {
118
- const patches = patch.clientID ? (body.desiredQueriesPatches ??= {})[patch.clientID] ??= [] : body.gotQueriesPatch ??= [];
119
- if (op === "put") patches.push({
120
- op,
121
- hash: patch.id
122
- });
123
- else patches.push({
123
+ case "query":
124
+ (patch.clientID ? (target.desiredQueriesPatches ??= {})[patch.clientID] ??= [] : target.gotQueriesPatch ??= []).push({
124
125
  op,
125
126
  hash: patch.id
126
127
  });
127
128
  break;
128
- }
129
129
  case "row":
130
- if (patch.id.table === this.#zeroClientsTable) this.#updateLMIDs(body.lastMutationIDChanges ??= {}, patch);
130
+ if (patch.id.table === this.#zeroClientsTable) this.#updateLMIDs(target.lastMutationIDChanges ??= {}, patch);
131
131
  else if (patch.id.table === this.#zeroMutationsTable) {
132
- const patches = body.mutationsPatch ??= [];
132
+ const patches = target.mutationsPatch ??= [];
133
133
  if (op === "put") {
134
134
  const row = parse(ensureSafeJSON(patch.contents), mutationRowSchema, "passthrough");
135
135
  patches.push({
@@ -155,11 +155,16 @@ var ClientHandler = class {
155
155
  }
156
156
  });
157
157
  }
158
- } else (body.rowsPatch ??= []).push(makeRowPatch(patch));
158
+ } else {
159
+ const rowPatch = makeRowPatch(patch);
160
+ (target.rowsPatch ??= []).push(rowPatch);
161
+ serializedRowsLength += JSON.stringify(rowPatch).length;
162
+ }
159
163
  break;
160
164
  default: unreachable(patch);
161
165
  }
162
- if (++partCount >= PART_COUNT_FLUSH_THRESHOLD) await flushBody();
166
+ partCount++;
167
+ if (serializedRowsLength >= 1048576 || partCount >= PART_COUNT_FLUSH_THRESHOLD) await flushBody();
163
168
  };
164
169
  return {
165
170
  addPatch: async (patchToVersion) => {
@@ -211,7 +216,10 @@ var ClientHandler = class {
211
216
  }
212
217
  sendInspectResponse(lc, response) {
213
218
  lc.debug?.("sending inspect response", response);
214
- this.#downstream.push(["inspect", response]);
219
+ this.#downstream.push({
220
+ message: ["inspect", response],
221
+ serialized: void 0
222
+ });
215
223
  }
216
224
  #updateLMIDs(lmids, patch) {
217
225
  if (patch.op === "put") {
@@ -1 +1 @@
1
- {"version":3,"file":"client-handler.js","names":["#clientGroupID","#zeroClientsTable","#zeroMutationsTable","#lc","#downstream","#pokeTime","#pokeTransactions","#pokedRows","#baseVersion","#push","#everPoked","#updateLMIDs"],"sources":["../../../../../../zero-cache/src/services/view-syncer/client-handler.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {assert, unreachable} from '../../../../shared/src/asserts.ts';\nimport type {JSONObject} from '../../../../shared/src/bigint-json.ts';\nimport {\n assertJSONValue,\n type JSONObject as SafeJSONObject,\n} from '../../../../shared/src/json.ts';\nimport {promiseVoid} from '../../../../shared/src/resolved-promises.ts';\nimport * as v from '../../../../shared/src/valita.ts';\nimport type {Writable} from '../../../../shared/src/writable.ts';\nimport type {ErroredQuery} from '../../../../zero-protocol/src/custom-queries.ts';\nimport {rowSchema} from '../../../../zero-protocol/src/data.ts';\nimport type {DeleteClientsBody} from '../../../../zero-protocol/src/delete-clients.ts';\nimport type {Downstream} from '../../../../zero-protocol/src/down.ts';\nimport {\n ProtocolError,\n type TransformFailedBody,\n} from '../../../../zero-protocol/src/error.ts';\nimport type {InspectDownBody} from '../../../../zero-protocol/src/inspect-down.ts';\nimport {mutationResultSchema} from '../../../../zero-protocol/src/mutation.ts';\nimport type {\n PokePartBody,\n PokeStartBody,\n} from '../../../../zero-protocol/src/poke.ts';\nimport {primaryKeyValueRecordSchema} from '../../../../zero-protocol/src/primary-key.ts';\nimport type {RowPatchOp} from '../../../../zero-protocol/src/row-patch.ts';\nimport {\n getOrCreateCounter,\n getOrCreateLatencyHistogram,\n} from '../../observability/metrics.ts';\nimport {\n getLogLevel,\n wrapWithProtocolError,\n} from '../../types/error-with-level.ts';\nimport {upstreamSchema, type ShardID} from '../../types/shards.ts';\nimport type {Subscription} from '../../types/subscription.ts';\nimport {\n cmpVersions,\n cookieToVersion,\n versionToCookie,\n versionToNullableCookie,\n type CVRVersion,\n type DelQueryPatch,\n type NullableCVRVersion,\n type PutQueryPatch,\n type RowID,\n} from './schema/types.ts';\n\nexport type PutRowPatch = {\n type: 'row';\n op: 'put';\n id: RowID;\n contents: JSONObject;\n};\n\nexport type DeleteRowPatch = {\n type: 'row';\n op: 'del';\n id: RowID;\n};\n\nexport type RowPatch = PutRowPatch | DeleteRowPatch;\nexport type ConfigPatch = DelQueryPatch | PutQueryPatch;\n\nexport type Patch = ConfigPatch | RowPatch;\n\nexport type PatchToVersion = {\n patch: Patch;\n toVersion: CVRVersion;\n};\n\nexport interface PokeHandler {\n addPatch(patch: PatchToVersion): Promise<void>;\n cancel(): Promise<void>;\n end(finalVersion: CVRVersion): Promise<void>;\n}\n\nconst NOOP: PokeHandler = {\n addPatch: () => promiseVoid,\n cancel: () => promiseVoid,\n end: () => promiseVoid,\n};\n\n/** Wraps PokeHandlers for multiple clients in a single PokeHandler. */\nexport function startPoke(\n clients: ClientHandler[],\n tentativeVersion: CVRVersion,\n): PokeHandler {\n const pokers = clients.map(c => c.startPoke(tentativeVersion));\n\n // Promise.allSettled() ensures that a failed (e.g. disconnected) client\n // does not prevent other clients from receiving the pokes. However, the\n // rate (per client group) will be limited by the slowest connection.\n return {\n addPatch: async patch => {\n await Promise.allSettled(pokers.map(poker => poker.addPatch(patch)));\n },\n cancel: async () => {\n await Promise.allSettled(pokers.map(poker => poker.cancel()));\n },\n end: async finalVersion => {\n await Promise.allSettled(pokers.map(poker => poker.end(finalVersion)));\n },\n };\n}\n\n// Semi-arbitrary threshold at which poke body parts are flushed.\n// When row size is being computed, that should be used as a threshold instead.\nconst PART_COUNT_FLUSH_THRESHOLD = 100;\n\n/**\n * Handles a single `ViewSyncer` connection.\n */\nexport class ClientHandler {\n readonly #clientGroupID: string;\n readonly clientID: string;\n readonly wsID: string;\n readonly #zeroClientsTable: string;\n readonly #zeroMutationsTable: string;\n readonly #lc: LogContext;\n readonly #downstream: Subscription<Downstream>;\n #baseVersion: NullableCVRVersion;\n // We will send a poke on connect even if the client is already caught up, so that it can learn its\n // got-queries state has been reconciled with the server. After that, we will only send a poke if\n // the client is behind.\n #everPoked = false;\n\n readonly #pokeTime = getOrCreateLatencyHistogram(\n 'sync',\n 'poke.time',\n 'Time elapsed for each poke transaction. Canceled / noop pokes are excluded.',\n );\n\n readonly #pokeTransactions = getOrCreateCounter(\n 'sync',\n 'poke.transactions',\n 'Count of poke transactions.',\n );\n\n readonly #pokedRows = getOrCreateCounter(\n 'sync',\n 'poke.rows',\n 'Count of poked rows.',\n );\n\n constructor(\n lc: LogContext,\n clientGroupID: string,\n clientID: string,\n wsID: string,\n shard: ShardID,\n baseCookie: string | null,\n downstream: Subscription<Downstream>,\n ) {\n lc.debug?.('new client handler');\n this.#clientGroupID = clientGroupID;\n this.clientID = clientID;\n this.wsID = wsID;\n this.#zeroClientsTable = `${upstreamSchema(shard)}.clients`;\n this.#zeroMutationsTable = `${upstreamSchema(shard)}.mutations`;\n this.#lc = lc;\n this.#downstream = downstream;\n this.#baseVersion = cookieToVersion(baseCookie);\n }\n\n version(): NullableCVRVersion {\n return this.#baseVersion;\n }\n\n async #push(msg: Downstream): Promise<void> {\n const {result} = this.#downstream.push(msg);\n await result;\n }\n\n fail(e: unknown) {\n this.#lc[getLogLevel(e)]?.(\n `view-syncer closing connection with error: ${String(e)}`,\n e,\n );\n this.#downstream.fail(wrapWithProtocolError(e));\n }\n\n close(reason: string) {\n this.#lc.debug?.(`view-syncer closing connection: ${reason}`);\n this.#downstream.cancel();\n }\n\n startPoke(tentativeVersion: CVRVersion): PokeHandler {\n const pokeID = versionToCookie(tentativeVersion);\n const lc = this.#lc.withContext('pokeID', pokeID);\n\n // Force an (empty) initial poke even when already caught up; see #everPoked.\n const forceInitialPoke = !this.#everPoked;\n const cmp = cmpVersions(this.#baseVersion, tentativeVersion);\n if (cmp > 0 || (cmp === 0 && !forceInitialPoke)) {\n lc.info?.(`already caught up, not sending poke.`);\n return NOOP;\n }\n\n const baseCookie = versionToNullableCookie(this.#baseVersion);\n const cookie = versionToCookie(tentativeVersion);\n lc.debug?.(`starting poke from ${baseCookie} to ${cookie}`);\n\n const start = performance.now();\n\n const pokeStart: PokeStartBody = {pokeID, baseCookie};\n\n let pokeStarted = false;\n let body: PokePartBody | undefined;\n let partCount = 0;\n const ensureBody = async () => {\n if (!pokeStarted) {\n await this.#push(['pokeStart', pokeStart]);\n pokeStarted = true;\n }\n return (body ??= {pokeID});\n };\n const flushBody = async () => {\n if (body) {\n await this.#push(['pokePart', body]);\n body = undefined;\n partCount = 0;\n }\n };\n\n const addPatch = async (patchToVersion: PatchToVersion) => {\n const {patch, toVersion} = patchToVersion;\n if (cmpVersions(toVersion, this.#baseVersion) <= 0) {\n return;\n }\n const body = await ensureBody();\n\n const {type, op} = patch;\n switch (type) {\n case 'query': {\n const patches = patch.clientID\n ? ((body.desiredQueriesPatches ??= {})[patch.clientID] ??= [])\n : (body.gotQueriesPatch ??= []);\n if (op === 'put') {\n patches.push({op, hash: patch.id});\n } else {\n patches.push({op, hash: patch.id});\n }\n break;\n }\n case 'row':\n if (patch.id.table === this.#zeroClientsTable) {\n this.#updateLMIDs((body.lastMutationIDChanges ??= {}), patch);\n } else if (patch.id.table === this.#zeroMutationsTable) {\n const patches = (body.mutationsPatch ??= []);\n if (op === 'put') {\n const row = v.parse(\n ensureSafeJSON(patch.contents),\n mutationRowSchema,\n 'passthrough',\n );\n patches.push({\n op: 'put',\n mutation: {\n id: {\n clientID: row.clientID,\n id: row.mutationID,\n },\n result: row.result,\n },\n });\n } else {\n const {clientID, mutationID} = patch.id.rowKey;\n assert(\n typeof clientID === 'string',\n 'client id must be a string',\n );\n const id = Number(mutationID);\n assert(\n !Number.isNaN(id) && Number.isFinite(id) && id >= 0,\n 'mutation id must be a finite number',\n );\n patches.push({\n op: 'del',\n id: {\n clientID,\n id,\n },\n });\n }\n } else {\n (body.rowsPatch ??= []).push(makeRowPatch(patch));\n }\n break;\n default:\n unreachable(patch);\n }\n\n if (++partCount >= PART_COUNT_FLUSH_THRESHOLD) {\n await flushBody();\n }\n };\n\n return {\n addPatch: async (patchToVersion: PatchToVersion) => {\n try {\n await addPatch(patchToVersion);\n if (patchToVersion.patch.type === 'row') {\n this.#pokedRows.add(1);\n }\n } catch (e) {\n this.#downstream.fail(wrapWithProtocolError(e));\n }\n },\n\n cancel: async () => {\n if (pokeStarted) {\n await this.#push(['pokeEnd', {pokeID, cookie: '', cancel: true}]);\n }\n },\n\n end: async (finalVersion: CVRVersion) => {\n const cookie = versionToCookie(finalVersion);\n if (!pokeStarted) {\n if (\n cmpVersions(this.#baseVersion, finalVersion) === 0 &&\n !forceInitialPoke\n ) {\n return; // Nothing changed and nothing was sent.\n }\n await this.#push(['pokeStart', pokeStart]);\n } else if (cmpVersions(this.#baseVersion, finalVersion) >= 0) {\n // Sanity check: If the poke was started, the finalVersion\n // must be > #baseVersion.\n throw new Error(\n `Patches were sent but finalVersion ${finalVersion} is ` +\n `not greater than baseVersion ${this.#baseVersion}`,\n );\n }\n await flushBody();\n await this.#push(['pokeEnd', {pokeID, cookie}]);\n this.#baseVersion = finalVersion;\n this.#everPoked = true;\n\n const elapsed = performance.now() - start;\n this.#pokeTransactions.add(1);\n this.#pokeTime.recordMs(elapsed);\n },\n };\n }\n\n async sendDeleteClients(\n lc: LogContext,\n deletedClientIDs: string[],\n deletedClientGroupIDs: string[],\n ) {\n const deleteClientsBody: Writable<DeleteClientsBody> = {};\n if (deletedClientIDs.length > 0) {\n deleteClientsBody.clientIDs = deletedClientIDs;\n }\n if (deletedClientGroupIDs.length > 0) {\n deleteClientsBody.clientGroupIDs = deletedClientGroupIDs;\n }\n lc.debug?.('sending deleteClients', deleteClientsBody);\n await this.#push(['deleteClients', deleteClientsBody]);\n }\n\n sendQueryTransformApplicationErrors(errors: ErroredQuery[]) {\n void this.#push(['transformError', errors]);\n }\n\n sendQueryTransformFailedError(error: TransformFailedBody) {\n this.fail(new ProtocolError(error));\n }\n\n sendInspectResponse(lc: LogContext, response: InspectDownBody): void {\n lc.debug?.('sending inspect response', response);\n this.#downstream.push(['inspect', response]);\n }\n\n #updateLMIDs(lmids: Record<string, number>, patch: RowPatch) {\n if (patch.op === 'put') {\n const row = ensureSafeJSON(patch.contents);\n const {clientGroupID, clientID, lastMutationID} = v.parse(\n row,\n lmidRowSchema,\n 'passthrough',\n );\n if (clientGroupID !== this.#clientGroupID) {\n this.#lc.error?.(\n `Received clients row for wrong clientGroupID. Ignoring.`,\n clientGroupID,\n );\n } else {\n lmids[clientID] = lastMutationID;\n }\n } else {\n // The 'constrain' and 'del' ops for clients can be ignored.\n patch.op satisfies 'constrain' | 'del';\n }\n }\n}\n\n// Note: The {APP_ID}_{SHARD_ID}.clients table is set up in replicator/initial-sync.ts.\nconst lmidRowSchema = v.object({\n clientGroupID: v.string(),\n clientID: v.string(),\n lastMutationID: v.number(), // Actually returned as a bigint, but converted by ensureSafeJSON().\n});\n\nconst mutationRowSchema = v.object({\n clientGroupID: v.string(),\n clientID: v.string(),\n mutationID: v.number(),\n result: mutationResultSchema,\n});\n\nfunction makeRowPatch(patch: RowPatch): RowPatchOp {\n const {\n op,\n id: {table: tableName, rowKey: id},\n } = patch;\n\n switch (op) {\n case 'put':\n return {\n op: 'put',\n tableName,\n value: v.parse(ensureSafeJSON(patch.contents), rowSchema),\n };\n\n case 'del':\n return {\n op,\n tableName,\n id: v.parse(id, primaryKeyValueRecordSchema),\n };\n\n default:\n unreachable(op);\n }\n}\n\n/**\n * Column values of type INT8 are returned as the `bigint` from the\n * Postgres library. These are converted to `number` if they are within\n * the safe Number range, allowing the protocol to support numbers larger\n * than 32-bits. Values outside of the safe number range (e.g. > 2^53) will\n * result in an Error.\n */\nexport function ensureSafeJSON(row: JSONObject): SafeJSONObject {\n const modified = Object.entries(row)\n .filter(([k, v]) => {\n if (typeof v === 'bigint') {\n if (v >= Number.MIN_SAFE_INTEGER && v <= Number.MAX_SAFE_INTEGER) {\n return true; // send this entry onto the next map() step.\n }\n throw new Error(`Value of \"${k}\" exceeds safe Number range (${v})`);\n } else if (typeof v === 'object') {\n assertJSONValue(v);\n }\n return false;\n })\n .map(([k, v]) => [k, Number(v)]);\n\n return modified.length\n ? {...row, ...Object.fromEntries(modified)}\n : (row as SafeJSONObject);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"client-handler.js","names":["#clientGroupID","#zeroClientsTable","#zeroMutationsTable","#lc","#downstream","#pokeTime","#pokeTransactions","#pokedRows","#baseVersion","#push","#everPoked","#updateLMIDs"],"sources":["../../../../../../zero-cache/src/services/view-syncer/client-handler.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {assert, unreachable} from '../../../../shared/src/asserts.ts';\nimport type {JSONObject} from '../../../../shared/src/bigint-json.ts';\nimport {\n assertJSONValue,\n type JSONObject as SafeJSONObject,\n} from '../../../../shared/src/json.ts';\nimport {promiseVoid} from '../../../../shared/src/resolved-promises.ts';\nimport * as v from '../../../../shared/src/valita.ts';\nimport type {Writable} from '../../../../shared/src/writable.ts';\nimport type {ErroredQuery} from '../../../../zero-protocol/src/custom-queries.ts';\nimport {rowSchema} from '../../../../zero-protocol/src/data.ts';\nimport type {DeleteClientsBody} from '../../../../zero-protocol/src/delete-clients.ts';\nimport type {Downstream} from '../../../../zero-protocol/src/down.ts';\nimport {\n ProtocolError,\n type TransformFailedBody,\n} from '../../../../zero-protocol/src/error.ts';\nimport type {InspectDownBody} from '../../../../zero-protocol/src/inspect-down.ts';\nimport {mutationResultSchema} from '../../../../zero-protocol/src/mutation.ts';\nimport type {\n PokePartBody,\n PokePartMessage,\n PokeStartBody,\n} from '../../../../zero-protocol/src/poke.ts';\nimport {primaryKeyValueRecordSchema} from '../../../../zero-protocol/src/primary-key.ts';\nimport type {RowPatchOp} from '../../../../zero-protocol/src/row-patch.ts';\nimport {\n getOrCreateCounter,\n getOrCreateLatencyHistogram,\n} from '../../observability/metrics.ts';\nimport type {ViewSyncerDownstream} from '../../types/downstream.ts';\nimport {\n getLogLevel,\n wrapWithProtocolError,\n} from '../../types/error-with-level.ts';\nimport {upstreamSchema, type ShardID} from '../../types/shards.ts';\nimport type {Subscription} from '../../types/subscription.ts';\nimport {\n cmpVersions,\n cookieToVersion,\n versionToCookie,\n versionToNullableCookie,\n type CVRVersion,\n type DelQueryPatch,\n type NullableCVRVersion,\n type PutQueryPatch,\n type RowID,\n} from './schema/types.ts';\n\nexport type PutRowPatch = {\n type: 'row';\n op: 'put';\n id: RowID;\n contents: JSONObject;\n};\n\nexport type DeleteRowPatch = {\n type: 'row';\n op: 'del';\n id: RowID;\n};\n\nexport type RowPatch = PutRowPatch | DeleteRowPatch;\nexport type ConfigPatch = DelQueryPatch | PutQueryPatch;\n\nexport type Patch = ConfigPatch | RowPatch;\n\nexport type PatchToVersion = {\n patch: Patch;\n toVersion: CVRVersion;\n};\n\nexport interface PokeHandler {\n addPatch(patch: PatchToVersion): Promise<void>;\n cancel(): Promise<void>;\n end(finalVersion: CVRVersion): Promise<void>;\n}\n\nconst NOOP: PokeHandler = {\n addPatch: () => promiseVoid,\n cancel: () => promiseVoid,\n end: () => promiseVoid,\n};\n\n/** Wraps PokeHandlers for multiple clients in a single PokeHandler. */\nexport function startPoke(\n clients: ClientHandler[],\n tentativeVersion: CVRVersion,\n): PokeHandler {\n const pokers = clients.map(c => c.startPoke(tentativeVersion));\n\n // Promise.allSettled() ensures that a failed (e.g. disconnected) client\n // does not prevent other clients from receiving the pokes. However, the\n // rate (per client group) will be limited by the slowest connection.\n return {\n addPatch: async patch => {\n await Promise.allSettled(pokers.map(poker => poker.addPatch(patch)));\n },\n cancel: async () => {\n await Promise.allSettled(pokers.map(poker => poker.cancel()));\n },\n end: async finalVersion => {\n await Promise.allSettled(pokers.map(poker => poker.end(finalVersion)));\n },\n };\n}\n\n// Soft limit on the serialized row characters accumulated in a poke part.\n// This bounds view-syncer memory and keeps legacy JSON messages reasonably\n// sized. PokeChunkEncoder separately enforces the binary frame limit in bytes.\nexport const POKE_PART_FLUSH_THRESHOLD_CHARS = 1024 * 1024;\nconst PART_COUNT_FLUSH_THRESHOLD = 100;\n\n/**\n * Handles a single `ViewSyncer` connection.\n */\nexport class ClientHandler {\n readonly #clientGroupID: string;\n readonly clientID: string;\n readonly wsID: string;\n readonly #zeroClientsTable: string;\n readonly #zeroMutationsTable: string;\n readonly #lc: LogContext;\n readonly #downstream: Subscription<ViewSyncerDownstream>;\n #baseVersion: NullableCVRVersion;\n // We will send a poke on connect even if the client is already caught up, so that it can learn its\n // got-queries state has been reconciled with the server. After that, we will only send a poke if\n // the client is behind.\n #everPoked = false;\n\n readonly #pokeTime = getOrCreateLatencyHistogram(\n 'sync',\n 'poke.time',\n 'Time elapsed for each poke transaction. Canceled / noop pokes are excluded.',\n );\n\n readonly #pokeTransactions = getOrCreateCounter(\n 'sync',\n 'poke.transactions',\n 'Count of poke transactions.',\n );\n\n readonly #pokedRows = getOrCreateCounter(\n 'sync',\n 'poke.rows',\n 'Count of poked rows.',\n );\n\n constructor(\n lc: LogContext,\n clientGroupID: string,\n clientID: string,\n wsID: string,\n shard: ShardID,\n baseCookie: string | null,\n downstream: Subscription<ViewSyncerDownstream>,\n ) {\n lc.debug?.('new client handler');\n this.#clientGroupID = clientGroupID;\n this.clientID = clientID;\n this.wsID = wsID;\n this.#zeroClientsTable = `${upstreamSchema(shard)}.clients`;\n this.#zeroMutationsTable = `${upstreamSchema(shard)}.mutations`;\n this.#lc = lc;\n this.#downstream = downstream;\n this.#baseVersion = cookieToVersion(baseCookie);\n }\n\n version(): NullableCVRVersion {\n return this.#baseVersion;\n }\n\n async #push(msg: Downstream, serialized?: string | undefined): Promise<void> {\n const {result} = this.#downstream.push({message: msg, serialized});\n await result;\n }\n\n fail(e: unknown) {\n this.#lc[getLogLevel(e)]?.(\n `view-syncer closing connection with error: ${String(e)}`,\n e,\n );\n this.#downstream.fail(wrapWithProtocolError(e));\n }\n\n close(reason: string) {\n this.#lc.debug?.(`view-syncer closing connection: ${reason}`);\n this.#downstream.cancel();\n }\n\n startPoke(tentativeVersion: CVRVersion): PokeHandler {\n const pokeID = versionToCookie(tentativeVersion);\n const lc = this.#lc.withContext('pokeID', pokeID);\n\n // Force an (empty) initial poke even when already caught up; see #everPoked.\n const forceInitialPoke = !this.#everPoked;\n const cmp = cmpVersions(this.#baseVersion, tentativeVersion);\n if (cmp > 0 || (cmp === 0 && !forceInitialPoke)) {\n lc.info?.(`already caught up, not sending poke.`);\n return NOOP;\n }\n\n const baseCookie = versionToNullableCookie(this.#baseVersion);\n const cookie = versionToCookie(tentativeVersion);\n lc.debug?.(`starting poke from ${baseCookie} to ${cookie}`);\n\n const start = performance.now();\n\n const pokeStart: PokeStartBody = {pokeID, baseCookie};\n\n let pokeStarted = false;\n let body: PokePartBody | undefined;\n let partCount = 0;\n let serializedRowsLength = 0;\n\n const ensureBody = async () => {\n if (!pokeStarted) {\n await this.#push(['pokeStart', pokeStart]);\n pokeStarted = true;\n }\n return (body ??= {pokeID});\n };\n\n const flushBody = async () => {\n if (body) {\n const message = ['pokePart', body] satisfies PokePartMessage;\n await this.#push(message, JSON.stringify(message));\n body = undefined;\n partCount = 0;\n serializedRowsLength = 0;\n }\n };\n\n const addPatch = async (patchToVersion: PatchToVersion) => {\n const {patch, toVersion} = patchToVersion;\n if (cmpVersions(toVersion, this.#baseVersion) <= 0) {\n return;\n }\n const target = await ensureBody();\n\n const {type, op} = patch;\n switch (type) {\n case 'query': {\n const patches = patch.clientID\n ? ((target.desiredQueriesPatches ??= {})[patch.clientID] ??= [])\n : (target.gotQueriesPatch ??= []);\n patches.push({op, hash: patch.id});\n break;\n }\n case 'row':\n if (patch.id.table === this.#zeroClientsTable) {\n this.#updateLMIDs((target.lastMutationIDChanges ??= {}), patch);\n } else if (patch.id.table === this.#zeroMutationsTable) {\n const patches = (target.mutationsPatch ??= []);\n if (op === 'put') {\n const row = v.parse(\n ensureSafeJSON(patch.contents),\n mutationRowSchema,\n 'passthrough',\n );\n patches.push({\n op: 'put',\n mutation: {\n id: {\n clientID: row.clientID,\n id: row.mutationID,\n },\n result: row.result,\n },\n });\n } else {\n const {clientID, mutationID} = patch.id.rowKey;\n assert(\n typeof clientID === 'string',\n 'client id must be a string',\n );\n const id = Number(mutationID);\n assert(\n !Number.isNaN(id) && Number.isFinite(id) && id >= 0,\n 'mutation id must be a finite number',\n );\n patches.push({\n op: 'del',\n id: {\n clientID,\n id,\n },\n });\n }\n } else {\n const rowPatch = makeRowPatch(patch);\n (target.rowsPatch ??= []).push(rowPatch);\n serializedRowsLength += JSON.stringify(rowPatch).length;\n }\n break;\n default:\n unreachable(patch);\n }\n\n partCount++;\n if (\n serializedRowsLength >= POKE_PART_FLUSH_THRESHOLD_CHARS ||\n partCount >= PART_COUNT_FLUSH_THRESHOLD\n ) {\n await flushBody();\n }\n };\n\n return {\n addPatch: async (patchToVersion: PatchToVersion) => {\n try {\n await addPatch(patchToVersion);\n if (patchToVersion.patch.type === 'row') {\n this.#pokedRows.add(1);\n }\n } catch (e) {\n this.#downstream.fail(wrapWithProtocolError(e));\n }\n },\n\n cancel: async () => {\n if (pokeStarted) {\n await this.#push(['pokeEnd', {pokeID, cookie: '', cancel: true}]);\n }\n },\n\n end: async (finalVersion: CVRVersion) => {\n const cookie = versionToCookie(finalVersion);\n if (!pokeStarted) {\n if (\n cmpVersions(this.#baseVersion, finalVersion) === 0 &&\n !forceInitialPoke\n ) {\n return; // Nothing changed and nothing was sent.\n }\n await this.#push(['pokeStart', pokeStart]);\n } else if (cmpVersions(this.#baseVersion, finalVersion) >= 0) {\n // Sanity check: If the poke was started, the finalVersion\n // must be > #baseVersion.\n throw new Error(\n `Patches were sent but finalVersion ${finalVersion} is ` +\n `not greater than baseVersion ${this.#baseVersion}`,\n );\n }\n await flushBody();\n await this.#push(['pokeEnd', {pokeID, cookie}]);\n this.#baseVersion = finalVersion;\n this.#everPoked = true;\n\n const elapsed = performance.now() - start;\n this.#pokeTransactions.add(1);\n this.#pokeTime.recordMs(elapsed);\n },\n };\n }\n\n async sendDeleteClients(\n lc: LogContext,\n deletedClientIDs: string[],\n deletedClientGroupIDs: string[],\n ) {\n const deleteClientsBody: Writable<DeleteClientsBody> = {};\n if (deletedClientIDs.length > 0) {\n deleteClientsBody.clientIDs = deletedClientIDs;\n }\n if (deletedClientGroupIDs.length > 0) {\n deleteClientsBody.clientGroupIDs = deletedClientGroupIDs;\n }\n lc.debug?.('sending deleteClients', deleteClientsBody);\n await this.#push(['deleteClients', deleteClientsBody]);\n }\n\n sendQueryTransformApplicationErrors(errors: ErroredQuery[]) {\n void this.#push(['transformError', errors]);\n }\n\n sendQueryTransformFailedError(error: TransformFailedBody) {\n this.fail(new ProtocolError(error));\n }\n\n sendInspectResponse(lc: LogContext, response: InspectDownBody): void {\n lc.debug?.('sending inspect response', response);\n this.#downstream.push({\n message: ['inspect', response],\n serialized: undefined,\n });\n }\n\n #updateLMIDs(lmids: Record<string, number>, patch: RowPatch) {\n if (patch.op === 'put') {\n const row = ensureSafeJSON(patch.contents);\n const {clientGroupID, clientID, lastMutationID} = v.parse(\n row,\n lmidRowSchema,\n 'passthrough',\n );\n if (clientGroupID !== this.#clientGroupID) {\n this.#lc.error?.(\n `Received clients row for wrong clientGroupID. Ignoring.`,\n clientGroupID,\n );\n } else {\n lmids[clientID] = lastMutationID;\n }\n } else {\n // The 'constrain' and 'del' ops for clients can be ignored.\n patch.op satisfies 'constrain' | 'del';\n }\n }\n}\n\n// Note: The {APP_ID}_{SHARD_ID}.clients table is set up in replicator/initial-sync.ts.\nconst lmidRowSchema = v.object({\n clientGroupID: v.string(),\n clientID: v.string(),\n lastMutationID: v.number(), // Actually returned as a bigint, but converted by ensureSafeJSON().\n});\n\nconst mutationRowSchema = v.object({\n clientGroupID: v.string(),\n clientID: v.string(),\n mutationID: v.number(),\n result: mutationResultSchema,\n});\n\nfunction makeRowPatch(patch: RowPatch): RowPatchOp {\n const {\n op,\n id: {table: tableName, rowKey: id},\n } = patch;\n\n switch (op) {\n case 'put':\n return {\n op: 'put',\n tableName,\n value: v.parse(ensureSafeJSON(patch.contents), rowSchema),\n };\n\n case 'del':\n return {\n op,\n tableName,\n id: v.parse(id, primaryKeyValueRecordSchema),\n };\n\n default:\n unreachable(op);\n }\n}\n\n/**\n * Column values of type INT8 are returned as the `bigint` from the\n * Postgres library. These are converted to `number` if they are within\n * the safe Number range, allowing the protocol to support numbers larger\n * than 32-bits. Values outside of the safe number range (e.g. > 2^53) will\n * result in an Error.\n */\nexport function ensureSafeJSON(row: JSONObject): SafeJSONObject {\n const modified = Object.entries(row)\n .filter(([k, v]) => {\n if (typeof v === 'bigint') {\n if (v >= Number.MIN_SAFE_INTEGER && v <= Number.MAX_SAFE_INTEGER) {\n return true; // send this entry onto the next map() step.\n }\n throw new Error(`Value of \"${k}\" exceeds safe Number range (${v})`);\n } else if (typeof v === 'object') {\n assertJSONValue(v);\n }\n return false;\n })\n .map(([k, v]) => [k, Number(v)]);\n\n return modified.length\n ? {...row, ...Object.fromEntries(modified)}\n : (row as SafeJSONObject);\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"cvr-store.d.ts","sourceRoot":"","sources":["../../../../../../zero-cache/src/services/view-syncer/cvr-store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cvr-store.d.ts","sourceRoot":"","sources":["../../../../../../zero-cache/src/services/view-syncer/cvr-store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAkBjD,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,+CAA+C,CAAC;AAUnF,OAAO,EAAC,sBAAsB,EAAC,MAAM,iCAAiC,CAAC;AACvE,OAAO,KAAK,EAAC,UAAU,EAAE,mBAAmB,EAAC,MAAM,mBAAmB,CAAC;AAEvE,OAAO,EAAY,KAAK,OAAO,EAAC,MAAM,uBAAuB,CAAC;AAC9D,OAAO,KAAK,EAAQ,cAAc,EAAC,MAAM,qBAAqB,CAAC;AAC/D,OAAO,KAAK,EAAC,GAAG,EAAE,WAAW,EAAC,MAAM,UAAU,CAAC;AAE/C,OAAO,EAKL,KAAK,OAAO,EACb,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAEL,KAAK,YAAY,EAGjB,KAAK,UAAU,EAGf,KAAK,kBAAkB,EACvB,KAAK,UAAU,EACf,KAAK,WAAW,EAEhB,KAAK,KAAK,EACV,KAAK,SAAS,EAGf,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,KAAK,QAAQ,EAGd,MAAM,gBAAgB,CAAC;AAExB,MAAM,MAAM,aAAa,GAAG;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAyGF,qBAAa,QAAQ;;gBAkDjB,EAAE,EAAE,UAAU,EACd,KAAK,EAAE,UAAU,EACjB,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,EACjC,qBAAqB,SAA2B,EAChD,eAAe,SAAoB,EACnC,yBAAyB,SAAM,EAAE,qBAAqB;IACtD,YAAY,oBAAa;IAmC3B,IAAI,CAAC,EAAE,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAsP3D,aAAa,IAAI,OAAO,CAAC,WAAW,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IAIvD,YAAY,CAAC,GAAG,EAAE,SAAS,GAAG,IAAI;IAIlC;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,EAAE,KAAK,GAAG,IAAI;IAI7B;;;;OAIG;IACH,YAAY,CAAC,GAAG,GAAG,EAAE,KAAK,EAAE;IAM5B;;;;OAIG;IACG,cAAc,CAAC,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAO3E;;;;;OAKG;IACG,WAAW,IAAI,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC;IAelD,WAAW,CAAC,EACV,OAAO,EACP,cAAc,EACd,UAAU,EACV,YAAY,EACZ,SAAS,EACT,QAAQ,GACT,EAAE,IAAI,CACL,WAAW,EACT,SAAS,GACT,gBAAgB,GAChB,YAAY,GACZ,cAAc,GACd,WAAW,GACX,UAAU,CACb,GAAG,IAAI;IAqBR,kBAAkB,CAAC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,GAAG,IAAI;IASrE,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI;IAelC,WAAW,CAAC,KAAK,EAAE,WAAW;IAc9B,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAIjE,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI;IAYxC,YAAY,CAAC,QAAQ,EAAE,MAAM;IAU7B,eAAe,CACb,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE;QAAC,EAAE,EAAE,MAAM,CAAA;KAAC,EACnB,MAAM,EAAE;QAAC,EAAE,EAAE,MAAM,CAAA;KAAC,EACpB,OAAO,EAAE,OAAO,EAChB,aAAa,EAAE,QAAQ,GAAG,SAAS,EACnC,GAAG,EAAE,MAAM,GACV,IAAI;IAkBP,iBAAiB,CACf,EAAE,EAAE,UAAU,EACd,YAAY,EAAE,kBAAkB,EAChC,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,UAAU,EACnB,kBAAkB,GAAE,MAAM,EAAO,GAChC,cAAc,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,CAAC;IAUvC,oBAAoB,CACxB,EAAE,EAAE,UAAU,EACd,YAAY,EAAE,kBAAkB,EAChC,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC,cAAc,EAAE,CAAC;IAsgB5B,IAAI,QAAQ,IAAI,MAAM,CAErB;IAEK,KAAK,CACT,EAAE,EAAE,UAAU,EACd,sBAAsB,EAAE,UAAU,EAClC,GAAG,EAAE,WAAW,EAChB,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IA2ChC,iBAAiB,IAAI,OAAO;IAI5B,qDAAqD;IACrD,OAAO,CAAC,EAAE,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhC,cAAc,CAClB,EAAE,EAAE,UAAU,EACd,QAAQ,EAAE,QAAQ,EAClB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,eAAe,EAAE,CAAC;CAsC9B;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAChC,EAAE,EAAE,mBAAmB,EACvB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,EACrB,sBAAsB,EAAE,UAAU,GACjC,OAAO,CAAC,IAAI,CAAC,CAUf;AAED,qBAAa,mBAAoB,SAAQ,sBAAsB;gBACjD,OAAO,EAAE,MAAM;CAU5B;AAED,qBAAa,+BAAgC,SAAQ,sBAAsB;IACzE,QAAQ,CAAC,IAAI,qCAAqC;gBAEtC,eAAe,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM;CAU3D;AAED,qBAAa,cAAe,SAAQ,sBAAsB;IACxD,QAAQ,CAAC,IAAI,oBAAoB;gBAG/B,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,eAAe,EAAE,MAAM;CAe1B;AAED,qBAAa,wBAAyB,SAAQ,sBAAsB;IAClE,QAAQ,CAAC,IAAI,8BAA8B;gBAE/B,KAAK,EAAE,OAAO;CAW3B;AAkBD,qBAAa,sBAAuB,SAAQ,KAAK;IAC/C,QAAQ,CAAC,IAAI,4BAA4B;IACzC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;gBAExB,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI;CAK3D"}
@@ -665,10 +665,23 @@ var CVRStore = class {
665
665
  async #checkVersionAndOwnership(lc, tx, expectedCurrentVersion, lastConnectTime) {
666
666
  const start = Date.now();
667
667
  lc.debug?.("checking cvr version and ownership");
668
+ const expected = versionString(expectedCurrentVersion);
669
+ if (expected === EMPTY_CVR_VERSION.stateVersion) await tx`
670
+ INSERT INTO ${this.#cvr("instances")} (
671
+ "clientGroupID",
672
+ "version",
673
+ "lastActive"
674
+ )
675
+ VALUES (
676
+ ${this.#id},
677
+ ${EMPTY_CVR_VERSION.stateVersion},
678
+ to_timestamp(0)
679
+ )
680
+ ON CONFLICT ("clientGroupID") DO NOTHING
681
+ `;
668
682
  const result = await tx`SELECT "version", "owner", "grantedAt" FROM ${this.#cvr("instances")}
669
683
  WHERE "clientGroupID" = ${this.#id}
670
684
  FOR UPDATE`;
671
- const expected = versionString(expectedCurrentVersion);
672
685
  const { version, owner, grantedAt } = result.length > 0 ? result[0] : {
673
686
  version: EMPTY_CVR_VERSION.stateVersion,
674
687
  owner: null,