@rocicorp/zero 1.10.0-canary.0 → 1.10.0-canary.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/out/replicache/src/db/commit.js +1 -4
- package/out/replicache/src/db/commit.js.map +1 -1
- package/out/replicache/src/db/read.d.ts +1 -0
- package/out/replicache/src/db/read.d.ts.map +1 -1
- package/out/replicache/src/db/read.js +1 -4
- package/out/replicache/src/db/read.js.map +1 -1
- package/out/replicache/src/db/write.d.ts +2 -1
- package/out/replicache/src/db/write.d.ts.map +1 -1
- package/out/replicache/src/db/write.js +4 -51
- package/out/replicache/src/db/write.js.map +1 -1
- package/out/replicache/src/persist/clients.d.ts +1 -0
- package/out/replicache/src/persist/clients.d.ts.map +1 -1
- package/out/replicache/src/persist/clients.js +4 -31
- package/out/replicache/src/persist/clients.js.map +1 -1
- package/out/replicache/src/process-env.d.ts +28 -0
- package/out/replicache/src/process-env.d.ts.map +1 -0
- package/out/replicache/src/replicache-impl.d.ts.map +1 -1
- package/out/replicache/src/replicache-impl.js.map +1 -1
- package/out/replicache/src/scan-iterator.js +2 -14
- package/out/replicache/src/scan-iterator.js.map +1 -1
- package/out/replicache/src/subscriptions.d.ts +1 -0
- package/out/replicache/src/subscriptions.d.ts.map +1 -1
- package/out/replicache/src/subscriptions.js +2 -10
- package/out/replicache/src/subscriptions.js.map +1 -1
- package/out/replicache/src/transactions.d.ts +1 -0
- package/out/replicache/src/transactions.d.ts.map +1 -1
- package/out/replicache/src/transactions.js +2 -4
- package/out/replicache/src/transactions.js.map +1 -1
- package/out/z2s/src/compiler.d.ts.map +1 -1
- package/out/z2s/src/compiler.js +1 -22
- package/out/z2s/src/compiler.js.map +1 -1
- package/out/zero/package.js +3 -3
- package/out/zero/package.js.map +1 -1
- package/out/zero-cache/src/config/normalize.d.ts +1 -0
- package/out/zero-cache/src/config/normalize.d.ts.map +1 -1
- package/out/zero-cache/src/config/normalize.js +10 -1
- package/out/zero-cache/src/config/normalize.js.map +1 -1
- package/out/zero-cache/src/config/zero-config.d.ts +52 -1
- package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
- package/out/zero-cache/src/config/zero-config.js +171 -22
- package/out/zero-cache/src/config/zero-config.js.map +1 -1
- package/out/zero-cache/src/custom/fetch.js +1 -1
- package/out/zero-cache/src/custom/fetch.js.map +1 -1
- package/out/zero-cache/src/db/delete-lite-db.js +2 -1
- package/out/zero-cache/src/db/delete-lite-db.js.map +1 -1
- package/out/zero-cache/src/db/migration-lite.d.ts.map +1 -1
- package/out/zero-cache/src/db/migration-lite.js +5 -2
- package/out/zero-cache/src/db/migration-lite.js.map +1 -1
- package/out/zero-cache/src/db/migration.d.ts.map +1 -1
- package/out/zero-cache/src/db/migration.js +4 -2
- package/out/zero-cache/src/db/migration.js.map +1 -1
- package/out/zero-cache/src/db/sqlite-corruption.d.ts +3 -2
- package/out/zero-cache/src/db/sqlite-corruption.d.ts.map +1 -1
- package/out/zero-cache/src/db/sqlite-corruption.js +13 -8
- package/out/zero-cache/src/db/sqlite-corruption.js.map +1 -1
- package/out/zero-cache/src/observability/metrics.d.ts +6 -1
- package/out/zero-cache/src/observability/metrics.d.ts.map +1 -1
- package/out/zero-cache/src/observability/metrics.js +20 -2
- package/out/zero-cache/src/observability/metrics.js.map +1 -1
- package/out/zero-cache/src/server/backup-watermark-poller.js +31 -0
- package/out/zero-cache/src/server/backup-watermark-poller.js.map +1 -0
- package/out/zero-cache/src/server/change-streamer.d.ts.map +1 -1
- package/out/zero-cache/src/server/change-streamer.js +91 -31
- package/out/zero-cache/src/server/change-streamer.js.map +1 -1
- package/out/zero-cache/src/server/main.d.ts.map +1 -1
- package/out/zero-cache/src/server/main.js +6 -16
- package/out/zero-cache/src/server/main.js.map +1 -1
- package/out/zero-cache/src/server/replicator.d.ts.map +1 -1
- package/out/zero-cache/src/server/replicator.js +48 -5
- package/out/zero-cache/src/server/replicator.js.map +1 -1
- package/out/zero-cache/src/server/runner/run-worker.js +2 -1
- package/out/zero-cache/src/server/runner/run-worker.js.map +1 -1
- package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
- package/out/zero-cache/src/server/syncer.js +1 -1
- package/out/zero-cache/src/server/syncer.js.map +1 -1
- package/out/zero-cache/src/server/worker-urls.d.ts +1 -1
- package/out/zero-cache/src/server/worker-urls.js +2 -2
- package/out/zero-cache/src/server/worker-urls.js.map +1 -1
- package/out/zero-cache/src/services/change-source/change-source.d.ts +4 -2
- package/out/zero-cache/src/services/change-source/change-source.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/common/replica-restore.d.ts +35 -0
- package/out/zero-cache/src/services/change-source/common/replica-restore.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-source/common/replica-restore.js +34 -0
- package/out/zero-cache/src/services/change-source/common/replica-restore.js.map +1 -0
- package/out/zero-cache/src/services/change-source/common/replica-schema.d.ts +2 -0
- package/out/zero-cache/src/services/change-source/common/replica-schema.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/common/replica-schema.js +73 -1
- package/out/zero-cache/src/services/change-source/common/replica-schema.js.map +1 -1
- package/out/zero-cache/src/services/change-source/custom/change-source.d.ts +2 -6
- package/out/zero-cache/src/services/change-source/custom/change-source.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/custom/change-source.js +14 -5
- package/out/zero-cache/src/services/change-source/custom/change-source.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/backfill-stream.js +4 -7
- package/out/zero-cache/src/services/change-source/pg/backfill-stream.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/change-source.d.ts +7 -7
- package/out/zero-cache/src/services/change-source/pg/change-source.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/change-source.js +82 -25
- package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts +9 -1
- package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/initial-sync.js +12 -4
- package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.d.ts +45 -2
- package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js +59 -8
- package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/replication-slots.d.ts +4 -2
- package/out/zero-cache/src/services/change-source/pg/replication-slots.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/replication-slots.js +7 -4
- package/out/zero-cache/src/services/change-source/pg/replication-slots.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/init.d.ts +0 -5
- package/out/zero-cache/src/services/change-source/pg/schema/init.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/init.js +29 -41
- package/out/zero-cache/src/services/change-source/pg/schema/init.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts +35 -16
- package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/shard.js +77 -7
- package/out/zero-cache/src/services/change-source/pg/schema/shard.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts +2 -1
- package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/data.js +5 -13
- package/out/zero-cache/src/services/change-source/protocol/current/data.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts +6 -3
- package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/schema-change-tags.d.ts +6 -0
- package/out/zero-cache/src/services/change-source/protocol/current/schema-change-tags.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-source/protocol/current/schema-change-tags.js +21 -0
- package/out/zero-cache/src/services/change-source/protocol/current/schema-change-tags.js.map +1 -0
- package/out/zero-cache/src/services/change-source/protocol/current/status.d.ts +1 -0
- package/out/zero-cache/src/services/change-source/protocol/current/status.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/upstream.d.ts +1 -0
- package/out/zero-cache/src/services/change-source/protocol/current/upstream.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/backup-cleanup-monitor-factory.d.ts +5 -6
- package/out/zero-cache/src/services/change-streamer/backup-cleanup-monitor-factory.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/backup-cleanup-monitor-factory.js +32 -9
- package/out/zero-cache/src/services/change-streamer/backup-cleanup-monitor-factory.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/backup-monitor.d.ts +15 -5
- package/out/zero-cache/src/services/change-streamer/backup-monitor.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/backup-monitor.js +66 -0
- package/out/zero-cache/src/services/change-streamer/backup-monitor.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/broadcast.d.ts +68 -78
- package/out/zero-cache/src/services/change-streamer/broadcast.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/broadcast.js +84 -92
- package/out/zero-cache/src/services/change-streamer/broadcast.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-log-codec.d.ts +19 -0
- package/out/zero-cache/src/services/change-streamer/change-log-codec.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/change-log-codec.js +50 -0
- package/out/zero-cache/src/services/change-streamer/change-log-codec.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/change-log-initializer.d.ts +141 -0
- package/out/zero-cache/src/services/change-streamer/change-log-initializer.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/change-log-initializer.js +270 -0
- package/out/zero-cache/src/services/change-streamer/change-log-initializer.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/change-log-transaction-hash.d.ts +19 -0
- package/out/zero-cache/src/services/change-streamer/change-log-transaction-hash.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/change-log-transaction-hash.js +39 -0
- package/out/zero-cache/src/services/change-streamer/change-log-transaction-hash.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts +3 -4
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +12 -17
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts +69 -24
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.js +333 -66
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts +56 -13
- package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/error-type-enum.d.ts +8 -0
- package/out/zero-cache/src/services/change-streamer/error-type-enum.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/forwarder.d.ts +14 -3
- package/out/zero-cache/src/services/change-streamer/forwarder.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/forwarder.js +41 -11
- package/out/zero-cache/src/services/change-streamer/forwarder.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/{litestream3-backup-monitor.d.ts → litestream3-prometheus-poller.d.ts} +19 -45
- package/out/zero-cache/src/services/change-streamer/litestream3-prometheus-poller.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/{litestream3-backup-monitor.js → litestream3-prometheus-poller.js} +57 -171
- package/out/zero-cache/src/services/change-streamer/litestream3-prometheus-poller.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/replica-poller.d.ts +15 -0
- package/out/zero-cache/src/services/change-streamer/replica-poller.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/replica-poller.js +55 -0
- package/out/zero-cache/src/services/change-streamer/replica-poller.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/schema/tables.d.ts +5 -1
- package/out/zero-cache/src/services/change-streamer/schema/tables.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/schema/tables.js +2 -1
- package/out/zero-cache/src/services/change-streamer/schema/tables.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/snapshot-reservations.d.ts +14 -0
- package/out/zero-cache/src/services/change-streamer/snapshot-reservations.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/snapshot-reservations.js +86 -0
- package/out/zero-cache/src/services/change-streamer/snapshot-reservations.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/snapshot.d.ts +4 -1
- package/out/zero-cache/src/services/change-streamer/snapshot.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/snapshot.js +39 -14
- package/out/zero-cache/src/services/change-streamer/snapshot.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-catchup.d.ts +75 -0
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-catchup.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-catchup.js +261 -0
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-catchup.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-purge-scheduler.d.ts +121 -0
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-purge-scheduler.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-purge-scheduler.js +391 -0
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-purge-scheduler.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-reader.d.ts +62 -0
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-reader.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-reader.js +159 -0
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-reader.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.d.ts +109 -0
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.js +258 -0
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/storer.d.ts +28 -12
- package/out/zero-cache/src/services/change-streamer/storer.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/storer.js +116 -121
- package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/subscriber.d.ts +61 -10
- package/out/zero-cache/src/services/change-streamer/subscriber.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/subscriber.js +101 -8
- package/out/zero-cache/src/services/change-streamer/subscriber.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/upstream-acker.d.ts +34 -0
- package/out/zero-cache/src/services/change-streamer/upstream-acker.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/upstream-acker.js +86 -0
- package/out/zero-cache/src/services/change-streamer/upstream-acker.js.map +1 -0
- package/out/zero-cache/src/services/life-cycle.d.ts +1 -1
- package/out/zero-cache/src/services/life-cycle.d.ts.map +1 -1
- package/out/zero-cache/src/services/life-cycle.js +4 -3
- package/out/zero-cache/src/services/life-cycle.js.map +1 -1
- package/out/zero-cache/src/services/litestream/commands.d.ts +12 -11
- package/out/zero-cache/src/services/litestream/commands.d.ts.map +1 -1
- package/out/zero-cache/src/services/litestream/commands.js +107 -148
- package/out/zero-cache/src/services/litestream/commands.js.map +1 -1
- package/out/zero-cache/src/services/litestream/config-v5.yml +42 -0
- package/out/zero-cache/src/services/litestream/config.yml +3 -2
- package/out/zero-cache/src/services/litestream/metrics.d.ts +4 -4
- package/out/zero-cache/src/services/litestream/metrics.d.ts.map +1 -1
- package/out/zero-cache/src/services/litestream/metrics.js +7 -10
- package/out/zero-cache/src/services/litestream/metrics.js.map +1 -1
- package/out/zero-cache/src/services/litestream/vfs-watermark-poller.d.ts +57 -0
- package/out/zero-cache/src/services/litestream/vfs-watermark-poller.d.ts.map +1 -0
- package/out/zero-cache/src/services/litestream/vfs-watermark-poller.js +137 -0
- package/out/zero-cache/src/services/litestream/vfs-watermark-poller.js.map +1 -0
- package/out/zero-cache/src/services/mutagen/mutagen.d.ts.map +1 -1
- package/out/zero-cache/src/services/mutagen/mutagen.js +4 -1
- package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -1
- package/out/zero-cache/src/services/replicator/change-log-cookies.d.ts +169 -0
- package/out/zero-cache/src/services/replicator/change-log-cookies.d.ts.map +1 -0
- package/out/zero-cache/src/services/replicator/change-log-cookies.js +434 -0
- package/out/zero-cache/src/services/replicator/change-log-cookies.js.map +1 -0
- package/out/zero-cache/src/services/replicator/change-log-db.d.ts +358 -0
- package/out/zero-cache/src/services/replicator/change-log-db.d.ts.map +1 -0
- package/out/zero-cache/src/services/replicator/change-log-db.js +477 -0
- package/out/zero-cache/src/services/replicator/change-log-db.js.map +1 -0
- package/out/zero-cache/src/services/replicator/change-log-stream-writer.d.ts +55 -0
- package/out/zero-cache/src/services/replicator/change-log-stream-writer.d.ts.map +1 -0
- package/out/zero-cache/src/services/replicator/change-log-stream-writer.js +150 -0
- package/out/zero-cache/src/services/replicator/change-log-stream-writer.js.map +1 -0
- package/out/zero-cache/src/services/replicator/change-processor.d.ts +6 -0
- package/out/zero-cache/src/services/replicator/change-processor.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/change-processor.js +70 -25
- package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
- package/out/zero-cache/src/services/replicator/incremental-sync.d.ts +1 -1
- package/out/zero-cache/src/services/replicator/incremental-sync.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/incremental-sync.js +19 -6
- package/out/zero-cache/src/services/replicator/incremental-sync.js.map +1 -1
- package/out/zero-cache/src/services/replicator/notifier.d.ts +0 -22
- package/out/zero-cache/src/services/replicator/notifier.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/notifier.js +7 -1
- package/out/zero-cache/src/services/replicator/notifier.js.map +1 -1
- package/out/zero-cache/src/services/replicator/replicator.d.ts +17 -2
- package/out/zero-cache/src/services/replicator/replicator.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/replicator.js +9 -3
- package/out/zero-cache/src/services/replicator/replicator.js.map +1 -1
- package/out/zero-cache/src/services/replicator/reporter/recorder.d.ts +27 -0
- package/out/zero-cache/src/services/replicator/reporter/recorder.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/reporter/recorder.js +32 -0
- package/out/zero-cache/src/services/replicator/reporter/recorder.js.map +1 -1
- package/out/zero-cache/src/services/replicator/reporter/report-schema.d.ts +1 -1
- package/out/zero-cache/src/services/replicator/schema/backfilling.d.ts +119 -0
- package/out/zero-cache/src/services/replicator/schema/backfilling.d.ts.map +1 -0
- package/out/zero-cache/src/services/replicator/schema/backfilling.js +214 -0
- package/out/zero-cache/src/services/replicator/schema/backfilling.js.map +1 -0
- package/out/zero-cache/src/services/replicator/schema/change-log.d.ts +3 -3
- package/out/zero-cache/src/services/replicator/schema/column-metadata.js +1 -1
- package/out/zero-cache/src/services/replicator/schema/column-metadata.js.map +1 -1
- package/out/zero-cache/src/services/replicator/schema/replication-state.d.ts +1 -1
- package/out/zero-cache/src/services/replicator/schema/replication-state.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/schema/replication-state.js +9 -5
- package/out/zero-cache/src/services/replicator/schema/replication-state.js.map +1 -1
- package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.d.ts +131 -0
- package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.d.ts.map +1 -0
- package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.js +413 -0
- package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.js.map +1 -0
- package/out/zero-cache/src/services/replicator/sqlite-change-log-purger.d.ts +120 -0
- package/out/zero-cache/src/services/replicator/sqlite-change-log-purger.d.ts.map +1 -0
- package/out/zero-cache/src/services/replicator/sqlite-change-log-purger.js +283 -0
- package/out/zero-cache/src/services/replicator/sqlite-change-log-purger.js.map +1 -0
- package/out/zero-cache/src/services/replicator/write-worker.js +23 -12
- package/out/zero-cache/src/services/replicator/write-worker.js.map +1 -1
- package/out/zero-cache/src/services/run-ast.d.ts.map +1 -1
- package/out/zero-cache/src/services/run-ast.js +2 -1
- package/out/zero-cache/src/services/run-ast.js.map +1 -1
- package/out/zero-cache/src/services/running-state.d.ts +1 -1
- package/out/zero-cache/src/services/running-state.d.ts.map +1 -1
- package/out/zero-cache/src/services/running-state.js +1 -0
- package/out/zero-cache/src/services/running-state.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/e2e-serving-lag.d.ts +53 -0
- package/out/zero-cache/src/services/view-syncer/e2e-serving-lag.d.ts.map +1 -0
- package/out/zero-cache/src/services/view-syncer/e2e-serving-lag.js +68 -0
- package/out/zero-cache/src/services/view-syncer/e2e-serving-lag.js.map +1 -0
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +18 -3
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts +11 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.js +64 -6
- package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
- package/out/zero-cache/src/types/processes.d.ts +1 -2
- package/out/zero-cache/src/types/processes.d.ts.map +1 -1
- package/out/zero-cache/src/types/processes.js +1 -25
- package/out/zero-cache/src/types/processes.js.map +1 -1
- package/out/zero-cache/src/types/streams.d.ts +21 -0
- package/out/zero-cache/src/types/streams.d.ts.map +1 -1
- package/out/zero-cache/src/types/streams.js +25 -4
- package/out/zero-cache/src/types/streams.js.map +1 -1
- package/out/zero-cache/src/types/subscription.d.ts +11 -0
- package/out/zero-cache/src/types/subscription.d.ts.map +1 -1
- package/out/zero-cache/src/types/subscription.js +27 -0
- package/out/zero-cache/src/types/subscription.js.map +1 -1
- package/out/zero-cache/src/workers/connection.d.ts +1 -0
- package/out/zero-cache/src/workers/connection.d.ts.map +1 -1
- package/out/zero-cache/src/workers/connection.js +24 -2
- package/out/zero-cache/src/workers/connection.js.map +1 -1
- package/out/zero-cache/src/workers/replicator.d.ts +25 -0
- package/out/zero-cache/src/workers/replicator.d.ts.map +1 -1
- package/out/zero-cache/src/workers/replicator.js +33 -1
- package/out/zero-cache/src/workers/replicator.js.map +1 -1
- package/out/zero-cache/src/workers/syncer.d.ts +12 -0
- package/out/zero-cache/src/workers/syncer.d.ts.map +1 -1
- package/out/zero-cache/src/workers/syncer.js +75 -0
- package/out/zero-cache/src/workers/syncer.js.map +1 -1
- package/out/zero-client/src/client/version.js +1 -1
- package/out/zero-client/src/client/zero.d.ts +6 -7
- package/out/zero-client/src/client/zero.d.ts.map +1 -1
- package/out/zero-client/src/client/zero.js +156 -101
- package/out/zero-client/src/client/zero.js.map +1 -1
- package/out/zero-schema/src/builder/table-builder.d.ts +23 -0
- package/out/zero-schema/src/builder/table-builder.d.ts.map +1 -1
- package/out/zero-schema/src/builder/table-builder.js +18 -0
- package/out/zero-schema/src/builder/table-builder.js.map +1 -1
- package/out/zero-server/src/custom.js +10 -3
- package/out/zero-server/src/custom.js.map +1 -1
- package/out/zero-server/src/schema.d.ts +8 -0
- package/out/zero-server/src/schema.d.ts.map +1 -1
- package/out/zero-server/src/schema.js +63 -24
- package/out/zero-server/src/schema.js.map +1 -1
- package/out/zero-types/src/schema.d.ts +11 -0
- package/out/zero-types/src/schema.d.ts.map +1 -1
- package/out/zql/src/mutate/crud.d.ts +10 -8
- package/out/zql/src/mutate/crud.d.ts.map +1 -1
- package/out/zql/src/mutate/crud.js.map +1 -1
- package/out/zql/src/query/query-delegate-base.d.ts.map +1 -1
- package/out/zql/src/query/query-delegate-base.js +5 -1
- package/out/zql/src/query/query-delegate-base.js.map +1 -1
- package/out/zql/src/query/query-impl.d.ts +2 -2
- package/out/zql/src/query/query-impl.d.ts.map +1 -1
- package/out/zql/src/query/query-impl.js.map +1 -1
- package/out/zql/src/query/query.d.ts +83 -14
- package/out/zql/src/query/query.d.ts.map +1 -1
- package/out/zql/src/query/static-query.d.ts +1 -1
- package/out/zql/src/query/static-query.d.ts.map +1 -1
- package/out/zqlite/src/db.js +2 -2
- package/out/zqlite/src/resolve-scalar-subqueries.d.ts +15 -0
- package/out/zqlite/src/resolve-scalar-subqueries.d.ts.map +1 -1
- package/out/zqlite/src/resolve-scalar-subqueries.js +33 -14
- package/out/zqlite/src/resolve-scalar-subqueries.js.map +1 -1
- package/out/zqlite/src/sqlite-cost-model.js +5 -5
- package/out/zqlite/src/table-source.js +3 -3
- package/package.json +3 -3
- package/out/replicache/src/db/index.js +0 -91
- package/out/replicache/src/db/index.js.map +0 -1
- package/out/replicache/src/lazy.d.ts +0 -2
- package/out/replicache/src/lazy.d.ts.map +0 -1
- package/out/replicache/src/lazy.js +0 -12
- package/out/replicache/src/lazy.js.map +0 -1
- package/out/zero-cache/src/server/backup-watermark-reader.js +0 -35
- package/out/zero-cache/src/server/backup-watermark-reader.js.map +0 -1
- package/out/zero-cache/src/services/change-streamer/litestream3-backup-monitor.d.ts.map +0 -1
- package/out/zero-cache/src/services/change-streamer/litestream3-backup-monitor.js.map +0 -1
- package/out/zero-cache/src/services/change-streamer/replica-monitor.d.ts +0 -16
- package/out/zero-cache/src/services/change-streamer/replica-monitor.d.ts.map +0 -1
- package/out/zero-cache/src/services/change-streamer/replica-monitor.js +0 -54
- package/out/zero-cache/src/services/change-streamer/replica-monitor.js.map +0 -1
- package/out/zero-cache/src/services/change-streamer/vfs-backup-monitor.d.ts +0 -25
- package/out/zero-cache/src/services/change-streamer/vfs-backup-monitor.d.ts.map +0 -1
- package/out/zero-cache/src/services/change-streamer/vfs-backup-monitor.js +0 -159
- package/out/zero-cache/src/services/change-streamer/vfs-backup-monitor.js.map +0 -1
- package/out/zero-cache/src/services/litestream/vfs-watermark-reader.d.ts +0 -44
- package/out/zero-cache/src/services/litestream/vfs-watermark-reader.d.ts.map +0 -1
- package/out/zero-cache/src/services/litestream/vfs-watermark-reader.js +0 -65
- package/out/zero-cache/src/services/litestream/vfs-watermark-reader.js.map +0 -1
- package/out/zero-cache/src/services/litestream/vfs-watermark-worker-source.d.ts +0 -11
- package/out/zero-cache/src/services/litestream/vfs-watermark-worker-source.d.ts.map +0 -1
- package/out/zero-cache/src/services/litestream/vfs-watermark-worker-source.js +0 -74
- package/out/zero-cache/src/services/litestream/vfs-watermark-worker-source.js.map +0 -1
- package/out/zero-cache/src/services/litestream/vfs-watermark-worker.d.ts +0 -42
- package/out/zero-cache/src/services/litestream/vfs-watermark-worker.d.ts.map +0 -1
- package/out/zero-cache/src/services/litestream/vfs-watermark-worker.js +0 -117
- package/out/zero-cache/src/services/litestream/vfs-watermark-worker.js.map +0 -1
|
@@ -148,6 +148,9 @@ function shardSetup(shardConfig, metadataPublication) {
|
|
|
148
148
|
"rank" BIGSERIAL,
|
|
149
149
|
"slot" TEXT NOT NULL,
|
|
150
150
|
"version" TEXT NOT NULL,
|
|
151
|
+
"generation" TEXT, -- to replace version, NULL-able in the interim
|
|
152
|
+
"backupPath" TEXT, -- subpath within the litestream backup URL
|
|
153
|
+
"backupV5" BOOL DEFAULT false,
|
|
151
154
|
"initialSchema" JSON, -- set after initial sync
|
|
152
155
|
"initialSyncContext" JSON,
|
|
153
156
|
"subscriberContext" JSON
|
|
@@ -167,15 +170,38 @@ var internalShardConfigSchema = valita_exports.object({
|
|
|
167
170
|
publications: valita_exports.array(valita_exports.string()),
|
|
168
171
|
ddlDetection: valita_exports.boolean()
|
|
169
172
|
});
|
|
170
|
-
var
|
|
173
|
+
var replicaInfoSchema = valita_exports.object({
|
|
171
174
|
id: valita_exports.string(),
|
|
172
175
|
rank: valita_exports.bigint(),
|
|
173
176
|
slot: valita_exports.string(),
|
|
174
177
|
version: valita_exports.string(),
|
|
178
|
+
generation: valita_exports.string().nullable(),
|
|
179
|
+
backupPath: valita_exports.string().nullable(),
|
|
180
|
+
backupV5: valita_exports.boolean()
|
|
181
|
+
});
|
|
182
|
+
var fullReplicaRowSchema = replicaInfoSchema.extend({
|
|
175
183
|
initialSchema: publishedSchema,
|
|
176
184
|
initialSyncContext: jsonObjectSchema.nullable(),
|
|
177
185
|
subscriberContext: jsonObjectSchema.nullable()
|
|
178
186
|
});
|
|
187
|
+
var replicaSchema = internalShardConfigSchema.extend(fullReplicaRowSchema.shape).map((replica) => {
|
|
188
|
+
const { version, generation, ...r } = replica;
|
|
189
|
+
return {
|
|
190
|
+
...r,
|
|
191
|
+
generation: generation ?? version
|
|
192
|
+
};
|
|
193
|
+
});
|
|
194
|
+
var replicationSlotStateSchema = valita_exports.object({
|
|
195
|
+
active: valita_exports.boolean(),
|
|
196
|
+
confirmedFlushLsn: valita_exports.string().nullable()
|
|
197
|
+
});
|
|
198
|
+
var replicaStateSchema = replicaInfoSchema.extend(replicationSlotStateSchema.shape).map((replica) => {
|
|
199
|
+
const { version, generation, ...r } = replica;
|
|
200
|
+
return {
|
|
201
|
+
...r,
|
|
202
|
+
generation: generation ?? version
|
|
203
|
+
};
|
|
204
|
+
});
|
|
179
205
|
function triggerSetup(shard) {
|
|
180
206
|
const schema = id(upstreamSchema(shard));
|
|
181
207
|
return createEventTriggerStatements(shard) + `UPDATE ${schema}."shardConfig" SET "ddlDetection" = true;`;
|
|
@@ -189,12 +215,15 @@ function triggerSetup(shard) {
|
|
|
189
215
|
* Once initial sync is complete, {@link initReplica} should be called to
|
|
190
216
|
* make the replica usable for incremental sync.
|
|
191
217
|
*/
|
|
192
|
-
async function createReplica(sql, shard, id, slot, replicaVersion) {
|
|
218
|
+
async function createReplica(sql, shard, id, slot, replicaVersion, { backupPath, backupV5 }) {
|
|
193
219
|
const schema = upstreamSchema(shard);
|
|
194
220
|
const values = {
|
|
195
221
|
id,
|
|
196
222
|
slot,
|
|
197
|
-
version: replicaVersion
|
|
223
|
+
version: replicaVersion,
|
|
224
|
+
generation: replicaVersion,
|
|
225
|
+
backupPath,
|
|
226
|
+
backupV5
|
|
198
227
|
};
|
|
199
228
|
await sql`INSERT INTO ${sql(schema)}.replicas ${sql(values)}`;
|
|
200
229
|
}
|
|
@@ -210,9 +239,10 @@ async function initReplica(sql, shard, id, { tables, indexes }, initialSyncConte
|
|
|
210
239
|
await sql`UPDATE ${sql(schema)}.replicas SET ${sql(values)} WHERE id = ${id}`;
|
|
211
240
|
}
|
|
212
241
|
/**
|
|
213
|
-
* Gets the
|
|
242
|
+
* Gets at the given version and optional ID. If no ID is specified, gets
|
|
243
|
+
* the latest (i.e. highest rank) replica with that version.
|
|
214
244
|
*/
|
|
215
|
-
async function getReplicaAtVersion(lc, sql, shard, replicaVersion, context) {
|
|
245
|
+
async function getReplicaAtVersion(lc, sql, shard, replicaVersion, id = null, context) {
|
|
216
246
|
const schema = sql(upstreamSchema(shard));
|
|
217
247
|
const result = await sql`
|
|
218
248
|
SELECT
|
|
@@ -220,6 +250,9 @@ async function getReplicaAtVersion(lc, sql, shard, replicaVersion, context) {
|
|
|
220
250
|
replicas."rank",
|
|
221
251
|
replicas."slot",
|
|
222
252
|
replicas."version",
|
|
253
|
+
replicas."generation",
|
|
254
|
+
replicas."backupPath",
|
|
255
|
+
replicas."backupV5",
|
|
223
256
|
replicas."initialSchema",
|
|
224
257
|
replicas."initialSyncContext",
|
|
225
258
|
replicas."subscriberContext",
|
|
@@ -227,17 +260,54 @@ async function getReplicaAtVersion(lc, sql, shard, replicaVersion, context) {
|
|
|
227
260
|
"shardConfig"."ddlDetection"
|
|
228
261
|
FROM ${schema}.replicas JOIN ${schema}."shardConfig" ON true
|
|
229
262
|
WHERE version = ${replicaVersion} AND "initialSyncContext" IS NOT NULL
|
|
263
|
+
AND id = COALESCE(${id}, id)
|
|
230
264
|
ORDER BY rank DESC LIMIT 1;
|
|
231
265
|
`;
|
|
232
266
|
if (result.length === 0) {
|
|
233
267
|
const allReplicas = await sql`
|
|
234
268
|
SELECT id, slot, version, "initialSyncContext", "subscriberContext"
|
|
235
269
|
FROM ${schema}.replicas`;
|
|
236
|
-
lc.info?.(`Replica ${replicaVersion}
|
|
270
|
+
lc.info?.(`Replica ${id}@${replicaVersion}` + (context ? `(context: ${stringify(context)}) ` : "") + `not found in: ${stringify(allReplicas)}`);
|
|
237
271
|
return null;
|
|
238
272
|
}
|
|
239
273
|
return parse(result[0], replicaSchema, "passthrough");
|
|
240
274
|
}
|
|
275
|
+
async function getActiveReplicas(lc, sql, shard) {
|
|
276
|
+
const replicas = parse(await sql`
|
|
277
|
+
SELECT
|
|
278
|
+
replicas."id",
|
|
279
|
+
replicas."rank",
|
|
280
|
+
replicas."slot",
|
|
281
|
+
replicas."version",
|
|
282
|
+
replicas."generation",
|
|
283
|
+
replicas."backupPath",
|
|
284
|
+
replicas."backupV5",
|
|
285
|
+
slots."active",
|
|
286
|
+
slots."confirmed_flush_lsn" as "confirmedFlushLsn"
|
|
287
|
+
FROM ${sql(upstreamSchema(shard))}.replicas JOIN pg_replication_slots slots ON slot = slot_name
|
|
288
|
+
WHERE "initialSyncContext" IS NOT NULL
|
|
289
|
+
ORDER BY generation DESC, confirmed_flush_lsn DESC;
|
|
290
|
+
`, valita_exports.array(replicaStateSchema), "passthrough");
|
|
291
|
+
lc.info?.(`current replicas`, { replicas });
|
|
292
|
+
return replicas;
|
|
293
|
+
}
|
|
294
|
+
async function getReplicaState(sql, shard, id) {
|
|
295
|
+
const results = await sql`
|
|
296
|
+
SELECT
|
|
297
|
+
replicas."id",
|
|
298
|
+
replicas."rank",
|
|
299
|
+
replicas."slot",
|
|
300
|
+
replicas."version",
|
|
301
|
+
replicas."generation",
|
|
302
|
+
replicas."backupPath",
|
|
303
|
+
replicas."backupV5",
|
|
304
|
+
slots."active",
|
|
305
|
+
slots."confirmed_flush_lsn" as "confirmedFlushLsn"
|
|
306
|
+
FROM ${sql(upstreamSchema(shard))}.replicas JOIN pg_replication_slots slots ON slot = slot_name
|
|
307
|
+
WHERE "id" = ${id};
|
|
308
|
+
`;
|
|
309
|
+
return results.length ? parse(results[0], replicaStateSchema, "passthrough") : null;
|
|
310
|
+
}
|
|
241
311
|
async function getInternalShardConfig(sql, shard) {
|
|
242
312
|
const result = await sql`
|
|
243
313
|
SELECT "publications", "ddlDetection"
|
|
@@ -325,6 +395,6 @@ function replicaIdentitiesForTablesWithoutPrimaryKeys(pubs) {
|
|
|
325
395
|
} };
|
|
326
396
|
}
|
|
327
397
|
//#endregion
|
|
328
|
-
export { SHARD_CONFIG_TABLE, createReplica, dropShard, ensureGlobalTables, getInternalShardConfig, getMutationsTableDefinition, getReplicaAtVersion, initReplica, internalPublicationPrefix, legacyReplicationSlot, metadataPublicationName, replicaIdentitiesForTablesWithoutPrimaryKeys, replicationSlotExpression, replicationSlotPrefix, setupTablesAndReplication, setupTriggers, validatePublications };
|
|
398
|
+
export { SHARD_CONFIG_TABLE, createReplica, dropShard, ensureGlobalTables, getActiveReplicas, getInternalShardConfig, getMutationsTableDefinition, getReplicaAtVersion, getReplicaState, initReplica, internalPublicationPrefix, legacyReplicationSlot, metadataPublicationName, replicaIdentitiesForTablesWithoutPrimaryKeys, replicationSlotExpression, replicationSlotPrefix, setupTablesAndReplication, setupTriggers, validatePublications };
|
|
329
399
|
|
|
330
400
|
//# sourceMappingURL=shard.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shard.js","names":[],"sources":["../../../../../../../../zero-cache/src/services/change-source/pg/schema/shard.ts"],"sourcesContent":["import {PG_INSUFFICIENT_PRIVILEGE} from '@drdgvhbh/postgres-error-codes';\nimport type {LogContext} from '@rocicorp/logger';\nimport {literal} from 'pg-format';\nimport postgres from 'postgres';\nimport {assert} from '../../../../../../shared/src/asserts.ts';\nimport {\n jsonObjectSchema,\n stringify,\n type JSONObject,\n} from '../../../../../../shared/src/bigint-json.ts';\nimport * as v from '../../../../../../shared/src/valita.ts';\nimport {Default} from '../../../../db/postgres-replica-identity-enum.ts';\nimport type {PostgresDB, PostgresTransaction} from '../../../../types/pg.ts';\nimport type {AppID, ShardConfig, ShardID} from '../../../../types/shards.ts';\nimport {appSchema, check, upstreamSchema} from '../../../../types/shards.ts';\nimport {id} from '../../../../types/sql.ts';\nimport {\n createEventFunctionStatements,\n createEventTriggerStatements,\n} from './ddl.ts';\nimport {\n getPublicationInfo,\n publishedSchema,\n type PublicationInfo,\n type PublishedSchema,\n} from './published.ts';\nimport {validate} from './validation.ts';\n\n/**\n * PostgreSQL unquoted identifiers must start with a letter or underscore\n * and contain only letters, digits, and underscores.\n */\nconst VALID_PUBLICATION_NAME = /^[a-zA-Z_][a-zA-Z0-9_]*$/;\n\n/**\n * Validates that a publication name is a valid PostgreSQL identifier.\n * This provides defense-in-depth against SQL injection when publication\n * names are used in replication commands.\n */\nexport function validatePublicationName(name: string): void {\n if (!VALID_PUBLICATION_NAME.test(name)) {\n throw new Error(\n `Invalid publication name \"${name}\". Publication names must start with a letter or underscore ` +\n `and contain only letters, digits, and underscores.`,\n );\n }\n if (name.length > 63) {\n throw new Error(\n `Publication name \"${name}\" exceeds PostgreSQL's 63-character identifier limit.`,\n );\n }\n}\n\nexport function internalPublicationPrefix({appID}: AppID) {\n return `_${appID}_`;\n}\n\nexport function legacyReplicationSlot({appID, shardNum}: ShardID) {\n return `${appID}_${shardNum}`;\n}\n\nexport function replicationSlotPrefix(shard: ShardID) {\n const {appID, shardNum} = check(shard);\n return `${appID}_${shardNum}_`;\n}\n\n/**\n * An expression used to match replication slots in the shard\n * in a Postgres `LIKE` operator.\n */\nexport function replicationSlotExpression(shard: ShardID) {\n // Underscores have a special meaning in LIKE values\n // so they have to be escaped.\n return `${replicationSlotPrefix(shard)}%`.replaceAll('_', '\\\\_');\n}\n\nfunction defaultPublicationName(appID: string, shardID: string | number) {\n return `_${appID}_public_${shardID}`;\n}\n\nexport function metadataPublicationName(\n appID: string,\n shardID: string | number,\n) {\n return `_${appID}_metadata_${shardID}`;\n}\n\n// The GLOBAL_SETUP must be idempotent as it can be run multiple times for different shards.\nfunction globalSetup(appID: AppID): string {\n const app = id(appSchema(appID));\n\n return /*sql*/ `\n CREATE SCHEMA IF NOT EXISTS ${app};\n\n CREATE TABLE IF NOT EXISTS ${app}.permissions (\n \"permissions\" JSONB,\n \"hash\" TEXT,\n\n -- Ensure that there is only a single row in the table.\n -- Application code can be agnostic to this column, and\n -- simply invoke UPDATE statements on the version columns.\n \"lock\" BOOL PRIMARY KEY DEFAULT true CHECK (lock)\n );\n\n CREATE OR REPLACE FUNCTION ${app}.set_permissions_hash()\n RETURNS TRIGGER AS $$\n BEGIN\n NEW.hash = md5(NEW.permissions::text);\n RETURN NEW;\n END;\n $$ LANGUAGE plpgsql;\n\n CREATE OR REPLACE TRIGGER on_set_permissions \n BEFORE INSERT OR UPDATE ON ${app}.permissions\n FOR EACH ROW\n EXECUTE FUNCTION ${app}.set_permissions_hash();\n\n INSERT INTO ${app}.permissions (permissions) VALUES (NULL) ON CONFLICT DO NOTHING;\n`;\n}\n\nexport async function ensureGlobalTables(db: PostgresDB, appID: AppID) {\n await db.unsafe(globalSetup(appID));\n}\n\nexport function getClientsTableDefinition(schema: string) {\n return /*sql*/ `\n CREATE TABLE ${schema}.\"clients\" (\n \"clientGroupID\" TEXT NOT NULL,\n \"clientID\" TEXT NOT NULL,\n \"lastMutationID\" BIGINT NOT NULL,\n \"userID\" TEXT,\n PRIMARY KEY(\"clientGroupID\", \"clientID\")\n );`;\n}\n\n/**\n * Tracks the results of mutations.\n * 1. It is an error for the same mutation ID to be used twice.\n * 2. The result is JSONB to allow for arbitrary results.\n *\n * The tables must be cleaned up as the clients\n * receive the mutation responses and as clients are removed.\n */\nexport function getMutationsTableDefinition(schema: string) {\n return /*sql*/ `\n CREATE TABLE ${schema}.\"mutations\" (\n \"clientGroupID\" TEXT NOT NULL,\n \"clientID\" TEXT NOT NULL,\n \"mutationID\" BIGINT NOT NULL,\n \"result\" JSON NOT NULL,\n PRIMARY KEY(\"clientGroupID\", \"clientID\", \"mutationID\")\n );`;\n}\n\nexport const SHARD_CONFIG_TABLE = 'shardConfig';\n\nexport function shardSetup(\n shardConfig: ShardConfig,\n metadataPublication: string,\n): string {\n const app = id(appSchema(shardConfig));\n const shard = id(upstreamSchema(shardConfig));\n\n const pubs = shardConfig.publications.toSorted();\n assert(\n pubs.includes(metadataPublication),\n () => `Publications must include ${metadataPublication}`,\n );\n\n return /*sql*/ `\n CREATE SCHEMA IF NOT EXISTS ${shard};\n\n ${getClientsTableDefinition(shard)}\n ${getMutationsTableDefinition(shard)}\n\n DROP PUBLICATION IF EXISTS ${id(metadataPublication)};\n CREATE PUBLICATION ${id(metadataPublication)}\n FOR TABLE ${app}.\"permissions\", TABLE ${shard}.\"clients\", ${shard}.\"mutations\";\n\n CREATE TABLE ${shard}.\"${SHARD_CONFIG_TABLE}\" (\n \"publications\" TEXT[] NOT NULL,\n \"ddlDetection\" BOOL NOT NULL,\n\n -- Ensure that there is only a single row in the table.\n \"lock\" BOOL PRIMARY KEY DEFAULT true CHECK (lock)\n );\n\n INSERT INTO ${shard}.\"${SHARD_CONFIG_TABLE}\" (\n \"publications\",\n \"ddlDetection\" \n ) VALUES (\n ARRAY[${literal(pubs)}], \n false -- set in SAVEPOINT with triggerSetup() statements\n );\n\n CREATE TABLE ${shard}.replicas (\n -- The DEFAULT exists purely for backwards compatibility support.\n -- New code always specifies a value based on Date.now().\n \"id\" TEXT PRIMARY KEY DEFAULT replace(gen_random_uuid()::text, '-', ''),\n \"rank\" BIGSERIAL,\n \"slot\" TEXT NOT NULL,\n \"version\" TEXT NOT NULL,\n \"initialSchema\" JSON, -- set after initial sync\n \"initialSyncContext\" JSON,\n \"subscriberContext\" JSON\n );\n `;\n}\n\nexport function dropShard(appID: string, shardID: string | number): string {\n const schema = `${appID}_${shardID}`;\n const metadataPublication = metadataPublicationName(appID, shardID);\n const defaultPublication = defaultPublicationName(appID, shardID);\n\n // DROP SCHEMA ... CASCADE does not drop dependent PUBLICATIONS,\n // so PUBLICATIONs must be dropped explicitly.\n return /*sql*/ `\n DROP PUBLICATION IF EXISTS ${id(defaultPublication)};\n DROP PUBLICATION IF EXISTS ${id(metadataPublication)};\n DROP SCHEMA IF EXISTS ${id(schema)} CASCADE;\n `;\n}\n\nconst internalShardConfigSchema = v.object({\n publications: v.array(v.string()),\n ddlDetection: v.boolean(),\n});\n\nexport type InternalShardConfig = v.Infer<typeof internalShardConfigSchema>;\n\nconst replicaSchema = internalShardConfigSchema.extend({\n id: v.string(),\n rank: v.bigint(),\n slot: v.string(),\n version: v.string(),\n initialSchema: publishedSchema,\n initialSyncContext: jsonObjectSchema.nullable(),\n subscriberContext: jsonObjectSchema.nullable(),\n});\n\nexport type Replica = v.Infer<typeof replicaSchema>;\n\n// triggerSetup is run separately in a sub-transaction (i.e. SAVEPOINT) so\n// that a failure (e.g. due to lack of superuser permissions) can be handled\n// by continuing in a degraded mode (ddlDetection = false).\nfunction triggerSetup(shard: ShardConfig): string {\n const schema = id(upstreamSchema(shard));\n return (\n createEventTriggerStatements(shard) +\n /*sql*/ `UPDATE ${schema}.\"shardConfig\" SET \"ddlDetection\" = true;`\n );\n}\n\n/**\n * Creates a new replica to mark it as the owner of a specified `slot`.\n * This should be done with an advisory lock for replica/slot management\n * to ensure that the slot does not get dropped by concurrent cleanup\n * logic.\n *\n * Once initial sync is complete, {@link initReplica} should be called to\n * make the replica usable for incremental sync.\n */\nexport async function createReplica(\n sql: PostgresDB,\n shard: ShardID,\n id: string,\n slot: string,\n replicaVersion: string,\n) {\n const schema = upstreamSchema(shard);\n const values = {id, slot, version: replicaVersion};\n await sql`INSERT INTO ${sql(schema)}.replicas ${sql(values)}`;\n}\n\n// Called in initial-sync to store the exact schema that was initially synced.\nexport async function initReplica(\n sql: PostgresDB,\n shard: ShardID,\n id: string,\n {tables, indexes}: PublishedSchema,\n initialSyncContext: JSONObject,\n) {\n const schema = upstreamSchema(shard);\n const synced: PublishedSchema = {tables, indexes};\n const values = {initialSchema: synced, initialSyncContext};\n await sql`UPDATE ${sql(schema)}.replicas SET ${sql(values)} WHERE id = ${id}`;\n}\n\n/**\n * Gets the latest initialized replica at the specified version.\n */\nexport async function getReplicaAtVersion(\n lc: LogContext,\n sql: PostgresDB,\n shard: ShardID,\n replicaVersion: string,\n context?: JSONObject,\n): Promise<Replica | null> {\n const schema = sql(upstreamSchema(shard));\n const result = await sql`\n SELECT\n replicas.\"id\",\n replicas.\"rank\",\n replicas.\"slot\",\n replicas.\"version\",\n replicas.\"initialSchema\",\n replicas.\"initialSyncContext\",\n replicas.\"subscriberContext\",\n \"shardConfig\".\"publications\",\n \"shardConfig\".\"ddlDetection\"\n FROM ${schema}.replicas JOIN ${schema}.\"shardConfig\" ON true\n WHERE version = ${replicaVersion} AND \"initialSyncContext\" IS NOT NULL\n ORDER BY rank DESC LIMIT 1;\n `;\n if (result.length === 0) {\n // log out all the replicas and the joined shardConfig\n const allReplicas = await sql`\n SELECT id, slot, version, \"initialSyncContext\", \"subscriberContext\" \n FROM ${schema}.replicas`;\n lc.info?.(\n `Replica ${replicaVersion} ` +\n (context ? `(context: ${stringify(context)}) ` : '') +\n `not found in: ${stringify(allReplicas)}`,\n );\n return null;\n }\n return v.parse(result[0], replicaSchema, 'passthrough');\n}\n\nexport async function getInternalShardConfig(\n sql: PostgresDB,\n shard: ShardID,\n): Promise<InternalShardConfig> {\n const result = await sql`\n SELECT \"publications\", \"ddlDetection\"\n FROM ${sql(upstreamSchema(shard))}.\"shardConfig\";\n `;\n assert(\n result.length === 1,\n () => `Expected exactly one shardConfig row, got ${result.length}`,\n );\n return v.parse(result[0], internalShardConfigSchema, 'passthrough');\n}\n\n/**\n * Sets up and returns all publications (including internal ones) for\n * the given shard.\n */\nexport async function setupTablesAndReplication(\n lc: LogContext,\n sql: PostgresTransaction,\n requested: ShardConfig,\n) {\n const {publications} = requested;\n // Validate requested publications.\n for (const pub of publications) {\n validatePublicationName(pub);\n if (pub.startsWith('_')) {\n throw new Error(\n `Publication names starting with \"_\" are reserved for internal use.\\n` +\n `Please use a different name for publication \"${pub}\".`,\n );\n }\n }\n const allPublications: string[] = [];\n\n // Setup application publications.\n if (publications.length) {\n const results = await sql<{pubname: string}[]>`\n SELECT pubname from pg_publication WHERE pubname IN ${sql(\n publications,\n )}`.values();\n\n if (results.length !== publications.length) {\n throw new Error(\n `Unknown or invalid publications. Specified: [${publications}]. Found: [${results.flat()}]`,\n );\n }\n allPublications.push(...publications);\n } else {\n const defaultPublication = defaultPublicationName(\n requested.appID,\n requested.shardNum,\n );\n await sql`\n DROP PUBLICATION IF EXISTS ${sql(defaultPublication)}`;\n await sql`\n CREATE PUBLICATION ${sql(defaultPublication)} \n FOR TABLES IN SCHEMA public\n WITH (publish_via_partition_root = true)`;\n allPublications.push(defaultPublication);\n }\n\n const metadataPublication = metadataPublicationName(\n requested.appID,\n requested.shardNum,\n );\n allPublications.push(metadataPublication);\n\n const shard = {...requested, publications: allPublications};\n\n // Setup the global tables and shard tables / publications.\n await sql.unsafe(globalSetup(shard) + shardSetup(shard, metadataPublication));\n\n const pubs = await getPublicationInfo(sql, allPublications);\n await replicaIdentitiesForTablesWithoutPrimaryKeys(pubs)?.apply(lc, sql);\n\n await setupTriggers(lc, sql, shard);\n}\n\nexport async function setupTriggers(\n lc: LogContext,\n tx: PostgresTransaction,\n shard: ShardConfig,\n) {\n const schema = upstreamSchema(shard);\n const [{ddlDetection}] = await tx<InternalShardConfig[]> /*sql*/ `\n SELECT \"ddlDetection\" FROM ${tx(schema)}.\"shardConfig\"`;\n\n // The functions invoked by event triggers are installed even if\n // event triggers are not supported/allowed by the db provider.\n // This allows users to manually invoke the update_schemas() function\n // as a workaround.\n await tx.unsafe(createEventFunctionStatements(shard));\n try {\n await tx.savepoint(sub => sub.unsafe(triggerSetup(shard)));\n } catch (e) {\n if (ddlDetection) {\n // If ddlDetection has already been enabled, subsequent failures to\n // upgrade the trigger should be propagated rather than swallowed.\n throw e;\n }\n if (\n !(\n e instanceof postgres.PostgresError &&\n e.code === PG_INSUFFICIENT_PRIVILEGE\n )\n ) {\n throw e;\n }\n // If triggerSetup() fails, replication continues in ddlDetection=false mode.\n lc.warn?.(\n `Unable to create event triggers for schema change detection:\\n\\n` +\n `\"${e.hint ?? e.message}\"\\n\\n` +\n `Proceeding in degraded mode: schema changes will halt replication,\\n` +\n `requiring the replica to be reset (manually or with --auto-reset).`,\n );\n }\n}\n\nexport function validatePublications(\n lc: LogContext,\n published: PublicationInfo,\n) {\n // Verify that all publications export the proper events.\n published.publications.forEach(pub => {\n if (\n !pub.pubinsert ||\n !pub.pubupdate ||\n !pub.pubdelete ||\n !pub.pubtruncate\n ) {\n // TODO: Make APIError?\n throw new Error(\n `PUBLICATION ${pub.pubname} must publish insert, update, delete, and truncate`,\n );\n }\n });\n\n published.tables.forEach(table => validate(lc, table));\n}\n\ntype ReplicaIdentities = {\n apply(lc: LogContext, db: PostgresDB): Promise<void>;\n};\n\nexport function replicaIdentitiesForTablesWithoutPrimaryKeys(\n pubs: PublishedSchema,\n): ReplicaIdentities | undefined {\n const replicaIdentities: {\n schema: string;\n tableName: string;\n indexName: string;\n }[] = [];\n for (const table of pubs.tables) {\n if (!table.primaryKey?.length && table.replicaIdentity === Default) {\n // Look for an index that can serve as the REPLICA IDENTITY USING INDEX. It must be:\n // - UNIQUE\n // - NOT NULL columns\n // - not deferrable (i.e. isImmediate)\n // - not partial (are already filtered out)\n //\n // https://www.postgresql.org/docs/current/sql-altertable.html#SQL-ALTERTABLE-REPLICA-IDENTITY\n const {schema, name: tableName} = table;\n for (const {columns, name: indexName} of pubs.indexes.filter(\n idx =>\n idx.schema === schema &&\n idx.tableName === tableName &&\n idx.unique &&\n idx.isImmediate,\n )) {\n if (Object.keys(columns).some(col => !table.columns[col].notNull)) {\n continue; // Only indexes with all NOT NULL columns are suitable.\n }\n replicaIdentities.push({schema, tableName, indexName});\n break;\n }\n }\n }\n\n if (replicaIdentities.length === 0) {\n return undefined;\n }\n return {\n apply: async (lc: LogContext, sql: PostgresDB) => {\n for (const {schema, tableName, indexName} of replicaIdentities) {\n lc.info?.(\n `setting \"${indexName}\" as the REPLICA IDENTITY for \"${tableName}\"`,\n );\n await sql`\n ALTER TABLE ${sql(schema)}.${sql(tableName)} \n REPLICA IDENTITY USING INDEX ${sql(indexName)}`;\n }\n },\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"shard.js","names":[],"sources":["../../../../../../../../zero-cache/src/services/change-source/pg/schema/shard.ts"],"sourcesContent":["import {PG_INSUFFICIENT_PRIVILEGE} from '@drdgvhbh/postgres-error-codes';\nimport type {LogContext} from '@rocicorp/logger';\nimport {literal} from 'pg-format';\nimport postgres from 'postgres';\nimport {assert} from '../../../../../../shared/src/asserts.ts';\nimport {\n jsonObjectSchema,\n stringify,\n type JSONObject,\n} from '../../../../../../shared/src/bigint-json.ts';\nimport * as v from '../../../../../../shared/src/valita.ts';\nimport {Default} from '../../../../db/postgres-replica-identity-enum.ts';\nimport type {PostgresDB, PostgresTransaction} from '../../../../types/pg.ts';\nimport type {AppID, ShardConfig, ShardID} from '../../../../types/shards.ts';\nimport {appSchema, check, upstreamSchema} from '../../../../types/shards.ts';\nimport {id} from '../../../../types/sql.ts';\nimport {\n createEventFunctionStatements,\n createEventTriggerStatements,\n} from './ddl.ts';\nimport {\n getPublicationInfo,\n publishedSchema,\n type PublicationInfo,\n type PublishedSchema,\n} from './published.ts';\nimport {validate} from './validation.ts';\n\n/**\n * PostgreSQL unquoted identifiers must start with a letter or underscore\n * and contain only letters, digits, and underscores.\n */\nconst VALID_PUBLICATION_NAME = /^[a-zA-Z_][a-zA-Z0-9_]*$/;\n\n/**\n * Validates that a publication name is a valid PostgreSQL identifier.\n * This provides defense-in-depth against SQL injection when publication\n * names are used in replication commands.\n */\nexport function validatePublicationName(name: string): void {\n if (!VALID_PUBLICATION_NAME.test(name)) {\n throw new Error(\n `Invalid publication name \"${name}\". Publication names must start with a letter or underscore ` +\n `and contain only letters, digits, and underscores.`,\n );\n }\n if (name.length > 63) {\n throw new Error(\n `Publication name \"${name}\" exceeds PostgreSQL's 63-character identifier limit.`,\n );\n }\n}\n\nexport function internalPublicationPrefix({appID}: AppID) {\n return `_${appID}_`;\n}\n\nexport function legacyReplicationSlot({appID, shardNum}: ShardID) {\n return `${appID}_${shardNum}`;\n}\n\nexport function replicationSlotPrefix(shard: ShardID) {\n const {appID, shardNum} = check(shard);\n return `${appID}_${shardNum}_`;\n}\n\n/**\n * An expression used to match replication slots in the shard\n * in a Postgres `LIKE` operator.\n */\nexport function replicationSlotExpression(shard: ShardID) {\n // Underscores have a special meaning in LIKE values\n // so they have to be escaped.\n return `${replicationSlotPrefix(shard)}%`.replaceAll('_', '\\\\_');\n}\n\nfunction defaultPublicationName(appID: string, shardID: string | number) {\n return `_${appID}_public_${shardID}`;\n}\n\nexport function metadataPublicationName(\n appID: string,\n shardID: string | number,\n) {\n return `_${appID}_metadata_${shardID}`;\n}\n\n// The GLOBAL_SETUP must be idempotent as it can be run multiple times for different shards.\nfunction globalSetup(appID: AppID): string {\n const app = id(appSchema(appID));\n\n return /*sql*/ `\n CREATE SCHEMA IF NOT EXISTS ${app};\n\n CREATE TABLE IF NOT EXISTS ${app}.permissions (\n \"permissions\" JSONB,\n \"hash\" TEXT,\n\n -- Ensure that there is only a single row in the table.\n -- Application code can be agnostic to this column, and\n -- simply invoke UPDATE statements on the version columns.\n \"lock\" BOOL PRIMARY KEY DEFAULT true CHECK (lock)\n );\n\n CREATE OR REPLACE FUNCTION ${app}.set_permissions_hash()\n RETURNS TRIGGER AS $$\n BEGIN\n NEW.hash = md5(NEW.permissions::text);\n RETURN NEW;\n END;\n $$ LANGUAGE plpgsql;\n\n CREATE OR REPLACE TRIGGER on_set_permissions \n BEFORE INSERT OR UPDATE ON ${app}.permissions\n FOR EACH ROW\n EXECUTE FUNCTION ${app}.set_permissions_hash();\n\n INSERT INTO ${app}.permissions (permissions) VALUES (NULL) ON CONFLICT DO NOTHING;\n`;\n}\n\nexport async function ensureGlobalTables(db: PostgresDB, appID: AppID) {\n await db.unsafe(globalSetup(appID));\n}\n\nexport function getClientsTableDefinition(schema: string) {\n return /*sql*/ `\n CREATE TABLE ${schema}.\"clients\" (\n \"clientGroupID\" TEXT NOT NULL,\n \"clientID\" TEXT NOT NULL,\n \"lastMutationID\" BIGINT NOT NULL,\n \"userID\" TEXT,\n PRIMARY KEY(\"clientGroupID\", \"clientID\")\n );`;\n}\n\n/**\n * Tracks the results of mutations.\n * 1. It is an error for the same mutation ID to be used twice.\n * 2. The result is JSONB to allow for arbitrary results.\n *\n * The tables must be cleaned up as the clients\n * receive the mutation responses and as clients are removed.\n */\nexport function getMutationsTableDefinition(schema: string) {\n return /*sql*/ `\n CREATE TABLE ${schema}.\"mutations\" (\n \"clientGroupID\" TEXT NOT NULL,\n \"clientID\" TEXT NOT NULL,\n \"mutationID\" BIGINT NOT NULL,\n \"result\" JSON NOT NULL,\n PRIMARY KEY(\"clientGroupID\", \"clientID\", \"mutationID\")\n );`;\n}\n\nexport const SHARD_CONFIG_TABLE = 'shardConfig';\n\nexport function shardSetup(\n shardConfig: ShardConfig,\n metadataPublication: string,\n): string {\n const app = id(appSchema(shardConfig));\n const shard = id(upstreamSchema(shardConfig));\n\n const pubs = shardConfig.publications.toSorted();\n assert(\n pubs.includes(metadataPublication),\n () => `Publications must include ${metadataPublication}`,\n );\n\n return /*sql*/ `\n CREATE SCHEMA IF NOT EXISTS ${shard};\n\n ${getClientsTableDefinition(shard)}\n ${getMutationsTableDefinition(shard)}\n\n DROP PUBLICATION IF EXISTS ${id(metadataPublication)};\n CREATE PUBLICATION ${id(metadataPublication)}\n FOR TABLE ${app}.\"permissions\", TABLE ${shard}.\"clients\", ${shard}.\"mutations\";\n\n CREATE TABLE ${shard}.\"${SHARD_CONFIG_TABLE}\" (\n \"publications\" TEXT[] NOT NULL,\n \"ddlDetection\" BOOL NOT NULL,\n\n -- Ensure that there is only a single row in the table.\n \"lock\" BOOL PRIMARY KEY DEFAULT true CHECK (lock)\n );\n\n INSERT INTO ${shard}.\"${SHARD_CONFIG_TABLE}\" (\n \"publications\",\n \"ddlDetection\" \n ) VALUES (\n ARRAY[${literal(pubs)}], \n false -- set in SAVEPOINT with triggerSetup() statements\n );\n\n CREATE TABLE ${shard}.replicas (\n -- The DEFAULT exists purely for backwards compatibility support.\n -- New code always specifies a value based on Date.now().\n \"id\" TEXT PRIMARY KEY DEFAULT replace(gen_random_uuid()::text, '-', ''),\n \"rank\" BIGSERIAL,\n \"slot\" TEXT NOT NULL,\n \"version\" TEXT NOT NULL,\n \"generation\" TEXT, -- to replace version, NULL-able in the interim\n \"backupPath\" TEXT, -- subpath within the litestream backup URL\n \"backupV5\" BOOL DEFAULT false,\n \"initialSchema\" JSON, -- set after initial sync\n \"initialSyncContext\" JSON,\n \"subscriberContext\" JSON\n );\n `;\n}\n\nexport function dropShard(appID: string, shardID: string | number): string {\n const schema = `${appID}_${shardID}`;\n const metadataPublication = metadataPublicationName(appID, shardID);\n const defaultPublication = defaultPublicationName(appID, shardID);\n\n // DROP SCHEMA ... CASCADE does not drop dependent PUBLICATIONS,\n // so PUBLICATIONs must be dropped explicitly.\n return /*sql*/ `\n DROP PUBLICATION IF EXISTS ${id(defaultPublication)};\n DROP PUBLICATION IF EXISTS ${id(metadataPublication)};\n DROP SCHEMA IF EXISTS ${id(schema)} CASCADE;\n `;\n}\n\nconst internalShardConfigSchema = v.object({\n publications: v.array(v.string()),\n ddlDetection: v.boolean(),\n});\n\nexport type InternalShardConfig = v.Infer<typeof internalShardConfigSchema>;\n\nconst replicaInfoSchema = v.object({\n id: v.string(),\n rank: v.bigint(),\n slot: v.string(),\n version: v.string(),\n generation: v.string().nullable(),\n backupPath: v.string().nullable(),\n backupV5: v.boolean(),\n});\n\nconst fullReplicaRowSchema = replicaInfoSchema.extend({\n initialSchema: publishedSchema,\n initialSyncContext: jsonObjectSchema.nullable(),\n subscriberContext: jsonObjectSchema.nullable(),\n});\n\nconst replicaSchema = internalShardConfigSchema\n .extend(fullReplicaRowSchema.shape)\n .map(replica => {\n const {version, generation, ...r} = replica;\n return {...r, generation: generation ?? version};\n });\n\nexport type Replica = v.Infer<typeof replicaSchema>;\n\nconst replicationSlotStateSchema = v.object({\n active: v.boolean(),\n confirmedFlushLsn: v.string().nullable(),\n});\n\nconst replicaStateSchema = replicaInfoSchema\n .extend(replicationSlotStateSchema.shape)\n .map(replica => {\n const {version, generation, ...r} = replica;\n return {...r, generation: generation ?? version};\n });\n\nexport type ReplicaState = v.Infer<typeof replicaStateSchema>;\n\n// triggerSetup is run separately in a sub-transaction (i.e. SAVEPOINT) so\n// that a failure (e.g. due to lack of superuser permissions) can be handled\n// by continuing in a degraded mode (ddlDetection = false).\nfunction triggerSetup(shard: ShardConfig): string {\n const schema = id(upstreamSchema(shard));\n return (\n createEventTriggerStatements(shard) +\n /*sql*/ `UPDATE ${schema}.\"shardConfig\" SET \"ddlDetection\" = true;`\n );\n}\n\nexport type BackupOptions = {\n backupPath: string | null;\n backupV5: boolean;\n};\n\n/**\n * Creates a new replica to mark it as the owner of a specified `slot`.\n * This should be done with an advisory lock for replica/slot management\n * to ensure that the slot does not get dropped by concurrent cleanup\n * logic.\n *\n * Once initial sync is complete, {@link initReplica} should be called to\n * make the replica usable for incremental sync.\n */\nexport async function createReplica(\n sql: PostgresDB,\n shard: ShardID,\n id: string,\n slot: string,\n replicaVersion: string,\n {backupPath, backupV5}: BackupOptions,\n) {\n const schema = upstreamSchema(shard);\n const values: Partial<v.Infer<typeof fullReplicaRowSchema>> = {\n id,\n slot,\n version: replicaVersion,\n generation: replicaVersion,\n backupPath,\n backupV5,\n };\n await sql`INSERT INTO ${sql(schema)}.replicas ${sql(values)}`;\n}\n\n// Called in initial-sync to store the exact schema that was initially synced.\nexport async function initReplica(\n sql: PostgresDB,\n shard: ShardID,\n id: string,\n {tables, indexes}: PublishedSchema,\n initialSyncContext: JSONObject,\n) {\n const schema = upstreamSchema(shard);\n const synced: PublishedSchema = {tables, indexes};\n const values = {initialSchema: synced, initialSyncContext};\n await sql`UPDATE ${sql(schema)}.replicas SET ${sql(values)} WHERE id = ${id}`;\n}\n\n/**\n * Gets at the given version and optional ID. If no ID is specified, gets\n * the latest (i.e. highest rank) replica with that version.\n */\nexport async function getReplicaAtVersion(\n lc: LogContext,\n sql: PostgresDB,\n shard: ShardID,\n replicaVersion: string,\n id: string | null = null,\n context?: JSONObject,\n): Promise<Replica | null> {\n const schema = sql(upstreamSchema(shard));\n const result = await sql`\n SELECT\n replicas.\"id\",\n replicas.\"rank\",\n replicas.\"slot\",\n replicas.\"version\",\n replicas.\"generation\",\n replicas.\"backupPath\",\n replicas.\"backupV5\",\n replicas.\"initialSchema\",\n replicas.\"initialSyncContext\",\n replicas.\"subscriberContext\",\n \"shardConfig\".\"publications\",\n \"shardConfig\".\"ddlDetection\"\n FROM ${schema}.replicas JOIN ${schema}.\"shardConfig\" ON true\n WHERE version = ${replicaVersion} AND \"initialSyncContext\" IS NOT NULL\n AND id = COALESCE(${id}, id)\n ORDER BY rank DESC LIMIT 1;\n `;\n if (result.length === 0) {\n // log out all the replicas and the joined shardConfig\n const allReplicas = await sql`\n SELECT id, slot, version, \"initialSyncContext\", \"subscriberContext\" \n FROM ${schema}.replicas`;\n lc.info?.(\n `Replica ${id}@${replicaVersion}` +\n (context ? `(context: ${stringify(context)}) ` : '') +\n `not found in: ${stringify(allReplicas)}`,\n );\n return null;\n }\n return v.parse(result[0], replicaSchema, 'passthrough');\n}\n\nexport async function getActiveReplicas(\n lc: LogContext,\n sql: PostgresDB,\n shard: ShardID,\n): Promise<ReplicaState[]> {\n const schema = sql(upstreamSchema(shard));\n const results = await sql`\n SELECT\n replicas.\"id\",\n replicas.\"rank\",\n replicas.\"slot\",\n replicas.\"version\",\n replicas.\"generation\",\n replicas.\"backupPath\",\n replicas.\"backupV5\",\n slots.\"active\",\n slots.\"confirmed_flush_lsn\" as \"confirmedFlushLsn\"\n FROM ${schema}.replicas JOIN pg_replication_slots slots ON slot = slot_name\n WHERE \"initialSyncContext\" IS NOT NULL\n ORDER BY generation DESC, confirmed_flush_lsn DESC;\n `;\n const replicas = v.parse(results, v.array(replicaStateSchema), 'passthrough');\n lc.info?.(`current replicas`, {replicas});\n return replicas;\n}\n\nexport async function getReplicaState(\n sql: PostgresDB,\n shard: ShardID,\n id: string,\n): Promise<ReplicaState | null> {\n const schema = sql(upstreamSchema(shard));\n const results = await sql`\n SELECT\n replicas.\"id\",\n replicas.\"rank\",\n replicas.\"slot\",\n replicas.\"version\",\n replicas.\"generation\",\n replicas.\"backupPath\",\n replicas.\"backupV5\",\n slots.\"active\",\n slots.\"confirmed_flush_lsn\" as \"confirmedFlushLsn\"\n FROM ${schema}.replicas JOIN pg_replication_slots slots ON slot = slot_name\n WHERE \"id\" = ${id};\n `;\n return results.length\n ? v.parse(results[0], replicaStateSchema, 'passthrough')\n : null;\n}\n\nexport async function getInternalShardConfig(\n sql: PostgresDB,\n shard: ShardID,\n): Promise<InternalShardConfig> {\n const result = await sql`\n SELECT \"publications\", \"ddlDetection\"\n FROM ${sql(upstreamSchema(shard))}.\"shardConfig\";\n `;\n assert(\n result.length === 1,\n () => `Expected exactly one shardConfig row, got ${result.length}`,\n );\n return v.parse(result[0], internalShardConfigSchema, 'passthrough');\n}\n\n/**\n * Sets up and returns all publications (including internal ones) for\n * the given shard.\n */\nexport async function setupTablesAndReplication(\n lc: LogContext,\n sql: PostgresTransaction,\n requested: ShardConfig,\n) {\n const {publications} = requested;\n // Validate requested publications.\n for (const pub of publications) {\n validatePublicationName(pub);\n if (pub.startsWith('_')) {\n throw new Error(\n `Publication names starting with \"_\" are reserved for internal use.\\n` +\n `Please use a different name for publication \"${pub}\".`,\n );\n }\n }\n const allPublications: string[] = [];\n\n // Setup application publications.\n if (publications.length) {\n const results = await sql<{pubname: string}[]>`\n SELECT pubname from pg_publication WHERE pubname IN ${sql(\n publications,\n )}`.values();\n\n if (results.length !== publications.length) {\n throw new Error(\n `Unknown or invalid publications. Specified: [${publications}]. Found: [${results.flat()}]`,\n );\n }\n allPublications.push(...publications);\n } else {\n const defaultPublication = defaultPublicationName(\n requested.appID,\n requested.shardNum,\n );\n await sql`\n DROP PUBLICATION IF EXISTS ${sql(defaultPublication)}`;\n await sql`\n CREATE PUBLICATION ${sql(defaultPublication)} \n FOR TABLES IN SCHEMA public\n WITH (publish_via_partition_root = true)`;\n allPublications.push(defaultPublication);\n }\n\n const metadataPublication = metadataPublicationName(\n requested.appID,\n requested.shardNum,\n );\n allPublications.push(metadataPublication);\n\n const shard = {...requested, publications: allPublications};\n\n // Setup the global tables and shard tables / publications.\n await sql.unsafe(globalSetup(shard) + shardSetup(shard, metadataPublication));\n\n const pubs = await getPublicationInfo(sql, allPublications);\n await replicaIdentitiesForTablesWithoutPrimaryKeys(pubs)?.apply(lc, sql);\n\n await setupTriggers(lc, sql, shard);\n}\n\nexport async function setupTriggers(\n lc: LogContext,\n tx: PostgresTransaction,\n shard: ShardConfig,\n) {\n const schema = upstreamSchema(shard);\n const [{ddlDetection}] = await tx<InternalShardConfig[]> /*sql*/ `\n SELECT \"ddlDetection\" FROM ${tx(schema)}.\"shardConfig\"`;\n\n // The functions invoked by event triggers are installed even if\n // event triggers are not supported/allowed by the db provider.\n // This allows users to manually invoke the update_schemas() function\n // as a workaround.\n await tx.unsafe(createEventFunctionStatements(shard));\n try {\n await tx.savepoint(sub => sub.unsafe(triggerSetup(shard)));\n } catch (e) {\n if (ddlDetection) {\n // If ddlDetection has already been enabled, subsequent failures to\n // upgrade the trigger should be propagated rather than swallowed.\n throw e;\n }\n if (\n !(\n e instanceof postgres.PostgresError &&\n e.code === PG_INSUFFICIENT_PRIVILEGE\n )\n ) {\n throw e;\n }\n // If triggerSetup() fails, replication continues in ddlDetection=false mode.\n lc.warn?.(\n `Unable to create event triggers for schema change detection:\\n\\n` +\n `\"${e.hint ?? e.message}\"\\n\\n` +\n `Proceeding in degraded mode: schema changes will halt replication,\\n` +\n `requiring the replica to be reset (manually or with --auto-reset).`,\n );\n }\n}\n\nexport function validatePublications(\n lc: LogContext,\n published: PublicationInfo,\n) {\n // Verify that all publications export the proper events.\n published.publications.forEach(pub => {\n if (\n !pub.pubinsert ||\n !pub.pubupdate ||\n !pub.pubdelete ||\n !pub.pubtruncate\n ) {\n // TODO: Make APIError?\n throw new Error(\n `PUBLICATION ${pub.pubname} must publish insert, update, delete, and truncate`,\n );\n }\n });\n\n published.tables.forEach(table => validate(lc, table));\n}\n\ntype ReplicaIdentities = {\n apply(lc: LogContext, db: PostgresDB): Promise<void>;\n};\n\nexport function replicaIdentitiesForTablesWithoutPrimaryKeys(\n pubs: PublishedSchema,\n): ReplicaIdentities | undefined {\n const replicaIdentities: {\n schema: string;\n tableName: string;\n indexName: string;\n }[] = [];\n for (const table of pubs.tables) {\n if (!table.primaryKey?.length && table.replicaIdentity === Default) {\n // Look for an index that can serve as the REPLICA IDENTITY USING INDEX. It must be:\n // - UNIQUE\n // - NOT NULL columns\n // - not deferrable (i.e. isImmediate)\n // - not partial (are already filtered out)\n //\n // https://www.postgresql.org/docs/current/sql-altertable.html#SQL-ALTERTABLE-REPLICA-IDENTITY\n const {schema, name: tableName} = table;\n for (const {columns, name: indexName} of pubs.indexes.filter(\n idx =>\n idx.schema === schema &&\n idx.tableName === tableName &&\n idx.unique &&\n idx.isImmediate,\n )) {\n if (Object.keys(columns).some(col => !table.columns[col].notNull)) {\n continue; // Only indexes with all NOT NULL columns are suitable.\n }\n replicaIdentities.push({schema, tableName, indexName});\n break;\n }\n }\n }\n\n if (replicaIdentities.length === 0) {\n return undefined;\n }\n return {\n apply: async (lc: LogContext, sql: PostgresDB) => {\n for (const {schema, tableName, indexName} of replicaIdentities) {\n lc.info?.(\n `setting \"${indexName}\" as the REPLICA IDENTITY for \"${tableName}\"`,\n );\n await sql`\n ALTER TABLE ${sql(schema)}.${sql(tableName)} \n REPLICA IDENTITY USING INDEX ${sql(indexName)}`;\n }\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -8,11 +8,12 @@ import * as v from '../../../../../../shared/src/valita.ts';
|
|
|
8
8
|
import type { Satisfies } from '../../../../types/satisfies.ts';
|
|
9
9
|
export declare const beginSchema: v.ObjectType<{
|
|
10
10
|
tag: v.Type<"begin">;
|
|
11
|
-
json: v.Optional<"
|
|
11
|
+
json: v.Optional<"s" | "p">;
|
|
12
12
|
skipAck: v.Optional<boolean>;
|
|
13
13
|
}, undefined>;
|
|
14
14
|
export declare const commitSchema: v.ObjectType<{
|
|
15
15
|
tag: v.Type<"commit">;
|
|
16
|
+
commitTimeMs: v.Optional<number>;
|
|
16
17
|
}, undefined>;
|
|
17
18
|
export declare const rollbackSchema: v.ObjectType<{
|
|
18
19
|
tag: v.Type<"rollback">;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data.d.ts","sourceRoot":"","sources":["../../../../../../../../zero-cache/src/services/change-source/protocol/current/data.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAEL,KAAK,UAAU,EAChB,MAAM,6CAA6C,CAAC;AAErD,OAAO,KAAK,CAAC,MAAM,wCAAwC,CAAC;AAE5D,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"data.d.ts","sourceRoot":"","sources":["../../../../../../../../zero-cache/src/services/change-source/protocol/current/data.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,7 @@ import { must } from "../../../../../../shared/src/must.js";
|
|
|
3
3
|
import { jsonValueSchema } from "../../../../../../shared/src/bigint-json.js";
|
|
4
4
|
import { jsonObjectSchema } from "./json.js";
|
|
5
5
|
import { columnSpec, indexSpec, tableSpec } from "../../../../db/specs.js";
|
|
6
|
+
import { schemaChangeTags } from "./schema-change-tags.js";
|
|
6
7
|
//#region ../zero-cache/src/services/change-source/protocol/current/data.ts
|
|
7
8
|
/**
|
|
8
9
|
* Data plane messages encapsulate changes that are sent by ChangeSources,
|
|
@@ -14,7 +15,10 @@ var beginSchema = valita_exports.object({
|
|
|
14
15
|
json: literalUnion("p", "s").optional(),
|
|
15
16
|
skipAck: valita_exports.boolean().optional()
|
|
16
17
|
});
|
|
17
|
-
var commitSchema = valita_exports.object({
|
|
18
|
+
var commitSchema = valita_exports.object({
|
|
19
|
+
tag: valita_exports.literal("commit"),
|
|
20
|
+
commitTimeMs: valita_exports.number().optional()
|
|
21
|
+
});
|
|
18
22
|
var rollbackSchema = valita_exports.object({ tag: valita_exports.literal("rollback") });
|
|
19
23
|
var rowKeySchema = valita_exports.object({
|
|
20
24
|
columns: valita_exports.array(valita_exports.string()),
|
|
@@ -166,18 +170,6 @@ var schemaChanges = [
|
|
|
166
170
|
dropIndexSchema,
|
|
167
171
|
backfillCompletedSchema
|
|
168
172
|
];
|
|
169
|
-
var schemaChangeTags = [
|
|
170
|
-
"create-table",
|
|
171
|
-
"rename-table",
|
|
172
|
-
"update-table-metadata",
|
|
173
|
-
"add-column",
|
|
174
|
-
"update-column",
|
|
175
|
-
"drop-column",
|
|
176
|
-
"drop-table",
|
|
177
|
-
"create-index",
|
|
178
|
-
"drop-index",
|
|
179
|
-
"backfill-completed"
|
|
180
|
-
];
|
|
181
173
|
var schemaChangeSchema = valita_exports.union(...schemaChanges);
|
|
182
174
|
literalUnion(...schemaChangeTags);
|
|
183
175
|
var schemaChangeTagSet = new Set(schemaChangeTags);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data.js","names":[],"sources":["../../../../../../../../zero-cache/src/services/change-source/protocol/current/data.ts"],"sourcesContent":["/**\n * Data plane messages encapsulate changes that are sent by ChangeSources,\n * forwarded / fanned out to subscribers by the ChangeStreamerService, and\n * stored in the Change DB for catchup of old subscribers.\n */\n\nimport {\n jsonValueSchema,\n type JSONObject,\n} from '../../../../../../shared/src/bigint-json.ts';\nimport {must} from '../../../../../../shared/src/must.ts';\nimport * as v from '../../../../../../shared/src/valita.ts';\nimport {columnSpec, indexSpec, tableSpec} from '../../../../db/specs.ts';\nimport type {Satisfies} from '../../../../types/satisfies.ts';\nimport {jsonObjectSchema} from './json.ts';\n\nexport const beginSchema = v.object({\n tag: v.literal('begin'),\n // The format of values of \"json\"-typed columns (e.g. \"JSON\" and \"JSONB\").\n // - 'p' is for parsed JSON, which may include JSON values or JSON objects.\n // These values are parsed and stringified at every process boundary\n // between the change-source and the replica.\n // - 's' is for stringified JSON. These values skip the parsing and\n // stringification, and are directly ferried to the replica as a JSON\n // string. For JSON values this improves performance by 20~25% in the\n // change-streamer and 25~30% in the replicator.\n //\n // If absent, the format is assumed to be 'p' (parsed JSON objects/values).\n json: v.literalUnion('p', 's').optional(),\n\n // Directs the change-streamer to skip the ACK for the corresponding commit.\n skipAck: v.boolean().optional(),\n});\n\nexport const commitSchema = v.object({\n tag: v.literal('commit'),\n});\n\nexport const rollbackSchema = v.object({\n tag: v.literal('rollback'),\n});\n\nconst rowKeySchema = v.object({\n // The columns used to identify a row in insert, update, and delete changes.\n columns: v.array(v.string()),\n\n // An optional qualifier identifying how the key is chosen. Currently this\n // is postgres-specific, describing the REPLICA IDENTITY, for which replica\n // identity 'full' (FULL) is handled differently; the replicator handles\n // these tables by extracting a row key from the full row based on the\n // table's PRIMARY KEY or UNIQUE INDEX.\n type: v.literalUnion('default', 'nothing', 'full', 'index').optional(),\n});\n\nexport const relationSchema = v\n .object({\n schema: v.string(),\n name: v.string(),\n\n // This will become required.\n rowKey: rowKeySchema.optional(),\n\n /** Deprecated: set the rowKey.columns instead. */\n keyColumns: v.array(v.string()).optional(),\n /** Deprecated: set the rowKey.columns instead. */\n replicaIdentity: v\n .literalUnion('default', 'nothing', 'full', 'index')\n .optional(),\n })\n .map(rel => {\n const {rowKey, ...rest} = rel;\n if (rowKey) {\n return {...rest, rowKey};\n }\n return {\n ...rest,\n rowKey: {\n columns: must(rel.keyColumns),\n type: rel.replicaIdentity,\n },\n };\n });\n\n// The eventual fate of relationSchema\nexport const newRelationSchema = v.object({\n schema: v.string(),\n name: v.string(),\n\n rowKey: rowKeySchema,\n});\n\n// TableMetadata contains table-related configuration that does not affect the\n// actual data in the table, but rather how the table's change messages are\n// handled. The is an opaque object that clients must track (and update) based\n// on `create-table`, `add-column`, and `table-update-metadata` messages, and\n// pass in BackfillRequests when there are columns to be backfilled.\n//\n// Note that the backfill-related change-source implementation does, however,\n// rely on the rowKey (columns) being specified in the message.\nexport const tableMetadataSchema = v\n .object({rowKey: v.record(jsonValueSchema)})\n .rest(jsonValueSchema);\n\nexport type TableMetadata = v.Infer<typeof tableMetadataSchema>;\n\nexport const rowSchema = v.record(jsonValueSchema);\n\nexport const insertSchema = v.object({\n tag: v.literal('insert'),\n relation: relationSchema,\n new: rowSchema,\n});\n\nexport const updateSchema = v.object({\n tag: v.literal('update'),\n relation: relationSchema,\n // `key` is present if the update changed the key of the row, or if the\n // table's replicaIdentity === 'full'\n key: rowSchema.nullable(),\n // `new` is the full row (and not just the updated columns). This is\n // necessary for \"catchup\" replication scenarios such as adding tables\n // to a publication, or resharding.\n new: rowSchema,\n});\n\nexport const deleteSchema = v.object({\n tag: v.literal('delete'),\n relation: relationSchema,\n // key is the full row if replicaIdentity === 'full'\n key: rowSchema,\n});\n\nexport const truncateSchema = v.object({\n tag: v.literal('truncate'),\n relations: v.array(relationSchema),\n});\n\nexport const identifierSchema = v.object({\n schema: v.string(),\n name: v.string(),\n});\n\nexport type Identifier = v.Infer<typeof identifierSchema>;\n\n// A BackfillID is an upstream specific stable identifier for a column\n// that needs backfilling. This id is used to ensure that the schema, table,\n// and column names of a requested backfill still match the original\n// underlying upstream ID.\n//\n// The change-streamer stores these IDs as opaque values while a column is\n// being backfilled, and initiates new change-source streams with the IDs\n// in order to restart backfills that did not complete in previous sessions.\nexport const backfillIDSchema = jsonObjectSchema;\n\nexport type BackfillID = v.Infer<typeof backfillIDSchema>;\n\nexport const createTableSchema = v.object({\n tag: v.literal('create-table'),\n spec: tableSpec,\n\n // This must be set by change source implementations that support\n // table/column backfill.\n //\n // TODO: to simplify the protocol, see if we can make this required\n metadata: tableMetadataSchema.optional(),\n\n // Indicate that columns of the table require backfilling. These columns\n // should be created on the replica but not yet synced the clients.\n //\n // ## State Persistence\n //\n // To obviate the need for change-source implementations to persist state\n // related to backfill progress, the change-source only tracks backfills\n // **for the current session**. In the event that the session is interrupted\n // before columns have been fully backfilled, it is the responsibility of the\n // change-streamer to send {@link BackfillRequest}s when it reconnects.\n //\n // This means that the change-streamer must track and persist:\n // * the backfill IDs of the columns requiring backfilling\n // * the most current table metadata of the associated table(s)\n //\n // The change-streamer then uses this information to send backfill requests\n // when it reconnects.\n backfill: v.record(backfillIDSchema).optional(),\n});\n\nexport const renameTableSchema = v.object({\n tag: v.literal('rename-table'),\n old: identifierSchema,\n new: identifierSchema,\n});\n\nexport const updateTableMetadataSchema = v.object({\n tag: v.literal('update-table-metadata'),\n table: identifierSchema,\n old: tableMetadataSchema,\n new: tableMetadataSchema,\n});\n\nconst columnSchema = v.object({\n name: v.string(),\n spec: columnSpec,\n});\n\nexport const addColumnSchema = v.object({\n tag: v.literal('add-column'),\n table: identifierSchema,\n column: columnSchema,\n\n // This must be set by change source implementations that support\n // table/column backfill.\n //\n // TODO: to simplify the protocol, see if we can make this required\n tableMetadata: tableMetadataSchema.optional(),\n\n // See documentation for the `backfill` field of the `create-table` change.\n backfill: backfillIDSchema.optional(),\n});\n\nexport const updateColumnSchema = v.object({\n tag: v.literal('update-column'),\n table: identifierSchema,\n old: columnSchema,\n new: columnSchema,\n});\n\nexport const dropColumnSchema = v.object({\n tag: v.literal('drop-column'),\n table: identifierSchema,\n column: v.string(),\n});\n\nexport const dropTableSchema = v.object({\n tag: v.literal('drop-table'),\n id: identifierSchema,\n});\n\nexport const createIndexSchema = v.object({\n tag: v.literal('create-index'),\n spec: indexSpec,\n});\n\nexport const dropIndexSchema = v.object({\n tag: v.literal('drop-index'),\n id: identifierSchema,\n});\n\nexport const downloadStatusSchema = v.object({\n rows: v.number(),\n totalRows: v.number(),\n totalBytes: v.number().optional(),\n});\n\nexport type DownloadStatus = v.Infer<typeof downloadStatusSchema>;\n\n// A batch of rows from a single table containing column values\n// to be backfilled.\nexport const backfillSchema = v.object({\n tag: v.literal('backfill'),\n\n relation: newRelationSchema,\n\n // The columns to be backfilled. `rowKey` columns are automatically excluded,\n // which means that this field may be empty.\n columns: v.array(v.string()),\n\n // The watermark at which the backfill data was queried. Note that this\n // generally will be different from the commit watermarks of the main change\n // stream, and in particular, the commit watermark of the backfill change's\n // enclosing transaction.\n watermark: v.string(),\n\n // A batch of row values, each row consisting of the `rowKey`\n // values, followed by the `column` values, in the same order in which\n // the column names appear in their respective fields, e.g.\n //\n // ```\n // [\n // [...rowKeyValues, ...columnValues], // row 1\n // [...rowKeyValues, ...columnValues], // row 2\n // ]\n // ```\n rowValues: v.array(v.array(jsonValueSchema)),\n\n // Optionally includes the progress of the backfill operation,\n // for display purposes.\n status: downloadStatusSchema.optional(),\n});\n\n// Indicates that the backfill for the specified columns have\n// been successfully backfilled and can be published to clients.\nexport const backfillCompletedSchema = v.object({\n tag: v.literal('backfill-completed'),\n\n relation: newRelationSchema,\n\n // The columns to be backfilled. `rowKey` columns are automatically excluded,\n // which means that this field may be empty.\n columns: v.array(v.string()),\n\n // The watermark at which the backfill data was queried. Note that this\n // generally will be different from the commit watermarks of the main change\n // stream, and in particular, the commit watermark of the backfill change's\n // enclosing transaction.\n watermark: v.string(),\n\n // Optionally includes the final status of the backfill operation,\n // for display purposes.\n status: downloadStatusSchema.optional(),\n});\n\nexport type MessageBegin = v.Infer<typeof beginSchema>;\nexport type MessageCommit = v.Infer<typeof commitSchema>;\nexport type MessageRollback = v.Infer<typeof rollbackSchema>;\n\nexport type MessageRelation = v.Infer<typeof relationSchema>;\nexport type MessageInsert = v.Infer<typeof insertSchema>;\nexport type MessageUpdate = v.Infer<typeof updateSchema>;\nexport type MessageDelete = v.Infer<typeof deleteSchema>;\nexport type MessageTruncate = v.Infer<typeof truncateSchema>;\n\nexport type MessageBackfill = v.Infer<typeof backfillSchema>;\n\nexport type TableCreate = v.Infer<typeof createTableSchema>;\nexport type TableRename = v.Infer<typeof renameTableSchema>;\nexport type TableUpdateMetadata = v.Infer<typeof updateTableMetadataSchema>;\nexport type ColumnAdd = v.Infer<typeof addColumnSchema>;\nexport type ColumnUpdate = v.Infer<typeof updateColumnSchema>;\nexport type ColumnDrop = v.Infer<typeof dropColumnSchema>;\nexport type TableDrop = v.Infer<typeof dropTableSchema>;\nexport type IndexCreate = v.Infer<typeof createIndexSchema>;\nexport type IndexDrop = v.Infer<typeof dropIndexSchema>;\nexport type BackfillCompleted = v.Infer<typeof backfillCompletedSchema>;\n\nexport const dataChangeSchema = v.union(\n insertSchema,\n updateSchema,\n deleteSchema,\n truncateSchema,\n backfillSchema,\n);\n\n// Note: keep in sync or the tag tests will fail\nconst dataChangeTags = [\n 'insert',\n 'update',\n 'delete',\n 'truncate',\n 'backfill',\n] as const;\n\nconst dataChangeTagsSchema = v.literalUnion(...dataChangeTags);\n\nexport type DataChange = Satisfies<\n JSONObject, // guarantees serialization over IPC or network\n v.Infer<typeof dataChangeSchema>\n>;\n\nexport type DataChangeTag = v.Infer<typeof dataChangeTagsSchema>;\n\nconst schemaChanges = [\n createTableSchema,\n renameTableSchema,\n updateTableMetadataSchema,\n addColumnSchema,\n updateColumnSchema,\n dropColumnSchema,\n dropTableSchema,\n createIndexSchema,\n dropIndexSchema,\n backfillCompletedSchema,\n] as const;\n\n// Note: keep in sync or the tag tests will fail\nconst schemaChangeTags = [\n 'create-table',\n 'rename-table',\n 'update-table-metadata',\n 'add-column',\n 'update-column',\n 'drop-column',\n 'drop-table',\n 'create-index',\n 'drop-index',\n 'backfill-completed',\n] as const;\n\nexport const schemaChangeSchema = v.union(...schemaChanges);\n\nconst schemaChangeTagsSchema = v.literalUnion(...schemaChangeTags);\n\nexport type SchemaChange = Satisfies<\n JSONObject,\n v.Infer<typeof schemaChangeSchema>\n>;\n\nexport type SchemaChangeTag = v.Infer<typeof schemaChangeTagsSchema>;\n\nexport type DataOrSchemaChange = DataChange | SchemaChange;\n\nexport type Change =\n | MessageBegin\n | DataOrSchemaChange\n | MessageCommit\n | MessageRollback;\n\nexport type ChangeTag = Change['tag'];\n\nconst schemaChangeTagSet = new Set<string>(schemaChangeTags);\n\nexport function isSchemaChange(change: Change): change is SchemaChange {\n return schemaChangeTagSet.has(change.tag);\n}\n\nconst dataChangeTagSet = new Set<string>(dataChangeTags);\n\nexport function isDataChange(change: Change): change is DataChange {\n return dataChangeTagSet.has(change.tag);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"data.js","names":[],"sources":["../../../../../../../../zero-cache/src/services/change-source/protocol/current/data.ts"],"sourcesContent":["/**\n * Data plane messages encapsulate changes that are sent by ChangeSources,\n * forwarded / fanned out to subscribers by the ChangeStreamerService, and\n * stored in the Change DB for catchup of old subscribers.\n */\n\nimport {\n jsonValueSchema,\n type JSONObject,\n} from '../../../../../../shared/src/bigint-json.ts';\nimport {must} from '../../../../../../shared/src/must.ts';\nimport * as v from '../../../../../../shared/src/valita.ts';\nimport {columnSpec, indexSpec, tableSpec} from '../../../../db/specs.ts';\nimport type {Satisfies} from '../../../../types/satisfies.ts';\nimport {jsonObjectSchema} from './json.ts';\nimport {schemaChangeTags} from './schema-change-tags.ts';\n\nexport const beginSchema = v.object({\n tag: v.literal('begin'),\n // The format of values of \"json\"-typed columns (e.g. \"JSON\" and \"JSONB\").\n // - 'p' is for parsed JSON, which may include JSON values or JSON objects.\n // These values are parsed and stringified at every process boundary\n // between the change-source and the replica.\n // - 's' is for stringified JSON. These values skip the parsing and\n // stringification, and are directly ferried to the replica as a JSON\n // string. For JSON values this improves performance by 20~25% in the\n // change-streamer and 25~30% in the replicator.\n //\n // If absent, the format is assumed to be 'p' (parsed JSON objects/values).\n json: v.literalUnion('p', 's').optional(),\n\n // Directs the change-streamer to skip the ACK for the corresponding commit.\n skipAck: v.boolean().optional(),\n});\n\nexport const commitSchema = v.object({\n tag: v.literal('commit'),\n\n // Millisecond epoch at which the transaction committed upstream, as reported\n // by the upstream database (e.g. the `commitTime` of the Postgres logical\n // replication Commit message).\n //\n // This is the origin timestamp of the end-to-end serving lag measurement:\n // it is carried through the replication stream to the ViewSyncer, which\n // records `now - commitTimeMs` once the change has been poked to clients.\n //\n // Optional because it is absent from changes written to the Change DB by\n // older versions, which are replayed verbatim during catchup, and from\n // ChangeSources that do not report a commit time.\n commitTimeMs: v.number().optional(),\n});\n\nexport const rollbackSchema = v.object({\n tag: v.literal('rollback'),\n});\n\nconst rowKeySchema = v.object({\n // The columns used to identify a row in insert, update, and delete changes.\n columns: v.array(v.string()),\n\n // An optional qualifier identifying how the key is chosen. Currently this\n // is postgres-specific, describing the REPLICA IDENTITY, for which replica\n // identity 'full' (FULL) is handled differently; the replicator handles\n // these tables by extracting a row key from the full row based on the\n // table's PRIMARY KEY or UNIQUE INDEX.\n type: v.literalUnion('default', 'nothing', 'full', 'index').optional(),\n});\n\nexport const relationSchema = v\n .object({\n schema: v.string(),\n name: v.string(),\n\n // This will become required.\n rowKey: rowKeySchema.optional(),\n\n /** Deprecated: set the rowKey.columns instead. */\n keyColumns: v.array(v.string()).optional(),\n /** Deprecated: set the rowKey.columns instead. */\n replicaIdentity: v\n .literalUnion('default', 'nothing', 'full', 'index')\n .optional(),\n })\n .map(rel => {\n const {rowKey, ...rest} = rel;\n if (rowKey) {\n return {...rest, rowKey};\n }\n return {\n ...rest,\n rowKey: {\n columns: must(rel.keyColumns),\n type: rel.replicaIdentity,\n },\n };\n });\n\n// The eventual fate of relationSchema\nexport const newRelationSchema = v.object({\n schema: v.string(),\n name: v.string(),\n\n rowKey: rowKeySchema,\n});\n\n// TableMetadata contains table-related configuration that does not affect the\n// actual data in the table, but rather how the table's change messages are\n// handled. The is an opaque object that clients must track (and update) based\n// on `create-table`, `add-column`, and `table-update-metadata` messages, and\n// pass in BackfillRequests when there are columns to be backfilled.\n//\n// Note that the backfill-related change-source implementation does, however,\n// rely on the rowKey (columns) being specified in the message.\nexport const tableMetadataSchema = v\n .object({rowKey: v.record(jsonValueSchema)})\n .rest(jsonValueSchema);\n\nexport type TableMetadata = v.Infer<typeof tableMetadataSchema>;\n\nexport const rowSchema = v.record(jsonValueSchema);\n\nexport const insertSchema = v.object({\n tag: v.literal('insert'),\n relation: relationSchema,\n new: rowSchema,\n});\n\nexport const updateSchema = v.object({\n tag: v.literal('update'),\n relation: relationSchema,\n // `key` is present if the update changed the key of the row, or if the\n // table's replicaIdentity === 'full'\n key: rowSchema.nullable(),\n // `new` is the full row (and not just the updated columns). This is\n // necessary for \"catchup\" replication scenarios such as adding tables\n // to a publication, or resharding.\n new: rowSchema,\n});\n\nexport const deleteSchema = v.object({\n tag: v.literal('delete'),\n relation: relationSchema,\n // key is the full row if replicaIdentity === 'full'\n key: rowSchema,\n});\n\nexport const truncateSchema = v.object({\n tag: v.literal('truncate'),\n relations: v.array(relationSchema),\n});\n\nexport const identifierSchema = v.object({\n schema: v.string(),\n name: v.string(),\n});\n\nexport type Identifier = v.Infer<typeof identifierSchema>;\n\n// A BackfillID is an upstream specific stable identifier for a column\n// that needs backfilling. This id is used to ensure that the schema, table,\n// and column names of a requested backfill still match the original\n// underlying upstream ID.\n//\n// The change-streamer stores these IDs as opaque values while a column is\n// being backfilled, and initiates new change-source streams with the IDs\n// in order to restart backfills that did not complete in previous sessions.\nexport const backfillIDSchema = jsonObjectSchema;\n\nexport type BackfillID = v.Infer<typeof backfillIDSchema>;\n\nexport const createTableSchema = v.object({\n tag: v.literal('create-table'),\n spec: tableSpec,\n\n // This must be set by change source implementations that support\n // table/column backfill.\n //\n // TODO: to simplify the protocol, see if we can make this required\n metadata: tableMetadataSchema.optional(),\n\n // Indicate that columns of the table require backfilling. These columns\n // should be created on the replica but not yet synced the clients.\n //\n // ## State Persistence\n //\n // To obviate the need for change-source implementations to persist state\n // related to backfill progress, the change-source only tracks backfills\n // **for the current session**. In the event that the session is interrupted\n // before columns have been fully backfilled, it is the responsibility of the\n // change-streamer to send {@link BackfillRequest}s when it reconnects.\n //\n // This means that the change-streamer must track and persist:\n // * the backfill IDs of the columns requiring backfilling\n // * the most current table metadata of the associated table(s)\n //\n // The change-streamer then uses this information to send backfill requests\n // when it reconnects.\n backfill: v.record(backfillIDSchema).optional(),\n});\n\nexport const renameTableSchema = v.object({\n tag: v.literal('rename-table'),\n old: identifierSchema,\n new: identifierSchema,\n});\n\nexport const updateTableMetadataSchema = v.object({\n tag: v.literal('update-table-metadata'),\n table: identifierSchema,\n old: tableMetadataSchema,\n new: tableMetadataSchema,\n});\n\nconst columnSchema = v.object({\n name: v.string(),\n spec: columnSpec,\n});\n\nexport const addColumnSchema = v.object({\n tag: v.literal('add-column'),\n table: identifierSchema,\n column: columnSchema,\n\n // This must be set by change source implementations that support\n // table/column backfill.\n //\n // TODO: to simplify the protocol, see if we can make this required\n tableMetadata: tableMetadataSchema.optional(),\n\n // See documentation for the `backfill` field of the `create-table` change.\n backfill: backfillIDSchema.optional(),\n});\n\nexport const updateColumnSchema = v.object({\n tag: v.literal('update-column'),\n table: identifierSchema,\n old: columnSchema,\n new: columnSchema,\n});\n\nexport const dropColumnSchema = v.object({\n tag: v.literal('drop-column'),\n table: identifierSchema,\n column: v.string(),\n});\n\nexport const dropTableSchema = v.object({\n tag: v.literal('drop-table'),\n id: identifierSchema,\n});\n\nexport const createIndexSchema = v.object({\n tag: v.literal('create-index'),\n spec: indexSpec,\n});\n\nexport const dropIndexSchema = v.object({\n tag: v.literal('drop-index'),\n id: identifierSchema,\n});\n\nexport const downloadStatusSchema = v.object({\n rows: v.number(),\n totalRows: v.number(),\n totalBytes: v.number().optional(),\n});\n\nexport type DownloadStatus = v.Infer<typeof downloadStatusSchema>;\n\n// A batch of rows from a single table containing column values\n// to be backfilled.\nexport const backfillSchema = v.object({\n tag: v.literal('backfill'),\n\n relation: newRelationSchema,\n\n // The columns to be backfilled. `rowKey` columns are automatically excluded,\n // which means that this field may be empty.\n columns: v.array(v.string()),\n\n // The watermark at which the backfill data was queried. Note that this\n // generally will be different from the commit watermarks of the main change\n // stream, and in particular, the commit watermark of the backfill change's\n // enclosing transaction.\n watermark: v.string(),\n\n // A batch of row values, each row consisting of the `rowKey`\n // values, followed by the `column` values, in the same order in which\n // the column names appear in their respective fields, e.g.\n //\n // ```\n // [\n // [...rowKeyValues, ...columnValues], // row 1\n // [...rowKeyValues, ...columnValues], // row 2\n // ]\n // ```\n rowValues: v.array(v.array(jsonValueSchema)),\n\n // Optionally includes the progress of the backfill operation,\n // for display purposes.\n status: downloadStatusSchema.optional(),\n});\n\n// Indicates that the backfill for the specified columns have\n// been successfully backfilled and can be published to clients.\nexport const backfillCompletedSchema = v.object({\n tag: v.literal('backfill-completed'),\n\n relation: newRelationSchema,\n\n // The columns to be backfilled. `rowKey` columns are automatically excluded,\n // which means that this field may be empty.\n columns: v.array(v.string()),\n\n // The watermark at which the backfill data was queried. Note that this\n // generally will be different from the commit watermarks of the main change\n // stream, and in particular, the commit watermark of the backfill change's\n // enclosing transaction.\n watermark: v.string(),\n\n // Optionally includes the final status of the backfill operation,\n // for display purposes.\n status: downloadStatusSchema.optional(),\n});\n\nexport type MessageBegin = v.Infer<typeof beginSchema>;\nexport type MessageCommit = v.Infer<typeof commitSchema>;\nexport type MessageRollback = v.Infer<typeof rollbackSchema>;\n\nexport type MessageRelation = v.Infer<typeof relationSchema>;\nexport type MessageInsert = v.Infer<typeof insertSchema>;\nexport type MessageUpdate = v.Infer<typeof updateSchema>;\nexport type MessageDelete = v.Infer<typeof deleteSchema>;\nexport type MessageTruncate = v.Infer<typeof truncateSchema>;\n\nexport type MessageBackfill = v.Infer<typeof backfillSchema>;\n\nexport type TableCreate = v.Infer<typeof createTableSchema>;\nexport type TableRename = v.Infer<typeof renameTableSchema>;\nexport type TableUpdateMetadata = v.Infer<typeof updateTableMetadataSchema>;\nexport type ColumnAdd = v.Infer<typeof addColumnSchema>;\nexport type ColumnUpdate = v.Infer<typeof updateColumnSchema>;\nexport type ColumnDrop = v.Infer<typeof dropColumnSchema>;\nexport type TableDrop = v.Infer<typeof dropTableSchema>;\nexport type IndexCreate = v.Infer<typeof createIndexSchema>;\nexport type IndexDrop = v.Infer<typeof dropIndexSchema>;\nexport type BackfillCompleted = v.Infer<typeof backfillCompletedSchema>;\n\nexport const dataChangeSchema = v.union(\n insertSchema,\n updateSchema,\n deleteSchema,\n truncateSchema,\n backfillSchema,\n);\n\n// Note: keep in sync or the tag tests will fail\nconst dataChangeTags = [\n 'insert',\n 'update',\n 'delete',\n 'truncate',\n 'backfill',\n] as const;\n\nconst dataChangeTagsSchema = v.literalUnion(...dataChangeTags);\n\nexport type DataChange = Satisfies<\n JSONObject, // guarantees serialization over IPC or network\n v.Infer<typeof dataChangeSchema>\n>;\n\nexport type DataChangeTag = v.Infer<typeof dataChangeTagsSchema>;\n\nconst schemaChanges = [\n createTableSchema,\n renameTableSchema,\n updateTableMetadataSchema,\n addColumnSchema,\n updateColumnSchema,\n dropColumnSchema,\n dropTableSchema,\n createIndexSchema,\n dropIndexSchema,\n backfillCompletedSchema,\n] as const;\n\nexport const schemaChangeSchema = v.union(...schemaChanges);\n\nconst schemaChangeTagsSchema = v.literalUnion(...schemaChangeTags);\n\nexport type SchemaChange = Satisfies<\n JSONObject,\n v.Infer<typeof schemaChangeSchema>\n>;\n\nexport type SchemaChangeTag = v.Infer<typeof schemaChangeTagsSchema>;\n\nexport type DataOrSchemaChange = DataChange | SchemaChange;\n\nexport type Change =\n | MessageBegin\n | DataOrSchemaChange\n | MessageCommit\n | MessageRollback;\n\nexport type ChangeTag = Change['tag'];\n\nconst schemaChangeTagSet = new Set<string>(schemaChangeTags);\n\nexport function isSchemaChange(change: Change): change is SchemaChange {\n return schemaChangeTagSet.has(change.tag);\n}\n\nconst dataChangeTagSet = new Set<string>(dataChangeTags);\n\nexport function isDataChange(change: Change): change is DataChange {\n return dataChangeTagSet.has(change.tag);\n}\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as v from '../../../../../../shared/src/valita.ts';
|
|
2
2
|
declare const begin: v.TupleType<[v.Type<"begin">, v.ObjectType<{
|
|
3
3
|
tag: v.Type<"begin">;
|
|
4
|
-
json: v.Optional<"
|
|
4
|
+
json: v.Optional<"s" | "p">;
|
|
5
5
|
skipAck: v.Optional<boolean>;
|
|
6
6
|
}, undefined>, v.ObjectType<{
|
|
7
7
|
commitWatermark: v.Type<string>;
|
|
@@ -222,6 +222,7 @@ declare const data: v.TupleType<[v.Type<"data">, v.UnionType<[v.UnionType<[v.Obj
|
|
|
222
222
|
}, undefined>]>]>]>;
|
|
223
223
|
declare const commit: v.TupleType<[v.Type<"commit">, v.ObjectType<{
|
|
224
224
|
tag: v.Type<"commit">;
|
|
225
|
+
commitTimeMs: v.Optional<number>;
|
|
225
226
|
}, undefined>, v.ObjectType<{
|
|
226
227
|
watermark: v.Type<string>;
|
|
227
228
|
}, undefined>]>;
|
|
@@ -234,7 +235,7 @@ export type Commit = v.Infer<typeof commit>;
|
|
|
234
235
|
export type Rollback = v.Infer<typeof rollback>;
|
|
235
236
|
export declare const changeStreamDataSchema: v.UnionType<[v.TupleType<[v.Type<"begin">, v.ObjectType<{
|
|
236
237
|
tag: v.Type<"begin">;
|
|
237
|
-
json: v.Optional<"
|
|
238
|
+
json: v.Optional<"s" | "p">;
|
|
238
239
|
skipAck: v.Optional<boolean>;
|
|
239
240
|
}, undefined>, v.ObjectType<{
|
|
240
241
|
commitWatermark: v.Type<string>;
|
|
@@ -453,6 +454,7 @@ export declare const changeStreamDataSchema: v.UnionType<[v.TupleType<[v.Type<"b
|
|
|
453
454
|
}>;
|
|
454
455
|
}, undefined>]>]>]>, v.TupleType<[v.Type<"commit">, v.ObjectType<{
|
|
455
456
|
tag: v.Type<"commit">;
|
|
457
|
+
commitTimeMs: v.Optional<number>;
|
|
456
458
|
}, undefined>, v.ObjectType<{
|
|
457
459
|
watermark: v.Type<string>;
|
|
458
460
|
}, undefined>]>, v.TupleType<[v.Type<"rollback">, v.ObjectType<{
|
|
@@ -468,7 +470,7 @@ export type ChangeStreamControl = v.Infer<typeof changeStreamControlSchema>;
|
|
|
468
470
|
/** Downstream messages consist of data plane and control plane messages. */
|
|
469
471
|
export declare const changeStreamMessageSchema: v.UnionType<[v.UnionType<[v.TupleType<[v.Type<"begin">, v.ObjectType<{
|
|
470
472
|
tag: v.Type<"begin">;
|
|
471
|
-
json: v.Optional<"
|
|
473
|
+
json: v.Optional<"s" | "p">;
|
|
472
474
|
skipAck: v.Optional<boolean>;
|
|
473
475
|
}, undefined>, v.ObjectType<{
|
|
474
476
|
commitWatermark: v.Type<string>;
|
|
@@ -687,6 +689,7 @@ export declare const changeStreamMessageSchema: v.UnionType<[v.UnionType<[v.Tupl
|
|
|
687
689
|
}>;
|
|
688
690
|
}, undefined>]>]>]>, v.TupleType<[v.Type<"commit">, v.ObjectType<{
|
|
689
691
|
tag: v.Type<"commit">;
|
|
692
|
+
commitTimeMs: v.Optional<number>;
|
|
690
693
|
}, undefined>, v.ObjectType<{
|
|
691
694
|
watermark: v.Type<string>;
|
|
692
695
|
}, undefined>]>, v.TupleType<[v.Type<"rollback">, v.ObjectType<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"downstream.d.ts","sourceRoot":"","sources":["../../../../../../../../zero-cache/src/services/change-source/protocol/current/downstream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,wCAAwC,CAAC;AAW5D,QAAA,MAAM,KAAK;;;;;;eAIT,CAAC;AACH,QAAA,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mBAGR,CAAC;AACH,QAAA,MAAM,MAAM
|
|
1
|
+
{"version":3,"file":"downstream.d.ts","sourceRoot":"","sources":["../../../../../../../../zero-cache/src/services/change-source/protocol/current/downstream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,wCAAwC,CAAC;AAW5D,QAAA,MAAM,KAAK;;;;;;eAIT,CAAC;AACH,QAAA,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mBAGR,CAAC;AACH,QAAA,MAAM,MAAM;;;;;eAIV,CAAC;AACH,QAAA,MAAM,QAAQ;;eAAmD,CAAC;AAElE,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,KAAK,CAAC,CAAC;AAC1C,MAAM,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;AACxC,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,MAAM,CAAC,CAAC;AAC5C,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,QAAQ,CAAC,CAAC;AAEhD,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAAyC,CAAC;AAC7E,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE,eAAO,MAAM,yBAAyB;;;;eAGpC,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAE5E,4EAA4E;AAC5E,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAIrC,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Kept in a module that is not re-exported by the public change protocol so
|
|
3
|
+
* internal consumers can share the tag list without expanding the public API.
|
|
4
|
+
*/
|
|
5
|
+
export declare const schemaChangeTags: readonly ["create-table", "rename-table", "update-table-metadata", "add-column", "update-column", "drop-column", "drop-table", "create-index", "drop-index", "backfill-completed"];
|
|
6
|
+
//# sourceMappingURL=schema-change-tags.d.ts.map
|
package/out/zero-cache/src/services/change-source/protocol/current/schema-change-tags.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-change-tags.d.ts","sourceRoot":"","sources":["../../../../../../../../zero-cache/src/services/change-source/protocol/current/schema-change-tags.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,gBAAgB,oLAWnB,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
//#region ../zero-cache/src/services/change-source/protocol/current/schema-change-tags.ts
|
|
2
|
+
/**
|
|
3
|
+
* Kept in a module that is not re-exported by the public change protocol so
|
|
4
|
+
* internal consumers can share the tag list without expanding the public API.
|
|
5
|
+
*/
|
|
6
|
+
var schemaChangeTags = [
|
|
7
|
+
"create-table",
|
|
8
|
+
"rename-table",
|
|
9
|
+
"update-table-metadata",
|
|
10
|
+
"add-column",
|
|
11
|
+
"update-column",
|
|
12
|
+
"drop-column",
|
|
13
|
+
"drop-table",
|
|
14
|
+
"create-index",
|
|
15
|
+
"drop-index",
|
|
16
|
+
"backfill-completed"
|
|
17
|
+
];
|
|
18
|
+
//#endregion
|
|
19
|
+
export { schemaChangeTags };
|
|
20
|
+
|
|
21
|
+
//# sourceMappingURL=schema-change-tags.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-change-tags.js","names":[],"sources":["../../../../../../../../zero-cache/src/services/change-source/protocol/current/schema-change-tags.ts"],"sourcesContent":["/**\n * Kept in a module that is not re-exported by the public change protocol so\n * internal consumers can share the tag list without expanding the public API.\n */\nexport const schemaChangeTags = [\n 'create-table',\n 'rename-table',\n 'update-table-metadata',\n 'add-column',\n 'update-column',\n 'drop-column',\n 'drop-table',\n 'create-index',\n 'drop-index',\n 'backfill-completed',\n] as const;\n"],"mappings":";;;;;AAIA,IAAa,mBAAmB;CAC9B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF"}
|
|
@@ -47,6 +47,7 @@ export declare const upstreamStatusMessageSchema: v.TupleType<[v.Type<"status">,
|
|
|
47
47
|
}>;
|
|
48
48
|
}, undefined>, v.ObjectType<{
|
|
49
49
|
tag: v.Type<"commit">;
|
|
50
|
+
commitTimeMs: v.Optional<number>;
|
|
50
51
|
}, undefined>]>, v.ObjectType<{
|
|
51
52
|
watermark: v.Type<string>;
|
|
52
53
|
}, undefined>]>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../../../../../../zero-cache/src/services/change-source/protocol/current/status.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,wCAAwC,CAAC;AAI5D;;;;GAIG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;aAQjC,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE,eAAO,MAAM,6BAA6B;;;;;;;;;;;;eAIxC,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../../../../../../zero-cache/src/services/change-source/protocol/current/status.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,wCAAwC,CAAC;AAI5D;;;;GAIG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;aAQjC,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE,eAAO,MAAM,6BAA6B;;;;;;;;;;;;eAIxC,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;eAItC,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAC3C,OAAO,6BAA6B,CACrC,CAAC;AACF,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC"}
|
|
@@ -12,6 +12,7 @@ export declare const changeSourceUpstreamSchema: v.TupleType<[v.Type<"status">,
|
|
|
12
12
|
}>;
|
|
13
13
|
}, undefined>, v.ObjectType<{
|
|
14
14
|
tag: v.Type<"commit">;
|
|
15
|
+
commitTimeMs: v.Optional<number>;
|
|
15
16
|
}, undefined>]>, v.ObjectType<{
|
|
16
17
|
watermark: v.Type<string>;
|
|
17
18
|
}, undefined>]>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upstream.d.ts","sourceRoot":"","sources":["../../../../../../../../zero-cache/src/services/change-source/protocol/current/upstream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,wCAAwC,CAAC;AAQ5D,sEAAsE;AACtE,eAAO,MAAM,0BAA0B
|
|
1
|
+
{"version":3,"file":"upstream.d.ts","sourceRoot":"","sources":["../../../../../../../../zero-cache/src/services/change-source/protocol/current/upstream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,wCAAwC,CAAC;AAQ5D,sEAAsE;AACtE,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;eAA8B,CAAC;AACtE,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAE9E;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;;;;aAOhC,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC"}
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
import type { LogContext } from '@rocicorp/logger';
|
|
2
2
|
import type { NormalizedZeroConfig } from '../../config/normalize.ts';
|
|
3
|
-
import type {
|
|
3
|
+
import type { ProcessManager } from '../life-cycle.ts';
|
|
4
|
+
import { BackupMonitor } from './backup-monitor.ts';
|
|
4
5
|
import type { ChangeStreamerService } from './change-streamer.ts';
|
|
5
|
-
import { type BackupStateVerifier } from './litestream3-
|
|
6
|
-
import { type VfsBackupWatermarkSource } from './vfs-backup-monitor.ts';
|
|
6
|
+
import { type BackupStateVerifier } from './litestream3-prometheus-poller.ts';
|
|
7
7
|
export type BackupCleanupMonitorFactoryOptions = {
|
|
8
8
|
lc: LogContext;
|
|
9
9
|
config: NormalizedZeroConfig;
|
|
10
|
+
processes: ProcessManager;
|
|
10
11
|
replicaFile: string;
|
|
11
12
|
changeStreamer: ChangeStreamerService;
|
|
12
|
-
initialCleanupDelayMs: number;
|
|
13
13
|
verifyBackupState?: BackupStateVerifier | undefined;
|
|
14
|
-
vfsBackupWatermarkSource?: VfsBackupWatermarkSource | undefined;
|
|
15
14
|
env?: NodeJS.ProcessEnv | undefined;
|
|
16
15
|
};
|
|
17
|
-
export declare function createBackupCleanupMonitor({ lc, config, replicaFile, changeStreamer,
|
|
16
|
+
export declare function createBackupCleanupMonitor({ lc, config, processes, replicaFile, changeStreamer, verifyBackupState, env, }: BackupCleanupMonitorFactoryOptions): BackupMonitor;
|
|
18
17
|
//# sourceMappingURL=backup-cleanup-monitor-factory.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"backup-cleanup-monitor-factory.d.ts","sourceRoot":"","sources":["../../../../../../zero-cache/src/services/change-streamer/backup-cleanup-monitor-factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EAAC,oBAAoB,EAAC,MAAM,2BAA2B,CAAC;AAKpE,OAAO,KAAK,EAAC,
|
|
1
|
+
{"version":3,"file":"backup-cleanup-monitor-factory.d.ts","sourceRoot":"","sources":["../../../../../../zero-cache/src/services/change-streamer/backup-cleanup-monitor-factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EAAC,oBAAoB,EAAC,MAAM,2BAA2B,CAAC;AAKpE,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAC;AAMrD,OAAO,EAAyB,aAAa,EAAC,MAAM,qBAAqB,CAAC;AAC1E,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,sBAAsB,CAAC;AAChE,OAAO,EACL,KAAK,mBAAmB,EAEzB,MAAM,oCAAoC,CAAC;AAG5C,MAAM,MAAM,kCAAkC,GAAG;IAC/C,EAAE,EAAE,UAAU,CAAC;IACf,MAAM,EAAE,oBAAoB,CAAC;IAC7B,SAAS,EAAE,cAAc,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,qBAAqB,CAAC;IACtC,iBAAiB,CAAC,EAAE,mBAAmB,GAAG,SAAS,CAAC;IACpD,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,GAAG,SAAS,CAAC;CACrC,CAAC;AAEF,wBAAgB,0BAA0B,CAAC,EACzC,EAAE,EACF,MAAM,EACN,SAAS,EACT,WAAW,EACX,cAAc,EACd,iBAAiB,EACjB,GAAiB,GAClB,EAAE,kCAAkC,GAAG,aAAa,CAgDpD"}
|