@rocicorp/zero 0.26.0-canary.2 → 0.26.0-canary.3

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 (333) hide show
  1. package/README.md +1 -1
  2. package/out/replicache/src/persist/collect-idb-databases.d.ts +4 -4
  3. package/out/replicache/src/persist/collect-idb-databases.d.ts.map +1 -1
  4. package/out/replicache/src/persist/collect-idb-databases.js +22 -19
  5. package/out/replicache/src/persist/collect-idb-databases.js.map +1 -1
  6. package/out/replicache/src/persist/refresh.d.ts.map +1 -1
  7. package/out/replicache/src/persist/refresh.js +0 -8
  8. package/out/replicache/src/persist/refresh.js.map +1 -1
  9. package/out/replicache/src/process-scheduler.d.ts +23 -0
  10. package/out/replicache/src/process-scheduler.d.ts.map +1 -1
  11. package/out/replicache/src/process-scheduler.js +50 -1
  12. package/out/replicache/src/process-scheduler.js.map +1 -1
  13. package/out/replicache/src/replicache-impl.d.ts +8 -0
  14. package/out/replicache/src/replicache-impl.d.ts.map +1 -1
  15. package/out/replicache/src/replicache-impl.js +11 -2
  16. package/out/replicache/src/replicache-impl.js.map +1 -1
  17. package/out/shared/src/falsy.d.ts +3 -0
  18. package/out/shared/src/falsy.d.ts.map +1 -0
  19. package/out/zero/package.json.js +1 -1
  20. package/out/zero/src/adapters/drizzle.js +1 -2
  21. package/out/zero/src/adapters/prisma.d.ts +2 -0
  22. package/out/zero/src/adapters/prisma.d.ts.map +1 -0
  23. package/out/zero/src/adapters/prisma.js +6 -0
  24. package/out/zero/src/adapters/prisma.js.map +1 -0
  25. package/out/zero/src/pg.js +4 -7
  26. package/out/zero/src/react.js +3 -1
  27. package/out/zero/src/react.js.map +1 -1
  28. package/out/zero/src/server.js +5 -8
  29. package/out/zero-cache/src/auth/load-permissions.d.ts +3 -2
  30. package/out/zero-cache/src/auth/load-permissions.d.ts.map +1 -1
  31. package/out/zero-cache/src/auth/load-permissions.js +14 -8
  32. package/out/zero-cache/src/auth/load-permissions.js.map +1 -1
  33. package/out/zero-cache/src/auth/write-authorizer.d.ts +6 -0
  34. package/out/zero-cache/src/auth/write-authorizer.d.ts.map +1 -1
  35. package/out/zero-cache/src/auth/write-authorizer.js +16 -3
  36. package/out/zero-cache/src/auth/write-authorizer.js.map +1 -1
  37. package/out/zero-cache/src/config/zero-config.d.ts +44 -8
  38. package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
  39. package/out/zero-cache/src/config/zero-config.js +53 -13
  40. package/out/zero-cache/src/config/zero-config.js.map +1 -1
  41. package/out/zero-cache/src/custom/fetch.d.ts +3 -0
  42. package/out/zero-cache/src/custom/fetch.d.ts.map +1 -1
  43. package/out/zero-cache/src/custom/fetch.js +26 -0
  44. package/out/zero-cache/src/custom/fetch.js.map +1 -1
  45. package/out/zero-cache/src/db/lite-tables.js +1 -1
  46. package/out/zero-cache/src/db/lite-tables.js.map +1 -1
  47. package/out/zero-cache/src/db/migration-lite.d.ts.map +1 -1
  48. package/out/zero-cache/src/db/migration-lite.js +9 -3
  49. package/out/zero-cache/src/db/migration-lite.js.map +1 -1
  50. package/out/zero-cache/src/db/migration.d.ts.map +1 -1
  51. package/out/zero-cache/src/db/migration.js +9 -3
  52. package/out/zero-cache/src/db/migration.js.map +1 -1
  53. package/out/zero-cache/src/db/specs.d.ts +4 -3
  54. package/out/zero-cache/src/db/specs.d.ts.map +1 -1
  55. package/out/zero-cache/src/db/specs.js +4 -1
  56. package/out/zero-cache/src/db/specs.js.map +1 -1
  57. package/out/zero-cache/src/db/transaction-pool.d.ts.map +1 -1
  58. package/out/zero-cache/src/db/transaction-pool.js +9 -3
  59. package/out/zero-cache/src/db/transaction-pool.js.map +1 -1
  60. package/out/zero-cache/src/server/inspector-delegate.d.ts +1 -1
  61. package/out/zero-cache/src/server/inspector-delegate.d.ts.map +1 -1
  62. package/out/zero-cache/src/server/inspector-delegate.js +11 -30
  63. package/out/zero-cache/src/server/inspector-delegate.js.map +1 -1
  64. package/out/zero-cache/src/server/main.js +1 -1
  65. package/out/zero-cache/src/server/main.js.map +1 -1
  66. package/out/zero-cache/src/server/priority-op.d.ts +8 -0
  67. package/out/zero-cache/src/server/priority-op.d.ts.map +1 -0
  68. package/out/zero-cache/src/server/priority-op.js +29 -0
  69. package/out/zero-cache/src/server/priority-op.js.map +1 -0
  70. package/out/zero-cache/src/server/syncer.d.ts +0 -1
  71. package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
  72. package/out/zero-cache/src/server/syncer.js +3 -21
  73. package/out/zero-cache/src/server/syncer.js.map +1 -1
  74. package/out/zero-cache/src/services/analyze.js +1 -1
  75. package/out/zero-cache/src/services/analyze.js.map +1 -1
  76. package/out/zero-cache/src/services/change-source/custom/change-source.d.ts.map +1 -1
  77. package/out/zero-cache/src/services/change-source/custom/change-source.js +4 -3
  78. package/out/zero-cache/src/services/change-source/custom/change-source.js.map +1 -1
  79. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts.map +1 -1
  80. package/out/zero-cache/src/services/change-source/pg/change-source.js +68 -13
  81. package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
  82. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts.map +1 -1
  83. package/out/zero-cache/src/services/change-source/pg/initial-sync.js +7 -2
  84. package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
  85. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.d.ts.map +1 -1
  86. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js +7 -4
  87. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js.map +1 -1
  88. package/out/zero-cache/src/services/change-source/pg/schema/ddl.d.ts +125 -180
  89. package/out/zero-cache/src/services/change-source/pg/schema/ddl.d.ts.map +1 -1
  90. package/out/zero-cache/src/services/change-source/pg/schema/init.d.ts.map +1 -1
  91. package/out/zero-cache/src/services/change-source/pg/schema/init.js +18 -10
  92. package/out/zero-cache/src/services/change-source/pg/schema/init.js.map +1 -1
  93. package/out/zero-cache/src/services/change-source/pg/schema/published.d.ts +36 -90
  94. package/out/zero-cache/src/services/change-source/pg/schema/published.d.ts.map +1 -1
  95. package/out/zero-cache/src/services/change-source/pg/schema/published.js +51 -14
  96. package/out/zero-cache/src/services/change-source/pg/schema/published.js.map +1 -1
  97. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts +31 -36
  98. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts.map +1 -1
  99. package/out/zero-cache/src/services/change-source/pg/schema/shard.js +24 -3
  100. package/out/zero-cache/src/services/change-source/pg/schema/shard.js.map +1 -1
  101. package/out/zero-cache/src/services/change-source/pg/schema/validation.d.ts +2 -2
  102. package/out/zero-cache/src/services/change-source/pg/schema/validation.d.ts.map +1 -1
  103. package/out/zero-cache/src/services/change-source/pg/schema/validation.js +2 -4
  104. package/out/zero-cache/src/services/change-source/pg/schema/validation.js.map +1 -1
  105. package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts +158 -53
  106. package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts.map +1 -1
  107. package/out/zero-cache/src/services/change-source/protocol/current/data.js +55 -10
  108. package/out/zero-cache/src/services/change-source/protocol/current/data.js.map +1 -1
  109. package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts +210 -72
  110. package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts.map +1 -1
  111. package/out/zero-cache/src/services/change-source/protocol/current.js +4 -2
  112. package/out/zero-cache/src/services/change-source/replica-schema.d.ts.map +1 -1
  113. package/out/zero-cache/src/services/change-source/replica-schema.js +19 -10
  114. package/out/zero-cache/src/services/change-source/replica-schema.js.map +1 -1
  115. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js +1 -1
  116. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -1
  117. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts +71 -25
  118. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts.map +1 -1
  119. package/out/zero-cache/src/services/change-streamer/change-streamer.js +1 -1
  120. package/out/zero-cache/src/services/change-streamer/change-streamer.js.map +1 -1
  121. package/out/zero-cache/src/services/change-streamer/schema/tables.d.ts +1 -0
  122. package/out/zero-cache/src/services/change-streamer/schema/tables.d.ts.map +1 -1
  123. package/out/zero-cache/src/services/change-streamer/schema/tables.js +6 -5
  124. package/out/zero-cache/src/services/change-streamer/schema/tables.js.map +1 -1
  125. package/out/zero-cache/src/services/change-streamer/storer.js +1 -1
  126. package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
  127. package/out/zero-cache/src/services/change-streamer/subscriber.d.ts +2 -0
  128. package/out/zero-cache/src/services/change-streamer/subscriber.d.ts.map +1 -1
  129. package/out/zero-cache/src/services/change-streamer/subscriber.js +14 -1
  130. package/out/zero-cache/src/services/change-streamer/subscriber.js.map +1 -1
  131. package/out/zero-cache/src/services/heapz.d.ts.map +1 -1
  132. package/out/zero-cache/src/services/heapz.js +1 -0
  133. package/out/zero-cache/src/services/heapz.js.map +1 -1
  134. package/out/zero-cache/src/services/mutagen/error.d.ts.map +1 -1
  135. package/out/zero-cache/src/services/mutagen/error.js +4 -1
  136. package/out/zero-cache/src/services/mutagen/error.js.map +1 -1
  137. package/out/zero-cache/src/services/mutagen/mutagen.d.ts.map +1 -1
  138. package/out/zero-cache/src/services/mutagen/mutagen.js +1 -0
  139. package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -1
  140. package/out/zero-cache/src/services/mutagen/pusher.d.ts +7 -4
  141. package/out/zero-cache/src/services/mutagen/pusher.d.ts.map +1 -1
  142. package/out/zero-cache/src/services/mutagen/pusher.js +80 -8
  143. package/out/zero-cache/src/services/mutagen/pusher.js.map +1 -1
  144. package/out/zero-cache/src/services/replicator/change-processor.d.ts.map +1 -1
  145. package/out/zero-cache/src/services/replicator/change-processor.js +21 -29
  146. package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
  147. package/out/zero-cache/src/services/replicator/schema/change-log.d.ts +1 -2
  148. package/out/zero-cache/src/services/replicator/schema/change-log.d.ts.map +1 -1
  149. package/out/zero-cache/src/services/replicator/schema/change-log.js +2 -5
  150. package/out/zero-cache/src/services/replicator/schema/change-log.js.map +1 -1
  151. package/out/zero-cache/src/services/{change-source → replicator/schema}/column-metadata.d.ts +3 -3
  152. package/out/zero-cache/src/services/replicator/schema/column-metadata.d.ts.map +1 -0
  153. package/out/zero-cache/src/services/{change-source → replicator/schema}/column-metadata.js +3 -3
  154. package/out/zero-cache/src/services/replicator/schema/column-metadata.js.map +1 -0
  155. package/out/zero-cache/src/services/replicator/schema/replication-state.d.ts.map +1 -1
  156. package/out/zero-cache/src/services/replicator/schema/replication-state.js +3 -1
  157. package/out/zero-cache/src/services/replicator/schema/replication-state.js.map +1 -1
  158. package/out/zero-cache/src/services/run-ast.js +1 -1
  159. package/out/zero-cache/src/services/run-ast.js.map +1 -1
  160. package/out/zero-cache/src/services/statz.d.ts.map +1 -1
  161. package/out/zero-cache/src/services/statz.js +1 -0
  162. package/out/zero-cache/src/services/statz.js.map +1 -1
  163. package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts +1 -1
  164. package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts.map +1 -1
  165. package/out/zero-cache/src/services/view-syncer/cvr-store.js +59 -40
  166. package/out/zero-cache/src/services/view-syncer/cvr-store.js.map +1 -1
  167. package/out/zero-cache/src/services/view-syncer/cvr.d.ts +0 -1
  168. package/out/zero-cache/src/services/view-syncer/cvr.d.ts.map +1 -1
  169. package/out/zero-cache/src/services/view-syncer/cvr.js +23 -6
  170. package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
  171. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts +13 -14
  172. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
  173. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +44 -56
  174. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
  175. package/out/zero-cache/src/services/view-syncer/row-record-cache.d.ts +1 -1
  176. package/out/zero-cache/src/services/view-syncer/row-record-cache.d.ts.map +1 -1
  177. package/out/zero-cache/src/services/view-syncer/row-record-cache.js +22 -11
  178. package/out/zero-cache/src/services/view-syncer/row-record-cache.js.map +1 -1
  179. package/out/zero-cache/src/services/view-syncer/snapshotter.js +1 -1
  180. package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
  181. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts +6 -3
  182. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
  183. package/out/zero-cache/src/services/view-syncer/view-syncer.js +192 -217
  184. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  185. package/out/zero-cache/src/types/lexi-version.d.ts.map +1 -1
  186. package/out/zero-cache/src/types/lexi-version.js +4 -1
  187. package/out/zero-cache/src/types/lexi-version.js.map +1 -1
  188. package/out/zero-cache/src/types/lite.d.ts.map +1 -1
  189. package/out/zero-cache/src/types/lite.js +8 -2
  190. package/out/zero-cache/src/types/lite.js.map +1 -1
  191. package/out/zero-cache/src/types/shards.js +1 -1
  192. package/out/zero-cache/src/types/shards.js.map +1 -1
  193. package/out/zero-cache/src/types/sql.d.ts +5 -0
  194. package/out/zero-cache/src/types/sql.d.ts.map +1 -1
  195. package/out/zero-cache/src/types/sql.js +5 -1
  196. package/out/zero-cache/src/types/sql.js.map +1 -1
  197. package/out/zero-cache/src/types/subscription.js +1 -1
  198. package/out/zero-cache/src/types/subscription.js.map +1 -1
  199. package/out/zero-cache/src/workers/connect-params.d.ts +1 -0
  200. package/out/zero-cache/src/workers/connect-params.d.ts.map +1 -1
  201. package/out/zero-cache/src/workers/connect-params.js +2 -1
  202. package/out/zero-cache/src/workers/connect-params.js.map +1 -1
  203. package/out/zero-cache/src/workers/syncer-ws-message-handler.d.ts.map +1 -1
  204. package/out/zero-cache/src/workers/syncer-ws-message-handler.js +14 -6
  205. package/out/zero-cache/src/workers/syncer-ws-message-handler.js.map +1 -1
  206. package/out/zero-cache/src/workers/syncer.d.ts.map +1 -1
  207. package/out/zero-cache/src/workers/syncer.js +17 -10
  208. package/out/zero-cache/src/workers/syncer.js.map +1 -1
  209. package/out/zero-client/src/client/connection-manager.d.ts +8 -0
  210. package/out/zero-client/src/client/connection-manager.d.ts.map +1 -1
  211. package/out/zero-client/src/client/connection-manager.js +33 -0
  212. package/out/zero-client/src/client/connection-manager.js.map +1 -1
  213. package/out/zero-client/src/client/connection.d.ts.map +1 -1
  214. package/out/zero-client/src/client/connection.js +6 -3
  215. package/out/zero-client/src/client/connection.js.map +1 -1
  216. package/out/zero-client/src/client/error.js +1 -1
  217. package/out/zero-client/src/client/error.js.map +1 -1
  218. package/out/zero-client/src/client/mutator-proxy.d.ts.map +1 -1
  219. package/out/zero-client/src/client/mutator-proxy.js +15 -1
  220. package/out/zero-client/src/client/mutator-proxy.js.map +1 -1
  221. package/out/zero-client/src/client/options.d.ts +10 -0
  222. package/out/zero-client/src/client/options.d.ts.map +1 -1
  223. package/out/zero-client/src/client/options.js.map +1 -1
  224. package/out/zero-client/src/client/query-manager.d.ts +4 -0
  225. package/out/zero-client/src/client/query-manager.d.ts.map +1 -1
  226. package/out/zero-client/src/client/query-manager.js +7 -0
  227. package/out/zero-client/src/client/query-manager.js.map +1 -1
  228. package/out/zero-client/src/client/version.js +1 -1
  229. package/out/zero-client/src/client/zero.d.ts +3 -1
  230. package/out/zero-client/src/client/zero.d.ts.map +1 -1
  231. package/out/zero-client/src/client/zero.js +52 -7
  232. package/out/zero-client/src/client/zero.js.map +1 -1
  233. package/out/zero-client/src/mod.d.ts +1 -0
  234. package/out/zero-client/src/mod.d.ts.map +1 -1
  235. package/out/zero-protocol/src/connect.d.ts +4 -0
  236. package/out/zero-protocol/src/connect.d.ts.map +1 -1
  237. package/out/zero-protocol/src/connect.js +3 -1
  238. package/out/zero-protocol/src/connect.js.map +1 -1
  239. package/out/zero-protocol/src/protocol-version.d.ts +1 -1
  240. package/out/zero-protocol/src/protocol-version.d.ts.map +1 -1
  241. package/out/zero-protocol/src/protocol-version.js +1 -1
  242. package/out/zero-protocol/src/protocol-version.js.map +1 -1
  243. package/out/zero-protocol/src/push.d.ts +11 -2
  244. package/out/zero-protocol/src/push.d.ts.map +1 -1
  245. package/out/zero-protocol/src/push.js +22 -6
  246. package/out/zero-protocol/src/push.js.map +1 -1
  247. package/out/zero-protocol/src/up.d.ts +2 -0
  248. package/out/zero-protocol/src/up.d.ts.map +1 -1
  249. package/out/zero-react/src/mod.d.ts +3 -1
  250. package/out/zero-react/src/mod.d.ts.map +1 -1
  251. package/out/zero-react/src/paging-reducer.d.ts +61 -0
  252. package/out/zero-react/src/paging-reducer.d.ts.map +1 -0
  253. package/out/zero-react/src/paging-reducer.js +77 -0
  254. package/out/zero-react/src/paging-reducer.js.map +1 -0
  255. package/out/zero-react/src/use-query.d.ts +11 -1
  256. package/out/zero-react/src/use-query.d.ts.map +1 -1
  257. package/out/zero-react/src/use-query.js +13 -11
  258. package/out/zero-react/src/use-query.js.map +1 -1
  259. package/out/zero-react/src/use-rows.d.ts +39 -0
  260. package/out/zero-react/src/use-rows.d.ts.map +1 -0
  261. package/out/zero-react/src/use-rows.js +130 -0
  262. package/out/zero-react/src/use-rows.js.map +1 -0
  263. package/out/zero-react/src/use-zero-virtualizer.d.ts +122 -0
  264. package/out/zero-react/src/use-zero-virtualizer.d.ts.map +1 -0
  265. package/out/zero-react/src/use-zero-virtualizer.js +342 -0
  266. package/out/zero-react/src/use-zero-virtualizer.js.map +1 -0
  267. package/out/zero-react/src/zero-provider.js +1 -1
  268. package/out/zero-react/src/zero-provider.js.map +1 -1
  269. package/out/zero-server/src/adapters/drizzle.d.ts +18 -18
  270. package/out/zero-server/src/adapters/drizzle.d.ts.map +1 -1
  271. package/out/zero-server/src/adapters/drizzle.js +8 -22
  272. package/out/zero-server/src/adapters/drizzle.js.map +1 -1
  273. package/out/zero-server/src/adapters/pg.d.ts +19 -13
  274. package/out/zero-server/src/adapters/pg.d.ts.map +1 -1
  275. package/out/zero-server/src/adapters/pg.js.map +1 -1
  276. package/out/zero-server/src/adapters/postgresjs.d.ts +19 -13
  277. package/out/zero-server/src/adapters/postgresjs.d.ts.map +1 -1
  278. package/out/zero-server/src/adapters/postgresjs.js.map +1 -1
  279. package/out/zero-server/src/adapters/prisma.d.ts +66 -0
  280. package/out/zero-server/src/adapters/prisma.d.ts.map +1 -0
  281. package/out/zero-server/src/adapters/prisma.js +63 -0
  282. package/out/zero-server/src/adapters/prisma.js.map +1 -0
  283. package/out/zero-server/src/custom.js +1 -15
  284. package/out/zero-server/src/custom.js.map +1 -1
  285. package/out/zero-server/src/mod.d.ts +9 -8
  286. package/out/zero-server/src/mod.d.ts.map +1 -1
  287. package/out/zero-server/src/process-mutations.d.ts +2 -2
  288. package/out/zero-server/src/process-mutations.d.ts.map +1 -1
  289. package/out/zero-server/src/process-mutations.js +4 -8
  290. package/out/zero-server/src/process-mutations.js.map +1 -1
  291. package/out/zero-server/src/push-processor.js +1 -1
  292. package/out/zero-server/src/push-processor.js.map +1 -1
  293. package/out/zero-server/src/schema.d.ts.map +1 -1
  294. package/out/zero-server/src/schema.js +4 -1
  295. package/out/zero-server/src/schema.js.map +1 -1
  296. package/out/zero-server/src/zql-database.d.ts.map +1 -1
  297. package/out/zero-server/src/zql-database.js +17 -8
  298. package/out/zero-server/src/zql-database.js.map +1 -1
  299. package/out/zero-solid/src/mod.d.ts +1 -1
  300. package/out/zero-solid/src/mod.d.ts.map +1 -1
  301. package/out/zero-solid/src/use-query.d.ts +10 -1
  302. package/out/zero-solid/src/use-query.d.ts.map +1 -1
  303. package/out/zero-solid/src/use-query.js +21 -5
  304. package/out/zero-solid/src/use-query.js.map +1 -1
  305. package/out/zero-solid/src/use-zero.js +1 -1
  306. package/out/zero-solid/src/use-zero.js.map +1 -1
  307. package/out/zql/src/ivm/constraint.d.ts.map +1 -1
  308. package/out/zql/src/ivm/constraint.js +4 -1
  309. package/out/zql/src/ivm/constraint.js.map +1 -1
  310. package/out/zql/src/ivm/exists.d.ts.map +1 -1
  311. package/out/zql/src/ivm/exists.js +4 -1
  312. package/out/zql/src/ivm/exists.js.map +1 -1
  313. package/out/zql/src/ivm/join-utils.d.ts.map +1 -1
  314. package/out/zql/src/ivm/join-utils.js +8 -2
  315. package/out/zql/src/ivm/join-utils.js.map +1 -1
  316. package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
  317. package/out/zql/src/ivm/memory-source.js +12 -3
  318. package/out/zql/src/ivm/memory-source.js.map +1 -1
  319. package/out/zql/src/ivm/push-accumulated.d.ts.map +1 -1
  320. package/out/zql/src/ivm/push-accumulated.js +25 -2
  321. package/out/zql/src/ivm/push-accumulated.js.map +1 -1
  322. package/out/zql/src/ivm/take.d.ts.map +1 -1
  323. package/out/zql/src/ivm/take.js +24 -6
  324. package/out/zql/src/ivm/take.js.map +1 -1
  325. package/out/zql/src/ivm/union-fan-in.d.ts.map +1 -1
  326. package/out/zql/src/ivm/union-fan-in.js +12 -3
  327. package/out/zql/src/ivm/union-fan-in.js.map +1 -1
  328. package/out/zqlite/src/table-source.d.ts.map +1 -1
  329. package/out/zqlite/src/table-source.js +1 -2
  330. package/out/zqlite/src/table-source.js.map +1 -1
  331. package/package.json +6 -2
  332. package/out/zero-cache/src/services/change-source/column-metadata.d.ts.map +0 -1
  333. package/out/zero-cache/src/services/change-source/column-metadata.js.map +0 -1
@@ -0,0 +1,29 @@
1
+ let priorityOpCounter = 0;
2
+ let runningPriorityOpCounter = 0;
3
+ async function runPriorityOp(lc, description, op) {
4
+ const id = priorityOpCounter++;
5
+ runningPriorityOpCounter++;
6
+ const start = Date.now();
7
+ lc = lc.withContext("priorityOpID", id);
8
+ try {
9
+ lc.debug?.(`running priority op ${description}`);
10
+ const result = await op();
11
+ lc.debug?.(
12
+ `finished priority op ${description} in ${Date.now() - start} ms`
13
+ );
14
+ return result;
15
+ } catch (e) {
16
+ lc.debug?.(`failed priority op ${description} in ${Date.now() - start} ms`);
17
+ throw e;
18
+ } finally {
19
+ runningPriorityOpCounter--;
20
+ }
21
+ }
22
+ function isPriorityOpRunning() {
23
+ return runningPriorityOpCounter > 0;
24
+ }
25
+ export {
26
+ isPriorityOpRunning,
27
+ runPriorityOp
28
+ };
29
+ //# sourceMappingURL=priority-op.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"priority-op.js","sources":["../../../../../zero-cache/src/server/priority-op.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\n\nlet priorityOpCounter = 0;\nlet runningPriorityOpCounter = 0;\n\n/**\n * Run an operation with priority, indicating that IVM should use smaller time\n * slices to allow this operation to proceed more quickly\n */\nexport async function runPriorityOp<T>(\n lc: LogContext,\n description: string,\n op: () => Promise<T>,\n) {\n const id = priorityOpCounter++;\n runningPriorityOpCounter++;\n const start = Date.now();\n lc = lc.withContext('priorityOpID', id);\n try {\n lc.debug?.(`running priority op ${description}`);\n const result = await op();\n lc.debug?.(\n `finished priority op ${description} in ${Date.now() - start} ms`,\n );\n return result;\n } catch (e) {\n lc.debug?.(`failed priority op ${description} in ${Date.now() - start} ms`);\n throw e;\n } finally {\n runningPriorityOpCounter--;\n }\n}\n\nexport function isPriorityOpRunning() {\n return runningPriorityOpCounter > 0;\n}\n"],"names":[],"mappings":"AAEA,IAAI,oBAAoB;AACxB,IAAI,2BAA2B;AAM/B,eAAsB,cACpB,IACA,aACA,IACA;AACA,QAAM,KAAK;AACX;AACA,QAAM,QAAQ,KAAK,IAAA;AACnB,OAAK,GAAG,YAAY,gBAAgB,EAAE;AACtC,MAAI;AACF,OAAG,QAAQ,uBAAuB,WAAW,EAAE;AAC/C,UAAM,SAAS,MAAM,GAAA;AACrB,OAAG;AAAA,MACD,wBAAwB,WAAW,OAAO,KAAK,IAAA,IAAQ,KAAK;AAAA,IAAA;AAE9D,WAAO;AAAA,EACT,SAAS,GAAG;AACV,OAAG,QAAQ,sBAAsB,WAAW,OAAO,KAAK,IAAA,IAAQ,KAAK,KAAK;AAC1E,UAAM;AAAA,EACR,UAAA;AACE;AAAA,EACF;AACF;AAEO,SAAS,sBAAsB;AACpC,SAAO,2BAA2B;AACpC;"}
@@ -1,4 +1,3 @@
1
1
  import { type Worker } from '../types/processes.ts';
2
2
  export default function runWorker(parent: Worker, env: NodeJS.ProcessEnv, ...args: string[]): Promise<void>;
3
- export declare function isPriorityOpRunning(): boolean;
4
3
  //# sourceMappingURL=syncer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"syncer.d.ts","sourceRoot":"","sources":["../../../../../zero-cache/src/server/syncer.ts"],"names":[],"mappings":"AAuBA,OAAO,EAGL,KAAK,MAAM,EACZ,MAAM,uBAAuB,CAAC;AA6B/B,MAAM,CAAC,OAAO,UAAU,SAAS,CAC/B,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,GAAG,IAAI,EAAE,MAAM,EAAE,GAChB,OAAO,CAAC,IAAI,CAAC,CAoJf;AAwBD,wBAAgB,mBAAmB,YAElC"}
1
+ {"version":3,"file":"syncer.d.ts","sourceRoot":"","sources":["../../../../../zero-cache/src/server/syncer.ts"],"names":[],"mappings":"AAuBA,OAAO,EAGL,KAAK,MAAM,EACZ,MAAM,uBAAuB,CAAC;AA8B/B,MAAM,CAAC,OAAO,UAAU,SAAS,CAC/B,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,GAAG,IAAI,EAAE,MAAM,EAAE,GAChB,OAAO,CAAC,IAAI,CAAC,CA8If"}
@@ -26,6 +26,7 @@ import { startAnonymousTelemetry } from "./anonymous-otel-start.js";
26
26
  import { InspectorDelegate } from "./inspector-delegate.js";
27
27
  import { createLogContext } from "./logging.js";
28
28
  import { startOtelAuto } from "./otel-start.js";
29
+ import { runPriorityOp, isPriorityOpRunning } from "./priority-op.js";
29
30
  function randomID() {
30
31
  return randInt(1, Number.MAX_SAFE_INTEGER).toString(36);
31
32
  }
@@ -93,16 +94,10 @@ function runWorker(parent, env, ...args) {
93
94
  config.taskID,
94
95
  id,
95
96
  cvrDB,
96
- config.upstream.type === "pg" ? upstreamDB : void 0,
97
97
  new PipelineDriver(
98
98
  logger,
99
99
  config.log,
100
- new Snapshotter(
101
- logger,
102
- replicaFile,
103
- shard,
104
- config.replica.pageCacheSizeKib
105
- ),
100
+ new Snapshotter(logger, replicaFile, shard),
106
101
  shard,
107
102
  operatorStorage.createClientGroupStorage(id),
108
103
  id,
@@ -156,20 +151,7 @@ if (!singleProcessMode()) {
156
151
  () => runWorker(must(parentWorker), process.env, ...process.argv.slice(2))
157
152
  );
158
153
  }
159
- let priorityOpCounter = 0;
160
- async function runPriorityOp(op) {
161
- priorityOpCounter++;
162
- try {
163
- return await op();
164
- } finally {
165
- priorityOpCounter--;
166
- }
167
- }
168
- function isPriorityOpRunning() {
169
- return priorityOpCounter > 0;
170
- }
171
154
  export {
172
- runWorker as default,
173
- isPriorityOpRunning
155
+ runWorker as default
174
156
  };
175
157
  //# sourceMappingURL=syncer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"syncer.js","sources":["../../../../../zero-cache/src/server/syncer.ts"],"sourcesContent":["import {randomUUID} from 'node:crypto';\nimport {tmpdir} from 'node:os';\nimport path from 'node:path';\nimport {pid} from 'node:process';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport {randInt} from '../../../shared/src/rand.ts';\nimport * as v from '../../../shared/src/valita.ts';\nimport {DatabaseStorage} from '../../../zqlite/src/database-storage.ts';\nimport type {NormalizedZeroConfig} from '../config/normalize.ts';\nimport {getNormalizedZeroConfig} from '../config/zero-config.ts';\nimport {CustomQueryTransformer} from '../custom-queries/transform-query.ts';\nimport {warmupConnections} from '../db/warmup.ts';\nimport {initEventSink} from '../observability/events.ts';\nimport {exitAfter, runUntilKilled} from '../services/life-cycle.ts';\nimport {MutagenService} from '../services/mutagen/mutagen.ts';\nimport {PusherService} from '../services/mutagen/pusher.ts';\nimport type {ReplicaState} from '../services/replicator/replicator.ts';\nimport type {DrainCoordinator} from '../services/view-syncer/drain-coordinator.ts';\nimport {PipelineDriver} from '../services/view-syncer/pipeline-driver.ts';\nimport {Snapshotter} from '../services/view-syncer/snapshotter.ts';\nimport {ViewSyncerService} from '../services/view-syncer/view-syncer.ts';\nimport {pgClient} from '../types/pg.ts';\nimport {\n parentWorker,\n singleProcessMode,\n type Worker,\n} from '../types/processes.ts';\nimport {getShardID} from '../types/shards.ts';\nimport type {Subscription} from '../types/subscription.ts';\nimport {replicaFileModeSchema, replicaFileName} from '../workers/replicator.ts';\nimport {Syncer} from '../workers/syncer.ts';\nimport {startAnonymousTelemetry} from './anonymous-otel-start.ts';\nimport {InspectorDelegate} from './inspector-delegate.ts';\nimport {createLogContext} from './logging.ts';\nimport {startOtelAuto} from './otel-start.ts';\n\nfunction randomID() {\n return randInt(1, Number.MAX_SAFE_INTEGER).toString(36);\n}\n\nfunction getCustomQueryConfig(\n config: Pick<NormalizedZeroConfig, 'query' | 'getQueries'>,\n) {\n const queryConfig = config.query?.url ? config.query : config.getQueries;\n\n if (!queryConfig?.url) {\n return undefined;\n }\n\n return {\n url: queryConfig.url,\n forwardCookies: queryConfig.forwardCookies ?? false,\n };\n}\n\nexport default function runWorker(\n parent: Worker,\n env: NodeJS.ProcessEnv,\n ...args: string[]\n): Promise<void> {\n const config = getNormalizedZeroConfig({env, argv: args.slice(1)});\n\n startOtelAuto(createLogContext(config, {worker: 'syncer'}, false));\n const lc = createLogContext(config, {worker: 'syncer'}, true);\n initEventSink(lc, config);\n\n assert(args.length > 0, `replicator mode not specified`);\n const fileMode = v.parse(args[0], replicaFileModeSchema);\n\n const {cvr, upstream} = config;\n assert(cvr.maxConnsPerWorker, 'cvr.maxConnsPerWorker must be set');\n assert(upstream.maxConnsPerWorker, 'upstream.maxConnsPerWorker must be set');\n\n const replicaFile = replicaFileName(config.replica.file, fileMode);\n lc.debug?.(`running view-syncer on ${replicaFile}`);\n\n const cvrDB = pgClient(lc, cvr.db, {\n max: cvr.maxConnsPerWorker,\n connection: {['application_name']: `zero-sync-worker-${pid}-cvr`},\n });\n\n const upstreamDB = pgClient(lc, upstream.db, {\n max: upstream.maxConnsPerWorker,\n connection: {['application_name']: `zero-sync-worker-${pid}-upstream`},\n });\n\n const dbWarmup = Promise.allSettled([\n warmupConnections(lc, cvrDB, 'cvr'),\n warmupConnections(lc, upstreamDB, 'upstream'),\n ]);\n\n const tmpDir = config.storageDBTmpDir ?? tmpdir();\n const operatorStorage = DatabaseStorage.create(\n lc,\n path.join(tmpDir, `sync-worker-${randomUUID()}`),\n );\n const writeAuthzStorage = DatabaseStorage.create(\n lc,\n path.join(tmpDir, `mutagen-${randomUUID()}`),\n );\n\n const shard = getShardID(config);\n\n const viewSyncerFactory = (\n id: string,\n sub: Subscription<ReplicaState>,\n drainCoordinator: DrainCoordinator,\n ) => {\n const logger = lc\n .withContext('component', 'view-syncer')\n .withContext('clientGroupID', id)\n .withContext('instance', randomID());\n lc.debug?.(\n `creating view syncer. Query Planner Enabled: ${config.enableQueryPlanner}`,\n );\n\n // Create the custom query transformer if configured\n const customQueryConfig = getCustomQueryConfig(config);\n const customQueryTransformer =\n customQueryConfig &&\n new CustomQueryTransformer(logger, customQueryConfig, shard);\n\n const inspectorDelegate = new InspectorDelegate(customQueryTransformer);\n\n const priorityOpRunningYieldThresholdMs = Math.max(\n config.yieldThresholdMs / 4,\n 2,\n );\n const normalYieldThresholdMs = Math.max(config.yieldThresholdMs, 2);\n return new ViewSyncerService(\n config,\n logger,\n shard,\n config.taskID,\n id,\n cvrDB,\n config.upstream.type === 'pg' ? upstreamDB : undefined,\n new PipelineDriver(\n logger,\n config.log,\n new Snapshotter(\n logger,\n replicaFile,\n shard,\n config.replica.pageCacheSizeKib,\n ),\n shard,\n operatorStorage.createClientGroupStorage(id),\n id,\n inspectorDelegate,\n () =>\n isPriorityOpRunning()\n ? priorityOpRunningYieldThresholdMs\n : normalYieldThresholdMs,\n config.enableQueryPlanner,\n ),\n sub,\n drainCoordinator,\n config.log.slowHydrateThreshold,\n inspectorDelegate,\n customQueryTransformer,\n runPriorityOp,\n );\n };\n\n const mutagenFactory = (id: string) =>\n new MutagenService(\n lc.withContext('component', 'mutagen').withContext('clientGroupID', id),\n shard,\n id,\n upstreamDB,\n config,\n writeAuthzStorage,\n );\n\n const pusherFactory =\n config.push.url === undefined && config.mutate.url === undefined\n ? undefined\n : (id: string) =>\n new PusherService(\n config,\n {\n ...config.push,\n ...config.mutate,\n url: must(\n config.push.url ?? config.mutate.url,\n 'No push or mutate URL configured',\n ),\n },\n lc.withContext('clientGroupID', id),\n id,\n );\n\n const syncer = new Syncer(\n lc,\n config,\n viewSyncerFactory,\n mutagenFactory,\n pusherFactory,\n parent,\n );\n\n startAnonymousTelemetry(lc, config);\n\n void dbWarmup.then(() => parent.send(['ready', {ready: true}]));\n\n return runUntilKilled(lc, parent, syncer);\n}\n\n// fork()\nif (!singleProcessMode()) {\n void exitAfter(() =>\n runWorker(must(parentWorker), process.env, ...process.argv.slice(2)),\n );\n}\n\nlet priorityOpCounter = 0;\n\n/**\n * Run an operation with priority, indicating that IVM should use smaller time\n * slices to allow this operation to proceed more quickly\n */\nasync function runPriorityOp<T>(op: () => Promise<T>) {\n priorityOpCounter++;\n try {\n return await op();\n } finally {\n priorityOpCounter--;\n }\n}\n\nexport function isPriorityOpRunning() {\n return priorityOpCounter > 0;\n}\n"],"names":["v.parse"],"mappings":"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"}
1
+ {"version":3,"file":"syncer.js","sources":["../../../../../zero-cache/src/server/syncer.ts"],"sourcesContent":["import {randomUUID} from 'node:crypto';\nimport {tmpdir} from 'node:os';\nimport path from 'node:path';\nimport {pid} from 'node:process';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport {randInt} from '../../../shared/src/rand.ts';\nimport * as v from '../../../shared/src/valita.ts';\nimport {DatabaseStorage} from '../../../zqlite/src/database-storage.ts';\nimport type {NormalizedZeroConfig} from '../config/normalize.ts';\nimport {getNormalizedZeroConfig} from '../config/zero-config.ts';\nimport {CustomQueryTransformer} from '../custom-queries/transform-query.ts';\nimport {warmupConnections} from '../db/warmup.ts';\nimport {initEventSink} from '../observability/events.ts';\nimport {exitAfter, runUntilKilled} from '../services/life-cycle.ts';\nimport {MutagenService} from '../services/mutagen/mutagen.ts';\nimport {PusherService} from '../services/mutagen/pusher.ts';\nimport type {ReplicaState} from '../services/replicator/replicator.ts';\nimport type {DrainCoordinator} from '../services/view-syncer/drain-coordinator.ts';\nimport {PipelineDriver} from '../services/view-syncer/pipeline-driver.ts';\nimport {Snapshotter} from '../services/view-syncer/snapshotter.ts';\nimport {ViewSyncerService} from '../services/view-syncer/view-syncer.ts';\nimport {pgClient} from '../types/pg.ts';\nimport {\n parentWorker,\n singleProcessMode,\n type Worker,\n} from '../types/processes.ts';\nimport {getShardID} from '../types/shards.ts';\nimport type {Subscription} from '../types/subscription.ts';\nimport {replicaFileModeSchema, replicaFileName} from '../workers/replicator.ts';\nimport {Syncer} from '../workers/syncer.ts';\nimport {startAnonymousTelemetry} from './anonymous-otel-start.ts';\nimport {InspectorDelegate} from './inspector-delegate.ts';\nimport {createLogContext} from './logging.ts';\nimport {startOtelAuto} from './otel-start.ts';\nimport {isPriorityOpRunning, runPriorityOp} from './priority-op.ts';\n\nfunction randomID() {\n return randInt(1, Number.MAX_SAFE_INTEGER).toString(36);\n}\n\nfunction getCustomQueryConfig(\n config: Pick<NormalizedZeroConfig, 'query' | 'getQueries'>,\n) {\n const queryConfig = config.query?.url ? config.query : config.getQueries;\n\n if (!queryConfig?.url) {\n return undefined;\n }\n\n return {\n url: queryConfig.url,\n forwardCookies: queryConfig.forwardCookies ?? false,\n };\n}\n\nexport default function runWorker(\n parent: Worker,\n env: NodeJS.ProcessEnv,\n ...args: string[]\n): Promise<void> {\n const config = getNormalizedZeroConfig({env, argv: args.slice(1)});\n\n startOtelAuto(createLogContext(config, {worker: 'syncer'}, false));\n const lc = createLogContext(config, {worker: 'syncer'}, true);\n initEventSink(lc, config);\n\n assert(args.length > 0, `replicator mode not specified`);\n const fileMode = v.parse(args[0], replicaFileModeSchema);\n\n const {cvr, upstream} = config;\n assert(cvr.maxConnsPerWorker, 'cvr.maxConnsPerWorker must be set');\n assert(upstream.maxConnsPerWorker, 'upstream.maxConnsPerWorker must be set');\n\n const replicaFile = replicaFileName(config.replica.file, fileMode);\n lc.debug?.(`running view-syncer on ${replicaFile}`);\n\n const cvrDB = pgClient(lc, cvr.db, {\n max: cvr.maxConnsPerWorker,\n connection: {['application_name']: `zero-sync-worker-${pid}-cvr`},\n });\n\n const upstreamDB = pgClient(lc, upstream.db, {\n max: upstream.maxConnsPerWorker,\n connection: {['application_name']: `zero-sync-worker-${pid}-upstream`},\n });\n\n const dbWarmup = Promise.allSettled([\n warmupConnections(lc, cvrDB, 'cvr'),\n warmupConnections(lc, upstreamDB, 'upstream'),\n ]);\n\n const tmpDir = config.storageDBTmpDir ?? tmpdir();\n const operatorStorage = DatabaseStorage.create(\n lc,\n path.join(tmpDir, `sync-worker-${randomUUID()}`),\n );\n const writeAuthzStorage = DatabaseStorage.create(\n lc,\n path.join(tmpDir, `mutagen-${randomUUID()}`),\n );\n\n const shard = getShardID(config);\n\n const viewSyncerFactory = (\n id: string,\n sub: Subscription<ReplicaState>,\n drainCoordinator: DrainCoordinator,\n ) => {\n const logger = lc\n .withContext('component', 'view-syncer')\n .withContext('clientGroupID', id)\n .withContext('instance', randomID());\n lc.debug?.(\n `creating view syncer. Query Planner Enabled: ${config.enableQueryPlanner}`,\n );\n\n // Create the custom query transformer if configured\n const customQueryConfig = getCustomQueryConfig(config);\n const customQueryTransformer =\n customQueryConfig &&\n new CustomQueryTransformer(logger, customQueryConfig, shard);\n\n const inspectorDelegate = new InspectorDelegate(customQueryTransformer);\n\n const priorityOpRunningYieldThresholdMs = Math.max(\n config.yieldThresholdMs / 4,\n 2,\n );\n const normalYieldThresholdMs = Math.max(config.yieldThresholdMs, 2);\n return new ViewSyncerService(\n config,\n logger,\n shard,\n config.taskID,\n id,\n cvrDB,\n new PipelineDriver(\n logger,\n config.log,\n new Snapshotter(logger, replicaFile, shard),\n shard,\n operatorStorage.createClientGroupStorage(id),\n id,\n inspectorDelegate,\n () =>\n isPriorityOpRunning()\n ? priorityOpRunningYieldThresholdMs\n : normalYieldThresholdMs,\n config.enableQueryPlanner,\n ),\n sub,\n drainCoordinator,\n config.log.slowHydrateThreshold,\n inspectorDelegate,\n customQueryTransformer,\n runPriorityOp,\n );\n };\n\n const mutagenFactory = (id: string) =>\n new MutagenService(\n lc.withContext('component', 'mutagen').withContext('clientGroupID', id),\n shard,\n id,\n upstreamDB,\n config,\n writeAuthzStorage,\n );\n\n const pusherFactory =\n config.push.url === undefined && config.mutate.url === undefined\n ? undefined\n : (id: string) =>\n new PusherService(\n config,\n {\n ...config.push,\n ...config.mutate,\n url: must(\n config.push.url ?? config.mutate.url,\n 'No push or mutate URL configured',\n ),\n },\n lc.withContext('clientGroupID', id),\n id,\n );\n\n const syncer = new Syncer(\n lc,\n config,\n viewSyncerFactory,\n mutagenFactory,\n pusherFactory,\n parent,\n );\n\n startAnonymousTelemetry(lc, config);\n\n void dbWarmup.then(() => parent.send(['ready', {ready: true}]));\n\n return runUntilKilled(lc, parent, syncer);\n}\n\n// fork()\nif (!singleProcessMode()) {\n void exitAfter(() =>\n runWorker(must(parentWorker), process.env, ...process.argv.slice(2)),\n );\n}\n"],"names":["v.parse"],"mappings":"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"}
@@ -64,7 +64,7 @@ async function analyzeQuery(lc, config, clientSchema, ast, syncedRows = true, ve
64
64
  computeZqlSpecs(lc, db, tableSpecs, fullTables);
65
65
  const planDebugger = joinPlans ? new AccumulatorDebugger() : void 0;
66
66
  const costModel = joinPlans ? createSQLiteCostModel(db, tableSpecs) : void 0;
67
- const timer = await new TimeSliceTimer().start();
67
+ const timer = await new TimeSliceTimer(lc).start();
68
68
  const shouldYield = () => timer.elapsedLap() > TIME_SLICE_LAP_THRESHOLD_MS;
69
69
  const yieldProcess = () => timer.yieldProcess();
70
70
  const result = await runAst(
@@ -1 +1 @@
1
- {"version":3,"file":"analyze.js","sources":["../../../../../zero-cache/src/services/analyze.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport type {AnalyzeQueryResult} from '../../../zero-protocol/src/analyze-query-result.ts';\nimport type {AST} from '../../../zero-protocol/src/ast.ts';\nimport type {PermissionsConfig} from '../../../zero-schema/src/compiled-permissions.ts';\nimport {Debug} from '../../../zql/src/builder/debug-delegate.ts';\nimport {MemoryStorage} from '../../../zql/src/ivm/memory-storage.ts';\nimport {\n AccumulatorDebugger,\n serializePlanDebugEvents,\n} from '../../../zql/src/planner/planner-debug.ts';\nimport {Database} from '../../../zqlite/src/db.ts';\nimport {explainQueries} from '../../../zqlite/src/explain-queries.ts';\nimport {createSQLiteCostModel} from '../../../zqlite/src/sqlite-cost-model.ts';\nimport {TableSource} from '../../../zqlite/src/table-source.ts';\nimport type {NormalizedZeroConfig} from '../config/normalize.ts';\nimport {computeZqlSpecs, mustGetTableSpec} from '../db/lite-tables.ts';\nimport type {LiteAndZqlSpec, LiteTableSpec} from '../db/specs.ts';\nimport {runAst} from './run-ast.ts';\nimport {TimeSliceTimer, type TokenData} from './view-syncer/view-syncer.ts';\nimport type {ClientSchema} from '../../../zero-protocol/src/client-schema.ts';\n\nconst TIME_SLICE_LAP_THRESHOLD_MS = 200;\n\nexport async function analyzeQuery(\n lc: LogContext,\n config: NormalizedZeroConfig,\n clientSchema: ClientSchema,\n ast: AST,\n syncedRows = true,\n vendedRows = false,\n permissions?: PermissionsConfig,\n authData?: TokenData,\n joinPlans = false,\n): Promise<AnalyzeQueryResult> {\n using db = new Database(lc, config.replica.file);\n const fullTables = new Map<string, LiteTableSpec>();\n const tableSpecs = new Map<string, LiteAndZqlSpec>();\n const tables = new Map<string, TableSource>();\n\n computeZqlSpecs(lc, db, tableSpecs, fullTables);\n\n const planDebugger = joinPlans ? new AccumulatorDebugger() : undefined;\n const costModel = joinPlans\n ? createSQLiteCostModel(db, tableSpecs)\n : undefined;\n const timer = await new TimeSliceTimer().start();\n const shouldYield = () => timer.elapsedLap() > TIME_SLICE_LAP_THRESHOLD_MS;\n const yieldProcess = () => timer.yieldProcess();\n const result = await runAst(\n lc,\n clientSchema,\n ast,\n true,\n {\n applyPermissions: permissions !== undefined,\n syncedRows,\n vendedRows,\n authData,\n db,\n tableSpecs,\n permissions,\n costModel,\n planDebugger,\n host: {\n debug: new Debug(),\n getSource(tableName: string) {\n let source = tables.get(tableName);\n if (source) {\n return source;\n }\n\n const tableSpec = mustGetTableSpec(tableSpecs, tableName);\n const {primaryKey} = tableSpec.tableSpec;\n\n source = new TableSource(\n lc,\n config.log,\n db,\n tableName,\n tableSpec.zqlSpec,\n primaryKey,\n shouldYield,\n );\n tables.set(tableName, source);\n return source;\n },\n createStorage() {\n return new MemoryStorage();\n },\n decorateSourceInput: input => input,\n decorateInput: input => input,\n addEdge() {},\n decorateFilterInput: input => input,\n },\n },\n yieldProcess,\n );\n\n result.sqlitePlans = explainQueries(result.readRowCountsByQuery ?? {}, db);\n\n if (planDebugger) {\n result.joinPlans = serializePlanDebugEvents(planDebugger.events);\n }\n\n return result;\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqBA,MAAM,8BAA8B;AAEpC,eAAsB,aACpB,IACA,QACA,cACA,KACA,aAAa,MACb,aAAa,OACb,aACA,UACA,YAAY,OACiB;AAC7B;AAAA;AAAA,UAAM,KAAK,oBAAI,SAAS,IAAI,OAAO,QAAQ,IAAI;AAC/C,UAAM,iCAAiB,IAAA;AACvB,UAAM,iCAAiB,IAAA;AACvB,UAAM,6BAAa,IAAA;AAEnB,oBAAgB,IAAI,IAAI,YAAY,UAAU;AAE9C,UAAM,eAAe,YAAY,IAAI,oBAAA,IAAwB;AAC7D,UAAM,YAAY,YACd,sBAAsB,IAAI,UAAU,IACpC;AACJ,UAAM,QAAQ,MAAM,IAAI,eAAA,EAAiB,MAAA;AACzC,UAAM,cAAc,MAAM,MAAM,WAAA,IAAe;AAC/C,UAAM,eAAe,MAAM,MAAM,aAAA;AACjC,UAAM,SAAS,MAAM;AAAA,MACnB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,QACE,kBAAkB,gBAAgB;AAAA,QAClC;AAAA,QACA;AAAA,QACA;AAAA,QAGA;AAAA,QACA;AAAA,QACA;AAAA,QACA,MAAM;AAAA,UACJ,OAAO,IAAI,MAAA;AAAA,UACX,UAAU,WAAmB;AAC3B,gBAAI,SAAS,OAAO,IAAI,SAAS;AACjC,gBAAI,QAAQ;AACV,qBAAO;AAAA,YACT;AAEA,kBAAM,YAAY,iBAAiB,YAAY,SAAS;AACxD,kBAAM,EAAC,eAAc,UAAU;AAE/B,qBAAS,IAAI;AAAA,cACX;AAAA,cACA,OAAO;AAAA,cACP;AAAA,cACA;AAAA,cACA,UAAU;AAAA,cACV;AAAA,cACA;AAAA,YAAA;AAEF,mBAAO,IAAI,WAAW,MAAM;AAC5B,mBAAO;AAAA,UACT;AAAA,UACA,gBAAgB;AACd,mBAAO,IAAI,cAAA;AAAA,UACb;AAAA,UACA,qBAAqB,CAAA,UAAS;AAAA,UAC9B,eAAe,CAAA,UAAS;AAAA,UACxB,UAAU;AAAA,UAAC;AAAA,UACX,qBAAqB,CAAA,UAAS;AAAA,QAAA;AAAA,MAChC;AAAA,MAEF;AAAA,IAAA;AAGF,WAAO,cAAc,eAAe,OAAO,wBAAwB,CAAA,GAAI,EAAE;AAEzE,QAAI,cAAc;AAChB,aAAO,YAAY,yBAAyB,aAAa,MAAM;AAAA,IACjE;AAEA,WAAO;AAAA,WAtEP;AAAA;AAAA;AAAA;AAAA;AAuEF;"}
1
+ {"version":3,"file":"analyze.js","sources":["../../../../../zero-cache/src/services/analyze.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport type {AnalyzeQueryResult} from '../../../zero-protocol/src/analyze-query-result.ts';\nimport type {AST} from '../../../zero-protocol/src/ast.ts';\nimport type {PermissionsConfig} from '../../../zero-schema/src/compiled-permissions.ts';\nimport {Debug} from '../../../zql/src/builder/debug-delegate.ts';\nimport {MemoryStorage} from '../../../zql/src/ivm/memory-storage.ts';\nimport {\n AccumulatorDebugger,\n serializePlanDebugEvents,\n} from '../../../zql/src/planner/planner-debug.ts';\nimport {Database} from '../../../zqlite/src/db.ts';\nimport {explainQueries} from '../../../zqlite/src/explain-queries.ts';\nimport {createSQLiteCostModel} from '../../../zqlite/src/sqlite-cost-model.ts';\nimport {TableSource} from '../../../zqlite/src/table-source.ts';\nimport type {NormalizedZeroConfig} from '../config/normalize.ts';\nimport {computeZqlSpecs, mustGetTableSpec} from '../db/lite-tables.ts';\nimport type {LiteAndZqlSpec, LiteTableSpec} from '../db/specs.ts';\nimport {runAst} from './run-ast.ts';\nimport {TimeSliceTimer, type TokenData} from './view-syncer/view-syncer.ts';\nimport type {ClientSchema} from '../../../zero-protocol/src/client-schema.ts';\n\nconst TIME_SLICE_LAP_THRESHOLD_MS = 200;\n\nexport async function analyzeQuery(\n lc: LogContext,\n config: NormalizedZeroConfig,\n clientSchema: ClientSchema,\n ast: AST,\n syncedRows = true,\n vendedRows = false,\n permissions?: PermissionsConfig,\n authData?: TokenData,\n joinPlans = false,\n): Promise<AnalyzeQueryResult> {\n using db = new Database(lc, config.replica.file);\n const fullTables = new Map<string, LiteTableSpec>();\n const tableSpecs = new Map<string, LiteAndZqlSpec>();\n const tables = new Map<string, TableSource>();\n\n computeZqlSpecs(lc, db, tableSpecs, fullTables);\n\n const planDebugger = joinPlans ? new AccumulatorDebugger() : undefined;\n const costModel = joinPlans\n ? createSQLiteCostModel(db, tableSpecs)\n : undefined;\n const timer = await new TimeSliceTimer(lc).start();\n const shouldYield = () => timer.elapsedLap() > TIME_SLICE_LAP_THRESHOLD_MS;\n const yieldProcess = () => timer.yieldProcess();\n const result = await runAst(\n lc,\n clientSchema,\n ast,\n true,\n {\n applyPermissions: permissions !== undefined,\n syncedRows,\n vendedRows,\n authData,\n db,\n tableSpecs,\n permissions,\n costModel,\n planDebugger,\n host: {\n debug: new Debug(),\n getSource(tableName: string) {\n let source = tables.get(tableName);\n if (source) {\n return source;\n }\n\n const tableSpec = mustGetTableSpec(tableSpecs, tableName);\n const {primaryKey} = tableSpec.tableSpec;\n\n source = new TableSource(\n lc,\n config.log,\n db,\n tableName,\n tableSpec.zqlSpec,\n primaryKey,\n shouldYield,\n );\n tables.set(tableName, source);\n return source;\n },\n createStorage() {\n return new MemoryStorage();\n },\n decorateSourceInput: input => input,\n decorateInput: input => input,\n addEdge() {},\n decorateFilterInput: input => input,\n },\n },\n yieldProcess,\n );\n\n result.sqlitePlans = explainQueries(result.readRowCountsByQuery ?? {}, db);\n\n if (planDebugger) {\n result.joinPlans = serializePlanDebugEvents(planDebugger.events);\n }\n\n return result;\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqBA,MAAM,8BAA8B;AAEpC,eAAsB,aACpB,IACA,QACA,cACA,KACA,aAAa,MACb,aAAa,OACb,aACA,UACA,YAAY,OACiB;AAC7B;AAAA;AAAA,UAAM,KAAK,oBAAI,SAAS,IAAI,OAAO,QAAQ,IAAI;AAC/C,UAAM,iCAAiB,IAAA;AACvB,UAAM,iCAAiB,IAAA;AACvB,UAAM,6BAAa,IAAA;AAEnB,oBAAgB,IAAI,IAAI,YAAY,UAAU;AAE9C,UAAM,eAAe,YAAY,IAAI,oBAAA,IAAwB;AAC7D,UAAM,YAAY,YACd,sBAAsB,IAAI,UAAU,IACpC;AACJ,UAAM,QAAQ,MAAM,IAAI,eAAe,EAAE,EAAE,MAAA;AAC3C,UAAM,cAAc,MAAM,MAAM,WAAA,IAAe;AAC/C,UAAM,eAAe,MAAM,MAAM,aAAA;AACjC,UAAM,SAAS,MAAM;AAAA,MACnB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,QACE,kBAAkB,gBAAgB;AAAA,QAClC;AAAA,QACA;AAAA,QACA;AAAA,QAGA;AAAA,QACA;AAAA,QACA;AAAA,QACA,MAAM;AAAA,UACJ,OAAO,IAAI,MAAA;AAAA,UACX,UAAU,WAAmB;AAC3B,gBAAI,SAAS,OAAO,IAAI,SAAS;AACjC,gBAAI,QAAQ;AACV,qBAAO;AAAA,YACT;AAEA,kBAAM,YAAY,iBAAiB,YAAY,SAAS;AACxD,kBAAM,EAAC,eAAc,UAAU;AAE/B,qBAAS,IAAI;AAAA,cACX;AAAA,cACA,OAAO;AAAA,cACP;AAAA,cACA;AAAA,cACA,UAAU;AAAA,cACV;AAAA,cACA;AAAA,YAAA;AAEF,mBAAO,IAAI,WAAW,MAAM;AAC5B,mBAAO;AAAA,UACT;AAAA,UACA,gBAAgB;AACd,mBAAO,IAAI,cAAA;AAAA,UACb;AAAA,UACA,qBAAqB,CAAA,UAAS;AAAA,UAC9B,eAAe,CAAA,UAAS;AAAA,UACxB,UAAU;AAAA,UAAC;AAAA,UACX,qBAAqB,CAAA,UAAS;AAAA,QAAA;AAAA,MAChC;AAAA,MAEF;AAAA,IAAA;AAGF,WAAO,cAAc,eAAe,OAAO,wBAAwB,CAAA,GAAI,EAAE;AAEzE,QAAI,cAAc;AAChB,aAAO,YAAY,yBAAyB,aAAa,MAAM;AAAA,IACjE;AAEA,WAAO;AAAA,WAtEP;AAAA;AAAA;AAAA;AAAA;AAuEF;"}
@@ -1 +1 @@
1
- {"version":3,"file":"change-source.d.ts","sourceRoot":"","sources":["../../../../../../../zero-cache/src/services/change-source/custom/change-source.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAMjD,OAAO,EAAC,QAAQ,EAAC,MAAM,iCAAiC,CAAC;AAGzD,OAAO,KAAK,EAAC,WAAW,EAAU,MAAM,0BAA0B,CAAC;AAEnE,OAAO,KAAK,EACV,YAAY,EAEb,MAAM,kDAAkD,CAAC;AAQ1D,OAAO,EAGL,KAAK,iBAAiB,EACvB,MAAM,8CAA8C,CAAC;AAKtD;;;GAGG;AACH,wBAAsB,4BAA4B,CAChD,EAAE,EAAE,UAAU,EACd,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,WAAW,EAClB,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC;IAAC,iBAAiB,EAAE,iBAAiB,CAAC;IAAC,YAAY,EAAE,YAAY,CAAA;CAAC,CAAC,CAgC7E;AAwDD;;;;;;;;;;GAUG;AACH,wBAAsB,WAAW,CAC/B,EAAE,EAAE,UAAU,EACd,KAAK,EAAE,WAAW,EAClB,EAAE,EAAE,QAAQ,EACZ,WAAW,EAAE,MAAM,iBA+EpB"}
1
+ {"version":3,"file":"change-source.d.ts","sourceRoot":"","sources":["../../../../../../../zero-cache/src/services/change-source/custom/change-source.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAMjD,OAAO,EAAC,QAAQ,EAAC,MAAM,iCAAiC,CAAC;AAGzD,OAAO,KAAK,EAAC,WAAW,EAAU,MAAM,0BAA0B,CAAC;AAEnE,OAAO,KAAK,EACV,YAAY,EAEb,MAAM,kDAAkD,CAAC;AAO1D,OAAO,EAGL,KAAK,iBAAiB,EACvB,MAAM,8CAA8C,CAAC;AAKtD;;;GAGG;AACH,wBAAsB,4BAA4B,CAChD,EAAE,EAAE,UAAU,EACd,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,WAAW,EAClB,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC;IAAC,iBAAiB,EAAE,iBAAiB,CAAC;IAAC,YAAY,EAAE,YAAY,CAAA;CAAC,CAAC,CAgC7E;AA2DD;;;;;;;;;;GAUG;AACH,wBAAsB,WAAW,CAC/B,EAAE,EAAE,UAAU,EACd,KAAK,EAAE,WAAW,EAClB,EAAE,EAAE,QAAQ,EACZ,WAAW,EAAE,MAAM,iBA8EpB"}
@@ -9,7 +9,6 @@ import { stream } from "../../../types/streams.js";
9
9
  import { AutoResetSignal } from "../../change-streamer/schema/tables.js";
10
10
  import { ChangeProcessor } from "../../replicator/change-processor.js";
11
11
  import { ReplicationStatusPublisher } from "../../replicator/replication-status.js";
12
- import { initChangeLog } from "../../replicator/schema/change-log.js";
13
12
  import { getSubscriptionState, initReplicationState } from "../../replicator/schema/replication-state.js";
14
13
  import { changeStreamMessageSchema } from "../protocol/current/downstream.js";
15
14
  import "../protocol/current/status.js";
@@ -69,7 +68,10 @@ class CustomChangeSource {
69
68
  url.searchParams.append("publications", pub);
70
69
  }
71
70
  if (clientWatermark) {
72
- assert(replicaVersion.length);
71
+ assert(
72
+ replicaVersion.length,
73
+ "replicaVersion is required when clientWatermark is set"
74
+ );
73
75
  url.searchParams.set("lastWatermark", clientWatermark);
74
76
  url.searchParams.set("replicaVersion", replicaVersion);
75
77
  }
@@ -118,7 +120,6 @@ async function initialSync(lc, shard, tx, upstreamURI) {
118
120
  5e3
119
121
  );
120
122
  initReplicationState(tx, [...publications].sort(), commitWatermark);
121
- initChangeLog(tx);
122
123
  processor.processMessage(lc, change);
123
124
  break;
124
125
  }
@@ -1 +1 @@
1
- {"version":3,"file":"change-source.js","sources":["../../../../../../../zero-cache/src/services/change-source/custom/change-source.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {WebSocket} from 'ws';\nimport {assert, unreachable} from '../../../../../shared/src/asserts.ts';\nimport {stringify} from '../../../../../shared/src/bigint-json.ts';\nimport {deepEqual} from '../../../../../shared/src/json.ts';\nimport type {SchemaValue} from '../../../../../zero-schema/src/table-schema.ts';\nimport {Database} from '../../../../../zqlite/src/db.ts';\nimport {computeZqlSpecs} from '../../../db/lite-tables.ts';\nimport {StatementRunner} from '../../../db/statements.ts';\nimport type {ShardConfig, ShardID} from '../../../types/shards.ts';\nimport {stream} from '../../../types/streams.ts';\nimport type {\n ChangeSource,\n ChangeStream,\n} from '../../change-streamer/change-streamer-service.ts';\nimport {\n AutoResetSignal,\n type ReplicationConfig,\n} from '../../change-streamer/schema/tables.ts';\nimport {ChangeProcessor} from '../../replicator/change-processor.ts';\nimport {ReplicationStatusPublisher} from '../../replicator/replication-status.ts';\nimport {initChangeLog} from '../../replicator/schema/change-log.ts';\nimport {\n getSubscriptionState,\n initReplicationState,\n type SubscriptionState,\n} from '../../replicator/schema/replication-state.ts';\nimport {changeStreamMessageSchema} from '../protocol/current/downstream.ts';\nimport {type ChangeSourceUpstream} from '../protocol/current/upstream.ts';\nimport {initSyncSchema} from './sync-schema.ts';\n\n/**\n * Initializes a Custom change source before streaming changes from the\n * corresponding logical replication stream.\n */\nexport async function initializeCustomChangeSource(\n lc: LogContext,\n upstreamURI: string,\n shard: ShardConfig,\n replicaDbFile: string,\n): Promise<{subscriptionState: SubscriptionState; changeSource: ChangeSource}> {\n await initSyncSchema(\n lc,\n `replica-${shard.appID}-${shard.shardNum}`,\n shard,\n replicaDbFile,\n upstreamURI,\n );\n\n const replica = new Database(lc, replicaDbFile);\n const subscriptionState = getSubscriptionState(new StatementRunner(replica));\n replica.close();\n\n if (shard.publications.length) {\n // Verify that the publications match what has been synced.\n const requested = [...shard.publications].sort();\n const replicated = subscriptionState.publications.sort();\n if (!deepEqual(requested, replicated)) {\n throw new Error(\n `Invalid ShardConfig. Requested publications [${requested}] do not match synced publications: [${replicated}]`,\n );\n }\n }\n\n const changeSource = new CustomChangeSource(\n lc,\n upstreamURI,\n shard,\n subscriptionState,\n );\n\n return {subscriptionState, changeSource};\n}\n\nclass CustomChangeSource implements ChangeSource {\n readonly #lc: LogContext;\n readonly #upstreamUri: string;\n readonly #shard: ShardID;\n readonly #replicationConfig: ReplicationConfig;\n\n constructor(\n lc: LogContext,\n upstreamUri: string,\n shard: ShardID,\n replicationConfig: ReplicationConfig,\n ) {\n this.#lc = lc.withContext('component', 'change-source');\n this.#upstreamUri = upstreamUri;\n this.#shard = shard;\n this.#replicationConfig = replicationConfig;\n }\n\n initialSync(): ChangeStream {\n return this.#startStream();\n }\n\n startStream(clientWatermark: string): Promise<ChangeStream> {\n return Promise.resolve(this.#startStream(clientWatermark));\n }\n\n #startStream(clientWatermark?: string): ChangeStream {\n const {publications, replicaVersion} = this.#replicationConfig;\n const {appID, shardNum} = this.#shard;\n const url = new URL(this.#upstreamUri);\n url.searchParams.set('appID', appID);\n url.searchParams.set('shardNum', String(shardNum));\n for (const pub of publications) {\n url.searchParams.append('publications', pub);\n }\n if (clientWatermark) {\n assert(replicaVersion.length);\n url.searchParams.set('lastWatermark', clientWatermark);\n url.searchParams.set('replicaVersion', replicaVersion);\n }\n\n const ws = new WebSocket(url);\n const {instream, outstream} = stream(\n this.#lc,\n ws,\n changeStreamMessageSchema,\n // Upstream acks coalesce. If upstream exhibits back-pressure,\n // only the last ACK is kept / buffered.\n {coalesce: (curr: ChangeSourceUpstream) => curr},\n );\n return {changes: instream, acks: outstream};\n }\n}\n\n/**\n * Initial sync for a custom change source makes a request to the\n * change source endpoint with no `replicaVersion` or `lastWatermark`.\n * The initial transaction returned by the endpoint is treated as\n * the initial sync, and the commit watermark of that transaction\n * becomes the `replicaVersion` of the initialized replica.\n *\n * Note that this is equivalent to how the LSN of the Postgres WAL\n * at initial sync time is the `replicaVersion` (and starting\n * version for all initially-synced rows).\n */\nexport async function initialSync(\n lc: LogContext,\n shard: ShardConfig,\n tx: Database,\n upstreamURI: string,\n) {\n const {appID: id, publications} = shard;\n const changeSource = new CustomChangeSource(lc, upstreamURI, shard, {\n replicaVersion: '', // ignored for initialSync()\n publications,\n });\n const {changes} = changeSource.initialSync();\n\n const processor = new ChangeProcessor(\n new StatementRunner(tx),\n 'initial-sync',\n (_, err) => {\n throw err;\n },\n );\n\n const statusPublisher = new ReplicationStatusPublisher(tx);\n try {\n let num = 0;\n for await (const change of changes) {\n const [tag] = change;\n switch (tag) {\n case 'begin': {\n const {commitWatermark} = change[2];\n lc.info?.(\n `initial sync of shard ${id} at replicaVersion ${commitWatermark}`,\n );\n statusPublisher.publish(\n lc,\n 'Initializing',\n `Copying upstream tables at version ${commitWatermark}`,\n 5000,\n );\n initReplicationState(tx, [...publications].sort(), commitWatermark);\n initChangeLog(tx);\n processor.processMessage(lc, change);\n break;\n }\n case 'data':\n processor.processMessage(lc, change);\n if (++num % 1000 === 0) {\n lc.debug?.(`processed ${num} changes`);\n }\n break;\n case 'commit':\n processor.processMessage(lc, change);\n validateInitiallySyncedData(lc, tx, shard);\n lc.info?.(`finished initial-sync of ${num} changes`);\n return;\n\n case 'status':\n break; // Ignored\n // @ts-expect-error: falls through if the tag is not 'reset-required\n case 'control': {\n const {tag, message} = change[1];\n if (tag === 'reset-required') {\n throw new AutoResetSignal(\n message ?? 'auto-reset signaled by change source',\n );\n }\n }\n // falls through\n case 'rollback':\n throw new Error(\n `unexpected message during initial-sync: ${stringify(change)}`,\n );\n default:\n unreachable(change);\n }\n }\n throw new Error(\n `change source ${upstreamURI} closed before initial-sync completed`,\n );\n } catch (e) {\n await statusPublisher.publishAndThrowError(lc, 'Initializing', e);\n } finally {\n statusPublisher.stop();\n }\n}\n\n// Verify that the upstream tables expected by the sync logic\n// have been properly initialized.\nfunction getRequiredTables({\n appID,\n shardNum,\n}: ShardID): Record<string, Record<string, SchemaValue>> {\n return {\n [`${appID}_${shardNum}.clients`]: {\n clientGroupID: {type: 'string'},\n clientID: {type: 'string'},\n lastMutationID: {type: 'number'},\n userID: {type: 'string'},\n },\n [`${appID}_${shardNum}.mutations`]: {\n clientGroupID: {type: 'string'},\n clientID: {type: 'string'},\n mutationID: {type: 'number'},\n mutation: {type: 'json'},\n },\n [`${appID}.permissions`]: {\n permissions: {type: 'json'},\n hash: {type: 'string'},\n },\n };\n}\n\nfunction validateInitiallySyncedData(\n lc: LogContext,\n db: Database,\n shard: ShardID,\n) {\n const tables = computeZqlSpecs(lc, db);\n const required = getRequiredTables(shard);\n for (const [name, columns] of Object.entries(required)) {\n const table = tables.get(name)?.zqlSpec;\n if (!table) {\n throw new Error(\n `Upstream is missing the \"${name}\" table. (Found ${[\n ...tables.keys(),\n ]})` +\n `Please ensure that each table has a unique index over one ` +\n `or more non-null columns.`,\n );\n }\n for (const [col, {type}] of Object.entries(columns)) {\n const found = table[col];\n if (!found) {\n throw new Error(\n `Upstream \"${table}\" table is missing the \"${col}\" column`,\n );\n }\n if (found.type !== type) {\n throw new Error(\n `Upstream \"${table}.${col}\" column is a ${found.type} type but must be a ${type} type.`,\n );\n }\n }\n }\n}\n"],"names":["tag"],"mappings":";;;;;;;;;;;;;;;;AAmCA,eAAsB,6BACpB,IACA,aACA,OACA,eAC6E;AAC7E,QAAM;AAAA,IACJ;AAAA,IACA,WAAW,MAAM,KAAK,IAAI,MAAM,QAAQ;AAAA,IACxC;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAGF,QAAM,UAAU,IAAI,SAAS,IAAI,aAAa;AAC9C,QAAM,oBAAoB,qBAAqB,IAAI,gBAAgB,OAAO,CAAC;AAC3E,UAAQ,MAAA;AAER,MAAI,MAAM,aAAa,QAAQ;AAE7B,UAAM,YAAY,CAAC,GAAG,MAAM,YAAY,EAAE,KAAA;AAC1C,UAAM,aAAa,kBAAkB,aAAa,KAAA;AAClD,QAAI,CAAC,UAAU,WAAW,UAAU,GAAG;AACrC,YAAM,IAAI;AAAA,QACR,gDAAgD,SAAS,wCAAwC,UAAU;AAAA,MAAA;AAAA,IAE/G;AAAA,EACF;AAEA,QAAM,eAAe,IAAI;AAAA,IACvB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAGF,SAAO,EAAC,mBAAmB,aAAA;AAC7B;AAEA,MAAM,mBAA2C;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,YACE,IACA,aACA,OACA,mBACA;AACA,SAAK,MAAM,GAAG,YAAY,aAAa,eAAe;AACtD,SAAK,eAAe;AACpB,SAAK,SAAS;AACd,SAAK,qBAAqB;AAAA,EAC5B;AAAA,EAEA,cAA4B;AAC1B,WAAO,KAAK,aAAA;AAAA,EACd;AAAA,EAEA,YAAY,iBAAgD;AAC1D,WAAO,QAAQ,QAAQ,KAAK,aAAa,eAAe,CAAC;AAAA,EAC3D;AAAA,EAEA,aAAa,iBAAwC;AACnD,UAAM,EAAC,cAAc,eAAA,IAAkB,KAAK;AAC5C,UAAM,EAAC,OAAO,SAAA,IAAY,KAAK;AAC/B,UAAM,MAAM,IAAI,IAAI,KAAK,YAAY;AACrC,QAAI,aAAa,IAAI,SAAS,KAAK;AACnC,QAAI,aAAa,IAAI,YAAY,OAAO,QAAQ,CAAC;AACjD,eAAW,OAAO,cAAc;AAC9B,UAAI,aAAa,OAAO,gBAAgB,GAAG;AAAA,IAC7C;AACA,QAAI,iBAAiB;AACnB,aAAO,eAAe,MAAM;AAC5B,UAAI,aAAa,IAAI,iBAAiB,eAAe;AACrD,UAAI,aAAa,IAAI,kBAAkB,cAAc;AAAA,IACvD;AAEA,UAAM,KAAK,IAAI,UAAU,GAAG;AAC5B,UAAM,EAAC,UAAU,UAAA,IAAa;AAAA,MAC5B,KAAK;AAAA,MACL;AAAA,MACA;AAAA;AAAA;AAAA,MAGA,EAAC,UAAU,CAAC,SAA+B,KAAA;AAAA,IAAI;AAEjD,WAAO,EAAC,SAAS,UAAU,MAAM,UAAA;AAAA,EACnC;AACF;AAaA,eAAsB,YACpB,IACA,OACA,IACA,aACA;AACA,QAAM,EAAC,OAAO,IAAI,aAAA,IAAgB;AAClC,QAAM,eAAe,IAAI,mBAAmB,IAAI,aAAa,OAAO;AAAA,IAClE,gBAAgB;AAAA;AAAA,IAChB;AAAA,EAAA,CACD;AACD,QAAM,EAAC,QAAA,IAAW,aAAa,YAAA;AAE/B,QAAM,YAAY,IAAI;AAAA,IACpB,IAAI,gBAAgB,EAAE;AAAA,IACtB;AAAA,IACA,CAAC,GAAG,QAAQ;AACV,YAAM;AAAA,IACR;AAAA,EAAA;AAGF,QAAM,kBAAkB,IAAI,2BAA2B,EAAE;AACzD,MAAI;AACF,QAAI,MAAM;AACV,qBAAiB,UAAU,SAAS;AAClC,YAAM,CAAC,GAAG,IAAI;AACd,cAAQ,KAAA;AAAA,QACN,KAAK,SAAS;AACZ,gBAAM,EAAC,gBAAA,IAAmB,OAAO,CAAC;AAClC,aAAG;AAAA,YACD,yBAAyB,EAAE,sBAAsB,eAAe;AAAA,UAAA;AAElE,0BAAgB;AAAA,YACd;AAAA,YACA;AAAA,YACA,sCAAsC,eAAe;AAAA,YACrD;AAAA,UAAA;AAEF,+BAAqB,IAAI,CAAC,GAAG,YAAY,EAAE,KAAA,GAAQ,eAAe;AAClE,wBAAc,EAAE;AAChB,oBAAU,eAAe,IAAI,MAAM;AACnC;AAAA,QACF;AAAA,QACA,KAAK;AACH,oBAAU,eAAe,IAAI,MAAM;AACnC,cAAI,EAAE,MAAM,QAAS,GAAG;AACtB,eAAG,QAAQ,aAAa,GAAG,UAAU;AAAA,UACvC;AACA;AAAA,QACF,KAAK;AACH,oBAAU,eAAe,IAAI,MAAM;AACnC,sCAA4B,IAAI,IAAI,KAAK;AACzC,aAAG,OAAO,4BAA4B,GAAG,UAAU;AACnD;AAAA,QAEF,KAAK;AACH;AAAA;AAAA;AAAA,QAEF,KAAK,WAAW;AACd,gBAAM,EAAC,KAAAA,MAAK,QAAA,IAAW,OAAO,CAAC;AAC/B,cAAIA,SAAQ,kBAAkB;AAC5B,kBAAM,IAAI;AAAA,cACR,WAAW;AAAA,YAAA;AAAA,UAEf;AAAA,QACF;AAAA;AAAA,QAEA,KAAK;AACH,gBAAM,IAAI;AAAA,YACR,2CAA2C,UAAU,MAAM,CAAC;AAAA,UAAA;AAAA,QAEhE;AACE,sBAAY,MAAM;AAAA,MAAA;AAAA,IAExB;AACA,UAAM,IAAI;AAAA,MACR,iBAAiB,WAAW;AAAA,IAAA;AAAA,EAEhC,SAAS,GAAG;AACV,UAAM,gBAAgB,qBAAqB,IAAI,gBAAgB,CAAC;AAAA,EAClE,UAAA;AACE,oBAAgB,KAAA;AAAA,EAClB;AACF;AAIA,SAAS,kBAAkB;AAAA,EACzB;AAAA,EACA;AACF,GAAyD;AACvD,SAAO;AAAA,IACL,CAAC,GAAG,KAAK,IAAI,QAAQ,UAAU,GAAG;AAAA,MAChC,eAAe,EAAC,MAAM,SAAA;AAAA,MACtB,UAAU,EAAC,MAAM,SAAA;AAAA,MACjB,gBAAgB,EAAC,MAAM,SAAA;AAAA,MACvB,QAAQ,EAAC,MAAM,SAAA;AAAA,IAAQ;AAAA,IAEzB,CAAC,GAAG,KAAK,IAAI,QAAQ,YAAY,GAAG;AAAA,MAClC,eAAe,EAAC,MAAM,SAAA;AAAA,MACtB,UAAU,EAAC,MAAM,SAAA;AAAA,MACjB,YAAY,EAAC,MAAM,SAAA;AAAA,MACnB,UAAU,EAAC,MAAM,OAAA;AAAA,IAAM;AAAA,IAEzB,CAAC,GAAG,KAAK,cAAc,GAAG;AAAA,MACxB,aAAa,EAAC,MAAM,OAAA;AAAA,MACpB,MAAM,EAAC,MAAM,SAAA;AAAA,IAAQ;AAAA,EACvB;AAEJ;AAEA,SAAS,4BACP,IACA,IACA,OACA;AACA,QAAM,SAAS,gBAAgB,IAAI,EAAE;AACrC,QAAM,WAAW,kBAAkB,KAAK;AACxC,aAAW,CAAC,MAAM,OAAO,KAAK,OAAO,QAAQ,QAAQ,GAAG;AACtD,UAAM,QAAQ,OAAO,IAAI,IAAI,GAAG;AAChC,QAAI,CAAC,OAAO;AACV,YAAM,IAAI;AAAA,QACR,4BAA4B,IAAI,mBAAmB;AAAA,UACjD,GAAG,OAAO,KAAA;AAAA,QAAK,CAChB;AAAA,MAAA;AAAA,IAIL;AACA,eAAW,CAAC,KAAK,EAAC,KAAA,CAAK,KAAK,OAAO,QAAQ,OAAO,GAAG;AACnD,YAAM,QAAQ,MAAM,GAAG;AACvB,UAAI,CAAC,OAAO;AACV,cAAM,IAAI;AAAA,UACR,aAAa,KAAK,2BAA2B,GAAG;AAAA,QAAA;AAAA,MAEpD;AACA,UAAI,MAAM,SAAS,MAAM;AACvB,cAAM,IAAI;AAAA,UACR,aAAa,KAAK,IAAI,GAAG,iBAAiB,MAAM,IAAI,uBAAuB,IAAI;AAAA,QAAA;AAAA,MAEnF;AAAA,IACF;AAAA,EACF;AACF;"}
1
+ {"version":3,"file":"change-source.js","sources":["../../../../../../../zero-cache/src/services/change-source/custom/change-source.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {WebSocket} from 'ws';\nimport {assert, unreachable} from '../../../../../shared/src/asserts.ts';\nimport {stringify} from '../../../../../shared/src/bigint-json.ts';\nimport {deepEqual} from '../../../../../shared/src/json.ts';\nimport type {SchemaValue} from '../../../../../zero-schema/src/table-schema.ts';\nimport {Database} from '../../../../../zqlite/src/db.ts';\nimport {computeZqlSpecs} from '../../../db/lite-tables.ts';\nimport {StatementRunner} from '../../../db/statements.ts';\nimport type {ShardConfig, ShardID} from '../../../types/shards.ts';\nimport {stream} from '../../../types/streams.ts';\nimport type {\n ChangeSource,\n ChangeStream,\n} from '../../change-streamer/change-streamer-service.ts';\nimport {\n AutoResetSignal,\n type ReplicationConfig,\n} from '../../change-streamer/schema/tables.ts';\nimport {ChangeProcessor} from '../../replicator/change-processor.ts';\nimport {ReplicationStatusPublisher} from '../../replicator/replication-status.ts';\nimport {\n getSubscriptionState,\n initReplicationState,\n type SubscriptionState,\n} from '../../replicator/schema/replication-state.ts';\nimport {changeStreamMessageSchema} from '../protocol/current/downstream.ts';\nimport {type ChangeSourceUpstream} from '../protocol/current/upstream.ts';\nimport {initSyncSchema} from './sync-schema.ts';\n\n/**\n * Initializes a Custom change source before streaming changes from the\n * corresponding logical replication stream.\n */\nexport async function initializeCustomChangeSource(\n lc: LogContext,\n upstreamURI: string,\n shard: ShardConfig,\n replicaDbFile: string,\n): Promise<{subscriptionState: SubscriptionState; changeSource: ChangeSource}> {\n await initSyncSchema(\n lc,\n `replica-${shard.appID}-${shard.shardNum}`,\n shard,\n replicaDbFile,\n upstreamURI,\n );\n\n const replica = new Database(lc, replicaDbFile);\n const subscriptionState = getSubscriptionState(new StatementRunner(replica));\n replica.close();\n\n if (shard.publications.length) {\n // Verify that the publications match what has been synced.\n const requested = [...shard.publications].sort();\n const replicated = subscriptionState.publications.sort();\n if (!deepEqual(requested, replicated)) {\n throw new Error(\n `Invalid ShardConfig. Requested publications [${requested}] do not match synced publications: [${replicated}]`,\n );\n }\n }\n\n const changeSource = new CustomChangeSource(\n lc,\n upstreamURI,\n shard,\n subscriptionState,\n );\n\n return {subscriptionState, changeSource};\n}\n\nclass CustomChangeSource implements ChangeSource {\n readonly #lc: LogContext;\n readonly #upstreamUri: string;\n readonly #shard: ShardID;\n readonly #replicationConfig: ReplicationConfig;\n\n constructor(\n lc: LogContext,\n upstreamUri: string,\n shard: ShardID,\n replicationConfig: ReplicationConfig,\n ) {\n this.#lc = lc.withContext('component', 'change-source');\n this.#upstreamUri = upstreamUri;\n this.#shard = shard;\n this.#replicationConfig = replicationConfig;\n }\n\n initialSync(): ChangeStream {\n return this.#startStream();\n }\n\n startStream(clientWatermark: string): Promise<ChangeStream> {\n return Promise.resolve(this.#startStream(clientWatermark));\n }\n\n #startStream(clientWatermark?: string): ChangeStream {\n const {publications, replicaVersion} = this.#replicationConfig;\n const {appID, shardNum} = this.#shard;\n const url = new URL(this.#upstreamUri);\n url.searchParams.set('appID', appID);\n url.searchParams.set('shardNum', String(shardNum));\n for (const pub of publications) {\n url.searchParams.append('publications', pub);\n }\n if (clientWatermark) {\n assert(\n replicaVersion.length,\n 'replicaVersion is required when clientWatermark is set',\n );\n url.searchParams.set('lastWatermark', clientWatermark);\n url.searchParams.set('replicaVersion', replicaVersion);\n }\n\n const ws = new WebSocket(url);\n const {instream, outstream} = stream(\n this.#lc,\n ws,\n changeStreamMessageSchema,\n // Upstream acks coalesce. If upstream exhibits back-pressure,\n // only the last ACK is kept / buffered.\n {coalesce: (curr: ChangeSourceUpstream) => curr},\n );\n return {changes: instream, acks: outstream};\n }\n}\n\n/**\n * Initial sync for a custom change source makes a request to the\n * change source endpoint with no `replicaVersion` or `lastWatermark`.\n * The initial transaction returned by the endpoint is treated as\n * the initial sync, and the commit watermark of that transaction\n * becomes the `replicaVersion` of the initialized replica.\n *\n * Note that this is equivalent to how the LSN of the Postgres WAL\n * at initial sync time is the `replicaVersion` (and starting\n * version for all initially-synced rows).\n */\nexport async function initialSync(\n lc: LogContext,\n shard: ShardConfig,\n tx: Database,\n upstreamURI: string,\n) {\n const {appID: id, publications} = shard;\n const changeSource = new CustomChangeSource(lc, upstreamURI, shard, {\n replicaVersion: '', // ignored for initialSync()\n publications,\n });\n const {changes} = changeSource.initialSync();\n\n const processor = new ChangeProcessor(\n new StatementRunner(tx),\n 'initial-sync',\n (_, err) => {\n throw err;\n },\n );\n\n const statusPublisher = new ReplicationStatusPublisher(tx);\n try {\n let num = 0;\n for await (const change of changes) {\n const [tag] = change;\n switch (tag) {\n case 'begin': {\n const {commitWatermark} = change[2];\n lc.info?.(\n `initial sync of shard ${id} at replicaVersion ${commitWatermark}`,\n );\n statusPublisher.publish(\n lc,\n 'Initializing',\n `Copying upstream tables at version ${commitWatermark}`,\n 5000,\n );\n initReplicationState(tx, [...publications].sort(), commitWatermark);\n processor.processMessage(lc, change);\n break;\n }\n case 'data':\n processor.processMessage(lc, change);\n if (++num % 1000 === 0) {\n lc.debug?.(`processed ${num} changes`);\n }\n break;\n case 'commit':\n processor.processMessage(lc, change);\n validateInitiallySyncedData(lc, tx, shard);\n lc.info?.(`finished initial-sync of ${num} changes`);\n return;\n\n case 'status':\n break; // Ignored\n // @ts-expect-error: falls through if the tag is not 'reset-required\n case 'control': {\n const {tag, message} = change[1];\n if (tag === 'reset-required') {\n throw new AutoResetSignal(\n message ?? 'auto-reset signaled by change source',\n );\n }\n }\n // falls through\n case 'rollback':\n throw new Error(\n `unexpected message during initial-sync: ${stringify(change)}`,\n );\n default:\n unreachable(change);\n }\n }\n throw new Error(\n `change source ${upstreamURI} closed before initial-sync completed`,\n );\n } catch (e) {\n await statusPublisher.publishAndThrowError(lc, 'Initializing', e);\n } finally {\n statusPublisher.stop();\n }\n}\n\n// Verify that the upstream tables expected by the sync logic\n// have been properly initialized.\nfunction getRequiredTables({\n appID,\n shardNum,\n}: ShardID): Record<string, Record<string, SchemaValue>> {\n return {\n [`${appID}_${shardNum}.clients`]: {\n clientGroupID: {type: 'string'},\n clientID: {type: 'string'},\n lastMutationID: {type: 'number'},\n userID: {type: 'string'},\n },\n [`${appID}_${shardNum}.mutations`]: {\n clientGroupID: {type: 'string'},\n clientID: {type: 'string'},\n mutationID: {type: 'number'},\n mutation: {type: 'json'},\n },\n [`${appID}.permissions`]: {\n permissions: {type: 'json'},\n hash: {type: 'string'},\n },\n };\n}\n\nfunction validateInitiallySyncedData(\n lc: LogContext,\n db: Database,\n shard: ShardID,\n) {\n const tables = computeZqlSpecs(lc, db);\n const required = getRequiredTables(shard);\n for (const [name, columns] of Object.entries(required)) {\n const table = tables.get(name)?.zqlSpec;\n if (!table) {\n throw new Error(\n `Upstream is missing the \"${name}\" table. (Found ${[\n ...tables.keys(),\n ]})` +\n `Please ensure that each table has a unique index over one ` +\n `or more non-null columns.`,\n );\n }\n for (const [col, {type}] of Object.entries(columns)) {\n const found = table[col];\n if (!found) {\n throw new Error(\n `Upstream \"${table}\" table is missing the \"${col}\" column`,\n );\n }\n if (found.type !== type) {\n throw new Error(\n `Upstream \"${table}.${col}\" column is a ${found.type} type but must be a ${type} type.`,\n );\n }\n }\n }\n}\n"],"names":["tag"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"change-source.d.ts","sourceRoot":"","sources":["../../../../../../../zero-cache/src/services/change-source/pg/change-source.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAgBjD,OAAO,KAAK,EAEV,kBAAkB,EAEnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAIL,KAAK,WAAW,EACjB,MAAM,gCAAgC,CAAC;AAExC,OAAO,EAEL,KAAK,WAAW,EAEjB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,2BAA2B,CAAC;AAEpD,OAAO,KAAK,EACV,YAAY,EAEb,MAAM,kDAAkD,CAAC;AAE1D,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,8CAA8C,CAAC;AAYtD,OAAO,EAAC,KAAK,kBAAkB,EAAC,MAAM,mBAAmB,CAAC;AAC1D,OAAO,KAAK,EAGV,eAAe,IAAI,gBAAgB,EACpC,MAAM,yCAAyC,CAAC;AAoBjD;;;;GAIG;AACH,wBAAsB,8BAA8B,CAClD,EAAE,EAAE,UAAU,EACd,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,WAAW,EAClB,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,kBAAkB,GAC9B,OAAO,CAAC;IAAC,iBAAiB,EAAE,iBAAiB,CAAC;IAAC,YAAY,EAAE,YAAY,CAAA;CAAC,CAAC,CAoC7E;AA6PD,qBAAa,KAAK;;gBAIJ,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC;IAI9B,SAAS;IAiBT,GAAG,CAAC,SAAS,EAAE,WAAW;CAa3B;AAycD,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,kBAAkB,EAAE,CAAC,EAAE,gBAAgB,WAwB3E"}
1
+ {"version":3,"file":"change-source.d.ts","sourceRoot":"","sources":["../../../../../../../zero-cache/src/services/change-source/pg/change-source.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAkBjD,OAAO,KAAK,EAAa,kBAAkB,EAAC,MAAM,sBAAsB,CAAC;AAEzE,OAAO,EAIL,KAAK,WAAW,EACjB,MAAM,gCAAgC,CAAC;AAExC,OAAO,EAEL,KAAK,WAAW,EAEjB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,2BAA2B,CAAC;AAEpD,OAAO,KAAK,EACV,YAAY,EAEb,MAAM,kDAAkD,CAAC;AAE1D,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,8CAA8C,CAAC;AAatD,OAAO,EAAC,KAAK,kBAAkB,EAAC,MAAM,mBAAmB,CAAC;AAC1D,OAAO,KAAK,EAGV,eAAe,IAAI,gBAAgB,EACpC,MAAM,yCAAyC,CAAC;AAwBjD;;;;GAIG;AACH,wBAAsB,8BAA8B,CAClD,EAAE,EAAE,UAAU,EACd,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,WAAW,EAClB,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,kBAAkB,GAC9B,OAAO,CAAC;IAAC,iBAAiB,EAAE,iBAAiB,CAAC;IAAC,YAAY,EAAE,YAAY,CAAA;CAAC,CAAC,CAoC7E;AA6PD,qBAAa,KAAK;;gBAIJ,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC;IAI9B,SAAS;IAiBT,GAAG,CAAC,SAAS,EAAE,WAAW;CAa3B;AAieD,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,kBAAkB,EAAE,CAAC,EAAE,gBAAgB,WAwB3E"}
@@ -1,6 +1,8 @@
1
1
  import { PG_OBJECT_IN_USE, PG_ADMIN_SHUTDOWN } from "@drdgvhbh/postgres-error-codes";
2
2
  import postgres from "postgres";
3
3
  import { AbortError } from "../../../../../shared/src/abort-error.js";
4
+ import { areEqual } from "../../../../../shared/src/arrays.js";
5
+ import { unreachable } from "../../../../../shared/src/asserts.js";
4
6
  import { stringify } from "../../../../../shared/src/bigint-json.js";
5
7
  import { deepEqual } from "../../../../../shared/src/json.js";
6
8
  import { must } from "../../../../../shared/src/must.js";
@@ -22,7 +24,6 @@ import "@rocicorp/resolver";
22
24
  import "@rocicorp/logger";
23
25
  import "../../../../../zero-protocol/src/primary-key.js";
24
26
  import "../../../observability/events.js";
25
- import "../../replicator/schema/change-log.js";
26
27
  import { fromBigInt, toLexiVersion } from "./lsn.js";
27
28
  import { updateShardSchema } from "./schema/init.js";
28
29
  import { getPublicationInfo } from "./schema/published.js";
@@ -340,7 +341,7 @@ class ChangeMaker {
340
341
  "data",
341
342
  {
342
343
  ...msg,
343
- relation: withoutColumns(msg.relation),
344
+ relation: makeRelation(msg.relation),
344
345
  // https://www.postgresql.org/docs/current/protocol-logicalrep-message-formats.html#PROTOCOL-LOGICALREP-MESSAGE-FORMATS-DELETE
345
346
  key: must(msg.old ?? msg.key)
346
347
  }
@@ -353,7 +354,7 @@ class ChangeMaker {
353
354
  "data",
354
355
  {
355
356
  ...msg,
356
- relation: withoutColumns(msg.relation),
357
+ relation: makeRelation(msg.relation),
357
358
  // https://www.postgresql.org/docs/current/protocol-logicalrep-message-formats.html#PROTOCOL-LOGICALREP-MESSAGE-FORMATS-UPDATE
358
359
  key: msg.old ?? msg.key
359
360
  }
@@ -361,11 +362,9 @@ class ChangeMaker {
361
362
  ];
362
363
  }
363
364
  case "insert":
364
- return [["data", { ...msg, relation: withoutColumns(msg.relation) }]];
365
+ return [["data", { ...msg, relation: makeRelation(msg.relation) }]];
365
366
  case "truncate":
366
- return [
367
- ["data", { ...msg, relations: msg.relations.map(withoutColumns) }]
368
- ];
367
+ return [["data", { ...msg, relations: msg.relations.map(makeRelation) }]];
369
368
  case "message":
370
369
  if (msg.prefix !== this.#shardPrefix) {
371
370
  this.#lc.debug?.("ignoring message for different shard", msg.prefix);
@@ -447,7 +446,7 @@ class ChangeMaker {
447
446
  const [nextTbl, nextIdx] = specsByID(update.schema);
448
447
  const changes = [];
449
448
  for (const table of nextTbl.values()) {
450
- validate(this.#lc, table, update.schema.indexes);
449
+ validate(this.#lc, table);
451
450
  }
452
451
  const [droppedIdx, createdIdx] = symmetricDifferences(prevIdx, nextIdx);
453
452
  for (const id of droppedIdx) {
@@ -470,7 +469,11 @@ class ChangeMaker {
470
469
  }
471
470
  for (const id of createdTbl) {
472
471
  const spec = must(nextTbl.get(id));
473
- changes.push({ tag: "create-table", spec });
472
+ changes.push({
473
+ tag: "create-table",
474
+ spec,
475
+ metadata: getMetadata(spec)
476
+ });
474
477
  }
475
478
  for (const id of createdIdx) {
476
479
  const spec = must(nextIdx.get(id));
@@ -490,6 +493,17 @@ class ChangeMaker {
490
493
  new: { schema: newTable.schema, name: newTable.name }
491
494
  });
492
495
  }
496
+ if (oldTable.replicaIdentity !== newTable.replicaIdentity || !areEqual(
497
+ oldTable.replicaIdentityColumns,
498
+ newTable.replicaIdentityColumns
499
+ )) {
500
+ changes.push({
501
+ tag: "update-table-metadata",
502
+ table: { schema: newTable.schema, name: newTable.name },
503
+ old: getMetadata(oldTable),
504
+ new: getMetadata(newTable)
505
+ });
506
+ }
493
507
  const table = { schema: newTable.schema, name: newTable.name };
494
508
  const oldColumns = columnsByID(oldTable.columns);
495
509
  const newColumns = columnsByID(newTable.columns);
@@ -515,7 +529,12 @@ class ChangeMaker {
515
529
  const { name, ...spec } = must(newColumns.get(id));
516
530
  const column = { name, spec };
517
531
  mapPostgresToLiteColumn(table.name, column);
518
- changes.push({ tag: "add-column", table, column });
532
+ changes.push({
533
+ tag: "add-column",
534
+ table,
535
+ column,
536
+ tableMetadata: getMetadata(newTable)
537
+ });
519
538
  }
520
539
  return changes;
521
540
  }
@@ -649,9 +668,45 @@ function columnsByID(columns) {
649
668
  }
650
669
  return colsByID;
651
670
  }
652
- function withoutColumns(relation) {
653
- const { columns: _, ...rest } = relation;
654
- return rest;
671
+ function getMetadata(table) {
672
+ const metadata = {
673
+ rowKey: {
674
+ columns: table.replicaIdentityColumns
675
+ }
676
+ };
677
+ switch (table.replicaIdentity) {
678
+ case "d":
679
+ metadata.rowKey.type = "default";
680
+ break;
681
+ case "i":
682
+ metadata.rowKey.type = "index";
683
+ break;
684
+ case "f":
685
+ metadata.rowKey.type = "full";
686
+ break;
687
+ case "n":
688
+ metadata.rowKey.type = "nothing";
689
+ break;
690
+ case void 0:
691
+ break;
692
+ default:
693
+ unreachable(table.replicaIdentity);
694
+ }
695
+ return metadata;
696
+ }
697
+ function makeRelation(relation) {
698
+ const { columns: _, keyColumns, replicaIdentity, ...rest } = relation;
699
+ return {
700
+ ...rest,
701
+ rowKey: {
702
+ columns: keyColumns,
703
+ type: replicaIdentity
704
+ },
705
+ // For now, deprecated columns are sent for backwards compatibility.
706
+ // These can be removed when bumping the MIN_PROTOCOL_VERSION to 5.
707
+ keyColumns,
708
+ replicaIdentity
709
+ };
655
710
  }
656
711
  class UnsupportedSchemaChangeError extends Error {
657
712
  name = "UnsupportedSchemaChangeError";