@rocicorp/zero 1.11.0-canary.3 → 1.11.0-canary.30

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 (988) hide show
  1. package/out/analyze-query/src/analyze-cli.js +4 -4
  2. package/out/analyze-query/src/analyze-cli.js.map +1 -1
  3. package/out/analyze-query/src/bin-analyze.js +13 -12
  4. package/out/analyze-query/src/bin-analyze.js.map +1 -1
  5. package/out/analyze-query/src/bin-transform.js +1 -1
  6. package/out/analyze-query/src/bin-transform.js.map +1 -1
  7. package/out/ast-to-zql/src/ast-to-zql.d.ts +8 -1
  8. package/out/ast-to-zql/src/ast-to-zql.d.ts.map +1 -1
  9. package/out/ast-to-zql/src/ast-to-zql.js +25 -25
  10. package/out/ast-to-zql/src/ast-to-zql.js.map +1 -1
  11. package/out/otel/src/log-options.d.ts +16 -0
  12. package/out/otel/src/log-options.d.ts.map +1 -1
  13. package/out/otel/src/log-options.js +60 -6
  14. package/out/otel/src/log-options.js.map +1 -1
  15. package/out/replicache/src/bg-interval.d.ts +2 -1
  16. package/out/replicache/src/bg-interval.d.ts.map +1 -1
  17. package/out/replicache/src/bg-interval.js +13 -4
  18. package/out/replicache/src/bg-interval.js.map +1 -1
  19. package/out/replicache/src/btree/node.d.ts.map +1 -1
  20. package/out/replicache/src/btree/node.js +3 -6
  21. package/out/replicache/src/btree/node.js.map +1 -1
  22. package/out/replicache/src/dag/gc.d.ts.map +1 -1
  23. package/out/replicache/src/dag/gc.js +8 -11
  24. package/out/replicache/src/dag/gc.js.map +1 -1
  25. package/out/replicache/src/dag/invalid-ref-count-error.d.ts +12 -0
  26. package/out/replicache/src/dag/invalid-ref-count-error.d.ts.map +1 -0
  27. package/out/replicache/src/dag/invalid-ref-count-error.js +19 -0
  28. package/out/replicache/src/dag/invalid-ref-count-error.js.map +1 -0
  29. package/out/replicache/src/dag/lazy-store.d.ts +17 -4
  30. package/out/replicache/src/dag/lazy-store.d.ts.map +1 -1
  31. package/out/replicache/src/dag/lazy-store.js +35 -9
  32. package/out/replicache/src/dag/lazy-store.js.map +1 -1
  33. package/out/replicache/src/dag/store-impl.d.ts +12 -2
  34. package/out/replicache/src/dag/store-impl.d.ts.map +1 -1
  35. package/out/replicache/src/dag/store-impl.js +29 -9
  36. package/out/replicache/src/dag/store-impl.js.map +1 -1
  37. package/out/replicache/src/db/rebase.d.ts +14 -2
  38. package/out/replicache/src/db/rebase.d.ts.map +1 -1
  39. package/out/replicache/src/db/rebase.js +27 -5
  40. package/out/replicache/src/db/rebase.js.map +1 -1
  41. package/out/replicache/src/get-kv-store-provider.d.ts +1 -1
  42. package/out/replicache/src/get-kv-store-provider.d.ts.map +1 -1
  43. package/out/replicache/src/get-kv-store-provider.js +4 -4
  44. package/out/replicache/src/get-kv-store-provider.js.map +1 -1
  45. package/out/replicache/src/kv/expo-sqlite/store.d.ts.map +1 -1
  46. package/out/replicache/src/kv/expo-sqlite/store.js +28 -5
  47. package/out/replicache/src/kv/expo-sqlite/store.js.map +1 -1
  48. package/out/replicache/src/kv/idb-store.d.ts +18 -0
  49. package/out/replicache/src/kv/idb-store.d.ts.map +1 -1
  50. package/out/replicache/src/kv/idb-store.js +30 -2
  51. package/out/replicache/src/kv/idb-store.js.map +1 -1
  52. package/out/replicache/src/kv/mem-fallback-store.d.ts +54 -0
  53. package/out/replicache/src/kv/mem-fallback-store.d.ts.map +1 -0
  54. package/out/replicache/src/kv/mem-fallback-store.js +177 -0
  55. package/out/replicache/src/kv/mem-fallback-store.js.map +1 -0
  56. package/out/replicache/src/kv/mem-store.d.ts +1 -0
  57. package/out/replicache/src/kv/mem-store.d.ts.map +1 -1
  58. package/out/replicache/src/kv/mem-store.js +3 -0
  59. package/out/replicache/src/kv/mem-store.js.map +1 -1
  60. package/out/replicache/src/kv/op-sqlite/store.d.ts.map +1 -1
  61. package/out/replicache/src/kv/op-sqlite/store.js +4 -4
  62. package/out/replicache/src/kv/op-sqlite/store.js.map +1 -1
  63. package/out/replicache/src/kv/sqlite-store.d.ts +22 -1
  64. package/out/replicache/src/kv/sqlite-store.d.ts.map +1 -1
  65. package/out/replicache/src/kv/sqlite-store.js +159 -14
  66. package/out/replicache/src/kv/sqlite-store.js.map +1 -1
  67. package/out/replicache/src/kv/store.d.ts +6 -0
  68. package/out/replicache/src/kv/store.d.ts.map +1 -1
  69. package/out/replicache/src/new-client-channel.js.map +1 -1
  70. package/out/replicache/src/persist/client-gc.d.ts +2 -1
  71. package/out/replicache/src/persist/client-gc.d.ts.map +1 -1
  72. package/out/replicache/src/persist/client-gc.js +2 -2
  73. package/out/replicache/src/persist/client-gc.js.map +1 -1
  74. package/out/replicache/src/persist/client-group-gc.d.ts +2 -1
  75. package/out/replicache/src/persist/client-group-gc.d.ts.map +1 -1
  76. package/out/replicache/src/persist/client-group-gc.js +2 -2
  77. package/out/replicache/src/persist/client-group-gc.js.map +1 -1
  78. package/out/replicache/src/persist/clients.d.ts +2 -2
  79. package/out/replicache/src/persist/collect-idb-databases.d.ts +28 -8
  80. package/out/replicache/src/persist/collect-idb-databases.d.ts.map +1 -1
  81. package/out/replicache/src/persist/collect-idb-databases.js +97 -20
  82. package/out/replicache/src/persist/collect-idb-databases.js.map +1 -1
  83. package/out/replicache/src/persist/heartbeat.d.ts +2 -1
  84. package/out/replicache/src/persist/heartbeat.d.ts.map +1 -1
  85. package/out/replicache/src/persist/heartbeat.js +2 -2
  86. package/out/replicache/src/persist/heartbeat.js.map +1 -1
  87. package/out/replicache/src/persist/idb-databases-store-db-name.js +1 -1
  88. package/out/replicache/src/persist/idb-databases-store-db-name.js.map +1 -1
  89. package/out/replicache/src/persist/persist.d.ts.map +1 -1
  90. package/out/replicache/src/persist/persist.js +18 -8
  91. package/out/replicache/src/persist/persist.js.map +1 -1
  92. package/out/replicache/src/persist/refresh.js +6 -2
  93. package/out/replicache/src/persist/refresh.js.map +1 -1
  94. package/out/replicache/src/replicache-impl.d.ts +85 -3
  95. package/out/replicache/src/replicache-impl.d.ts.map +1 -1
  96. package/out/replicache/src/replicache-impl.js +321 -29
  97. package/out/replicache/src/replicache-impl.js.map +1 -1
  98. package/out/replicache/src/replicache-options.d.ts +9 -0
  99. package/out/replicache/src/replicache-options.d.ts.map +1 -1
  100. package/out/replicache/src/storage-failure.d.ts +37 -0
  101. package/out/replicache/src/storage-failure.d.ts.map +1 -0
  102. package/out/replicache/src/storage-failure.js +31 -0
  103. package/out/replicache/src/storage-failure.js.map +1 -0
  104. package/out/shared/src/arrays.d.ts +5 -0
  105. package/out/shared/src/arrays.d.ts.map +1 -1
  106. package/out/shared/src/arrays.js +8 -10
  107. package/out/shared/src/arrays.js.map +1 -1
  108. package/out/shared/src/base64.d.ts +19 -0
  109. package/out/shared/src/base64.d.ts.map +1 -0
  110. package/out/shared/src/base64.js +40 -0
  111. package/out/shared/src/base64.js.map +1 -0
  112. package/out/shared/src/centroid.d.ts +0 -1
  113. package/out/shared/src/centroid.d.ts.map +1 -1
  114. package/out/shared/src/centroid.js +1 -4
  115. package/out/shared/src/centroid.js.map +1 -1
  116. package/out/shared/src/error.d.ts +11 -0
  117. package/out/shared/src/error.d.ts.map +1 -1
  118. package/out/shared/src/error.js +35 -1
  119. package/out/shared/src/error.js.map +1 -1
  120. package/out/shared/src/hash.d.ts.map +1 -1
  121. package/out/shared/src/hash.js +32 -7
  122. package/out/shared/src/hash.js.map +1 -1
  123. package/out/shared/src/iterables.d.ts +2 -0
  124. package/out/shared/src/iterables.d.ts.map +1 -1
  125. package/out/shared/src/iterables.js +18 -1
  126. package/out/shared/src/iterables.js.map +1 -1
  127. package/out/shared/src/map.d.ts +24 -2
  128. package/out/shared/src/map.d.ts.map +1 -1
  129. package/out/shared/src/map.js +18 -4
  130. package/out/shared/src/map.js.map +1 -1
  131. package/out/shared/src/options-types.d.ts +2 -2
  132. package/out/shared/src/options.d.ts.map +1 -1
  133. package/out/shared/src/options.js +10 -7
  134. package/out/shared/src/options.js.map +1 -1
  135. package/out/shared/src/packed-boolean-map.d.ts +7 -0
  136. package/out/shared/src/packed-boolean-map.d.ts.map +1 -0
  137. package/out/shared/src/packed-boolean-map.js +36 -0
  138. package/out/shared/src/packed-boolean-map.js.map +1 -0
  139. package/out/shared/src/random-values.js +12 -1
  140. package/out/shared/src/random-values.js.map +1 -1
  141. package/out/shared/src/ring-buffer.d.ts +10 -0
  142. package/out/shared/src/ring-buffer.d.ts.map +1 -1
  143. package/out/shared/src/ring-buffer.js +26 -1
  144. package/out/shared/src/ring-buffer.js.map +1 -1
  145. package/out/shared/src/tdigest.d.ts +10 -0
  146. package/out/shared/src/tdigest.d.ts.map +1 -1
  147. package/out/shared/src/tdigest.js +147 -63
  148. package/out/shared/src/tdigest.js.map +1 -1
  149. package/out/shared/src/valita.d.ts +13 -0
  150. package/out/shared/src/valita.d.ts.map +1 -1
  151. package/out/shared/src/valita.js +23 -23
  152. package/out/shared/src/valita.js.map +1 -1
  153. package/out/z2s/src/compiler.d.ts.map +1 -1
  154. package/out/z2s/src/compiler.js +10 -6
  155. package/out/z2s/src/compiler.js.map +1 -1
  156. package/out/z2s/src/sql.d.ts.map +1 -1
  157. package/out/z2s/src/sql.js +9 -5
  158. package/out/z2s/src/sql.js.map +1 -1
  159. package/out/zero/package.js +4 -5
  160. package/out/zero/package.js.map +1 -1
  161. package/out/zero/src/zero.js +2 -1
  162. package/out/zero-cache/src/auth/write-authorizer.d.ts.map +1 -1
  163. package/out/zero-cache/src/auth/write-authorizer.js +1 -0
  164. package/out/zero-cache/src/auth/write-authorizer.js.map +1 -1
  165. package/out/zero-cache/src/config/normalize.d.ts +1 -0
  166. package/out/zero-cache/src/config/normalize.d.ts.map +1 -1
  167. package/out/zero-cache/src/config/normalize.js +46 -4
  168. package/out/zero-cache/src/config/normalize.js.map +1 -1
  169. package/out/zero-cache/src/config/zero-config.d.ts +116 -24
  170. package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
  171. package/out/zero-cache/src/config/zero-config.js +409 -157
  172. package/out/zero-cache/src/config/zero-config.js.map +1 -1
  173. package/out/zero-cache/src/custom/fetch.d.ts +1 -1
  174. package/out/zero-cache/src/custom/fetch.d.ts.map +1 -1
  175. package/out/zero-cache/src/custom/fetch.js.map +1 -1
  176. package/out/zero-cache/src/db/lite-tables.d.ts.map +1 -1
  177. package/out/zero-cache/src/db/lite-tables.js +3 -4
  178. package/out/zero-cache/src/db/lite-tables.js.map +1 -1
  179. package/out/zero-cache/src/db/migration-lite.d.ts.map +1 -1
  180. package/out/zero-cache/src/db/migration-lite.js +5 -3
  181. package/out/zero-cache/src/db/migration-lite.js.map +1 -1
  182. package/out/zero-cache/src/observability/events.js +4 -1
  183. package/out/zero-cache/src/observability/events.js.map +1 -1
  184. package/out/zero-cache/src/observability/log-throttle.d.ts +44 -0
  185. package/out/zero-cache/src/observability/log-throttle.d.ts.map +1 -0
  186. package/out/zero-cache/src/observability/log-throttle.js +76 -0
  187. package/out/zero-cache/src/observability/log-throttle.js.map +1 -0
  188. package/out/zero-cache/src/observability/metrics.d.ts.map +1 -1
  189. package/out/zero-cache/src/observability/metrics.js +2 -7
  190. package/out/zero-cache/src/observability/metrics.js.map +1 -1
  191. package/out/zero-cache/src/scripts/permissions.d.ts +16 -0
  192. package/out/zero-cache/src/scripts/permissions.d.ts.map +1 -1
  193. package/out/zero-cache/src/scripts/permissions.js +3 -3
  194. package/out/zero-cache/src/scripts/permissions.js.map +1 -1
  195. package/out/zero-cache/src/server/change-streamer.d.ts.map +1 -1
  196. package/out/zero-cache/src/server/change-streamer.js +117 -77
  197. package/out/zero-cache/src/server/change-streamer.js.map +1 -1
  198. package/out/zero-cache/src/server/inspector-delegate.d.ts +28 -2
  199. package/out/zero-cache/src/server/inspector-delegate.d.ts.map +1 -1
  200. package/out/zero-cache/src/server/inspector-delegate.js +37 -17
  201. package/out/zero-cache/src/server/inspector-delegate.js.map +1 -1
  202. package/out/zero-cache/src/server/main.d.ts.map +1 -1
  203. package/out/zero-cache/src/server/main.js +8 -1
  204. package/out/zero-cache/src/server/main.js.map +1 -1
  205. package/out/zero-cache/src/server/mutator.js +2 -0
  206. package/out/zero-cache/src/server/mutator.js.map +1 -1
  207. package/out/zero-cache/src/server/reaper.d.ts.map +1 -1
  208. package/out/zero-cache/src/server/reaper.js +2 -0
  209. package/out/zero-cache/src/server/reaper.js.map +1 -1
  210. package/out/zero-cache/src/server/replicator.d.ts +3 -0
  211. package/out/zero-cache/src/server/replicator.d.ts.map +1 -1
  212. package/out/zero-cache/src/server/replicator.js +95 -21
  213. package/out/zero-cache/src/server/replicator.js.map +1 -1
  214. package/out/zero-cache/src/server/runner/zero-dispatcher.d.ts.map +1 -1
  215. package/out/zero-cache/src/server/runner/zero-dispatcher.js +5 -0
  216. package/out/zero-cache/src/server/runner/zero-dispatcher.js.map +1 -1
  217. package/out/zero-cache/src/server/syncer-assigner.d.ts +14 -0
  218. package/out/zero-cache/src/server/syncer-assigner.d.ts.map +1 -0
  219. package/out/zero-cache/src/server/syncer-assigner.js +72 -0
  220. package/out/zero-cache/src/server/syncer-assigner.js.map +1 -0
  221. package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
  222. package/out/zero-cache/src/server/syncer.js +24 -2
  223. package/out/zero-cache/src/server/syncer.js.map +1 -1
  224. package/out/zero-cache/src/server/worker-dispatcher.d.ts.map +1 -1
  225. package/out/zero-cache/src/server/worker-dispatcher.js +21 -4
  226. package/out/zero-cache/src/server/worker-dispatcher.js.map +1 -1
  227. package/out/zero-cache/src/services/analyze.d.ts.map +1 -1
  228. package/out/zero-cache/src/services/analyze.js +11 -9
  229. package/out/zero-cache/src/services/analyze.js.map +1 -1
  230. package/out/zero-cache/src/services/change-source/common/backfill-manager.d.ts.map +1 -1
  231. package/out/zero-cache/src/services/change-source/common/backfill-manager.js +198 -24
  232. package/out/zero-cache/src/services/change-source/common/backfill-manager.js.map +1 -1
  233. package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.d.ts.map +1 -1
  234. package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.js +16 -4
  235. package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.js.map +1 -1
  236. package/out/zero-cache/src/services/change-source/common/init-cleanup.d.ts +24 -0
  237. package/out/zero-cache/src/services/change-source/common/init-cleanup.d.ts.map +1 -0
  238. package/out/zero-cache/src/services/change-source/common/init-cleanup.js +44 -0
  239. package/out/zero-cache/src/services/change-source/common/init-cleanup.js.map +1 -0
  240. package/out/zero-cache/src/services/change-source/common/replica-restore.d.ts +92 -2
  241. package/out/zero-cache/src/services/change-source/common/replica-restore.d.ts.map +1 -1
  242. package/out/zero-cache/src/services/change-source/common/replica-restore.js +27 -10
  243. package/out/zero-cache/src/services/change-source/common/replica-restore.js.map +1 -1
  244. package/out/zero-cache/src/services/change-source/common/replica-schema.d.ts +1 -0
  245. package/out/zero-cache/src/services/change-source/common/replica-schema.d.ts.map +1 -1
  246. package/out/zero-cache/src/services/change-source/common/replica-schema.js +15 -3
  247. package/out/zero-cache/src/services/change-source/common/replica-schema.js.map +1 -1
  248. package/out/zero-cache/src/services/change-source/custom/change-source.d.ts +1 -1
  249. package/out/zero-cache/src/services/change-source/custom/change-source.d.ts.map +1 -1
  250. package/out/zero-cache/src/services/change-source/custom/change-source.js +7 -3
  251. package/out/zero-cache/src/services/change-source/custom/change-source.js.map +1 -1
  252. package/out/zero-cache/src/services/change-source/pg/backfill-stream.d.ts +9 -0
  253. package/out/zero-cache/src/services/change-source/pg/backfill-stream.d.ts.map +1 -1
  254. package/out/zero-cache/src/services/change-source/pg/backfill-stream.js +206 -19
  255. package/out/zero-cache/src/services/change-source/pg/backfill-stream.js.map +1 -1
  256. package/out/zero-cache/src/services/change-source/pg/change-source-init.d.ts +55 -0
  257. package/out/zero-cache/src/services/change-source/pg/change-source-init.d.ts.map +1 -0
  258. package/out/zero-cache/src/services/change-source/pg/change-source-init.js +305 -0
  259. package/out/zero-cache/src/services/change-source/pg/change-source-init.js.map +1 -0
  260. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts +31 -18
  261. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts.map +1 -1
  262. package/out/zero-cache/src/services/change-source/pg/change-source.js +130 -157
  263. package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
  264. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts +38 -2
  265. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts.map +1 -1
  266. package/out/zero-cache/src/services/change-source/pg/initial-sync.js +55 -21
  267. package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
  268. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.d.ts +31 -0
  269. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.d.ts.map +1 -1
  270. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js +102 -3
  271. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js.map +1 -1
  272. package/out/zero-cache/src/services/change-source/pg/replication-slot-cleanup-monitor.d.ts +16 -0
  273. package/out/zero-cache/src/services/change-source/pg/replication-slot-cleanup-monitor.d.ts.map +1 -0
  274. package/out/zero-cache/src/services/change-source/pg/replication-slot-cleanup-monitor.js +113 -0
  275. package/out/zero-cache/src/services/change-source/pg/replication-slot-cleanup-monitor.js.map +1 -0
  276. package/out/zero-cache/src/services/change-source/pg/replication-slots.d.ts +40 -15
  277. package/out/zero-cache/src/services/change-source/pg/replication-slots.d.ts.map +1 -1
  278. package/out/zero-cache/src/services/change-source/pg/replication-slots.js +149 -27
  279. package/out/zero-cache/src/services/change-source/pg/replication-slots.js.map +1 -1
  280. package/out/zero-cache/src/services/change-source/pg/schema/index-predicate.d.ts.map +1 -1
  281. package/out/zero-cache/src/services/change-source/pg/schema/index-predicate.js +68 -8
  282. package/out/zero-cache/src/services/change-source/pg/schema/index-predicate.js.map +1 -1
  283. package/out/zero-cache/src/services/change-source/pg/schema/init.d.ts.map +1 -1
  284. package/out/zero-cache/src/services/change-source/pg/schema/init.js +32 -1
  285. package/out/zero-cache/src/services/change-source/pg/schema/init.js.map +1 -1
  286. package/out/zero-cache/src/services/change-source/pg/schema/replica-stage-enum.d.ts +10 -0
  287. package/out/zero-cache/src/services/change-source/pg/schema/replica-stage-enum.d.ts.map +1 -0
  288. package/out/zero-cache/src/services/change-source/pg/schema/replica-stage-enum.js +6 -0
  289. package/out/zero-cache/src/services/change-source/pg/schema/replica-stage-enum.js.map +1 -0
  290. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts +50 -27
  291. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts.map +1 -1
  292. package/out/zero-cache/src/services/change-source/pg/schema/shard.js +98 -34
  293. package/out/zero-cache/src/services/change-source/pg/schema/shard.js.map +1 -1
  294. package/out/zero-cache/src/services/change-source/protocol/backfill-progress.d.ts +68 -0
  295. package/out/zero-cache/src/services/change-source/protocol/backfill-progress.d.ts.map +1 -0
  296. package/out/zero-cache/src/services/change-source/protocol/backfill-progress.js +141 -0
  297. package/out/zero-cache/src/services/change-source/protocol/backfill-progress.js.map +1 -0
  298. package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts +45 -2
  299. package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts.map +1 -1
  300. package/out/zero-cache/src/services/change-source/protocol/current/data.js +10 -1
  301. package/out/zero-cache/src/services/change-source/protocol/current/data.js.map +1 -1
  302. package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts +60 -3
  303. package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts.map +1 -1
  304. package/out/zero-cache/src/services/change-source/protocol/current/upstream.d.ts +23 -10
  305. package/out/zero-cache/src/services/change-source/protocol/current/upstream.d.ts.map +1 -1
  306. package/out/zero-cache/src/services/change-source/protocol/current/upstream.js +17 -7
  307. package/out/zero-cache/src/services/change-source/protocol/current/upstream.js.map +1 -1
  308. package/out/zero-cache/src/services/change-source/protocol/current.js +2 -1
  309. package/out/zero-cache/src/services/change-streamer/backfill-state-tracker.d.ts +72 -0
  310. package/out/zero-cache/src/services/change-streamer/backfill-state-tracker.d.ts.map +1 -0
  311. package/out/zero-cache/src/services/change-streamer/backfill-state-tracker.js +162 -0
  312. package/out/zero-cache/src/services/change-streamer/backfill-state-tracker.js.map +1 -0
  313. package/out/zero-cache/src/services/change-streamer/backfill-state.d.ts +50 -0
  314. package/out/zero-cache/src/services/change-streamer/backfill-state.d.ts.map +1 -0
  315. package/out/zero-cache/src/services/change-streamer/backfill-state.js +268 -0
  316. package/out/zero-cache/src/services/change-streamer/backfill-state.js.map +1 -0
  317. package/out/zero-cache/src/services/change-streamer/backup-cleanup-monitor-factory.d.ts.map +1 -1
  318. package/out/zero-cache/src/services/change-streamer/backup-cleanup-monitor-factory.js +6 -17
  319. package/out/zero-cache/src/services/change-streamer/backup-cleanup-monitor-factory.js.map +1 -1
  320. package/out/zero-cache/src/services/change-streamer/backup-monitor.d.ts.map +1 -1
  321. package/out/zero-cache/src/services/change-streamer/backup-monitor.js +59 -8
  322. package/out/zero-cache/src/services/change-streamer/backup-monitor.js.map +1 -1
  323. package/out/zero-cache/src/services/change-streamer/broadcast.d.ts +8 -2
  324. package/out/zero-cache/src/services/change-streamer/broadcast.d.ts.map +1 -1
  325. package/out/zero-cache/src/services/change-streamer/broadcast.js +24 -4
  326. package/out/zero-cache/src/services/change-streamer/broadcast.js.map +1 -1
  327. package/out/zero-cache/src/services/change-streamer/change-log-codec.d.ts +19 -4
  328. package/out/zero-cache/src/services/change-streamer/change-log-codec.d.ts.map +1 -1
  329. package/out/zero-cache/src/services/change-streamer/change-log-codec.js +28 -8
  330. package/out/zero-cache/src/services/change-streamer/change-log-codec.js.map +1 -1
  331. package/out/zero-cache/src/services/change-streamer/change-log-initializer.d.ts +17 -0
  332. package/out/zero-cache/src/services/change-streamer/change-log-initializer.d.ts.map +1 -1
  333. package/out/zero-cache/src/services/change-streamer/change-log-initializer.js +44 -1
  334. package/out/zero-cache/src/services/change-streamer/change-log-initializer.js.map +1 -1
  335. package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts +48 -6
  336. package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts.map +1 -1
  337. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +131 -34
  338. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
  339. package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts +22 -0
  340. package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts.map +1 -1
  341. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js +149 -78
  342. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -1
  343. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts +38 -16
  344. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts.map +1 -1
  345. package/out/zero-cache/src/services/change-streamer/change-streamer.js.map +1 -1
  346. package/out/zero-cache/src/services/change-streamer/forwarder.d.ts +3 -3
  347. package/out/zero-cache/src/services/change-streamer/forwarder.d.ts.map +1 -1
  348. package/out/zero-cache/src/services/change-streamer/forwarder.js +36 -5
  349. package/out/zero-cache/src/services/change-streamer/forwarder.js.map +1 -1
  350. package/out/zero-cache/src/services/change-streamer/litestream-sync-requester.d.ts +53 -0
  351. package/out/zero-cache/src/services/change-streamer/litestream-sync-requester.d.ts.map +1 -0
  352. package/out/zero-cache/src/services/change-streamer/litestream-sync-requester.js +156 -0
  353. package/out/zero-cache/src/services/change-streamer/litestream-sync-requester.js.map +1 -0
  354. package/out/zero-cache/src/services/change-streamer/schema/tables.d.ts +58 -1
  355. package/out/zero-cache/src/services/change-streamer/schema/tables.d.ts.map +1 -1
  356. package/out/zero-cache/src/services/change-streamer/schema/tables.js +107 -16
  357. package/out/zero-cache/src/services/change-streamer/schema/tables.js.map +1 -1
  358. package/out/zero-cache/src/services/change-streamer/snapshot-message.d.ts +92 -0
  359. package/out/zero-cache/src/services/change-streamer/snapshot-message.d.ts.map +1 -0
  360. package/out/zero-cache/src/services/change-streamer/snapshot-message.js +42 -0
  361. package/out/zero-cache/src/services/change-streamer/snapshot-message.js.map +1 -0
  362. package/out/zero-cache/src/services/change-streamer/snapshot-reservations.d.ts +1 -1
  363. package/out/zero-cache/src/services/change-streamer/snapshot-reservations.d.ts.map +1 -1
  364. package/out/zero-cache/src/services/change-streamer/snapshot-reservations.js +16 -4
  365. package/out/zero-cache/src/services/change-streamer/snapshot-reservations.js.map +1 -1
  366. package/out/zero-cache/src/services/change-streamer/snapshot.d.ts +7 -69
  367. package/out/zero-cache/src/services/change-streamer/snapshot.d.ts.map +1 -1
  368. package/out/zero-cache/src/services/change-streamer/snapshot.js +21 -53
  369. package/out/zero-cache/src/services/change-streamer/snapshot.js.map +1 -1
  370. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.d.ts +6 -1
  371. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.d.ts.map +1 -1
  372. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.js +27 -9
  373. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.js.map +1 -1
  374. package/out/zero-cache/src/services/change-streamer/storer.d.ts +95 -4
  375. package/out/zero-cache/src/services/change-streamer/storer.d.ts.map +1 -1
  376. package/out/zero-cache/src/services/change-streamer/storer.js +293 -83
  377. package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
  378. package/out/zero-cache/src/services/change-streamer/subscribe.d.ts +446 -0
  379. package/out/zero-cache/src/services/change-streamer/subscribe.d.ts.map +1 -0
  380. package/out/zero-cache/src/services/change-streamer/subscribe.js +76 -0
  381. package/out/zero-cache/src/services/change-streamer/subscribe.js.map +1 -0
  382. package/out/zero-cache/src/services/change-streamer/subscriber.d.ts +58 -1
  383. package/out/zero-cache/src/services/change-streamer/subscriber.d.ts.map +1 -1
  384. package/out/zero-cache/src/services/change-streamer/subscriber.js +123 -12
  385. package/out/zero-cache/src/services/change-streamer/subscriber.js.map +1 -1
  386. package/out/zero-cache/src/services/change-streamer/upstream-acker.d.ts +19 -1
  387. package/out/zero-cache/src/services/change-streamer/upstream-acker.d.ts.map +1 -1
  388. package/out/zero-cache/src/services/change-streamer/upstream-acker.js +23 -3
  389. package/out/zero-cache/src/services/change-streamer/upstream-acker.js.map +1 -1
  390. package/out/zero-cache/src/services/http-service.d.ts +1 -1
  391. package/out/zero-cache/src/services/http-service.d.ts.map +1 -1
  392. package/out/zero-cache/src/services/http-service.js.map +1 -1
  393. package/out/zero-cache/src/services/life-cycle.d.ts.map +1 -1
  394. package/out/zero-cache/src/services/life-cycle.js +3 -1
  395. package/out/zero-cache/src/services/life-cycle.js.map +1 -1
  396. package/out/zero-cache/src/services/litestream/commands.d.ts +34 -3
  397. package/out/zero-cache/src/services/litestream/commands.d.ts.map +1 -1
  398. package/out/zero-cache/src/services/litestream/commands.js +121 -35
  399. package/out/zero-cache/src/services/litestream/commands.js.map +1 -1
  400. package/out/zero-cache/src/services/litestream/config-v5.yml +6 -7
  401. package/out/zero-cache/src/services/litestream/litestream-checkpointer.js +51 -24
  402. package/out/zero-cache/src/services/litestream/litestream-checkpointer.js.map +1 -1
  403. package/out/zero-cache/src/services/litestream/litestream-controller.d.ts +10 -2
  404. package/out/zero-cache/src/services/litestream/litestream-controller.d.ts.map +1 -1
  405. package/out/zero-cache/src/services/litestream/litestream-controller.js +3 -2
  406. package/out/zero-cache/src/services/litestream/litestream-controller.js.map +1 -1
  407. package/out/zero-cache/src/services/litestream/restore-progress.d.ts +24 -0
  408. package/out/zero-cache/src/services/litestream/restore-progress.d.ts.map +1 -0
  409. package/out/zero-cache/src/services/litestream/restore-progress.js +91 -0
  410. package/out/zero-cache/src/services/litestream/restore-progress.js.map +1 -0
  411. package/out/zero-cache/src/services/litestream/wal-keeper.d.ts +33 -0
  412. package/out/zero-cache/src/services/litestream/wal-keeper.d.ts.map +1 -0
  413. package/out/zero-cache/src/services/litestream/wal-keeper.js +49 -0
  414. package/out/zero-cache/src/services/litestream/wal-keeper.js.map +1 -0
  415. package/out/zero-cache/src/services/mutagen/mutagen.d.ts +5 -0
  416. package/out/zero-cache/src/services/mutagen/mutagen.d.ts.map +1 -1
  417. package/out/zero-cache/src/services/mutagen/mutagen.js +7 -1
  418. package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -1
  419. package/out/zero-cache/src/services/mutagen/pusher.d.ts.map +1 -1
  420. package/out/zero-cache/src/services/mutagen/pusher.js +5 -6
  421. package/out/zero-cache/src/services/mutagen/pusher.js.map +1 -1
  422. package/out/zero-cache/src/services/plannerz.d.ts +163 -0
  423. package/out/zero-cache/src/services/plannerz.d.ts.map +1 -0
  424. package/out/zero-cache/src/services/plannerz.js +267 -0
  425. package/out/zero-cache/src/services/plannerz.js.map +1 -0
  426. package/out/zero-cache/src/services/profz.d.ts +30 -0
  427. package/out/zero-cache/src/services/profz.d.ts.map +1 -0
  428. package/out/zero-cache/src/services/profz.js +163 -0
  429. package/out/zero-cache/src/services/profz.js.map +1 -0
  430. package/out/zero-cache/src/services/replicator/change-log-cookies.js +1 -1
  431. package/out/zero-cache/src/services/replicator/change-log-cookies.js.map +1 -1
  432. package/out/zero-cache/src/services/replicator/change-log-stream-writer.d.ts +5 -4
  433. package/out/zero-cache/src/services/replicator/change-log-stream-writer.d.ts.map +1 -1
  434. package/out/zero-cache/src/services/replicator/change-log-stream-writer.js +20 -22
  435. package/out/zero-cache/src/services/replicator/change-log-stream-writer.js.map +1 -1
  436. package/out/zero-cache/src/services/replicator/change-processor.d.ts.map +1 -1
  437. package/out/zero-cache/src/services/replicator/change-processor.js +51 -5
  438. package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
  439. package/out/zero-cache/src/services/replicator/incremental-sync.d.ts +5 -2
  440. package/out/zero-cache/src/services/replicator/incremental-sync.d.ts.map +1 -1
  441. package/out/zero-cache/src/services/replicator/incremental-sync.js +54 -21
  442. package/out/zero-cache/src/services/replicator/incremental-sync.js.map +1 -1
  443. package/out/zero-cache/src/services/replicator/replication-status.d.ts +35 -1
  444. package/out/zero-cache/src/services/replicator/replication-status.d.ts.map +1 -1
  445. package/out/zero-cache/src/services/replicator/replication-status.js +99 -8
  446. package/out/zero-cache/src/services/replicator/replication-status.js.map +1 -1
  447. package/out/zero-cache/src/services/replicator/replicator.d.ts +4 -1
  448. package/out/zero-cache/src/services/replicator/replicator.d.ts.map +1 -1
  449. package/out/zero-cache/src/services/replicator/replicator.js +5 -2
  450. package/out/zero-cache/src/services/replicator/replicator.js.map +1 -1
  451. package/out/zero-cache/src/services/replicator/reporter/recorder.d.ts +16 -1
  452. package/out/zero-cache/src/services/replicator/reporter/recorder.d.ts.map +1 -1
  453. package/out/zero-cache/src/services/replicator/reporter/recorder.js +70 -27
  454. package/out/zero-cache/src/services/replicator/reporter/recorder.js.map +1 -1
  455. package/out/zero-cache/src/services/replicator/schema/backfilling.d.ts +23 -2
  456. package/out/zero-cache/src/services/replicator/schema/backfilling.d.ts.map +1 -1
  457. package/out/zero-cache/src/services/replicator/schema/backfilling.js +54 -2
  458. package/out/zero-cache/src/services/replicator/schema/backfilling.js.map +1 -1
  459. package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.d.ts +6 -6
  460. package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.d.ts.map +1 -1
  461. package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.js +19 -14
  462. package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.js.map +1 -1
  463. package/out/zero-cache/src/services/replicator/write-worker-client.d.ts +11 -3
  464. package/out/zero-cache/src/services/replicator/write-worker-client.d.ts.map +1 -1
  465. package/out/zero-cache/src/services/replicator/write-worker-client.js.map +1 -1
  466. package/out/zero-cache/src/services/replicator/write-worker.js +5 -1
  467. package/out/zero-cache/src/services/replicator/write-worker.js.map +1 -1
  468. package/out/zero-cache/src/services/run-ast.d.ts +12 -0
  469. package/out/zero-cache/src/services/run-ast.d.ts.map +1 -1
  470. package/out/zero-cache/src/services/run-ast.js +42 -22
  471. package/out/zero-cache/src/services/run-ast.js.map +1 -1
  472. package/out/zero-cache/src/services/runner.d.ts +2 -1
  473. package/out/zero-cache/src/services/runner.d.ts.map +1 -1
  474. package/out/zero-cache/src/services/runner.js +10 -2
  475. package/out/zero-cache/src/services/runner.js.map +1 -1
  476. package/out/zero-cache/src/services/statz.d.ts +4 -0
  477. package/out/zero-cache/src/services/statz.d.ts.map +1 -1
  478. package/out/zero-cache/src/services/statz.js +22 -5
  479. package/out/zero-cache/src/services/statz.js.map +1 -1
  480. package/out/zero-cache/src/services/view-syncer/advancement-metrics.d.ts +26 -0
  481. package/out/zero-cache/src/services/view-syncer/advancement-metrics.d.ts.map +1 -0
  482. package/out/zero-cache/src/services/view-syncer/advancement-metrics.js +26 -0
  483. package/out/zero-cache/src/services/view-syncer/advancement-metrics.js.map +1 -0
  484. package/out/zero-cache/src/services/view-syncer/client-handler.d.ts +19 -2
  485. package/out/zero-cache/src/services/view-syncer/client-handler.d.ts.map +1 -1
  486. package/out/zero-cache/src/services/view-syncer/client-handler.js +42 -30
  487. package/out/zero-cache/src/services/view-syncer/client-handler.js.map +1 -1
  488. package/out/zero-cache/src/services/view-syncer/connection-context-manager.d.ts +2 -1
  489. package/out/zero-cache/src/services/view-syncer/connection-context-manager.d.ts.map +1 -1
  490. package/out/zero-cache/src/services/view-syncer/connection-context-manager.js +1 -0
  491. package/out/zero-cache/src/services/view-syncer/connection-context-manager.js.map +1 -1
  492. package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts +27 -2
  493. package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts.map +1 -1
  494. package/out/zero-cache/src/services/view-syncer/cvr-store.js +85 -20
  495. package/out/zero-cache/src/services/view-syncer/cvr-store.js.map +1 -1
  496. package/out/zero-cache/src/services/view-syncer/cvr.d.ts +76 -11
  497. package/out/zero-cache/src/services/view-syncer/cvr.d.ts.map +1 -1
  498. package/out/zero-cache/src/services/view-syncer/cvr.js +214 -40
  499. package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
  500. package/out/zero-cache/src/services/view-syncer/deferred-writes-budget.d.ts +81 -0
  501. package/out/zero-cache/src/services/view-syncer/deferred-writes-budget.d.ts.map +1 -0
  502. package/out/zero-cache/src/services/view-syncer/deferred-writes-budget.js +128 -0
  503. package/out/zero-cache/src/services/view-syncer/deferred-writes-budget.js.map +1 -0
  504. package/out/zero-cache/src/services/view-syncer/drain-coordinator.d.ts +14 -1
  505. package/out/zero-cache/src/services/view-syncer/drain-coordinator.d.ts.map +1 -1
  506. package/out/zero-cache/src/services/view-syncer/drain-coordinator.js +30 -4
  507. package/out/zero-cache/src/services/view-syncer/drain-coordinator.js.map +1 -1
  508. package/out/zero-cache/src/services/view-syncer/hydration-budget.d.ts +33 -0
  509. package/out/zero-cache/src/services/view-syncer/hydration-budget.d.ts.map +1 -0
  510. package/out/zero-cache/src/services/view-syncer/hydration-budget.js +62 -0
  511. package/out/zero-cache/src/services/view-syncer/hydration-budget.js.map +1 -0
  512. package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.d.ts +51 -0
  513. package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.d.ts.map +1 -0
  514. package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.js +78 -0
  515. package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.js.map +1 -0
  516. package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts +10 -1
  517. package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts.map +1 -1
  518. package/out/zero-cache/src/services/view-syncer/inspect-handler.js +18 -4
  519. package/out/zero-cache/src/services/view-syncer/inspect-handler.js.map +1 -1
  520. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts +80 -6
  521. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
  522. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +658 -195
  523. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
  524. package/out/zero-cache/src/services/view-syncer/plan-warnings.d.ts +7 -0
  525. package/out/zero-cache/src/services/view-syncer/plan-warnings.d.ts.map +1 -0
  526. package/out/zero-cache/src/services/view-syncer/plan-warnings.js +35 -0
  527. package/out/zero-cache/src/services/view-syncer/plan-warnings.js.map +1 -0
  528. package/out/zero-cache/src/services/view-syncer/query-covering.d.ts.map +1 -1
  529. package/out/zero-cache/src/services/view-syncer/query-covering.js +2 -6
  530. package/out/zero-cache/src/services/view-syncer/query-covering.js.map +1 -1
  531. package/out/zero-cache/src/services/view-syncer/query-shape.d.ts +25 -0
  532. package/out/zero-cache/src/services/view-syncer/query-shape.d.ts.map +1 -0
  533. package/out/zero-cache/src/services/view-syncer/query-shape.js +28 -0
  534. package/out/zero-cache/src/services/view-syncer/query-shape.js.map +1 -0
  535. package/out/zero-cache/src/services/view-syncer/query-stats.d.ts +82 -0
  536. package/out/zero-cache/src/services/view-syncer/query-stats.d.ts.map +1 -0
  537. package/out/zero-cache/src/services/view-syncer/query-stats.js +214 -0
  538. package/out/zero-cache/src/services/view-syncer/query-stats.js.map +1 -0
  539. package/out/zero-cache/src/services/view-syncer/schema/types.d.ts +2 -107
  540. package/out/zero-cache/src/services/view-syncer/schema/types.d.ts.map +1 -1
  541. package/out/zero-cache/src/services/view-syncer/schema/types.js +5 -20
  542. package/out/zero-cache/src/services/view-syncer/schema/types.js.map +1 -1
  543. package/out/zero-cache/src/services/view-syncer/snapshot-row-cache.d.ts +95 -0
  544. package/out/zero-cache/src/services/view-syncer/snapshot-row-cache.d.ts.map +1 -0
  545. package/out/zero-cache/src/services/view-syncer/snapshot-row-cache.js +155 -0
  546. package/out/zero-cache/src/services/view-syncer/snapshot-row-cache.js.map +1 -0
  547. package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts +96 -14
  548. package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts.map +1 -1
  549. package/out/zero-cache/src/services/view-syncer/snapshotter.js +214 -30
  550. package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
  551. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts +11 -1
  552. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
  553. package/out/zero-cache/src/services/view-syncer/view-syncer.js +566 -107
  554. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  555. package/out/zero-cache/src/types/pg-data-type.d.ts +2 -0
  556. package/out/zero-cache/src/types/pg-data-type.d.ts.map +1 -1
  557. package/out/zero-cache/src/types/pg-data-type.js +6 -1
  558. package/out/zero-cache/src/types/pg-data-type.js.map +1 -1
  559. package/out/zero-cache/src/types/pg.d.ts.map +1 -1
  560. package/out/zero-cache/src/types/pg.js +1 -1
  561. package/out/zero-cache/src/types/pg.js.map +1 -1
  562. package/out/zero-cache/src/types/processes.d.ts +39 -0
  563. package/out/zero-cache/src/types/processes.d.ts.map +1 -1
  564. package/out/zero-cache/src/types/processes.js +43 -4
  565. package/out/zero-cache/src/types/processes.js.map +1 -1
  566. package/out/zero-cache/src/types/profiler.d.ts +12 -0
  567. package/out/zero-cache/src/types/profiler.d.ts.map +1 -1
  568. package/out/zero-cache/src/types/profiler.js +46 -1
  569. package/out/zero-cache/src/types/profiler.js.map +1 -1
  570. package/out/zero-cache/src/types/row-key.d.ts +1 -15
  571. package/out/zero-cache/src/types/row-key.d.ts.map +1 -1
  572. package/out/zero-cache/src/types/row-key.js +6 -8
  573. package/out/zero-cache/src/types/row-key.js.map +1 -1
  574. package/out/zero-cache/src/types/streams.d.ts +49 -7
  575. package/out/zero-cache/src/types/streams.d.ts.map +1 -1
  576. package/out/zero-cache/src/types/streams.js +190 -58
  577. package/out/zero-cache/src/types/streams.js.map +1 -1
  578. package/out/zero-cache/src/types/subscription.d.ts +15 -0
  579. package/out/zero-cache/src/types/subscription.d.ts.map +1 -1
  580. package/out/zero-cache/src/types/subscription.js +123 -31
  581. package/out/zero-cache/src/types/subscription.js.map +1 -1
  582. package/out/zero-cache/src/types/websocket-handoff.d.ts +1 -1
  583. package/out/zero-cache/src/types/websocket-handoff.d.ts.map +1 -1
  584. package/out/zero-cache/src/types/websocket-handoff.js +18 -9
  585. package/out/zero-cache/src/types/websocket-handoff.js.map +1 -1
  586. package/out/zero-cache/src/types/ws.d.ts.map +1 -1
  587. package/out/zero-cache/src/types/ws.js +1 -16
  588. package/out/zero-cache/src/types/ws.js.map +1 -1
  589. package/out/zero-cache/src/workers/connect-params.d.ts +18 -1
  590. package/out/zero-cache/src/workers/connect-params.d.ts.map +1 -1
  591. package/out/zero-cache/src/workers/connect-params.js +25 -1
  592. package/out/zero-cache/src/workers/connect-params.js.map +1 -1
  593. package/out/zero-cache/src/workers/connection.d.ts +4 -4
  594. package/out/zero-cache/src/workers/connection.d.ts.map +1 -1
  595. package/out/zero-cache/src/workers/connection.js +8 -8
  596. package/out/zero-cache/src/workers/connection.js.map +1 -1
  597. package/out/zero-cache/src/workers/replicator.d.ts.map +1 -1
  598. package/out/zero-cache/src/workers/replicator.js +15 -7
  599. package/out/zero-cache/src/workers/replicator.js.map +1 -1
  600. package/out/zero-cache/src/workers/syncer-ws-message-handler.d.ts.map +1 -1
  601. package/out/zero-cache/src/workers/syncer-ws-message-handler.js +21 -16
  602. package/out/zero-cache/src/workers/syncer-ws-message-handler.js.map +1 -1
  603. package/out/zero-cache/src/workers/syncer.d.ts.map +1 -1
  604. package/out/zero-cache/src/workers/syncer.js +55 -4
  605. package/out/zero-cache/src/workers/syncer.js.map +1 -1
  606. package/out/zero-client/src/client/active-clients-manager.d.ts.map +1 -1
  607. package/out/zero-client/src/client/active-clients-manager.js +4 -1
  608. package/out/zero-client/src/client/active-clients-manager.js.map +1 -1
  609. package/out/zero-client/src/client/connection-manager.d.ts +20 -0
  610. package/out/zero-client/src/client/connection-manager.d.ts.map +1 -1
  611. package/out/zero-client/src/client/connection-manager.js +77 -13
  612. package/out/zero-client/src/client/connection-manager.js.map +1 -1
  613. package/out/zero-client/src/client/connection-status-enum.d.ts +2 -0
  614. package/out/zero-client/src/client/connection-status-enum.d.ts.map +1 -1
  615. package/out/zero-client/src/client/connection-status-enum.js +3 -1
  616. package/out/zero-client/src/client/connection-status-enum.js.map +1 -1
  617. package/out/zero-client/src/client/connection.d.ts +6 -0
  618. package/out/zero-client/src/client/connection.d.ts.map +1 -1
  619. package/out/zero-client/src/client/connection.js +2 -1
  620. package/out/zero-client/src/client/connection.js.map +1 -1
  621. package/out/zero-client/src/client/context.d.ts +23 -13
  622. package/out/zero-client/src/client/context.d.ts.map +1 -1
  623. package/out/zero-client/src/client/context.js +94 -26
  624. package/out/zero-client/src/client/context.js.map +1 -1
  625. package/out/zero-client/src/client/crud-impl.d.ts.map +1 -1
  626. package/out/zero-client/src/client/crud-impl.js +1 -1
  627. package/out/zero-client/src/client/crud-impl.js.map +1 -1
  628. package/out/zero-client/src/client/custom.d.ts +5 -4
  629. package/out/zero-client/src/client/custom.d.ts.map +1 -1
  630. package/out/zero-client/src/client/custom.js +3 -3
  631. package/out/zero-client/src/client/custom.js.map +1 -1
  632. package/out/zero-client/src/client/inspector/lazy-inspector.js +1 -1
  633. package/out/zero-client/src/client/ivm-branch.d.ts.map +1 -1
  634. package/out/zero-client/src/client/ivm-branch.js +20 -3
  635. package/out/zero-client/src/client/ivm-branch.js.map +1 -1
  636. package/out/zero-client/src/client/keys.d.ts.map +1 -1
  637. package/out/zero-client/src/client/keys.js +19 -1
  638. package/out/zero-client/src/client/keys.js.map +1 -1
  639. package/out/zero-client/src/client/make-mutate-property.d.ts +1 -1
  640. package/out/zero-client/src/client/make-mutate-property.d.ts.map +1 -1
  641. package/out/zero-client/src/client/make-mutate-property.js.map +1 -1
  642. package/out/zero-client/src/client/make-replicache-mutators.d.ts.map +1 -1
  643. package/out/zero-client/src/client/make-replicache-mutators.js +1 -1
  644. package/out/zero-client/src/client/make-replicache-mutators.js.map +1 -1
  645. package/out/zero-client/src/client/mutation-tracker.d.ts +2 -2
  646. package/out/zero-client/src/client/mutation-tracker.d.ts.map +1 -1
  647. package/out/zero-client/src/client/mutation-tracker.js +3 -7
  648. package/out/zero-client/src/client/mutation-tracker.js.map +1 -1
  649. package/out/zero-client/src/client/mutator-proxy.d.ts.map +1 -1
  650. package/out/zero-client/src/client/mutator-proxy.js +9 -4
  651. package/out/zero-client/src/client/mutator-proxy.js.map +1 -1
  652. package/out/zero-client/src/client/options.d.ts +33 -0
  653. package/out/zero-client/src/client/options.d.ts.map +1 -1
  654. package/out/zero-client/src/client/options.js.map +1 -1
  655. package/out/zero-client/src/client/query-manager.d.ts +9 -0
  656. package/out/zero-client/src/client/query-manager.d.ts.map +1 -1
  657. package/out/zero-client/src/client/query-manager.js +47 -14
  658. package/out/zero-client/src/client/query-manager.js.map +1 -1
  659. package/out/zero-client/src/client/reload-error-handler.js +2 -2
  660. package/out/zero-client/src/client/reload-error-handler.js.map +1 -1
  661. package/out/zero-client/src/client/version.js +1 -1
  662. package/out/zero-client/src/client/zero-rep.d.ts +1 -0
  663. package/out/zero-client/src/client/zero-rep.d.ts.map +1 -1
  664. package/out/zero-client/src/client/zero-rep.js +8 -6
  665. package/out/zero-client/src/client/zero-rep.js.map +1 -1
  666. package/out/zero-client/src/client/zero.d.ts +18 -3
  667. package/out/zero-client/src/client/zero.d.ts.map +1 -1
  668. package/out/zero-client/src/client/zero.js +89 -50
  669. package/out/zero-client/src/client/zero.js.map +1 -1
  670. package/out/zero-client/src/mod.d.ts +2 -1
  671. package/out/zero-client/src/mod.d.ts.map +1 -1
  672. package/out/zero-client/src/mod.js +1 -0
  673. package/out/zero-client/src/types/query-result.d.ts +2 -0
  674. package/out/zero-client/src/types/query-result.d.ts.map +1 -1
  675. package/out/zero-events/src/status.d.ts +64 -0
  676. package/out/zero-events/src/status.d.ts.map +1 -1
  677. package/out/zero-protocol/src/analyze-query-result.d.ts +5 -0
  678. package/out/zero-protocol/src/analyze-query-result.d.ts.map +1 -1
  679. package/out/zero-protocol/src/analyze-query-result.js.map +1 -1
  680. package/out/zero-protocol/src/ast.d.ts.map +1 -1
  681. package/out/zero-protocol/src/ast.js +13 -14
  682. package/out/zero-protocol/src/ast.js.map +1 -1
  683. package/out/zero-protocol/src/connect.d.ts +16 -0
  684. package/out/zero-protocol/src/connect.d.ts.map +1 -1
  685. package/out/zero-protocol/src/connect.js +27 -1
  686. package/out/zero-protocol/src/connect.js.map +1 -1
  687. package/out/zero-protocol/src/down.d.ts +31 -31
  688. package/out/zero-protocol/src/feature-flag-enum.d.ts +14 -0
  689. package/out/zero-protocol/src/feature-flag-enum.d.ts.map +1 -0
  690. package/out/zero-protocol/src/feature-flag-enum.js +10 -0
  691. package/out/zero-protocol/src/feature-flag-enum.js.map +1 -0
  692. package/out/zero-protocol/src/feature-flag.d.ts +5 -0
  693. package/out/zero-protocol/src/feature-flag.d.ts.map +1 -0
  694. package/out/zero-protocol/src/inspect-down.d.ts +16 -16
  695. package/out/zero-protocol/src/poke.d.ts +17 -10
  696. package/out/zero-protocol/src/poke.d.ts.map +1 -1
  697. package/out/zero-protocol/src/poke.js +3 -2
  698. package/out/zero-protocol/src/poke.js.map +1 -1
  699. package/out/zero-protocol/src/protocol-version.d.ts +30 -6
  700. package/out/zero-protocol/src/protocol-version.d.ts.map +1 -1
  701. package/out/zero-protocol/src/protocol-version.js +1 -1
  702. package/out/zero-protocol/src/protocol-version.js.map +1 -1
  703. package/out/zero-protocol/src/query-hash.d.ts.map +1 -1
  704. package/out/zero-protocol/src/query-hash.js +2 -5
  705. package/out/zero-protocol/src/query-hash.js.map +1 -1
  706. package/out/zero-react/src/use-query.d.ts +5 -4
  707. package/out/zero-react/src/use-query.d.ts.map +1 -1
  708. package/out/zero-react/src/use-query.js +74 -7
  709. package/out/zero-react/src/use-query.js.map +1 -1
  710. package/out/zero-react/src/zero.js +1 -0
  711. package/out/zero-server/src/adapters/drizzle.d.ts +2 -1
  712. package/out/zero-server/src/adapters/drizzle.d.ts.map +1 -1
  713. package/out/zero-server/src/adapters/drizzle.js +12 -7
  714. package/out/zero-server/src/adapters/drizzle.js.map +1 -1
  715. package/out/zero-server/src/adapters/kysely.d.ts +2 -1
  716. package/out/zero-server/src/adapters/kysely.d.ts.map +1 -1
  717. package/out/zero-server/src/adapters/kysely.js +8 -2
  718. package/out/zero-server/src/adapters/kysely.js.map +1 -1
  719. package/out/zero-server/src/adapters/pg.d.ts +5 -1
  720. package/out/zero-server/src/adapters/pg.d.ts.map +1 -1
  721. package/out/zero-server/src/adapters/pg.js +28 -7
  722. package/out/zero-server/src/adapters/pg.js.map +1 -1
  723. package/out/zero-server/src/adapters/postgresjs.d.ts +1 -0
  724. package/out/zero-server/src/adapters/postgresjs.d.ts.map +1 -1
  725. package/out/zero-server/src/adapters/postgresjs.js +7 -1
  726. package/out/zero-server/src/adapters/postgresjs.js.map +1 -1
  727. package/out/zero-server/src/adapters/prisma.d.ts +3 -2
  728. package/out/zero-server/src/adapters/prisma.d.ts.map +1 -1
  729. package/out/zero-server/src/adapters/prisma.js +8 -2
  730. package/out/zero-server/src/adapters/prisma.js.map +1 -1
  731. package/out/zero-server/src/closable-db-transaction.d.ts +16 -0
  732. package/out/zero-server/src/closable-db-transaction.d.ts.map +1 -0
  733. package/out/zero-server/src/closable-db-transaction.js +31 -0
  734. package/out/zero-server/src/closable-db-transaction.js.map +1 -0
  735. package/out/zero-server/src/custom.d.ts +10 -4
  736. package/out/zero-server/src/custom.d.ts.map +1 -1
  737. package/out/zero-server/src/custom.js +15 -6
  738. package/out/zero-server/src/custom.js.map +1 -1
  739. package/out/zero-server/src/logging.d.ts +2 -2
  740. package/out/zero-server/src/logging.d.ts.map +1 -1
  741. package/out/zero-server/src/logging.js +2 -2
  742. package/out/zero-server/src/logging.js.map +1 -1
  743. package/out/zero-server/src/mod.d.ts +1 -1
  744. package/out/zero-server/src/mod.d.ts.map +1 -1
  745. package/out/zero-server/src/pg-query-executor.d.ts +2 -2
  746. package/out/zero-server/src/pg-query-executor.d.ts.map +1 -1
  747. package/out/zero-server/src/pg-query-executor.js +2 -2
  748. package/out/zero-server/src/pg-query-executor.js.map +1 -1
  749. package/out/zero-server/src/process-mutations.d.ts +25 -4
  750. package/out/zero-server/src/process-mutations.d.ts.map +1 -1
  751. package/out/zero-server/src/process-mutations.js +103 -52
  752. package/out/zero-server/src/process-mutations.js.map +1 -1
  753. package/out/zero-server/src/push-processor.d.ts +8 -2
  754. package/out/zero-server/src/push-processor.d.ts.map +1 -1
  755. package/out/zero-server/src/push-processor.js +12 -4
  756. package/out/zero-server/src/push-processor.js.map +1 -1
  757. package/out/zero-server/src/schema.d.ts +2 -2
  758. package/out/zero-server/src/schema.d.ts.map +1 -1
  759. package/out/zero-server/src/schema.js +3 -2
  760. package/out/zero-server/src/schema.js.map +1 -1
  761. package/out/zero-server/src/zql-database.d.ts +21 -1
  762. package/out/zero-server/src/zql-database.d.ts.map +1 -1
  763. package/out/zero-server/src/zql-database.js +61 -24
  764. package/out/zero-server/src/zql-database.js.map +1 -1
  765. package/out/zero-solid/src/solid-view.d.ts +17 -0
  766. package/out/zero-solid/src/solid-view.d.ts.map +1 -1
  767. package/out/zero-solid/src/solid-view.js +39 -1
  768. package/out/zero-solid/src/solid-view.js.map +1 -1
  769. package/out/zero-solid/src/use-query.js +1 -2
  770. package/out/zero-solid/src/use-query.js.map +1 -1
  771. package/out/zero-solid/src/zero.js +1 -0
  772. package/out/zql/src/builder/builder.d.ts +25 -0
  773. package/out/zql/src/builder/builder.d.ts.map +1 -1
  774. package/out/zql/src/builder/builder.js +69 -19
  775. package/out/zql/src/builder/builder.js.map +1 -1
  776. package/out/zql/src/builder/correlated-predicate-pushdown.d.ts +43 -0
  777. package/out/zql/src/builder/correlated-predicate-pushdown.d.ts.map +1 -0
  778. package/out/zql/src/builder/correlated-predicate-pushdown.js +161 -0
  779. package/out/zql/src/builder/correlated-predicate-pushdown.js.map +1 -0
  780. package/out/zql/src/builder/debug-delegate.d.ts +6 -1
  781. package/out/zql/src/builder/debug-delegate.d.ts.map +1 -1
  782. package/out/zql/src/builder/debug-delegate.js +14 -2
  783. package/out/zql/src/builder/debug-delegate.js.map +1 -1
  784. package/out/zql/src/ivm/array-view.d.ts +29 -0
  785. package/out/zql/src/ivm/array-view.d.ts.map +1 -1
  786. package/out/zql/src/ivm/array-view.js +74 -16
  787. package/out/zql/src/ivm/array-view.js.map +1 -1
  788. package/out/zql/src/ivm/cap.d.ts +2 -1
  789. package/out/zql/src/ivm/cap.d.ts.map +1 -1
  790. package/out/zql/src/ivm/cap.js +14 -4
  791. package/out/zql/src/ivm/cap.js.map +1 -1
  792. package/out/zql/src/ivm/data.d.ts.map +1 -1
  793. package/out/zql/src/ivm/data.js +8 -3
  794. package/out/zql/src/ivm/data.js.map +1 -1
  795. package/out/zql/src/ivm/deferred-input.d.ts.map +1 -1
  796. package/out/zql/src/ivm/deferred-input.js +3 -2
  797. package/out/zql/src/ivm/deferred-input.js.map +1 -1
  798. package/out/zql/src/ivm/exists.d.ts +3 -1
  799. package/out/zql/src/ivm/exists.d.ts.map +1 -1
  800. package/out/zql/src/ivm/exists.js +4 -1
  801. package/out/zql/src/ivm/exists.js.map +1 -1
  802. package/out/zql/src/ivm/fan-in.d.ts +6 -2
  803. package/out/zql/src/ivm/fan-in.d.ts.map +1 -1
  804. package/out/zql/src/ivm/fan-in.js +13 -5
  805. package/out/zql/src/ivm/fan-in.js.map +1 -1
  806. package/out/zql/src/ivm/fan-out.d.ts +5 -2
  807. package/out/zql/src/ivm/fan-out.d.ts.map +1 -1
  808. package/out/zql/src/ivm/fan-out.js +4 -0
  809. package/out/zql/src/ivm/fan-out.js.map +1 -1
  810. package/out/zql/src/ivm/filter-operators.d.ts +8 -6
  811. package/out/zql/src/ivm/filter-operators.d.ts.map +1 -1
  812. package/out/zql/src/ivm/filter-operators.js +19 -8
  813. package/out/zql/src/ivm/filter-operators.js.map +1 -1
  814. package/out/zql/src/ivm/filter.d.ts +5 -2
  815. package/out/zql/src/ivm/filter.d.ts.map +1 -1
  816. package/out/zql/src/ivm/filter.js +10 -4
  817. package/out/zql/src/ivm/filter.js.map +1 -1
  818. package/out/zql/src/ivm/flipped-join.d.ts +9 -4
  819. package/out/zql/src/ivm/flipped-join.d.ts.map +1 -1
  820. package/out/zql/src/ivm/flipped-join.js +97 -46
  821. package/out/zql/src/ivm/flipped-join.js.map +1 -1
  822. package/out/zql/src/ivm/join-index-tap.d.ts +33 -0
  823. package/out/zql/src/ivm/join-index-tap.d.ts.map +1 -0
  824. package/out/zql/src/ivm/join-index-tap.js +70 -0
  825. package/out/zql/src/ivm/join-index-tap.js.map +1 -0
  826. package/out/zql/src/ivm/join-index.d.ts +35 -0
  827. package/out/zql/src/ivm/join-index.d.ts.map +1 -0
  828. package/out/zql/src/ivm/join-index.js +141 -0
  829. package/out/zql/src/ivm/join-index.js.map +1 -0
  830. package/out/zql/src/ivm/join-utils.d.ts +6 -0
  831. package/out/zql/src/ivm/join-utils.d.ts.map +1 -1
  832. package/out/zql/src/ivm/join-utils.js +22 -1
  833. package/out/zql/src/ivm/join-utils.js.map +1 -1
  834. package/out/zql/src/ivm/join.d.ts +19 -1
  835. package/out/zql/src/ivm/join.d.ts.map +1 -1
  836. package/out/zql/src/ivm/join.js +107 -15
  837. package/out/zql/src/ivm/join.js.map +1 -1
  838. package/out/zql/src/ivm/maybe-split-and-push-edit-change.d.ts +1 -1
  839. package/out/zql/src/ivm/maybe-split-and-push-edit-change.d.ts.map +1 -1
  840. package/out/zql/src/ivm/maybe-split-and-push-edit-change.js +6 -4
  841. package/out/zql/src/ivm/maybe-split-and-push-edit-change.js.map +1 -1
  842. package/out/zql/src/ivm/memory-source.d.ts +29 -4
  843. package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
  844. package/out/zql/src/ivm/memory-source.js +70 -34
  845. package/out/zql/src/ivm/memory-source.js.map +1 -1
  846. package/out/zql/src/ivm/memory-storage.d.ts +1 -0
  847. package/out/zql/src/ivm/memory-storage.d.ts.map +1 -1
  848. package/out/zql/src/ivm/memory-storage.js +1 -0
  849. package/out/zql/src/ivm/memory-storage.js.map +1 -1
  850. package/out/zql/src/ivm/operator.d.ts +45 -10
  851. package/out/zql/src/ivm/operator.d.ts.map +1 -1
  852. package/out/zql/src/ivm/operator.js +9 -4
  853. package/out/zql/src/ivm/operator.js.map +1 -1
  854. package/out/zql/src/ivm/push-accumulated.d.ts +6 -1
  855. package/out/zql/src/ivm/push-accumulated.d.ts.map +1 -1
  856. package/out/zql/src/ivm/push-accumulated.js +47 -2
  857. package/out/zql/src/ivm/push-accumulated.js.map +1 -1
  858. package/out/zql/src/ivm/skip.d.ts +2 -1
  859. package/out/zql/src/ivm/skip.d.ts.map +1 -1
  860. package/out/zql/src/ivm/skip.js +3 -0
  861. package/out/zql/src/ivm/skip.js.map +1 -1
  862. package/out/zql/src/ivm/take-gate.d.ts +57 -0
  863. package/out/zql/src/ivm/take-gate.d.ts.map +1 -0
  864. package/out/zql/src/ivm/take-gate.js +106 -0
  865. package/out/zql/src/ivm/take-gate.js.map +1 -0
  866. package/out/zql/src/ivm/take.d.ts +8 -2
  867. package/out/zql/src/ivm/take.d.ts.map +1 -1
  868. package/out/zql/src/ivm/take.js +139 -103
  869. package/out/zql/src/ivm/take.js.map +1 -1
  870. package/out/zql/src/ivm/union-fan-in.d.ts +3 -0
  871. package/out/zql/src/ivm/union-fan-in.d.ts.map +1 -1
  872. package/out/zql/src/ivm/union-fan-in.js +63 -10
  873. package/out/zql/src/ivm/union-fan-in.js.map +1 -1
  874. package/out/zql/src/ivm/union-fan-out.d.ts +2 -1
  875. package/out/zql/src/ivm/union-fan-out.d.ts.map +1 -1
  876. package/out/zql/src/ivm/union-fan-out.js +5 -0
  877. package/out/zql/src/ivm/union-fan-out.js.map +1 -1
  878. package/out/zql/src/ivm/view-apply-change.d.ts.map +1 -1
  879. package/out/zql/src/ivm/view-apply-change.js +9 -4
  880. package/out/zql/src/ivm/view-apply-change.js.map +1 -1
  881. package/out/zql/src/ivm/view.d.ts +15 -0
  882. package/out/zql/src/ivm/view.d.ts.map +1 -1
  883. package/out/zql/src/mutate/custom.d.ts +53 -1
  884. package/out/zql/src/mutate/custom.d.ts.map +1 -1
  885. package/out/zql/src/mutate/custom.js.map +1 -1
  886. package/out/zql/src/mutate/mutator-registry.d.ts.map +1 -1
  887. package/out/zql/src/mutate/mutator-registry.js +3 -3
  888. package/out/zql/src/mutate/mutator-registry.js.map +1 -1
  889. package/out/zql/src/mutate/mutator.d.ts +2 -2
  890. package/out/zql/src/mutate/mutator.d.ts.map +1 -1
  891. package/out/zql/src/mutate/mutator.js.map +1 -1
  892. package/out/zql/src/planner/planner-builder.d.ts +23 -3
  893. package/out/zql/src/planner/planner-builder.d.ts.map +1 -1
  894. package/out/zql/src/planner/planner-builder.js +34 -17
  895. package/out/zql/src/planner/planner-builder.js.map +1 -1
  896. package/out/zql/src/planner/planner-connection.d.ts +58 -2
  897. package/out/zql/src/planner/planner-connection.d.ts.map +1 -1
  898. package/out/zql/src/planner/planner-connection.js +103 -11
  899. package/out/zql/src/planner/planner-connection.js.map +1 -1
  900. package/out/zql/src/planner/planner-debug.d.ts.map +1 -1
  901. package/out/zql/src/planner/planner-debug.js +3 -8
  902. package/out/zql/src/planner/planner-debug.js.map +1 -1
  903. package/out/zql/src/planner/planner-graph.d.ts +10 -0
  904. package/out/zql/src/planner/planner-graph.d.ts.map +1 -1
  905. package/out/zql/src/planner/planner-graph.js +14 -0
  906. package/out/zql/src/planner/planner-graph.js.map +1 -1
  907. package/out/zql/src/planner/planner-source.d.ts +2 -2
  908. package/out/zql/src/planner/planner-source.d.ts.map +1 -1
  909. package/out/zql/src/planner/planner-source.js +2 -2
  910. package/out/zql/src/planner/planner-source.js.map +1 -1
  911. package/out/zql/src/planner/planner-warnings.d.ts +83 -0
  912. package/out/zql/src/planner/planner-warnings.d.ts.map +1 -0
  913. package/out/zql/src/planner/planner-warnings.js +78 -0
  914. package/out/zql/src/planner/planner-warnings.js.map +1 -0
  915. package/out/zql/src/query/measure-push-operator.d.ts +9 -2
  916. package/out/zql/src/query/measure-push-operator.d.ts.map +1 -1
  917. package/out/zql/src/query/measure-push-operator.js +52 -5
  918. package/out/zql/src/query/measure-push-operator.js.map +1 -1
  919. package/out/zql/src/query/query-delegate-base.d.ts +4 -2
  920. package/out/zql/src/query/query-delegate-base.d.ts.map +1 -1
  921. package/out/zql/src/query/query-delegate-base.js +66 -33
  922. package/out/zql/src/query/query-delegate-base.js.map +1 -1
  923. package/out/zql/src/query/query-delegate.d.ts +33 -6
  924. package/out/zql/src/query/query-delegate.d.ts.map +1 -1
  925. package/out/zql/src/query/query-impl.d.ts +1 -0
  926. package/out/zql/src/query/query-impl.d.ts.map +1 -1
  927. package/out/zql/src/query/query-impl.js +6 -23
  928. package/out/zql/src/query/query-impl.js.map +1 -1
  929. package/out/zql/src/query/query-transitions.d.ts.map +1 -1
  930. package/out/zql/src/query/query-transitions.js +2 -5
  931. package/out/zql/src/query/query-transitions.js.map +1 -1
  932. package/out/zql/src/query/query.d.ts +22 -5
  933. package/out/zql/src/query/query.d.ts.map +1 -1
  934. package/out/zql/src/query/runnable-query-impl.d.ts +1 -0
  935. package/out/zql/src/query/runnable-query-impl.d.ts.map +1 -1
  936. package/out/zql/src/query/runnable-query-impl.js +2 -10
  937. package/out/zql/src/query/runnable-query-impl.js.map +1 -1
  938. package/out/zql/src/query/typed-view.d.ts +1 -1
  939. package/out/zql/src/query/typed-view.d.ts.map +1 -1
  940. package/out/zqlite/src/database-storage.d.ts.map +1 -1
  941. package/out/zqlite/src/database-storage.js +9 -1
  942. package/out/zqlite/src/database-storage.js.map +1 -1
  943. package/out/zqlite/src/db.d.ts +9 -1
  944. package/out/zqlite/src/db.d.ts.map +1 -1
  945. package/out/zqlite/src/db.js +62 -30
  946. package/out/zqlite/src/db.js.map +1 -1
  947. package/out/zqlite/src/index-usage.d.ts +19 -0
  948. package/out/zqlite/src/index-usage.d.ts.map +1 -0
  949. package/out/zqlite/src/index-usage.js +49 -0
  950. package/out/zqlite/src/index-usage.js.map +1 -0
  951. package/out/zqlite/src/pending-delta.d.ts +110 -0
  952. package/out/zqlite/src/pending-delta.d.ts.map +1 -0
  953. package/out/zqlite/src/pending-delta.js +278 -0
  954. package/out/zqlite/src/pending-delta.js.map +1 -0
  955. package/out/zqlite/src/query-builder.d.ts +17 -1
  956. package/out/zqlite/src/query-builder.d.ts.map +1 -1
  957. package/out/zqlite/src/query-builder.js +111 -20
  958. package/out/zqlite/src/query-builder.js.map +1 -1
  959. package/out/zqlite/src/query-delegate.d.ts.map +1 -1
  960. package/out/zqlite/src/query-delegate.js +10 -7
  961. package/out/zqlite/src/query-delegate.js.map +1 -1
  962. package/out/zqlite/src/resolve-scalar-subqueries.d.ts +3 -1
  963. package/out/zqlite/src/resolve-scalar-subqueries.d.ts.map +1 -1
  964. package/out/zqlite/src/resolve-scalar-subqueries.js +1 -0
  965. package/out/zqlite/src/resolve-scalar-subqueries.js.map +1 -1
  966. package/out/zqlite/src/sqlite-cost-model.d.ts.map +1 -1
  967. package/out/zqlite/src/sqlite-cost-model.js +52 -1
  968. package/out/zqlite/src/sqlite-cost-model.js.map +1 -1
  969. package/out/zqlite/src/sqlite-stat-fanout.d.ts.map +1 -1
  970. package/out/zqlite/src/sqlite-stat-fanout.js +5 -31
  971. package/out/zqlite/src/sqlite-stat-fanout.js.map +1 -1
  972. package/out/zqlite/src/sqlite-stat4-sample.d.ts +37 -0
  973. package/out/zqlite/src/sqlite-stat4-sample.d.ts.map +1 -0
  974. package/out/zqlite/src/sqlite-stat4-sample.js +61 -0
  975. package/out/zqlite/src/sqlite-stat4-sample.js.map +1 -0
  976. package/out/zqlite/src/table-source.d.ts +87 -2
  977. package/out/zqlite/src/table-source.d.ts.map +1 -1
  978. package/out/zqlite/src/table-source.js +276 -42
  979. package/out/zqlite/src/table-source.js.map +1 -1
  980. package/package.json +4 -5
  981. package/out/replicache/src/kv/idb-store-with-mem-fallback.d.ts +0 -25
  982. package/out/replicache/src/kv/idb-store-with-mem-fallback.d.ts.map +0 -1
  983. package/out/replicache/src/kv/idb-store-with-mem-fallback.js +0 -83
  984. package/out/replicache/src/kv/idb-store-with-mem-fallback.js.map +0 -1
  985. package/out/zero-cache/src/services/change-streamer/vfs-watermark-poller.d.ts +0 -29
  986. package/out/zero-cache/src/services/change-streamer/vfs-watermark-poller.d.ts.map +0 -1
  987. package/out/zero-cache/src/services/change-streamer/vfs-watermark-poller.js +0 -154
  988. package/out/zero-cache/src/services/change-streamer/vfs-watermark-poller.js.map +0 -1
@@ -1,28 +1,80 @@
1
+ import { must } from "../../../../../shared/src/must.js";
1
2
  import { upstreamSchema } from "../../../types/shards.js";
2
3
  import { isPostgresError } from "../../../types/pg.js";
3
4
  import { toBigInt, toStateVersionString } from "./lsn.js";
4
5
  import { runTx } from "../../../db/run-transaction.js";
5
- import { createReplica, metadataPublicationName, replicationSlotExpression, replicationSlotPrefix } from "./schema/shard.js";
6
+ import "./schema/replica-stage-enum.js";
7
+ import { createReplica, getReplicaState, getRestoreCandidates, metadataPublicationName, replicationSlotExpression, replicationSlotPrefix } from "./schema/shard.js";
8
+ import { AutoResetSignal } from "../../change-streamer/schema/tables.js";
9
+ import "../../../types/pg-versions.js";
6
10
  import { orTimeout } from "../../../types/timeout.js";
7
11
  import { createReplicationSessionFor, keepSlotActiveUntilTakenOver } from "./logical-replication/stream.js";
8
12
  import { PG_CONFIGURATION_LIMIT_EXCEEDED, PG_INSUFFICIENT_PRIVILEGE } from "@drdgvhbh/postgres-error-codes";
9
13
  //#region ../zero-cache/src/services/change-source/pg/replication-slots.ts
10
- var CREATE_REPLICATION_SLOT_TIMEOUT_MS = 3e4;
14
+ var CREATE_REPLICATION_SLOT_TIMEOUT_MS = 6e4;
11
15
  var SERVER_LOCK_TIMEOUT_MS = CREATE_REPLICATION_SLOT_TIMEOUT_MS - 1e3;
12
- async function createReplicationSlot(lc, session, { slotName, failover, temporary, lockTimeout = SERVER_LOCK_TIMEOUT_MS }) {
16
+ async function createReplicationSlot(lc, session, { slotName, failover, temporary, lockTimeout = SERVER_LOCK_TIMEOUT_MS, diagnosticsDB }) {
13
17
  await session.unsafe(`SET lock_timeout = ${lockTimeout}`);
18
+ const { pgVersion, pid: walsenderPID } = (await session.unsafe(`
19
+ SELECT current_setting('server_version_num') as "pgVersion",
20
+ pg_backend_pid() as "pid";
21
+ `))[0];
14
22
  const maybeTemporary = temporary ? "TEMPORARY" : "";
15
- const options = failover ? "(FAILOVER)" : "";
23
+ const options = failover && pgVersion >= 17e4 ? "(FAILOVER)" : "";
16
24
  const raced = await orTimeout(session.unsafe(`
17
25
  CREATE_REPLICATION_SLOT "${slotName}" ${maybeTemporary} LOGICAL pgoutput ${options}`), CREATE_REPLICATION_SLOT_TIMEOUT_MS);
18
26
  if (raced === "timed-out") {
27
+ if (diagnosticsDB) await logSlotCreationBlockers(lc, diagnosticsDB, walsenderPID, slotName);
19
28
  session.end().catch((e) => lc.warn?.(`Error closing timed out replication slot session`, e));
20
- throw new Error(`Timed out after ${CREATE_REPLICATION_SLOT_TIMEOUT_MS} ms creating replication slot ${slotName}. Crashing to force a clean restart.`);
29
+ throw new Error(`Timed out after ${CREATE_REPLICATION_SLOT_TIMEOUT_MS} ms creating replication slot ${slotName}.`);
21
30
  }
22
31
  const [slot] = raced;
23
32
  lc.info?.(`Created replication slot ${slotName}`, slot);
24
33
  return slot;
25
34
  }
35
+ var SLOT_DIAGNOSTICS_TIMEOUT_MS = 5e3;
36
+ var SLOT_DIAGNOSTICS_MAX_TRANSACTIONS = 20;
37
+ /**
38
+ * Best-effort logging of what a timed out CREATE_REPLICATION_SLOT was waiting
39
+ * on: the walsender's wait event and blocking pids, and the oldest
40
+ * transactions holding an xid. Slot creation waits for every such transaction
41
+ * on the instance (in all databases), each with its own lock_timeout, so a
42
+ * chain of overlapping transactions can exceed the client-side timeout
43
+ * without the lock_timeout ever firing.
44
+ *
45
+ * Query text is deliberately omitted since it can contain row values.
46
+ *
47
+ * Exported for testing.
48
+ */
49
+ async function logSlotCreationBlockers(lc, sql, walsenderPID, slotName) {
50
+ try {
51
+ const result = await orTimeout(Promise.all([sql`
52
+ SELECT pid, wait_event_type as "waitEventType", wait_event as "waitEvent",
53
+ pg_blocking_pids(pid) as "blockingPIDs"
54
+ FROM pg_stat_activity WHERE pid = ${walsenderPID}`, sql`
55
+ SELECT pid, datname, usename, application_name as "applicationName",
56
+ backend_type as "backendType", state,
57
+ wait_event_type as "waitEventType", wait_event as "waitEvent",
58
+ backend_xid::text as xid,
59
+ xact_start::text as "xactStart",
60
+ extract(epoch from now() - xact_start)::float8 as "xactAgeSec"
61
+ FROM pg_stat_activity
62
+ WHERE backend_xid IS NOT NULL AND pid <> ${walsenderPID}
63
+ ORDER BY xact_start NULLS LAST
64
+ LIMIT ${SLOT_DIAGNOSTICS_MAX_TRANSACTIONS}`]), SLOT_DIAGNOSTICS_TIMEOUT_MS);
65
+ if (result === "timed-out") {
66
+ lc.warn?.(`Timed out collecting diagnostics for slot ${slotName}`);
67
+ return;
68
+ }
69
+ const [[walsender], transactions] = result;
70
+ lc.warn?.(`Replication slot ${slotName} creation blocked`, {
71
+ walsender: walsender ?? null,
72
+ transactions
73
+ });
74
+ } catch (e) {
75
+ lc.warn?.(`Unable to collect diagnostics for slot ${slotName}`, e);
76
+ }
77
+ }
26
78
  /**
27
79
  * Replica and slot creation involves two sessions for proper coordination
28
80
  * with other replica management logic:
@@ -62,8 +114,15 @@ async function createReplicationSlot(lc, session, { slotName, failover, temporar
62
114
  * PostgresChangeSource takes over the slot to process the stream in earnest.
63
115
  * It is also returned for cleanup in the case of failures (and for control
64
116
  * in unit tests).
117
+ *
118
+ * For replica's created in the `Restore` stage, the `generation` is
119
+ * initialized to an empty string instead of the slot's consistent point,
120
+ * since the slot is not being used for initial sync. It is the
121
+ * responsibiliy of the caller to call {@link initRestoreReplica} when
122
+ * the source replica has been selected for restoring, which will carry
123
+ * over the `generation` and other relevant values from the source.
65
124
  */
66
- async function createReplicaAndSlot(lc, sql, sessionName, shard, replicaID, failover, backupOptions, captureSnapshot) {
125
+ async function createReplicaAndSlot(lc, sql, sessionName, shard, epoch, replicaID, failover, backupOptions, captureSnapshot, stage) {
67
126
  const replicationSession = createReplicationSessionFor(sql, sessionName);
68
127
  const lockName = replicationSlotManagementLock(shard);
69
128
  const slotPoolPrefix = replicationSlotPrefix(shard);
@@ -73,6 +132,14 @@ async function createReplicaAndSlot(lc, sql, sessionName, shard, replicaID, fail
73
132
  try {
74
133
  return await runTx(sql, async (tx) => {
75
134
  await tx`SELECT pg_advisory_xact_lock(hashtext(${lockName}))`;
135
+ if (stage === 0) {
136
+ const others = await getRestoreCandidates(tx, shard, epoch);
137
+ lc.info?.(`current replicas at epoch ${epoch}`, { replicas: others });
138
+ if (others.length) {
139
+ const [{ id, stage, active }] = others;
140
+ if (stage === 0 && active) throw new AutoResetSignal(`another replica (${id}) is performing initial sync`);
141
+ }
142
+ }
76
143
  const names = await tx`
77
144
  SELECT slot_name as name FROM pg_replication_slots
78
145
  WHERE slot_name LIKE ${slotPoolPrefix + "%"};
@@ -87,15 +154,17 @@ async function createReplicaAndSlot(lc, sql, sessionName, shard, replicaID, fail
87
154
  }
88
155
  const slot = await createReplicationSlot(lc, replicationSession, {
89
156
  slotName,
90
- failover
157
+ failover,
158
+ diagnosticsDB: sql
91
159
  });
92
160
  const capturedSnapshot = await captureSnapshot(slot.snapshot_name);
93
161
  const initialSession = await keepSlotActiveUntilTakenOver(lc, replicationSession, slot.slot_name, metadataPublicationName(shard.appID, shard.shardNum), toBigInt(slot.consistent_point));
94
- await createReplica(tx, shard, replicaID, slot.slot_name, toStateVersionString(slot.consistent_point), backupOptions);
162
+ await createReplica(tx, shard, replicaID, slot.slot_name, epoch, stage === 0 ? toStateVersionString(slot.consistent_point) : "", backupOptions, stage);
95
163
  return {
96
164
  slot,
97
165
  capturedSnapshot,
98
- initialSession
166
+ initialSession,
167
+ replica: must(await getReplicaState(tx, shard, replicaID), `replica ${replicaID} was not created`)
99
168
  };
100
169
  });
101
170
  } catch (e) {
@@ -114,33 +183,78 @@ async function createReplicaAndSlot(lc, sql, sessionName, shard, replicaID, fail
114
183
  if (slotName) {
115
184
  lc.warn?.(`deleting slot ${slotName} due to error`, e);
116
185
  await replicationSession.end();
117
- await sql`SELECT pg_drop_replication_slot(${slotName})`;
186
+ await dropUnclaimedSlots(lc, sql, shard);
118
187
  }
119
188
  throw e;
120
189
  }
121
190
  }
122
191
  }
123
192
  /**
124
- * Deletes "old" replicas (i.e. those with a lower rank than the current)
125
- * and attempts to drop replication slots that are not associated with any
126
- * replica.
193
+ * Claims the inactive slot of the given replica for use by this task, opening
194
+ * a replication session to mark it as active. The process should follow up by
195
+ * taking over the slot via the PostgresChangeSource.
127
196
  *
128
- * If a slot could not be dropped because there is still an active subscriber,
129
- * it will be reflected in the `draining` count that is returned. When there
130
- * are draining slots, the method should be retried until all orphaned slots
131
- * have been dropped.
197
+ * The replica is identified by its ID (and not just its slot) because rows of
198
+ * replicas whose slots were dropped outside of zero-cache's control may share
199
+ * the slot name.
132
200
  */
133
- async function dropOldReplicasAndSlots(lc, sql, shard, beforeRank) {
201
+ async function claimSlotForResumption(lc, sql, shard, sessionName, { id: replicaID, slot }) {
202
+ const replicationSession = createReplicationSessionFor(sql, sessionName);
203
+ const lockName = replicationSlotManagementLock(shard);
134
204
  const replicasTable = `${upstreamSchema(shard)}.replicas`;
135
- const oldReplicas = await sql`
136
- SELECT id, rank::float8, slot, version, "initialSyncContext", "subscriberContext"
137
- FROM ${sql(replicasTable)} WHERE rank < ${beforeRank};
138
- `;
139
- if (oldReplicas.length) {
140
- lc.info?.(`Deleting ${oldReplicas.length} old replica(s)`, { oldReplicas });
141
- await sql`DELETE FROM ${sql(replicasTable)} WHERE rank < ${beforeRank}`;
205
+ try {
206
+ const reserved = await runTx(sql, async (tx) => {
207
+ await tx`SELECT pg_advisory_xact_lock(hashtext(${lockName}))`;
208
+ const replicas = await tx`
209
+ SELECT active, confirmed_flush_lsn as lsn
210
+ FROM pg_replication_slots
211
+ JOIN ${tx(replicasTable)} replica on slot_name = slot
212
+ WHERE slot_name = ${slot} AND replica.id = ${replicaID};
213
+ `;
214
+ if (replicas.length === 0) {
215
+ lc.warn?.(`no replica ${replicaID} found for slot ${slot}`);
216
+ return null;
217
+ }
218
+ const [{ active, lsn }] = replicas;
219
+ if (active) {
220
+ lc.warn?.(`replica ${replicaID} for slot ${slot} is active and cannot be claimed`);
221
+ return null;
222
+ }
223
+ await tx`
224
+ UPDATE ${tx(replicasTable)} SET "stage" = ${2} WHERE id = ${replicaID};
225
+ `;
226
+ return {
227
+ slot,
228
+ replica: must(await getReplicaState(tx, shard, replicaID), `replica ${replicaID} disappeared`),
229
+ reservation: await keepSlotActiveUntilTakenOver(lc, replicationSession, slot, metadataPublicationName(shard.appID, shard.shardNum), toBigInt(lsn))
230
+ };
231
+ });
232
+ lc.info?.(`successfully claimed slot ${slot}`);
233
+ return reserved;
234
+ } catch (e) {
235
+ lc.error?.(`unable to claim replication slot ${slot}`, e);
236
+ await replicationSession.end();
237
+ return null;
142
238
  }
143
- return dropUnclaimedSlots(lc, sql, shard);
239
+ }
240
+ function dropInactiveSlotsAndReplicas(lc, sql, shard, slots) {
241
+ const lockName = replicationSlotManagementLock(shard);
242
+ const replicasTable = `${upstreamSchema(shard)}.replicas`;
243
+ return runTx(sql, async (tx) => {
244
+ await tx`SELECT pg_advisory_xact_lock(hashtext(${lockName}))`;
245
+ const dropped = await tx`
246
+ SELECT slot_name as slot, replica.id as "replicaID", pg_drop_replication_slot(slot_name)
247
+ FROM pg_replication_slots
248
+ LEFT JOIN ${tx(replicasTable)} replica on slot_name = slot
249
+ WHERE slot_name IN ${tx(slots)} AND NOT active;
250
+ `;
251
+ if (dropped.length) lc.info?.(`dropped ${dropped.length} inactive replication slot(s)`, { dropped });
252
+ const replicas = dropped.map(({ replicaID }) => replicaID).filter((id) => id !== null);
253
+ if (replicas.length) {
254
+ await tx`DELETE FROM ${tx(replicasTable)} WHERE id IN ${tx(replicas)}`;
255
+ lc.info?.(`deleted ${replicas.length} old replica(s)`, { replicas });
256
+ }
257
+ });
144
258
  }
145
259
  function dropUnclaimedSlots(lc, sql, shard) {
146
260
  const lockName = replicationSlotManagementLock(shard);
@@ -157,6 +271,14 @@ function dropUnclaimedSlots(lc, sql, shard) {
157
271
  AND replica.id IS NULL;
158
272
  `;
159
273
  if (dropped.length) lc.info?.(`dropped inactive replication slots`, { dropped });
274
+ const orphaned = await tx`
275
+ DELETE FROM ${tx(replicasTable)} replica
276
+ WHERE NOT EXISTS (
277
+ SELECT 1 FROM pg_replication_slots WHERE slot_name = replica.slot
278
+ )
279
+ RETURNING id;
280
+ `;
281
+ if (orphaned.length) lc.warn?.(`deleted replicas whose slots no longer exist`, { replicas: orphaned.map(({ id }) => id) });
160
282
  const remaining = await tx`
161
283
  SELECT slot_name as slot, active_pid as pid, replica.id as id
162
284
  FROM pg_replication_slots
@@ -190,6 +312,6 @@ function replicationSlotManagementLock(shard) {
190
312
  return `replication-slot-management:${shard.appID}_${shard.shardNum}`;
191
313
  }
192
314
  //#endregion
193
- export { createReplicaAndSlot, createReplicationSlot, dropOldReplicasAndSlots };
315
+ export { claimSlotForResumption, createReplicaAndSlot, createReplicationSlot, dropInactiveSlotsAndReplicas };
194
316
 
195
317
  //# sourceMappingURL=replication-slots.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"replication-slots.js","names":[],"sources":["../../../../../../../zero-cache/src/services/change-source/pg/replication-slots.ts"],"sourcesContent":["import type {Readable} from 'node:stream';\nimport {\n PG_CONFIGURATION_LIMIT_EXCEEDED,\n PG_INSUFFICIENT_PRIVILEGE,\n} from '@drdgvhbh/postgres-error-codes';\nimport type {LogContext} from '@rocicorp/logger';\nimport type postgres from 'postgres';\nimport {runTx} from '../../../db/run-transaction.ts';\nimport {isPostgresError, type PostgresDB} from '../../../types/pg.ts';\nimport {upstreamSchema, type ShardID} from '../../../types/shards.ts';\nimport {orTimeout} from '../../../types/timeout.ts';\nimport {\n createReplicationSessionFor,\n keepSlotActiveUntilTakenOver,\n} from './logical-replication/stream.ts';\nimport {toBigInt, toStateVersionString} from './lsn.ts';\nimport {\n createReplica,\n metadataPublicationName,\n replicationSlotExpression,\n replicationSlotPrefix,\n type BackupOptions,\n} from './schema/shard.ts';\n\n// Record returned by `CREATE_REPLICATION_SLOT`\nexport type ReplicationSlot = {\n slot_name: string;\n consistent_point: string;\n snapshot_name: string;\n output_plugin: string;\n};\n\nexport type ReplicationSlotResult<T> = {\n slot: ReplicationSlot;\n capturedSnapshot: T;\n initialSession: Readable;\n};\n\nexport type CreateSlotSpec = {\n slotName: string;\n\n // Note: must be false if pgVersion < PG_17. Caller must verify.\n failover?: boolean;\n\n // Create a temporary slot (i.e. not persisted, and automatically\n // cleaned up when the replication session ends).\n temporary?: boolean;\n\n // For overriding in tests.\n lockTimeout?: number;\n};\n\n// When creating a replication slot, Postgres waits for open transactions\n// to complete before reserving a consistent_point (LSN) in the WAL and creating\n// a matching transaction snapshot. As such, it can technically take an arbitrary\n// amount of time (e.g. DDL operations, table-wide operations, etc.).\n//\n// However, to detect pathological situations, bound the amount of time that\n// the server waits for replication slot creation, so that a continual failure to\n// create a replication slot is surfaced by errors / alerts.\nconst CREATE_REPLICATION_SLOT_TIMEOUT_MS = 30_000;\n\n// The lock_timeout is set 1s before the client-side orTimeout so that\n// Postgres reliably aborts first and tears down the walsender cleanly.\n// The client-side timeout remains as a fallback for network-level failures.\nconst SERVER_LOCK_TIMEOUT_MS = CREATE_REPLICATION_SLOT_TIMEOUT_MS - 1_000;\n\n// Note: The replication connection does not support the extended query protocol,\n// so all commands must be sent using sql.unsafe(). This is technically safe\n// because all placeholder values are under our control (i.e. \"slotName\").\nexport async function createReplicationSlot(\n lc: LogContext,\n session: postgres.Sql,\n {\n slotName,\n failover,\n temporary,\n lockTimeout = SERVER_LOCK_TIMEOUT_MS,\n }: CreateSlotSpec,\n): Promise<ReplicationSlot> {\n // CREATE_REPLICATION_SLOT can hang indefinitely waiting for long-running\n // transactions to finish: internally it calls SnapBuildWaitSnapshot →\n // XactLockTableWait → LockAcquire on each running XID. statement_timeout\n // does NOT apply to replication commands, but lock_timeout does (it governs\n // the heavyweight lock wait inside LockAcquire). Setting it here causes\n // Postgres to raise ERRCODE_LOCK_NOT_AVAILABLE and cleanly tear down the\n // walsender, rather than relying solely on the client-side orTimeout\n // which can leave an orphaned backend.\n //\n // An orphaned walsender is actively harmful: by this point the replication\n // slot has already been created and is pinning WAL retention and catalog_xmin.\n // Worse, the slot is marked `active` (the walsender PID is still alive), so\n // the existing cleanup code (which drops inactive slots on retry) can't\n // reclaim it. Without lock_timeout the orphan persists until TCP keepalive\n // fires (~2h default) or the blocking transaction finishes.\n await session.unsafe(`SET lock_timeout = ${lockTimeout}`);\n\n const maybeTemporary = temporary ? 'TEMPORARY' : '';\n const options = failover ? '(FAILOVER)' : '';\n const createSlot = session.unsafe<ReplicationSlot[]>(/*sql*/ `\n CREATE_REPLICATION_SLOT \"${slotName}\" ${maybeTemporary} LOGICAL pgoutput ${options}`);\n\n const raced = await orTimeout(createSlot, CREATE_REPLICATION_SLOT_TIMEOUT_MS);\n if (raced === 'timed-out') {\n // Create slot can block indefinitely waiting for old transactions. End\n // this connection in the background and fail fast so the process restarts.\n void session\n .end()\n .catch(e =>\n lc.warn?.(`Error closing timed out replication slot session`, e),\n );\n throw new Error(\n `Timed out after ${CREATE_REPLICATION_SLOT_TIMEOUT_MS} ms creating replication slot ${slotName}. ` +\n `Crashing to force a clean restart.`,\n );\n }\n const [slot] = raced;\n lc.info?.(`Created replication slot ${slotName}`, slot);\n return slot;\n}\n\n/**\n * Replica and slot creation involves two sessions for proper coordination\n * with other replica management logic:\n *\n * * A normal transaction is started and acquires an advisory lock for\n * replica slot management. This is the same lock that cleanup logic\n * acquires before cleaning up replication slots.\n * * With the lock held, a new replication slot is created in a\n * replication session. The API of CREATE_REPLICATION_SLOT is such\n * that it cannot be done in a transaction, and cannot be followed by\n * any writes, or else its snapshot (which is needed for initial sync)\n * would be invalidated.\n * * Once the slot is created, the slot and replica information are recorded\n * in the `replicas` table before releasing the lock.\n *\n * This locking ensures that:\n * 1. multiple replication managers attempting to create a replication slot\n * will not use the same name for the replication slot (which is selected\n * from a pool of reused names).\n * 2. Running replication managers (which use an earlier replica of a lower\n * rank) will not delete the new slot during their cleanup logic, since\n * the slot will belong to a replica of a higher rank.\n *\n * When the replication slot is created, `captureSnapshot` callback is first\n * run while the snapshot at the consistent point is available. The callback\n * must capture the snapshot in postgres (e.g. `SET TRANSACTION SNAPSHOT`)\n * in order to use it. Once the callback completes, a placeholder replication\n * session (i.e. that does not consume any messages) is started, in order to\n * reserve the slot by mark it \"active\", effectively distinguishing the\n * initializing session from a failed or abandoned session.\n *\n * Note that starting the replication session releases the initial snapshot,\n * which is why the callback must capture it synchronously, before the\n * replication session is started.\n *\n * The placeholder replication session is closed when the\n * PostgresChangeSource takes over the slot to process the stream in earnest.\n * It is also returned for cleanup in the case of failures (and for control\n * in unit tests).\n */\nexport async function createReplicaAndSlot<T>(\n lc: LogContext,\n sql: PostgresDB,\n sessionName: string,\n shard: ShardID,\n replicaID: string,\n failover: boolean,\n backupOptions: BackupOptions,\n captureSnapshot: (snapshot: string) => Promise<T>,\n): Promise<ReplicationSlotResult<T>> {\n // Note: The replicationSession is closed by keepSlotActiveUntilTakenOver,\n // and only closed in this function if an error occurrs.\n const replicationSession = createReplicationSessionFor(sql, sessionName);\n const lockName = replicationSlotManagementLock(shard);\n const slotPoolPrefix = replicationSlotPrefix(shard);\n\n for (let first = true; ; first = false) {\n await dropUnclaimedSlots(lc, sql, shard);\n\n let slotName: string | undefined;\n try {\n return await runTx(sql, async tx => {\n await tx`SELECT pg_advisory_xact_lock(hashtext(${lockName}))`;\n\n // Pick an available slotName from the slotPoolPrefix pool.\n const names = await tx<{name: string}[]> /*sql*/ `\n SELECT slot_name as name FROM pg_replication_slots\n WHERE slot_name LIKE ${slotPoolPrefix + '%'};\n `.values();\n const inUse = new Set(names.flat());\n for (let next = 0; ; next++) {\n const candidateName = `${slotPoolPrefix}${slotPoolSuffix(next)}`;\n if (!inUse.has(candidateName)) {\n slotName = candidateName;\n break;\n }\n }\n\n const slot = await createReplicationSlot(lc, replicationSession, {\n slotName,\n failover,\n });\n const capturedSnapshot = await captureSnapshot(slot.snapshot_name);\n const initialSession = await keepSlotActiveUntilTakenOver(\n lc,\n replicationSession,\n slot.slot_name,\n metadataPublicationName(shard.appID, shard.shardNum),\n toBigInt(slot.consistent_point),\n );\n\n await createReplica(\n tx,\n shard,\n replicaID,\n slot.slot_name,\n toStateVersionString(slot.consistent_point),\n backupOptions,\n );\n\n return {slot, capturedSnapshot, initialSession};\n });\n } catch (e) {\n if (first && isPostgresError(e, PG_INSUFFICIENT_PRIVILEGE)) {\n // Some Postgres variants (e.g. Google Cloud SQL) require that\n // the user have the REPLICATION role in order to create a slot.\n // Note that this must be done by the upstreamDB connection, and\n // does not work in the replicationSession itself.\n await sql`ALTER ROLE current_user WITH REPLICATION`;\n lc.info?.(`Added the REPLICATION role to database user`);\n continue;\n }\n // Note: This is currently manually tested since max_replication_slots\n // is a PG startup parameter that other tests depend on.\n // TODO: Figure out a way to unit test this (with the full PG setup).\n if (first && isPostgresError(e, PG_CONFIGURATION_LIMIT_EXCEEDED)) {\n lc.warn?.(\n `Reached max replication slots. Attempting to clean up unused slots`,\n e,\n );\n // Drop any inactive replicas from failed initial syncs (e.g. inactive slots).\n const replicasTable = `${upstreamSchema(shard)}.replicas`;\n await sql`\n DELETE FROM ${sql(replicasTable)} USING pg_replication_slots slots\n WHERE replicas.slot = slots.slot_name AND NOT slots.active`;\n continue; // then let dropUnclaimedSlots() perform its cleanup\n }\n // Otherwise, clean up any created slot if something went wrong.\n if (slotName) {\n lc.warn?.(`deleting slot ${slotName} due to error`, e);\n await replicationSession.end();\n await sql`SELECT pg_drop_replication_slot(${slotName})`;\n }\n throw e;\n }\n }\n}\n\n/**\n * Deletes \"old\" replicas (i.e. those with a lower rank than the current)\n * and attempts to drop replication slots that are not associated with any\n * replica.\n *\n * If a slot could not be dropped because there is still an active subscriber,\n * it will be reflected in the `draining` count that is returned. When there\n * are draining slots, the method should be retried until all orphaned slots\n * have been dropped.\n */\nexport async function dropOldReplicasAndSlots(\n lc: LogContext,\n sql: PostgresDB,\n shard: ShardID,\n beforeRank: bigint,\n): Promise<{dropped: number; active: number; draining: number}> {\n const replicasTable = `${upstreamSchema(shard)}.replicas`;\n const oldReplicas = await sql`\n SELECT id, rank::float8, slot, version, \"initialSyncContext\", \"subscriberContext\"\n FROM ${sql(replicasTable)} WHERE rank < ${beforeRank};\n `;\n if (oldReplicas.length) {\n lc.info?.(`Deleting ${oldReplicas.length} old replica(s)`, {oldReplicas});\n await sql`DELETE FROM ${sql(replicasTable)} WHERE rank < ${beforeRank}`;\n }\n\n return dropUnclaimedSlots(lc, sql, shard);\n}\n\nfunction dropUnclaimedSlots(\n lc: LogContext,\n sql: PostgresDB,\n shard: ShardID,\n): Promise<{dropped: number; active: number; draining: number}> {\n // The slot / replica cleanup happens within a transaction while holding\n // the replication slot management lock for this shard, to ensure that no\n // slot that belongs to a newer replica is dropped.\n const lockName = replicationSlotManagementLock(shard);\n const slotExpression = replicationSlotExpression(shard);\n const replicasTable = `${upstreamSchema(shard)}.replicas`;\n\n return runTx(sql, async tx => {\n await tx`SELECT pg_advisory_xact_lock(hashtext(${lockName}))`;\n\n const dropped = await tx /*sql*/ `\n SELECT slot_name as slot, pg_drop_replication_slot(slot_name) \n FROM pg_replication_slots\n LEFT JOIN ${tx(replicasTable)} replica on slot_name = slot\n WHERE slot_name LIKE ${slotExpression} \n AND NOT active\n AND replica.id IS NULL;\n `;\n if (dropped.length) {\n lc.info?.(`dropped inactive replication slots`, {dropped});\n }\n\n const remaining = await tx<\n {slot: string; pid: number | null; id: string | null}[]\n > /*sql*/ `\n SELECT slot_name as slot, active_pid as pid, replica.id as id\n FROM pg_replication_slots\n LEFT JOIN ${tx(replicasTable)} replica on slot_name = slot\n WHERE slot_name LIKE ${slotExpression};\n `;\n if (remaining.length) {\n lc.info?.(`remaining replication slots`, {remaining});\n }\n\n let active = 0;\n let draining = 0;\n for (const {id} of remaining) {\n if (id === null) {\n draining++;\n } else {\n active++;\n }\n }\n\n return {\n dropped: dropped.length,\n active,\n draining,\n };\n });\n}\n\nconst ALPHABET = 'abcdefghijklmnopqrstuvwxyz';\n\n// Alphabetic notation is used as the slot pool suffix to distinguish\n// it from the (numeric) shard num that's also encoded in the slot name.\nexport function slotPoolSuffix(n: number) {\n n++; // Adjust for 0-based indexing\n\n let suffix = '';\n while (n > 0) {\n n--;\n suffix = ALPHABET[n % 26] + suffix;\n n = Math.floor(n / 26);\n }\n return suffix;\n}\n\nfunction replicationSlotManagementLock(shard: ShardID) {\n return `replication-slot-management:${shard.appID}_${shard.shardNum}`;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"replication-slots.js","names":[],"sources":["../../../../../../../zero-cache/src/services/change-source/pg/replication-slots.ts"],"sourcesContent":["import type {Readable} from 'node:stream';\nimport {\n PG_CONFIGURATION_LIMIT_EXCEEDED,\n PG_INSUFFICIENT_PRIVILEGE,\n} from '@drdgvhbh/postgres-error-codes';\nimport type {LogContext} from '@rocicorp/logger';\nimport type postgres from 'postgres';\nimport type {JSONObject} from '../../../../../shared/src/bigint-json.ts';\nimport {must} from '../../../../../shared/src/must.ts';\nimport {runTx} from '../../../db/run-transaction.ts';\nimport {PG_17} from '../../../types/pg-versions.ts';\nimport {isPostgresError, type PostgresDB} from '../../../types/pg.ts';\nimport {upstreamSchema, type ShardID} from '../../../types/shards.ts';\nimport {orTimeout} from '../../../types/timeout.ts';\nimport {AutoResetSignal} from '../../change-streamer/schema/tables.ts';\nimport {\n createReplicationSessionFor,\n keepSlotActiveUntilTakenOver,\n} from './logical-replication/stream.ts';\nimport {toBigInt, toStateVersionString} from './lsn.ts';\nimport {\n InitialSync,\n Restore,\n type ReplicaStage,\n} from './schema/replica-stage-enum.ts';\nimport {\n createReplica,\n getReplicaState,\n getRestoreCandidates,\n metadataPublicationName,\n replicationSlotExpression,\n replicationSlotPrefix,\n type BackupOptions,\n type ReplicaState,\n} from './schema/shard.ts';\n\n// Record returned by `CREATE_REPLICATION_SLOT`\nexport type ReplicationSlot = {\n slot_name: string;\n consistent_point: string;\n snapshot_name: string;\n output_plugin: string;\n};\n\nexport type ReplicationSlotResult<T> = {\n slot: ReplicationSlot;\n capturedSnapshot: T;\n initialSession: Readable;\n replica: ReplicaState;\n};\n\nexport type ReservedSlot = {\n slot: string;\n reservation: Readable;\n replica: ReplicaState;\n};\n\nexport type CreateSlotSpec = {\n slotName: string;\n\n // Note: ignored if pgVersion < PG_17.\n failover?: boolean;\n\n // Create a temporary slot (i.e. not persisted, and automatically\n // cleaned up when the replication session ends).\n temporary?: boolean;\n\n // For overriding in tests.\n lockTimeout?: number;\n\n // A (non-replication) connection to the same upstream instance, used to\n // log what slot creation was waiting on if it times out.\n diagnosticsDB?: PostgresDB | undefined;\n};\n\n// When creating a replication slot, Postgres waits for open transactions\n// to complete before reserving a consistent_point (LSN) in the WAL and creating\n// a matching transaction snapshot. As such, it can technically take an arbitrary\n// amount of time (e.g. DDL operations, table-wide operations, etc.).\n//\n// However, to detect pathological situations, bound the amount of time that\n// the server waits for replication slot creation, so that a continual failure to\n// create a replication slot is surfaced by errors / alerts.\nexport const CREATE_REPLICATION_SLOT_TIMEOUT_MS = 60_000;\n\n// The lock_timeout is set 1s before the client-side orTimeout so that\n// Postgres reliably aborts first and tears down the walsender cleanly.\n// The client-side timeout remains as a fallback for network-level failures.\nconst SERVER_LOCK_TIMEOUT_MS = CREATE_REPLICATION_SLOT_TIMEOUT_MS - 1_000;\n\n// Note: The replication connection does not support the extended query protocol,\n// so all commands must be sent using sql.unsafe(). This is technically safe\n// because all placeholder values are under our control (i.e. \"slotName\").\nexport async function createReplicationSlot(\n lc: LogContext,\n session: postgres.Sql,\n {\n slotName,\n failover,\n temporary,\n lockTimeout = SERVER_LOCK_TIMEOUT_MS,\n diagnosticsDB,\n }: CreateSlotSpec,\n): Promise<ReplicationSlot> {\n // CREATE_REPLICATION_SLOT can hang indefinitely waiting for long-running\n // transactions to finish: internally it calls SnapBuildWaitSnapshot →\n // XactLockTableWait → LockAcquire on each running XID. statement_timeout\n // does NOT apply to replication commands, but lock_timeout does (it governs\n // the heavyweight lock wait inside LockAcquire). Setting it here causes\n // Postgres to raise ERRCODE_LOCK_NOT_AVAILABLE and cleanly tear down the\n // walsender, rather than relying solely on the client-side orTimeout\n // which can leave an orphaned backend.\n //\n // An orphaned walsender is actively harmful: by this point the replication\n // slot has already been created and is pinning WAL retention and catalog_xmin.\n // Worse, the slot is marked `active` (the walsender PID is still alive), so\n // the existing cleanup code (which drops inactive slots on retry) can't\n // reclaim it. Without lock_timeout the orphan persists until TCP keepalive\n // fires (~2h default) or the blocking transaction finishes.\n await session.unsafe(`SET lock_timeout = ${lockTimeout}`);\n\n const {pgVersion, pid: walsenderPID} = (\n await session.unsafe<{pgVersion: number; pid: number}[]>(`\n SELECT current_setting('server_version_num') as \"pgVersion\",\n pg_backend_pid() as \"pid\";\n `)\n )[0];\n\n const maybeTemporary = temporary ? 'TEMPORARY' : '';\n const options = failover && pgVersion >= PG_17 ? '(FAILOVER)' : '';\n const createSlot = session.unsafe<ReplicationSlot[]>(/*sql*/ `\n CREATE_REPLICATION_SLOT \"${slotName}\" ${maybeTemporary} LOGICAL pgoutput ${options}`);\n\n const raced = await orTimeout(createSlot, CREATE_REPLICATION_SLOT_TIMEOUT_MS);\n if (raced === 'timed-out') {\n if (diagnosticsDB) {\n await logSlotCreationBlockers(lc, diagnosticsDB, walsenderPID, slotName);\n }\n // Create slot can block indefinitely waiting for old transactions. End\n // this connection in the background and fail fast so the process restarts.\n void session\n .end()\n .catch(e =>\n lc.warn?.(`Error closing timed out replication slot session`, e),\n );\n throw new Error(\n `Timed out after ${CREATE_REPLICATION_SLOT_TIMEOUT_MS} ms creating replication slot ${slotName}.`,\n );\n }\n const [slot] = raced;\n lc.info?.(`Created replication slot ${slotName}`, slot);\n return slot;\n}\n\nconst SLOT_DIAGNOSTICS_TIMEOUT_MS = 5_000;\nconst SLOT_DIAGNOSTICS_MAX_TRANSACTIONS = 20;\n\n/**\n * Best-effort logging of what a timed out CREATE_REPLICATION_SLOT was waiting\n * on: the walsender's wait event and blocking pids, and the oldest\n * transactions holding an xid. Slot creation waits for every such transaction\n * on the instance (in all databases), each with its own lock_timeout, so a\n * chain of overlapping transactions can exceed the client-side timeout\n * without the lock_timeout ever firing.\n *\n * Query text is deliberately omitted since it can contain row values.\n *\n * Exported for testing.\n */\nexport async function logSlotCreationBlockers(\n lc: LogContext,\n sql: PostgresDB,\n walsenderPID: number,\n slotName: string,\n) {\n try {\n const result = await orTimeout(\n Promise.all([\n sql<JSONObject[]> /*sql*/ `\n SELECT pid, wait_event_type as \"waitEventType\", wait_event as \"waitEvent\",\n pg_blocking_pids(pid) as \"blockingPIDs\"\n FROM pg_stat_activity WHERE pid = ${walsenderPID}`,\n sql<JSONObject[]> /*sql*/ `\n SELECT pid, datname, usename, application_name as \"applicationName\",\n backend_type as \"backendType\", state,\n wait_event_type as \"waitEventType\", wait_event as \"waitEvent\",\n backend_xid::text as xid,\n xact_start::text as \"xactStart\",\n extract(epoch from now() - xact_start)::float8 as \"xactAgeSec\"\n FROM pg_stat_activity\n WHERE backend_xid IS NOT NULL AND pid <> ${walsenderPID}\n ORDER BY xact_start NULLS LAST\n LIMIT ${SLOT_DIAGNOSTICS_MAX_TRANSACTIONS}`,\n ]),\n SLOT_DIAGNOSTICS_TIMEOUT_MS,\n );\n if (result === 'timed-out') {\n lc.warn?.(`Timed out collecting diagnostics for slot ${slotName}`);\n return;\n }\n const [[walsender], transactions] = result;\n lc.warn?.(`Replication slot ${slotName} creation blocked`, {\n walsender: walsender ?? null,\n transactions,\n });\n } catch (e) {\n lc.warn?.(`Unable to collect diagnostics for slot ${slotName}`, e);\n }\n}\n\n/**\n * Replica and slot creation involves two sessions for proper coordination\n * with other replica management logic:\n *\n * * A normal transaction is started and acquires an advisory lock for\n * replica slot management. This is the same lock that cleanup logic\n * acquires before cleaning up replication slots.\n * * With the lock held, a new replication slot is created in a\n * replication session. The API of CREATE_REPLICATION_SLOT is such\n * that it cannot be done in a transaction, and cannot be followed by\n * any writes, or else its snapshot (which is needed for initial sync)\n * would be invalidated.\n * * Once the slot is created, the slot and replica information are recorded\n * in the `replicas` table before releasing the lock.\n *\n * This locking ensures that:\n * 1. multiple replication managers attempting to create a replication slot\n * will not use the same name for the replication slot (which is selected\n * from a pool of reused names).\n * 2. Running replication managers (which use an earlier replica of a lower\n * rank) will not delete the new slot during their cleanup logic, since\n * the slot will belong to a replica of a higher rank.\n *\n * When the replication slot is created, `captureSnapshot` callback is first\n * run while the snapshot at the consistent point is available. The callback\n * must capture the snapshot in postgres (e.g. `SET TRANSACTION SNAPSHOT`)\n * in order to use it. Once the callback completes, a placeholder replication\n * session (i.e. that does not consume any messages) is started, in order to\n * reserve the slot by mark it \"active\", effectively distinguishing the\n * initializing session from a failed or abandoned session.\n *\n * Note that starting the replication session releases the initial snapshot,\n * which is why the callback must capture it synchronously, before the\n * replication session is started.\n *\n * The placeholder replication session is closed when the\n * PostgresChangeSource takes over the slot to process the stream in earnest.\n * It is also returned for cleanup in the case of failures (and for control\n * in unit tests).\n *\n * For replica's created in the `Restore` stage, the `generation` is\n * initialized to an empty string instead of the slot's consistent point,\n * since the slot is not being used for initial sync. It is the\n * responsibiliy of the caller to call {@link initRestoreReplica} when\n * the source replica has been selected for restoring, which will carry\n * over the `generation` and other relevant values from the source.\n */\nexport async function createReplicaAndSlot<T>(\n lc: LogContext,\n sql: PostgresDB,\n sessionName: string,\n shard: ShardID,\n epoch: number,\n replicaID: string,\n failover: boolean,\n backupOptions: BackupOptions,\n captureSnapshot: (snapshot: string) => Promise<T>,\n stage: ReplicaStage,\n): Promise<ReplicationSlotResult<T>> {\n // Note: The replicationSession is closed by keepSlotActiveUntilTakenOver,\n // and only closed in this function if an error occurrs.\n const replicationSession = createReplicationSessionFor(sql, sessionName);\n const lockName = replicationSlotManagementLock(shard);\n const slotPoolPrefix = replicationSlotPrefix(shard);\n\n for (let first = true; ; first = false) {\n await dropUnclaimedSlots(lc, sql, shard);\n\n let slotName: string | undefined;\n try {\n return await runTx(sql, async tx => {\n await tx`SELECT pg_advisory_xact_lock(hashtext(${lockName}))`;\n\n if (stage === InitialSync) {\n // With the lock acquired, ensure that only one initial sync is\n // active at a time. getRestoreCandidates() orders its results\n // with stage = InitialSync (and active = true) first.\n const others = await getRestoreCandidates(tx, shard, epoch);\n lc.info?.(`current replicas at epoch ${epoch}`, {replicas: others});\n if (others.length) {\n const [{id, stage, active}] = others;\n if (stage === InitialSync && active) {\n throw new AutoResetSignal(\n `another replica (${id}) is performing initial sync`,\n );\n }\n }\n }\n\n // Pick an available slotName from the slotPoolPrefix pool.\n const names = await tx<{name: string}[]> /*sql*/ `\n SELECT slot_name as name FROM pg_replication_slots\n WHERE slot_name LIKE ${slotPoolPrefix + '%'};\n `.values();\n const inUse = new Set(names.flat());\n for (let next = 0; ; next++) {\n const candidateName = `${slotPoolPrefix}${slotPoolSuffix(next)}`;\n if (!inUse.has(candidateName)) {\n slotName = candidateName;\n break;\n }\n }\n\n const slot = await createReplicationSlot(lc, replicationSession, {\n slotName,\n failover,\n diagnosticsDB: sql,\n });\n const capturedSnapshot = await captureSnapshot(slot.snapshot_name);\n const initialSession = await keepSlotActiveUntilTakenOver(\n lc,\n replicationSession,\n slot.slot_name,\n metadataPublicationName(shard.appID, shard.shardNum),\n toBigInt(slot.consistent_point),\n );\n\n await createReplica(\n tx,\n shard,\n replicaID,\n slot.slot_name,\n epoch,\n stage === InitialSync\n ? toStateVersionString(slot.consistent_point)\n : '', // initialized with initRestoreReplica\n backupOptions,\n stage,\n );\n\n const replica = must(\n await getReplicaState(tx, shard, replicaID),\n `replica ${replicaID} was not created`,\n );\n\n return {slot, capturedSnapshot, initialSession, replica};\n });\n } catch (e) {\n if (first && isPostgresError(e, PG_INSUFFICIENT_PRIVILEGE)) {\n // Some Postgres variants (e.g. Google Cloud SQL) require that\n // the user have the REPLICATION role in order to create a slot.\n // Note that this must be done by the upstreamDB connection, and\n // does not work in the replicationSession itself.\n await sql`ALTER ROLE current_user WITH REPLICATION`;\n lc.info?.(`Added the REPLICATION role to database user`);\n continue;\n }\n // Note: This is currently manually tested since max_replication_slots\n // is a PG startup parameter that other tests depend on.\n // TODO: Figure out a way to unit test this (with the full PG setup).\n if (first && isPostgresError(e, PG_CONFIGURATION_LIMIT_EXCEEDED)) {\n lc.warn?.(\n `Reached max replication slots. Attempting to clean up unused slots`,\n e,\n );\n // Drop any inactive replicas from failed initial syncs (e.g. inactive slots).\n const replicasTable = `${upstreamSchema(shard)}.replicas`;\n await sql`\n DELETE FROM ${sql(replicasTable)} USING pg_replication_slots slots\n WHERE replicas.slot = slots.slot_name AND NOT slots.active`;\n continue; // then let dropUnclaimedSlots() perform its cleanup\n }\n // Otherwise, clean up any created slot if something went wrong. The\n // slot may not exist (e.g. if its creation failed), and its name may\n // have been reused since the lock was released, so leave it to\n // dropUnclaimedSlots(), which only drops slots without a replica.\n if (slotName) {\n lc.warn?.(`deleting slot ${slotName} due to error`, e);\n await replicationSession.end();\n await dropUnclaimedSlots(lc, sql, shard);\n }\n throw e;\n }\n }\n}\n\n/**\n * Claims the inactive slot of the given replica for use by this task, opening\n * a replication session to mark it as active. The process should follow up by\n * taking over the slot via the PostgresChangeSource.\n *\n * The replica is identified by its ID (and not just its slot) because rows of\n * replicas whose slots were dropped outside of zero-cache's control may share\n * the slot name.\n */\nexport async function claimSlotForResumption(\n lc: LogContext,\n sql: PostgresDB,\n shard: ShardID,\n sessionName: string,\n {id: replicaID, slot}: Pick<ReplicaState, 'id' | 'slot'>,\n): Promise<ReservedSlot | null> {\n const replicationSession = createReplicationSessionFor(sql, sessionName);\n const lockName = replicationSlotManagementLock(shard);\n const replicasTable = `${upstreamSchema(shard)}.replicas`;\n\n try {\n const reserved = await runTx(sql, async tx => {\n await tx`SELECT pg_advisory_xact_lock(hashtext(${lockName}))`;\n\n const replicas = await tx<{active: boolean; lsn: string}[]> /*sql*/ `\n SELECT active, confirmed_flush_lsn as lsn\n FROM pg_replication_slots\n JOIN ${tx(replicasTable)} replica on slot_name = slot\n WHERE slot_name = ${slot} AND replica.id = ${replicaID};\n `;\n if (replicas.length === 0) {\n lc.warn?.(`no replica ${replicaID} found for slot ${slot}`);\n return null;\n }\n const [{active, lsn}] = replicas;\n if (active) {\n lc.warn?.(\n `replica ${replicaID} for slot ${slot} is active and cannot be claimed`,\n );\n return null;\n }\n // Mark the replica as Restoring.\n await tx`\n UPDATE ${tx(replicasTable)} SET \"stage\" = ${Restore} WHERE id = ${replicaID};\n `;\n const replica = must(\n await getReplicaState(tx, shard, replicaID),\n `replica ${replicaID} disappeared`,\n );\n\n return {\n slot,\n replica,\n reservation: await keepSlotActiveUntilTakenOver(\n lc,\n replicationSession,\n slot,\n metadataPublicationName(shard.appID, shard.shardNum),\n toBigInt(lsn),\n ),\n };\n });\n lc.info?.(`successfully claimed slot ${slot}`);\n return reserved;\n } catch (e) {\n lc.error?.(`unable to claim replication slot ${slot}`, e);\n await replicationSession.end();\n return null;\n }\n}\n\nexport function dropInactiveSlotsAndReplicas(\n lc: LogContext,\n sql: PostgresDB,\n shard: ShardID,\n slots: string[],\n) {\n const lockName = replicationSlotManagementLock(shard);\n const replicasTable = `${upstreamSchema(shard)}.replicas`;\n\n return runTx(sql, async tx => {\n await tx`SELECT pg_advisory_xact_lock(hashtext(${lockName}))`;\n\n const dropped = await tx<{slot: string; replicaID: string | null}[]>\n /*sql*/ `\n SELECT slot_name as slot, replica.id as \"replicaID\", pg_drop_replication_slot(slot_name) \n FROM pg_replication_slots\n LEFT JOIN ${tx(replicasTable)} replica on slot_name = slot\n WHERE slot_name IN ${tx(slots)} AND NOT active;\n `;\n if (dropped.length) {\n lc.info?.(`dropped ${dropped.length} inactive replication slot(s)`, {\n dropped,\n });\n }\n\n const replicas = dropped\n .map(({replicaID}) => replicaID)\n .filter(id => id !== null);\n if (replicas.length) {\n // Delete replicas associated with the inactive (and now dropped) slots.\n await tx\n /*sql*/ `DELETE FROM ${tx(replicasTable)} WHERE id IN ${tx(replicas)}`;\n lc.info?.(`deleted ${replicas.length} old replica(s)`, {replicas});\n }\n });\n}\n\nfunction dropUnclaimedSlots(\n lc: LogContext,\n sql: PostgresDB,\n shard: ShardID,\n): Promise<{dropped: number; active: number; draining: number}> {\n // The slot / replica cleanup happens within a transaction while holding\n // the replication slot management lock for this shard, to ensure that no\n // slot that belongs to a newer replica is dropped.\n const lockName = replicationSlotManagementLock(shard);\n const slotExpression = replicationSlotExpression(shard);\n const replicasTable = `${upstreamSchema(shard)}.replicas`;\n\n return runTx(sql, async tx => {\n await tx`SELECT pg_advisory_xact_lock(hashtext(${lockName}))`;\n\n const dropped = await tx /*sql*/ `\n SELECT slot_name as slot, pg_drop_replication_slot(slot_name) \n FROM pg_replication_slots\n LEFT JOIN ${tx(replicasTable)} replica on slot_name = slot\n WHERE slot_name LIKE ${slotExpression} \n AND NOT active\n AND replica.id IS NULL;\n `;\n if (dropped.length) {\n lc.info?.(`dropped inactive replication slots`, {dropped});\n }\n\n // Conversely, delete replicas whose slots no longer exist, e.g. because\n // they were dropped outside of zero-cache's control (such as in an\n // upstream failover). Slot names are reused, so such rows would otherwise\n // be associated with a new slot of the same name. This is done (and\n // committed) before the slot is created, both so that the rows are never\n // associated with it, and because CREATE_REPLICATION_SLOT waits for\n // transactions that have written (i.e. been assigned an xid).\n const orphaned = await tx<{id: string}[]> /*sql*/ `\n DELETE FROM ${tx(replicasTable)} replica\n WHERE NOT EXISTS (\n SELECT 1 FROM pg_replication_slots WHERE slot_name = replica.slot\n )\n RETURNING id;\n `;\n if (orphaned.length) {\n lc.warn?.(`deleted replicas whose slots no longer exist`, {\n replicas: orphaned.map(({id}) => id),\n });\n }\n\n const remaining = await tx<\n {slot: string; pid: number | null; id: string | null}[]\n > /*sql*/ `\n SELECT slot_name as slot, active_pid as pid, replica.id as id\n FROM pg_replication_slots\n LEFT JOIN ${tx(replicasTable)} replica on slot_name = slot\n WHERE slot_name LIKE ${slotExpression};\n `;\n if (remaining.length) {\n lc.info?.(`remaining replication slots`, {remaining});\n }\n\n let active = 0;\n let draining = 0;\n for (const {id} of remaining) {\n if (id === null) {\n draining++;\n } else {\n active++;\n }\n }\n\n return {\n dropped: dropped.length,\n active,\n draining,\n };\n });\n}\n\nconst ALPHABET = 'abcdefghijklmnopqrstuvwxyz';\n\n// Alphabetic notation is used as the slot pool suffix to distinguish\n// it from the (numeric) shard num that's also encoded in the slot name.\nexport function slotPoolSuffix(n: number) {\n n++; // Adjust for 0-based indexing\n\n let suffix = '';\n while (n > 0) {\n n--;\n suffix = ALPHABET[n % 26] + suffix;\n n = Math.floor(n / 26);\n }\n return suffix;\n}\n\nfunction replicationSlotManagementLock(shard: ShardID) {\n return `replication-slot-management:${shard.appID}_${shard.shardNum}`;\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index-predicate.d.ts","sourceRoot":"","sources":["../../../../../../../../zero-cache/src/services/change-source/pg/schema/index-predicate.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,cAAc,EAEd,kBAAkB,EACnB,MAAM,yBAAyB,CAAC;AAkBjC,eAAO,MAAM,2BAA2B,YACtC,oBAAoB,EACpB,kBAAkB,EAClB,sBAAsB,EACtB,sBAAsB,EACtB,kBAAkB,EAClB,oBAAoB,EACpB,6BAA6B,CACrB,CAAC;AAEX,MAAM,MAAM,0BAA0B,GACpC,CAAC,OAAO,2BAA2B,CAAC,CAAC,MAAM,CAAC,CAAC;AAE/C,MAAM,MAAM,oBAAoB,GAC5B;IAAC,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,cAAc,CAAA;CAAC,GAC9D;IAAC,QAAQ,CAAC,SAAS,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,0BAA0B,CAAA;CAAC,CAAC;AAE7E,KAAK,mBAAmB,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,GAAG;IACjE,QAAQ,CAAC,wBAAwB,CAAC,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC;CAChE,CAAC;AAEF,KAAK,kBAAkB,GAAG,IAAI,CAAC,kBAAkB,EAAE,SAAS,CAAC,GAAG;IAC9D,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC,CAAC;CACjE,CAAC;AAgEF,wBAAgB,+BAA+B,CAC7C,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,kBAAkB,GACxB,oBAAoB,CAetB"}
1
+ {"version":3,"file":"index-predicate.d.ts","sourceRoot":"","sources":["../../../../../../../../zero-cache/src/services/change-source/pg/schema/index-predicate.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,cAAc,EAEd,kBAAkB,EACnB,MAAM,yBAAyB,CAAC;AAmBjC,eAAO,MAAM,2BAA2B,YACtC,oBAAoB,EACpB,kBAAkB,EAClB,sBAAsB,EACtB,sBAAsB,EACtB,kBAAkB,EAClB,oBAAoB,EACpB,6BAA6B,CACrB,CAAC;AAEX,MAAM,MAAM,0BAA0B,GACpC,CAAC,OAAO,2BAA2B,CAAC,CAAC,MAAM,CAAC,CAAC;AAE/C,MAAM,MAAM,oBAAoB,GAC5B;IAAC,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,cAAc,CAAA;CAAC,GAC9D;IAAC,QAAQ,CAAC,SAAS,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,0BAA0B,CAAA;CAAC,CAAC;AAE7E,KAAK,mBAAmB,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,GAAG;IACjE,QAAQ,CAAC,wBAAwB,CAAC,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC;CAChE,CAAC;AAEF,KAAK,kBAAkB,GAAG,IAAI,CAAC,kBAAkB,EAAE,SAAS,CAAC,GAAG;IAC9D,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC,CAAC;CACjE,CAAC;AAoEF,wBAAgB,+BAA+B,CAC7C,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,kBAAkB,GACxB,oBAAoB,CAetB"}
@@ -3,6 +3,7 @@ var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
3
3
  var INTEGER_RE = /^[+-]?\d+$/;
4
4
  var WHITESPACE_RE = /\s/;
5
5
  var OPERATOR_TOKEN_RE = /^(?:::|<>|!=|<=|>=|=|<|>)/;
6
+ var UNSUPPORTED_OPERATOR_TOKEN_RE = /^(?:!~\*|!~|~\*|~)/;
6
7
  var INTEGER_TOKEN_RE = /^[+-]?\d+/;
7
8
  var WORD_TOKEN_RE = /^[A-Za-z_][A-Za-z0-9_$]*/;
8
9
  var SIMPLE_ESCAPES = {
@@ -80,9 +81,16 @@ var Parser = class {
80
81
  not
81
82
  };
82
83
  }
84
+ if (this.#take("IN")) {
85
+ this.expect("(");
86
+ const values = this.#parseOperandList(")");
87
+ this.expect(")");
88
+ return comparisons(left, values);
89
+ }
83
90
  const op = this.#tokens[this.#position]?.type;
84
91
  if (isComparison(op)) {
85
92
  this.#position++;
93
+ if (op === "=" && this.#takeIdentifier("ANY")) return comparisons(left, this.#parseLiteralArray());
86
94
  return {
87
95
  type: "comparison",
88
96
  left,
@@ -92,9 +100,31 @@ var Parser = class {
92
100
  }
93
101
  const next = this.#tokens[this.#position];
94
102
  if (next?.type === "identifier" && next.value.toUpperCase() === "COLLATE") throw new UnsupportedPredicateError("non-deterministic-collation");
103
+ if (next?.type === "unsupported" && UNSUPPORTED_OPERATOR_TOKEN_RE.test(next.value)) throw new UnsupportedPredicateError("unsupported-operator");
95
104
  if (next?.type === "identifier" && unsupportedOperatorWords.has(next.value.toUpperCase())) throw new UnsupportedPredicateError("unsupported-operator");
96
105
  return left;
97
106
  }
107
+ #parseLiteralArray() {
108
+ this.expect("(");
109
+ this.#expectIdentifier("ARRAY");
110
+ this.expect("[");
111
+ const values = this.#parseOperandList("]");
112
+ this.expect("]");
113
+ if (this.#take("::")) {
114
+ this.#parseCastName();
115
+ this.expect("[");
116
+ this.expect("]");
117
+ }
118
+ this.expect(")");
119
+ return values;
120
+ }
121
+ #parseOperandList(end) {
122
+ const values = [];
123
+ if (this.#tokens[this.#position]?.type === end) return values;
124
+ values.push(this.#parseOperand());
125
+ while (this.#take(",")) values.push(this.#parseOperand());
126
+ return values;
127
+ }
98
128
  #parseOperand() {
99
129
  let expression = this.#parsePrimary();
100
130
  while (this.#take("::")) expression = {
@@ -130,17 +160,27 @@ var Parser = class {
130
160
  #parseCastName() {
131
161
  const first = this.#expectIdentifier();
132
162
  const parts = [first];
163
+ let separator = ".";
133
164
  while (this.#take(".")) parts.push(this.#expectIdentifier());
134
165
  const next = this.#tokens[this.#position];
135
- if (first.toLowerCase() === "character" && next?.type === "identifier" && next.value.toLowerCase() === "varying") parts.push(this.#expectIdentifier());
166
+ if (first.toLowerCase() === "character" && next?.type === "identifier" && next.value.toLowerCase() === "varying") {
167
+ parts.push(this.#expectIdentifier());
168
+ separator = " ";
169
+ }
136
170
  if (this.#tokens[this.#position]?.type === "(") throw new UnsupportedPredicateError("unsupported-cast");
137
- return parts.join(".");
171
+ return parts.join(separator);
138
172
  }
139
- #expectIdentifier() {
173
+ #expectIdentifier(expected) {
140
174
  const token = this.#tokens[this.#position++];
141
- if (token?.type !== "identifier") throw new UnsupportedPredicateError("unsupported-cast");
175
+ if (token?.type !== "identifier" || expected !== void 0 && token.value.toUpperCase() !== expected) throw new UnsupportedPredicateError("unsupported-cast");
142
176
  return token.value;
143
177
  }
178
+ #takeIdentifier(expected) {
179
+ const token = this.#tokens[this.#position];
180
+ if (token?.type !== "identifier" || token.value.toUpperCase() !== expected) return false;
181
+ this.#position++;
182
+ return true;
183
+ }
144
184
  #take(type) {
145
185
  if (this.#tokens[this.#position]?.type !== type) return false;
146
186
  this.#position++;
@@ -152,13 +192,24 @@ var Parser = class {
152
192
  };
153
193
  var unsupportedOperatorWords = new Set([
154
194
  "ALL",
155
- "ANY",
156
195
  "BETWEEN",
157
196
  "ILIKE",
158
- "IN",
159
197
  "LIKE",
160
198
  "SIMILAR"
161
199
  ]);
200
+ function comparisons(left, values) {
201
+ if (values.length === 0) throw new UnsupportedPredicateError("unsupported-syntax");
202
+ const expressions = values.map((right) => ({
203
+ type: "comparison",
204
+ left,
205
+ op: "=",
206
+ right
207
+ }));
208
+ return expressions.length === 1 ? expressions[0] : {
209
+ type: "or",
210
+ expressions
211
+ };
212
+ }
162
213
  function normalize(expression, table) {
163
214
  switch (expression.type) {
164
215
  case "and":
@@ -419,7 +470,16 @@ function tokenize(sql) {
419
470
  i += operator.length;
420
471
  continue;
421
472
  }
422
- if (char === "(" || char === ")" || char === ".") {
473
+ const unsupportedOperator = UNSUPPORTED_OPERATOR_TOKEN_RE.exec(sql.slice(i))?.[0];
474
+ if (unsupportedOperator) {
475
+ tokens.push({
476
+ type: "unsupported",
477
+ value: unsupportedOperator
478
+ });
479
+ i += unsupportedOperator.length;
480
+ continue;
481
+ }
482
+ if (char === "(" || char === ")" || char === "[" || char === "]" || char === "," || char === ".") {
423
483
  tokens.push({ type: char });
424
484
  i++;
425
485
  continue;
@@ -448,7 +508,7 @@ function tokenize(sql) {
448
508
  literalType: "null",
449
509
  value: null
450
510
  });
451
- else if (keyword === "AND" || keyword === "OR" || keyword === "NOT" || keyword === "IS") tokens.push({ type: keyword });
511
+ else if (keyword === "AND" || keyword === "OR" || keyword === "NOT" || keyword === "IN" || keyword === "IS") tokens.push({ type: keyword });
452
512
  else tokens.push({
453
513
  type: "identifier",
454
514
  value: word.toLowerCase()