@rocicorp/zero 1.10.0-canary.0 → 1.10.0-canary.10
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/shared/src/promise-race.d.ts +14 -0
- package/out/shared/src/promise-race.d.ts.map +1 -1
- package/out/shared/src/promise-race.js +32 -1
- package/out/shared/src/promise-race.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/auth/write-authorizer.d.ts.map +1 -1
- package/out/zero-cache/src/auth/write-authorizer.js +8 -1
- package/out/zero-cache/src/auth/write-authorizer.js.map +1 -1
- package/out/zero-cache/src/config/normalize.d.ts +6 -0
- package/out/zero-cache/src/config/normalize.d.ts.map +1 -1
- package/out/zero-cache/src/config/normalize.js +24 -2
- package/out/zero-cache/src/config/normalize.js.map +1 -1
- package/out/zero-cache/src/config/zero-config.d.ts +65 -4
- package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
- package/out/zero-cache/src/config/zero-config.js +202 -35
- 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 +10 -5
- 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/db/transaction-pool.d.ts +5 -15
- package/out/zero-cache/src/db/transaction-pool.d.ts.map +1 -1
- package/out/zero-cache/src/db/transaction-pool.js +8 -72
- package/out/zero-cache/src/db/transaction-pool.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/change-streamer.d.ts.map +1 -1
- package/out/zero-cache/src/server/change-streamer.js +105 -34
- 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 +8 -18
- 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 +3 -2
- 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 +0 -1
- package/out/zero-cache/src/server/worker-urls.d.ts.map +1 -1
- package/out/zero-cache/src/server/worker-urls.js +1 -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 +81 -3
- 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.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/backfill-stream.js +22 -11
- 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 +90 -31
- package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/decommission.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/decommission.js +20 -11
- package/out/zero-cache/src/services/change-source/pg/decommission.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 +61 -76
- 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 +65 -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 +101 -10
- 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 +27 -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 +41 -8
- 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 +3 -7
- 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 +26 -10
- 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 +71 -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-compare-digest.d.ts +34 -0
- package/out/zero-cache/src/services/change-streamer/change-log-compare-digest.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/change-log-compare-digest.js +67 -0
- package/out/zero-cache/src/services/change-streamer/change-log-compare-digest.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 +5 -8
- 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 +20 -19
- 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 +90 -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 +456 -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 +50 -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 +42 -12
- 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} +68 -176
- 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/shard-sampling.d.ts +11 -0
- package/out/zero-cache/src/services/change-streamer/shard-sampling.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/shard-sampling.js +19 -0
- package/out/zero-cache/src/services/change-streamer/shard-sampling.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/snapshot-reservations.d.ts +24 -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 +119 -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 +99 -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 +344 -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-comparator.d.ts +83 -0
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-comparator.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-comparator.js +417 -0
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-comparator.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-read-router.d.ts +73 -0
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-read-router.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-read-router.js +157 -0
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-read-router.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 +164 -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 +85 -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 +286 -141
- 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/change-streamer/vfs-watermark-poller.d.ts +29 -0
- package/out/zero-cache/src/services/change-streamer/vfs-watermark-poller.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/vfs-watermark-poller.js +154 -0
- package/out/zero-cache/src/services/change-streamer/vfs-watermark-poller.js.map +1 -0
- package/out/zero-cache/src/services/http-service.d.ts +1 -0
- package/out/zero-cache/src/services/http-service.d.ts.map +1 -1
- package/out/zero-cache/src/services/http-service.js +7 -3
- package/out/zero-cache/src/services/http-service.js.map +1 -1
- 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 +115 -152
- 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 +5 -4
- package/out/zero-cache/src/services/litestream/metrics.d.ts.map +1 -1
- package/out/zero-cache/src/services/litestream/metrics.js +10 -10
- package/out/zero-cache/src/services/litestream/metrics.js.map +1 -1
- package/out/zero-cache/src/services/mutagen/mutagen.d.ts.map +1 -1
- package/out/zero-cache/src/services/mutagen/mutagen.js +5 -2
- 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 +368 -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 +491 -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 +132 -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 +415 -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/client-handler.d.ts +3 -2
- package/out/zero-cache/src/services/view-syncer/client-handler.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/client-handler.js +25 -17
- package/out/zero-cache/src/services/view-syncer/client-handler.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr-store.js +14 -1
- package/out/zero-cache/src/services/view-syncer/cvr-store.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 +14 -4
- 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 +70 -8
- package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
- package/out/zero-cache/src/types/downstream.d.ts +11 -0
- package/out/zero-cache/src/types/downstream.d.ts.map +1 -0
- package/out/zero-cache/src/types/pg.d.ts.map +1 -1
- package/out/zero-cache/src/types/pg.js +14 -4
- package/out/zero-cache/src/types/pg.js.map +1 -1
- package/out/zero-cache/src/types/poke-chunk.d.ts +18 -0
- package/out/zero-cache/src/types/poke-chunk.d.ts.map +1 -0
- package/out/zero-cache/src/types/poke-chunk.js +57 -0
- package/out/zero-cache/src/types/poke-chunk.js.map +1 -0
- 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 -28
- package/out/zero-cache/src/types/processes.js.map +1 -1
- package/out/zero-cache/src/types/streams.d.ts +16 -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 +2 -0
- package/out/zero-cache/src/types/subscription.d.ts.map +1 -1
- package/out/zero-cache/src/types/subscription.js +6 -0
- package/out/zero-cache/src/types/subscription.js.map +1 -1
- package/out/zero-cache/src/workers/connection.d.ts +23 -4
- package/out/zero-cache/src/workers/connection.d.ts.map +1 -1
- package/out/zero-cache/src/workers/connection.js +130 -10
- 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-poke-handler.d.ts +7 -2
- package/out/zero-client/src/client/zero-poke-handler.d.ts.map +1 -1
- package/out/zero-client/src/client/zero-poke-handler.js +52 -2
- package/out/zero-client/src/client/zero-poke-handler.js.map +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 +194 -107
- package/out/zero-client/src/client/zero.js.map +1 -1
- package/out/zero-protocol/src/down.d.ts +1 -1
- package/out/zero-protocol/src/poke.d.ts +89 -7
- package/out/zero-protocol/src/poke.d.ts.map +1 -1
- package/out/zero-protocol/src/poke.js +16 -8
- package/out/zero-protocol/src/poke.js.map +1 -1
- package/out/zero-protocol/src/protocol-version.d.ts +12 -7
- package/out/zero-protocol/src/protocol-version.d.ts.map +1 -1
- package/out/zero-protocol/src/protocol-version.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/ivm/memory-source.d.ts +10 -2
- package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
- package/out/zql/src/ivm/memory-source.js +14 -6
- package/out/zql/src/ivm/memory-source.js.map +1 -1
- package/out/zql/src/ivm/stream.d.ts +0 -1
- package/out/zql/src/ivm/stream.d.ts.map +1 -1
- package/out/zql/src/ivm/stream.js +1 -7
- package/out/zql/src/ivm/stream.js.map +1 -1
- package/out/zql/src/ivm/union-fan-in.d.ts +1 -1
- package/out/zql/src/ivm/union-fan-in.d.ts.map +1 -1
- package/out/zql/src/ivm/union-fan-in.js +11 -2
- package/out/zql/src/ivm/union-fan-in.js.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.d.ts.map +1 -1
- package/out/zqlite/src/table-source.js +4 -4
- package/out/zqlite/src/table-source.js.map +1 -1
- 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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"change-log-cookies.js","names":["#upsertMetadata","#upsertBackfill","#renameMetadataTable","#renameBackfillTable","#deleteMetadataTable","#deleteBackfillTable","#renameBackfillColumn","#deleteBackfillColumn","#run"],"sources":["../../../../../../zero-cache/src/services/replicator/change-log-cookies.ts"],"sourcesContent":["/**\n * The change log's *second* job.\n *\n * A change log is a buffer **and** a cookie jar. The buffer catches a\n * reconnecting subscriber up to the head; the cookie jar holds the backfill\n * progress state that the change-streamer hands the change-source on every\n * `startStream`, so that the change source never has to persist backfill state\n * upstream. See `change-log-db.ts` for the buffer.\n *\n * There are two cookies, mirroring the two `cdc` tables the Postgres change log\n * has always carried (`change-streamer/schema/tables.ts`):\n *\n * - **table metadata**, the most current {@link TableMetadata} of a table, which\n * a {@link BackfillRequest} has to carry; and\n * - **backfilling columns**, the opaque {@link BackfillID} of every column whose\n * backfill has not completed.\n *\n * Both are a *fold over the change stream*: the cookie set is only meaningful\n * paired with the watermark it was folded up to. {@link cookieOps} is that fold,\n * expressed transport-free so that the Postgres change log and the SQLite change\n * log cannot drift from each other — they must agree on all eight transitions\n * forever, and the failure mode if they disagree is a backfill that is silently\n * never re-requested. The two interpreters are {@link ChangeLogCookieWriter}\n * here and `Storer.#trackBackfillMetadata()` in\n * `change-streamer/storer.ts`.\n *\n * The tables live in the change-log database rather than in the replica: the\n * replicator is a subscriber *downstream* of the change-streamer's write loop,\n * so its state version trails the log's head, and pairing its cookies with the\n * log's resume watermark would lose every backfill that completed in between.\n * The replica's own copies (`_zero.tableMetadata`, `_zero.column_metadata`) are\n * the *seed* source; these are the *working* set.\n */\n\nimport {unreachable} from '../../../../shared/src/asserts.ts';\nimport {BigIntJSON} from '../../../../shared/src/bigint-json.ts';\nimport * as v from '../../../../shared/src/valita.ts';\nimport type {Database, Statement} from '../../../../zqlite/src/db.ts';\nimport type {\n BackfillID,\n Identifier,\n SchemaChange,\n TableMetadata,\n} from '../change-source/protocol/current/data.ts';\nimport {\n backfillRequestSchema,\n type BackfillRequest,\n} from '../change-source/protocol/current/upstream.ts';\n\nexport const CHANGE_LOG_TABLE_METADATA_TABLE = '_zero.changeLogTableMetadata';\nexport const CHANGE_LOG_BACKFILLING_TABLE = '_zero.changeLogBackfilling';\n\n// The names follow the file's existing convention, beside\n// \"_zero.changeLogStream\" and \"_zero.changeLogMeta\".\n//\n// `metadata` and `backfill` hold the JSON that the `cdc` tables hold as JSONB.\n// SQLite has no JSONB, and nothing here queries into the documents: they are\n// stored to be handed back to the change source verbatim.\nexport const CREATE_CHANGE_LOG_COOKIE_SCHEMA = /*sql*/ `\n CREATE TABLE \"${CHANGE_LOG_TABLE_METADATA_TABLE}\" (\n \"schema\" TEXT NOT NULL,\n \"table\" TEXT NOT NULL,\n \"metadata\" TEXT NOT NULL,\n PRIMARY KEY (\"schema\", \"table\")\n );\n\n CREATE TABLE \"${CHANGE_LOG_BACKFILLING_TABLE}\" (\n \"schema\" TEXT NOT NULL,\n \"table\" TEXT NOT NULL,\n \"column\" TEXT NOT NULL,\n \"backfill\" TEXT NOT NULL,\n PRIMARY KEY (\"schema\", \"table\", \"column\")\n );\n`;\n\nexport const DROP_CHANGE_LOG_COOKIE_TABLES = /*sql*/ `\n DROP TABLE IF EXISTS \"${CHANGE_LOG_TABLE_METADATA_TABLE}\";\n DROP TABLE IF EXISTS \"${CHANGE_LOG_BACKFILLING_TABLE}\";\n`;\n\nexport type TableMetadataCookie = {\n readonly schema: string;\n readonly table: string;\n readonly metadata: TableMetadata;\n};\n\nexport type BackfillCookie = {\n readonly schema: string;\n readonly table: string;\n readonly column: string;\n readonly backfill: BackfillID;\n};\n\n/**\n * The whole cookie set, as of the log's head. Both lists are ordered by their\n * primary key so that two stores' sets can be compared directly.\n */\nexport type CookieSet = {\n readonly tableMetadata: readonly TableMetadataCookie[];\n readonly backfilling: readonly BackfillCookie[];\n};\n\nexport const EMPTY_COOKIE_SET: CookieSet = {\n tableMetadata: [],\n backfilling: [],\n};\n\n/**\n * A transport-free description of a cookie mutation. This is the whole of what\n * a {@link SchemaChange} means to the cookie jar; everything else about the\n * change belongs to the buffer.\n */\nexport type CookieOp =\n | {op: 'upsert-metadata'; table: Identifier; metadata: TableMetadata}\n | {\n op: 'upsert-backfill';\n table: Identifier;\n column: string;\n backfill: BackfillID;\n }\n | {op: 'rename-table'; old: Identifier; new: Identifier}\n | {op: 'drop-table'; table: Identifier}\n | {op: 'rename-column'; table: Identifier; old: string; new: string}\n | {op: 'drop-column'; table: Identifier; column: string}\n | {op: 'complete-backfill'; table: Identifier; columns: readonly string[]};\n\nexport type CookieOpTag = CookieOp['op'];\n\n/**\n * The fold, and the only place either store decides what a schema change means\n * for the cookie set. Both interpreters are mechanical translations of what this\n * returns, in the order it returns them.\n *\n * Changes that carry no cookie state — index changes, and the `create-table` /\n * `add-column` variants whose optional `metadata` and `backfill` fields are\n * absent — produce no ops.\n */\nexport function cookieOps(change: SchemaChange): CookieOp[] {\n switch (change.tag) {\n case 'update-table-metadata':\n return [\n {op: 'upsert-metadata', table: change.table, metadata: change.new},\n ];\n\n case 'create-table': {\n const {spec, metadata, backfill} = change;\n const table = {schema: spec.schema, name: spec.name};\n const ops: CookieOp[] = [];\n if (metadata) {\n ops.push({op: 'upsert-metadata', table, metadata});\n }\n if (backfill) {\n for (const [column, id] of Object.entries(backfill)) {\n ops.push({op: 'upsert-backfill', table, column, backfill: id});\n }\n }\n return ops;\n }\n\n case 'rename-table':\n return [{op: 'rename-table', old: change.old, new: change.new}];\n\n case 'drop-table':\n return [{op: 'drop-table', table: change.id}];\n\n case 'add-column': {\n const {table, tableMetadata, column, backfill} = change;\n const ops: CookieOp[] = [];\n if (tableMetadata) {\n ops.push({op: 'upsert-metadata', table, metadata: tableMetadata});\n }\n if (backfill) {\n ops.push({\n op: 'upsert-backfill',\n table,\n column: column.name,\n backfill,\n });\n }\n return ops;\n }\n\n case 'update-column': {\n // Only a rename moves the cookie; the rest of a column update does not\n // affect whether or how it is being backfilled.\n const {table, old, new: updated} = change;\n return old.name === updated.name\n ? []\n : [{op: 'rename-column', table, old: old.name, new: updated.name}];\n }\n\n case 'drop-column':\n return [{op: 'drop-column', table: change.table, column: change.column}];\n\n case 'backfill-completed': {\n const {relation, columns} = change;\n // The rowKey columns are excluded from `columns` but are backfilled with\n // them, so both are cleared.\n const cleared = [...relation.rowKey.columns, ...columns];\n return cleared.length === 0\n ? []\n : [\n {\n op: 'complete-backfill',\n table: {schema: relation.schema, name: relation.name},\n columns: cleared,\n },\n ];\n }\n\n case 'create-index':\n case 'drop-index':\n return [];\n\n default:\n // Unreachable: `isSchemaChange()` gates on the same tag set this switch\n // covers. It is exhaustive so that a new schema-change tag is a compile\n // error here rather than a silently dropped backfill.\n unreachable(change);\n }\n}\n\n/**\n * The SQLite interpreter of {@link cookieOps}, over prepared statements on the\n * change-log database.\n *\n * The statements run inside the log's transaction, in stream order, at the point\n * the schema change is appended (see `ChangeLogStreamWriter`). That is what\n * makes the cookie set atomic with the head — a crash cannot leave cookies ahead\n * of or behind the rows they were folded from — and what makes an aborted\n * transaction discard its cookies with its rows, for free.\n *\n * Statements are prepared against the tables as they exist now, so an instance\n * does not survive a reconcile that drops and recreates them.\n */\nexport class ChangeLogCookieWriter {\n readonly #upsertMetadata: Statement;\n readonly #upsertBackfill: Statement;\n readonly #renameMetadataTable: Statement;\n readonly #renameBackfillTable: Statement;\n readonly #deleteMetadataTable: Statement;\n readonly #deleteBackfillTable: Statement;\n readonly #renameBackfillColumn: Statement;\n readonly #deleteBackfillColumn: Statement;\n\n constructor(db: Database) {\n this.#upsertMetadata = db.prepare(/*sql*/ `\n INSERT INTO \"${CHANGE_LOG_TABLE_METADATA_TABLE}\"\n (\"schema\", \"table\", \"metadata\") VALUES (?, ?, ?)\n ON CONFLICT (\"schema\", \"table\")\n DO UPDATE SET \"metadata\" = excluded.\"metadata\"\n `);\n this.#upsertBackfill = db.prepare(/*sql*/ `\n INSERT INTO \"${CHANGE_LOG_BACKFILLING_TABLE}\"\n (\"schema\", \"table\", \"column\", \"backfill\") VALUES (?, ?, ?, ?)\n ON CONFLICT (\"schema\", \"table\", \"column\")\n DO UPDATE SET \"backfill\" = excluded.\"backfill\"\n `);\n this.#renameMetadataTable = db.prepare(/*sql*/ `\n UPDATE \"${CHANGE_LOG_TABLE_METADATA_TABLE}\"\n SET \"schema\" = ?, \"table\" = ? WHERE \"schema\" = ? AND \"table\" = ?\n `);\n this.#renameBackfillTable = db.prepare(/*sql*/ `\n UPDATE \"${CHANGE_LOG_BACKFILLING_TABLE}\"\n SET \"schema\" = ?, \"table\" = ? WHERE \"schema\" = ? AND \"table\" = ?\n `);\n this.#deleteMetadataTable = db.prepare(/*sql*/ `\n DELETE FROM \"${CHANGE_LOG_TABLE_METADATA_TABLE}\"\n WHERE \"schema\" = ? AND \"table\" = ?\n `);\n this.#deleteBackfillTable = db.prepare(/*sql*/ `\n DELETE FROM \"${CHANGE_LOG_BACKFILLING_TABLE}\"\n WHERE \"schema\" = ? AND \"table\" = ?\n `);\n this.#renameBackfillColumn = db.prepare(/*sql*/ `\n UPDATE \"${CHANGE_LOG_BACKFILLING_TABLE}\" SET \"column\" = ?\n WHERE \"schema\" = ? AND \"table\" = ? AND \"column\" = ?\n `);\n this.#deleteBackfillColumn = db.prepare(/*sql*/ `\n DELETE FROM \"${CHANGE_LOG_BACKFILLING_TABLE}\"\n WHERE \"schema\" = ? AND \"table\" = ? AND \"column\" = ?\n `);\n }\n\n /** Applies the change's cookie ops, returning the ops that were applied. */\n apply(change: SchemaChange): CookieOp[] {\n const ops = cookieOps(change);\n for (const op of ops) {\n this.#run(op);\n }\n return ops;\n }\n\n #run(op: CookieOp): void {\n switch (op.op) {\n case 'upsert-metadata':\n this.#upsertMetadata.run(\n op.table.schema,\n op.table.name,\n BigIntJSON.stringify(op.metadata),\n );\n break;\n\n case 'upsert-backfill':\n this.#upsertBackfill.run(\n op.table.schema,\n op.table.name,\n op.column,\n BigIntJSON.stringify(op.backfill),\n );\n break;\n\n case 'rename-table':\n this.#renameMetadataTable.run(\n op.new.schema,\n op.new.name,\n op.old.schema,\n op.old.name,\n );\n this.#renameBackfillTable.run(\n op.new.schema,\n op.new.name,\n op.old.schema,\n op.old.name,\n );\n break;\n\n case 'drop-table':\n this.#deleteMetadataTable.run(op.table.schema, op.table.name);\n this.#deleteBackfillTable.run(op.table.schema, op.table.name);\n break;\n\n case 'rename-column':\n this.#renameBackfillColumn.run(\n op.new,\n op.table.schema,\n op.table.name,\n op.old,\n );\n break;\n\n case 'drop-column':\n this.#deleteBackfillColumn.run(\n op.table.schema,\n op.table.name,\n op.column,\n );\n break;\n\n case 'complete-backfill':\n // A per-column delete rather than an `IN` list, which cannot be a\n // single prepared statement across arities. The columns of one\n // completed backfill are few, and this runs only on schema changes.\n for (const column of op.columns) {\n this.#deleteBackfillColumn.run(\n op.table.schema,\n op.table.name,\n column,\n );\n }\n break;\n\n default:\n unreachable(op);\n }\n }\n}\n\nconst tableKey = (schema: string, table: string) =>\n JSON.stringify([schema, table]);\n\nconst columnKey = (schema: string, table: string, column: string) =>\n JSON.stringify([schema, table, column]);\n\nconst cmp = (a: string, b: string) => (a < b ? -1 : a > b ? 1 : 0);\n\n/**\n * The in-memory interpreter of {@link cookieOps}: the third one, and the only\n * one that is not a store.\n *\n * A replica-derived cookie set is a snapshot at the replica's state version,\n * which trails the change log's head, so it cannot be compared with a\n * Postgres-derived set directly. This carries it forward over the schema changes\n * the log holds in between, which turns \"the two stores disagree, but they are\n * also at different positions\" into an exact equality — and makes a\n * disagreement between any two of the three interpreters visible as an\n * inequality that neither store would have noticed on its own.\n *\n * `changes` must be the log's schema changes over `(from, to]` in stream order.\n * Anything else produces a set that belongs to no watermark.\n */\nexport function foldCookies(\n cookies: CookieSet,\n changes: Iterable<SchemaChange>,\n): CookieSet {\n const metadata = new Map<string, TableMetadataCookie>(\n cookies.tableMetadata.map(c => [tableKey(c.schema, c.table), c]),\n );\n const backfilling = new Map<string, BackfillCookie>(\n cookies.backfilling.map(c => [columnKey(c.schema, c.table, c.column), c]),\n );\n const dropColumn = ({schema, name}: Identifier, column: string) =>\n backfilling.delete(columnKey(schema, name, column));\n\n for (const change of changes) {\n for (const op of cookieOps(change)) {\n switch (op.op) {\n case 'upsert-metadata':\n metadata.set(tableKey(op.table.schema, op.table.name), {\n schema: op.table.schema,\n table: op.table.name,\n metadata: op.metadata,\n });\n break;\n\n case 'upsert-backfill':\n backfilling.set(\n columnKey(op.table.schema, op.table.name, op.column),\n {\n schema: op.table.schema,\n table: op.table.name,\n column: op.column,\n backfill: op.backfill,\n },\n );\n break;\n\n case 'rename-table': {\n const {old, new: renamed} = op;\n const moved = metadata.get(tableKey(old.schema, old.name));\n if (moved) {\n metadata.delete(tableKey(old.schema, old.name));\n metadata.set(tableKey(renamed.schema, renamed.name), {\n ...moved,\n schema: renamed.schema,\n table: renamed.name,\n });\n }\n // Snapshotted before mutating, since the rename both deletes and\n // inserts into the map being scanned.\n for (const [key, cookie] of [...backfilling]) {\n if (cookie.schema === old.schema && cookie.table === old.name) {\n backfilling.delete(key);\n backfilling.set(\n columnKey(renamed.schema, renamed.name, cookie.column),\n {...cookie, schema: renamed.schema, table: renamed.name},\n );\n }\n }\n break;\n }\n\n case 'drop-table': {\n const {schema, name} = op.table;\n metadata.delete(tableKey(schema, name));\n for (const [key, cookie] of [...backfilling]) {\n if (cookie.schema === schema && cookie.table === name) {\n backfilling.delete(key);\n }\n }\n break;\n }\n\n case 'rename-column': {\n const {schema, name} = op.table;\n const moved = backfilling.get(columnKey(schema, name, op.old));\n if (moved) {\n backfilling.delete(columnKey(schema, name, op.old));\n backfilling.set(columnKey(schema, name, op.new), {\n ...moved,\n column: op.new,\n });\n }\n break;\n }\n\n case 'drop-column':\n dropColumn(op.table, op.column);\n break;\n\n case 'complete-backfill':\n for (const column of op.columns) {\n dropColumn(op.table, column);\n }\n break;\n\n default:\n unreachable(op);\n }\n }\n }\n\n return {\n tableMetadata: [...metadata.values()].toSorted(\n (a, b) => cmp(a.schema, b.schema) || cmp(a.table, b.table),\n ),\n backfilling: [...backfilling.values()].toSorted(\n (a, b) =>\n cmp(a.schema, b.schema) ||\n cmp(a.table, b.table) ||\n cmp(a.column, b.column),\n ),\n };\n}\n\nconst backfillRequestsSchema = v.array(backfillRequestSchema);\n\n/**\n * Returns one {@link BackfillRequest} for each table with an active backfill.\n * Each request contains the stored table metadata, if available.\n */\nexport function backfillRequestsFrom(cookies: CookieSet): BackfillRequest[] {\n const metadata = new Map(\n cookies.tableMetadata.map(c => [tableKey(c.schema, c.table), c.metadata]),\n );\n const requests: BackfillRequest[] = [];\n let curr: BackfillRequest | undefined;\n for (const {schema, table, column, backfill} of cookies.backfilling) {\n if (curr?.table.schema !== schema || curr.table.name !== table) {\n curr = {\n table: {\n schema,\n name: table,\n // Use `null` when a backfilling table has no metadata. This matches\n // the result of the Postgres left join.\n metadata: metadata.get(tableKey(schema, table)) ?? null,\n },\n columns: {},\n };\n requests.push(curr);\n }\n curr.columns[column] = backfill;\n }\n return v.parse(requests, backfillRequestsSchema);\n}\n\n/**\n * Reads the whole cookie set, ordered by primary key. This is what a\n * change-streamer would hand `startStream`, and what the Postgres-derived and\n * replica-derived sets are compared against.\n */\nexport function readCookies(db: Database): CookieSet {\n const tableMetadata = db\n .prepare(/*sql*/ `\n SELECT \"schema\", \"table\", \"metadata\"\n FROM \"${CHANGE_LOG_TABLE_METADATA_TABLE}\"\n ORDER BY \"schema\", \"table\"\n `)\n .all<{schema: string; table: string; metadata: string}>()\n .map(({schema, table, metadata}) => ({\n schema,\n table,\n metadata: BigIntJSON.parse(metadata) as TableMetadata,\n }));\n\n const backfilling = db\n .prepare(/*sql*/ `\n SELECT \"schema\", \"table\", \"column\", \"backfill\"\n FROM \"${CHANGE_LOG_BACKFILLING_TABLE}\"\n ORDER BY \"schema\", \"table\", \"column\"\n `)\n .all<{schema: string; table: string; column: string; backfill: string}>()\n .map(({schema, table, column, backfill}) => ({\n schema,\n table,\n column,\n backfill: BigIntJSON.parse(backfill) as BackfillID,\n }));\n\n return {tableMetadata, backfilling};\n}\n\n/**\n * Replaces the cookie set wholesale.\n *\n * The cookies are unversioned point-in-time state, so a reconciliation that\n * moves the head invalidates them: truncating the stream above `W` does not roll\n * the cookie set back to `W`, and the truncated transactions can contain\n * `create-table`, `add-column`, and `backfill-completed`. The caller must run\n * this in the same transaction as the reconciliation that invalidated them.\n */\nexport function replaceCookies(db: Database, cookies: CookieSet): void {\n db.prepare(/*sql*/ `DELETE FROM \"${CHANGE_LOG_TABLE_METADATA_TABLE}\"`).run();\n db.prepare(/*sql*/ `DELETE FROM \"${CHANGE_LOG_BACKFILLING_TABLE}\"`).run();\n\n if (cookies.tableMetadata.length > 0) {\n const insert = db.prepare(/*sql*/ `\n INSERT INTO \"${CHANGE_LOG_TABLE_METADATA_TABLE}\"\n (\"schema\", \"table\", \"metadata\") VALUES (?, ?, ?)\n `);\n for (const {schema, table, metadata} of cookies.tableMetadata) {\n insert.run(schema, table, BigIntJSON.stringify(metadata));\n }\n }\n if (cookies.backfilling.length > 0) {\n const insert = db.prepare(/*sql*/ `\n INSERT INTO \"${CHANGE_LOG_BACKFILLING_TABLE}\"\n (\"schema\", \"table\", \"column\", \"backfill\") VALUES (?, ?, ?, ?)\n `);\n for (const {schema, table, column, backfill} of cookies.backfilling) {\n insert.run(schema, table, column, BigIntJSON.stringify(backfill));\n }\n }\n}\n\n/** Retained cookie rows, by table. Both are normally zero. */\nexport type CookieRowCounts = {\n readonly tableMetadata: number;\n readonly backfilling: number;\n};\n\nexport function readCookieRowCounts(db: Database): CookieRowCounts {\n return db\n .prepare(/*sql*/ `\n SELECT\n (SELECT count(*) FROM \"${CHANGE_LOG_TABLE_METADATA_TABLE}\")\n AS \"tableMetadata\",\n (SELECT count(*) FROM \"${CHANGE_LOG_BACKFILLING_TABLE}\")\n AS \"backfilling\"\n `)\n .get<CookieRowCounts>();\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The change log lives in its own SQLite database, `${replicaFile}-change-log`,
|
|
3
|
+
* rather than in the replica file. It is a catchup cache: everything it holds is
|
|
4
|
+
* either already durable in the replica's litestream backup or re-derivable from
|
|
5
|
+
* the upstream replication slot, so it is deliberately excluded from the backup
|
|
6
|
+
* and is never a source of truth.
|
|
7
|
+
*
|
|
8
|
+
* The change-streamer writes it, from the stream loop that fans changes out to
|
|
9
|
+
* subscribers, and commits it before forwarding each transaction's `commit`
|
|
10
|
+
* message. Its head is therefore always at or above the watermark the stream
|
|
11
|
+
* would resume from, which is what {@link reconcileChangeLog} anchors on.
|
|
12
|
+
*
|
|
13
|
+
* Beside the buffer it holds the log's *cookie jar* — the backfill progress
|
|
14
|
+
* state folded up to the same head. That is `change-log-cookies.ts`; this file
|
|
15
|
+
* owns its tables' lifecycle, because a cookie set is only meaningful paired
|
|
16
|
+
* with the watermark it was folded to, and so must be created, dropped, and —
|
|
17
|
+
* whenever reconciliation moves the head — replaced with the anchor's, all with
|
|
18
|
+
* the buffer rather than beside it.
|
|
19
|
+
*
|
|
20
|
+
* Because it is disposable, it has no migration framework. Any inconsistency —
|
|
21
|
+
* a schema change, a leftover file from a different replica, a gap left by a
|
|
22
|
+
* crash or by running with the writer disabled, a corrupt file — is resolved by
|
|
23
|
+
* {@link reconcileChangeLog} and {@link openChangeLogDBForWriting}, which
|
|
24
|
+
* truncate a bounded suffix or replace and reseed the log at the resume
|
|
25
|
+
* watermark. The worst outcome is a `too-old` for a lagging subscriber; a
|
|
26
|
+
* silently delivered gap is not reachable.
|
|
27
|
+
*
|
|
28
|
+
* Disk sizing: a task that writes the log needs room for the replica *plus* the
|
|
29
|
+
* retained change stream — the log's main file, its wal2 sidecars, and pages a
|
|
30
|
+
* purge has freed but not yet returned to the OS. The change-streamer schedules
|
|
31
|
+
* purges against the same floor as the PG change log, so retention is bounded
|
|
32
|
+
* by the confirmed backup watermark ANDed with the minimum retention window —
|
|
33
|
+
* a function of the backup interval, not a constant: 15–30+ minutes behind an
|
|
34
|
+
* RMv1 sync interval, ~60 seconds once litestream v5 backs up every 15–30 s.
|
|
35
|
+
* A held snapshot reservation pins retention unboundedly for its duration, so
|
|
36
|
+
* peak retained bytes is set by the slowest concurrent restore rather than by
|
|
37
|
+
* the retention setting — size disk and alerts on that. The log is excluded
|
|
38
|
+
* from the litestream backup, so this is local disk only and never S3.
|
|
39
|
+
*/
|
|
40
|
+
import type { LogContext } from '@rocicorp/logger';
|
|
41
|
+
import { Database } from '../../../../zqlite/src/db.ts';
|
|
42
|
+
import { type CookieSet } from './change-log-cookies.ts';
|
|
43
|
+
/**
|
|
44
|
+
* Bumped whenever the change-log database's schema changes. Since the file is a
|
|
45
|
+
* cache, a mismatch costs one reseed rather than a migration.
|
|
46
|
+
*
|
|
47
|
+
* v2 re-homed the writer to the change-streamer: the log anchors on the
|
|
48
|
+
* watermark its stream connection resumes from rather than on the replica's
|
|
49
|
+
* state version, and its meta row carries the replica's identity triple plus
|
|
50
|
+
* the seed point.
|
|
51
|
+
*
|
|
52
|
+
* v3 added the cookie tables (see `change-log-cookies.ts`), i.e. the log's
|
|
53
|
+
* second job. The reseed it costs on upgrade buys one retention window of
|
|
54
|
+
* catchup reach on a log nothing reads yet.
|
|
55
|
+
*
|
|
56
|
+
* v4 stores each row's tag and estimated retained bytes alongside its JSON.
|
|
57
|
+
* Readers can now filter without parsing arbitrary row payloads, and
|
|
58
|
+
* reconciliation can bound truncation by bytes as well as rows.
|
|
59
|
+
*
|
|
60
|
+
* `auto_vacuum = INCREMENTAL` arrived within v2, deliberately without a bump:
|
|
61
|
+
* it is a file-header property rather than a schema change, and the reseed a
|
|
62
|
+
* version mismatch triggers cannot enable it (see
|
|
63
|
+
* {@link applyChangeLogPragmas}), so {@link openChangeLogDBForWriting} guards
|
|
64
|
+
* on the pragma itself instead of on this number.
|
|
65
|
+
*/
|
|
66
|
+
export declare const CHANGE_LOG_DB_SCHEMA_VERSION = 4;
|
|
67
|
+
export declare const CHANGE_LOG_STREAM_TABLE = "_zero.changeLogStream";
|
|
68
|
+
export declare const CHANGE_LOG_STREAM_WRITE_TIME_INDEX = "_zero.changeLogStream_writeTimeMs";
|
|
69
|
+
/**
|
|
70
|
+
* Estimates the retained payload size of a stream row. This deliberately does
|
|
71
|
+
* not claim to measure SQLite b-tree/page overhead; it is stable across the
|
|
72
|
+
* write path, reconciliation, and the startup scan used by observability.
|
|
73
|
+
*/
|
|
74
|
+
export declare function estimateChangeLogStreamRowBytes(watermark: string, tag: string, change: string, precommit?: string, hasWriteTime?: boolean): number;
|
|
75
|
+
export declare const CREATE_CHANGE_LOG_STREAM_SCHEMA = "\n CREATE TABLE \"_zero.changeLogStream\" (\n \"watermark\" TEXT NOT NULL,\n \"pos\" INTEGER NOT NULL,\n \"tag\" TEXT NOT NULL,\n \"estimatedBytes\" INTEGER NOT NULL,\n \"change\" TEXT NOT NULL,\n \"precommit\" TEXT,\n \"writeTimeMs\" INTEGER,\n PRIMARY KEY (\"watermark\", \"pos\")\n );\n\n CREATE INDEX \"_zero.changeLogStream_writeTimeMs\"\n ON \"_zero.changeLogStream\" (\"writeTimeMs\", \"watermark\")\n WHERE \"writeTimeMs\" IS NOT NULL;\n";
|
|
76
|
+
export declare const CHANGE_LOG_META_TABLE = "_zero.changeLogMeta";
|
|
77
|
+
/**
|
|
78
|
+
* `${replicaFile}-change-log`, matching the `-serving-copy` convention.
|
|
79
|
+
*
|
|
80
|
+
* The name outlives the writer's move into the change-streamer: the
|
|
81
|
+
* change-streamer derives the path from the replica file it owns, so renaming
|
|
82
|
+
* would save no plumbing and would orphan the old file on every existing
|
|
83
|
+
* volume, where nothing would delete it.
|
|
84
|
+
*
|
|
85
|
+
* Its `-wal` / `-wal2` / `-shm` sidecars are suffixes of *this* name, so they
|
|
86
|
+
* never collide with the replica's own sidecars.
|
|
87
|
+
*/
|
|
88
|
+
export declare function changeLogFileName(replicaFile: string): string;
|
|
89
|
+
/**
|
|
90
|
+
* Removes the change-log database and its `-wal` / `-wal2` / `-shm` sidecars.
|
|
91
|
+
* Safe to call when the file does not exist.
|
|
92
|
+
*/
|
|
93
|
+
export declare function deleteChangeLogDB(replicaFile: string): void;
|
|
94
|
+
/**
|
|
95
|
+
* Which replica the log's contents belong to.
|
|
96
|
+
*
|
|
97
|
+
* `generation` is RMv1's `replicaVersion`: the version at which initial sync
|
|
98
|
+
* copied every row. It is shared by every sibling of a forked replica, which is
|
|
99
|
+
* why it cannot be the whole of the identity under RMv2 — `epoch` and
|
|
100
|
+
* `replicaID` are what distinguish two siblings' logs. Both are `null` until
|
|
101
|
+
* RMv2 supplies them, and a `null` matches only another `null`, so a log
|
|
102
|
+
* written before they exist is still recognized as this replica's.
|
|
103
|
+
*/
|
|
104
|
+
export type ChangeLogIdentity = {
|
|
105
|
+
readonly epoch: string | null;
|
|
106
|
+
readonly generation: string;
|
|
107
|
+
readonly replicaID: string | null;
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* Where the stream connection resumes, and everything the log's state at that
|
|
111
|
+
* position consists of.
|
|
112
|
+
*
|
|
113
|
+
* The two fields travel together because a cookie set is only meaningful paired
|
|
114
|
+
* with the watermark it was folded up to (invariant 15). They are read from one
|
|
115
|
+
* store, in one snapshot: `Storer.getStartStreamInitializationParameters()`
|
|
116
|
+
* reads both from Postgres in a single REPEATABLE READ transaction. Pairing one
|
|
117
|
+
* store's cookies with another's watermark would silently drop every backfill
|
|
118
|
+
* that completed in the interval, and those rows are unrecoverable — backfill
|
|
119
|
+
* transactions are synthesized by the change source rather than replayed from
|
|
120
|
+
* the slot.
|
|
121
|
+
*/
|
|
122
|
+
export type ChangeLogResumePoint = {
|
|
123
|
+
/**
|
|
124
|
+
* The watermark this stream connection resumes from. The log's own head is
|
|
125
|
+
* measured against it, and a reseed seeds a synthetic transaction at it.
|
|
126
|
+
*
|
|
127
|
+
* Deliberately *not* "the replica's state version": after the writer moved to
|
|
128
|
+
* the change-streamer, the canonical replicator is a subscriber downstream of
|
|
129
|
+
* the write loop, so its state version is a consequence of this log rather
|
|
130
|
+
* than a constraint on it.
|
|
131
|
+
*/
|
|
132
|
+
readonly resumeWatermark: string;
|
|
133
|
+
/**
|
|
134
|
+
* The cookie set that belongs to {@link resumeWatermark}. Any reconciliation
|
|
135
|
+
* that moves the head invalidates the set the log was holding — the cookies
|
|
136
|
+
* are unversioned point-in-time state, and truncating the stream above `W`
|
|
137
|
+
* does not roll them back to `W` — so the same transaction installs this one
|
|
138
|
+
* in its place (invariant 17).
|
|
139
|
+
*
|
|
140
|
+
* Postgres supplies it while it remains the store the stream resumes from. At
|
|
141
|
+
* the C5 flip the log's own head *is* the resume point, phantoms cannot
|
|
142
|
+
* exist, and both this field and the truncate-above path become dead code.
|
|
143
|
+
*/
|
|
144
|
+
readonly cookies: CookieSet;
|
|
145
|
+
};
|
|
146
|
+
/**
|
|
147
|
+
* What the log is reconciled against. Reconciliation runs once per stream
|
|
148
|
+
* connection, since every reconnect can re-read a different resume point.
|
|
149
|
+
*/
|
|
150
|
+
export type ChangeLogAnchor = ChangeLogResumePoint & {
|
|
151
|
+
readonly identity: ChangeLogIdentity;
|
|
152
|
+
/**
|
|
153
|
+
* The change-streamer's clock, at reconciliation time. Supplied rather than
|
|
154
|
+
* read inline so that tests control it. Used for `seededAtMs` and for the
|
|
155
|
+
* seed transaction's `writeTimeMs`, which is what the purger's time floor
|
|
156
|
+
* measures.
|
|
157
|
+
*/
|
|
158
|
+
readonly nowMs: number;
|
|
159
|
+
};
|
|
160
|
+
/** The meta row, i.e. everything the log records about itself. */
|
|
161
|
+
export type ChangeLogMeta = ChangeLogIdentity & {
|
|
162
|
+
readonly schemaVersion: number;
|
|
163
|
+
readonly seededAtMs: number;
|
|
164
|
+
readonly seedWatermark: string;
|
|
165
|
+
};
|
|
166
|
+
/**
|
|
167
|
+
* Opens the change-log database beside `replicaFile`.
|
|
168
|
+
*
|
|
169
|
+
* A writable handle creates the file if it is absent; a `readonly` handle
|
|
170
|
+
* throws, which is the normal state for a change-streamer whose writer is
|
|
171
|
+
* disabled. Pragmas are the caller's responsibility, since only the writer sets
|
|
172
|
+
* the persistent ones.
|
|
173
|
+
*/
|
|
174
|
+
export declare function openChangeLogDB(lc: LogContext, replicaFile: string, opts: {
|
|
175
|
+
readonly: boolean;
|
|
176
|
+
}): Database;
|
|
177
|
+
/**
|
|
178
|
+
* Configures the change-log database, which the change-streamer's writer owns
|
|
179
|
+
* exclusively. These are the settings the `separate-files` mode of
|
|
180
|
+
* `sqlite-change-log-ceiling.bench.ts` measured.
|
|
181
|
+
*
|
|
182
|
+
* `wal2` because the log is a continuous append that catchup reads
|
|
183
|
+
* continuously, which is the case wal2 exists for: it avoids checkpoint
|
|
184
|
+
* starvation without needing an autocheckpoint. `wal_autocheckpoint` therefore
|
|
185
|
+
* keeps its default, unlike the backup replica's 0, which hands checkpointing
|
|
186
|
+
* to litestream — nothing else owns this file.
|
|
187
|
+
*
|
|
188
|
+
* `synchronous = NORMAL` because the commit sits on the forward path, once per
|
|
189
|
+
* upstream transaction, and NORMAL keeps that from costing an fsync. It is not
|
|
190
|
+
* a durability compromise here: in WAL mode NORMAL still writes every commit
|
|
191
|
+
* through to the OS, so it survives a process crash, an OOM kill, or a SIGKILL.
|
|
192
|
+
* It is lost only to kernel panic or power loss, and those destroy the node —
|
|
193
|
+
* the task restarts elsewhere, restores the replica from S3, and has no
|
|
194
|
+
* change-log file at all. Whatever a power loss does take is detected by
|
|
195
|
+
* {@link reconcileChangeLog} and reseeded.
|
|
196
|
+
*
|
|
197
|
+
* `auto_vacuum = INCREMENTAL` so that purge can return freed pages to the OS
|
|
198
|
+
* rather than leaving the file at its high-water mark. **It must be the first
|
|
199
|
+
* statement here.** SQLite honours a `none` -> `incremental` transition only
|
|
200
|
+
* while the file is still empty, and `journal_mode = wal2` materializes page 1;
|
|
201
|
+
* appending the pragma instead of prepending it silently leaves the file at
|
|
202
|
+
* mode 0 forever, since neither `DROP TABLE` nor a reseed makes a file empty
|
|
203
|
+
* again. {@link openChangeLogDBForWriting} verifies the result.
|
|
204
|
+
*/
|
|
205
|
+
export declare function applyChangeLogPragmas(db: Database): void;
|
|
206
|
+
/**
|
|
207
|
+
* Opens the change-log database for the writer, applies its pragmas, and
|
|
208
|
+
* reconciles it against `anchor`, returning the handle and what reconciliation
|
|
209
|
+
* had to do.
|
|
210
|
+
*
|
|
211
|
+
* Corruption is answered with a rebuild rather than an escalation, which is a
|
|
212
|
+
* deliberate divergence from how the replica's own corruption is handled. A
|
|
213
|
+
* corrupt replica is a lost source of truth, so it ends in a restore or an
|
|
214
|
+
* auto-reset; the change log holds nothing that is not either already in the
|
|
215
|
+
* replica's litestream backup or re-derivable from the upstream slot, so the
|
|
216
|
+
* entire response is to delete the file and seed a new one at the resume
|
|
217
|
+
* watermark. The cost is one retention window of catchup — reconnecting
|
|
218
|
+
* subscribers below the head get `too-old` — which is what every other
|
|
219
|
+
* {@link ReseedReason} costs.
|
|
220
|
+
*
|
|
221
|
+
* Only corruption is rebuilt through. Anything else (a bad path, a permissions
|
|
222
|
+
* error, a full disk) is a problem with the environment rather than with the
|
|
223
|
+
* file's contents, and deleting a database in response would destroy state
|
|
224
|
+
* without fixing it. Those propagate to the caller, which disables the writer
|
|
225
|
+
* and keeps replicating.
|
|
226
|
+
*
|
|
227
|
+
* A file that predates `auto_vacuum = INCREMENTAL` takes the same rebuild, for
|
|
228
|
+
* the same reason and at the same cost: the pragma only takes on an empty file,
|
|
229
|
+
* so a reseed cannot enable it. Unlike corruption, a *second* failure there is
|
|
230
|
+
* tolerated rather than thrown — see {@link ensureIncrementalAutoVacuum}.
|
|
231
|
+
*/
|
|
232
|
+
/**
|
|
233
|
+
* Returns an anchor after the database opens.
|
|
234
|
+
*
|
|
235
|
+
* The resolver can inspect the existing file before it selects the anchor. A
|
|
236
|
+
* valid log can use its own head. A new or invalid log uses the replica seed.
|
|
237
|
+
* The rebuild path calls the resolver again for the new file.
|
|
238
|
+
*/
|
|
239
|
+
export type AnchorResolver = (db: Database) => ChangeLogAnchor;
|
|
240
|
+
export declare function openChangeLogDBForWriting(lc: LogContext, replicaFile: string, anchor: AnchorResolver): {
|
|
241
|
+
db: Database;
|
|
242
|
+
result: ReconcileResult;
|
|
243
|
+
replacedFile: boolean;
|
|
244
|
+
};
|
|
245
|
+
/**
|
|
246
|
+
* Replaces an already-closed change-log file after bounded reconciliation
|
|
247
|
+
* declined its work. The caller closes cached readers before calling this so
|
|
248
|
+
* none can continue serving the unlinked inode.
|
|
249
|
+
*/
|
|
250
|
+
export declare function rebuildChangeLogDBForWriting(lc: LogContext, replicaFile: string, anchor: ChangeLogAnchor, required: ChangeLogRebuildRequired): {
|
|
251
|
+
db: Database;
|
|
252
|
+
result: ReconcileResult;
|
|
253
|
+
replacedFile: true;
|
|
254
|
+
};
|
|
255
|
+
export type ReseedReason = 'created' | 'schema-mismatch' | 'identity-mismatch' | 'gap' | 'oversized-truncate';
|
|
256
|
+
/**
|
|
257
|
+
* Reconciliation runs synchronously on the change-streamer's event loop. A
|
|
258
|
+
* normal phantom is one transaction, so work above either limit is answered by
|
|
259
|
+
* unlinking and reseeding this disposable cache rather than deleting an
|
|
260
|
+
* arbitrarily large suffix in place.
|
|
261
|
+
*/
|
|
262
|
+
export declare const MAX_RECONCILE_TRUNCATE_ROWS = 10000;
|
|
263
|
+
export declare const MAX_RECONCILE_TRUNCATE_BYTES: number;
|
|
264
|
+
export declare class ChangeLogRebuildRequired extends Error {
|
|
265
|
+
readonly name = "ChangeLogRebuildRequired";
|
|
266
|
+
readonly reason: ReseedReason;
|
|
267
|
+
readonly rows?: number | undefined;
|
|
268
|
+
readonly estimatedBytes?: number | undefined;
|
|
269
|
+
constructor(reason: ReseedReason, rows?: number | undefined, estimatedBytes?: number | undefined);
|
|
270
|
+
}
|
|
271
|
+
type ReconcileOptions = {
|
|
272
|
+
/** Throw before an unbounded delete/drop so the file owner can unlink it. */
|
|
273
|
+
readonly rebuildInsteadOfUnboundedWork?: boolean | undefined;
|
|
274
|
+
/** Preserve the reason that caused an old file to be unlinked. */
|
|
275
|
+
readonly reseedReason?: ReseedReason | undefined;
|
|
276
|
+
};
|
|
277
|
+
/**
|
|
278
|
+
* `cookiesStale` records that the cookie set the log held did not survive
|
|
279
|
+
* reconciliation. The cookies are unversioned point-in-time state, so any
|
|
280
|
+
* reconciliation that moves the head invalidates them, and the same transaction
|
|
281
|
+
* replaces them with the anchor's — the set that belongs to the resume
|
|
282
|
+
* watermark (see `change-log-cookies.ts`). It is `action !== 'none'` today; it
|
|
283
|
+
* is a field rather than a derivation because the replacement reads as intent
|
|
284
|
+
* at the call site, and because it is what the `cookie_reseed` counter is keyed
|
|
285
|
+
* on.
|
|
286
|
+
*/
|
|
287
|
+
export type ReconcileResult = {
|
|
288
|
+
action: 'none';
|
|
289
|
+
head: string;
|
|
290
|
+
cookiesStale: false;
|
|
291
|
+
} | {
|
|
292
|
+
action: 'truncated';
|
|
293
|
+
head: string;
|
|
294
|
+
rows: number;
|
|
295
|
+
cookiesStale: true;
|
|
296
|
+
} | {
|
|
297
|
+
action: 'reseeded';
|
|
298
|
+
head: string;
|
|
299
|
+
reason: ReseedReason;
|
|
300
|
+
cookiesStale: true;
|
|
301
|
+
};
|
|
302
|
+
/**
|
|
303
|
+
* Brings the change log into agreement with the watermark its stream connection
|
|
304
|
+
* resumes from, in one transaction on the change-log database:
|
|
305
|
+
*
|
|
306
|
+
* ```
|
|
307
|
+
* head === resumeWatermark → keep appending
|
|
308
|
+
* head > resumeWatermark → truncate above resumeWatermark
|
|
309
|
+
* otherwise → wipe, seed at resumeWatermark, record the reason
|
|
310
|
+
* ```
|
|
311
|
+
*
|
|
312
|
+
* The log commits before anything that can advance the resume watermark, so a
|
|
313
|
+
* *phantom* — a transaction the log holds whose watermark the resumed stream
|
|
314
|
+
* re-delivers — is the normal state, and truncate-above is the whole of
|
|
315
|
+
* reconciliation rather than a special case. A phantom's rows all carry the
|
|
316
|
+
* transaction's commit watermark, which is strictly greater than the resume
|
|
317
|
+
* watermark, so deleting on that predicate removes phantoms whole and retains
|
|
318
|
+
* every transaction at or below the resume point.
|
|
319
|
+
*
|
|
320
|
+
* It must run per stream connection, not once per process: the stream loop
|
|
321
|
+
* re-reads its resume watermark on every reconnect, and the writer inserts with
|
|
322
|
+
* a plain `INSERT` against `PRIMARY KEY ("watermark","pos")`, so an
|
|
323
|
+
* un-truncated overlap is a constraint violation on the first re-delivered
|
|
324
|
+
* transaction.
|
|
325
|
+
*
|
|
326
|
+
* Anything truncation cannot resolve — the file was deleted, the writer was
|
|
327
|
+
* disabled for a while, the replica was restored, power was lost with
|
|
328
|
+
* `synchronous=NORMAL` — surfaces as a head that does not land on the resume
|
|
329
|
+
* watermark, and is resolved by wiping and reseeding there.
|
|
330
|
+
*
|
|
331
|
+
* Whichever of the two moves the head also replaces the cookie set with the one
|
|
332
|
+
* the anchor carries, in the same transaction: the head and the cookies are one
|
|
333
|
+
* position, and nothing may observe them at two.
|
|
334
|
+
*/
|
|
335
|
+
export declare function reconcileChangeLog(lc: LogContext, db: Database, anchor: ChangeLogAnchor, opts?: ReconcileOptions): ReconcileResult;
|
|
336
|
+
/**
|
|
337
|
+
* Returns the reason that the log must be recreated. Returns `undefined` when
|
|
338
|
+
* the writer can continue to use the log.
|
|
339
|
+
*
|
|
340
|
+
* This function takes only the expected identity because callers use the result
|
|
341
|
+
* to select the anchor.
|
|
342
|
+
*/
|
|
343
|
+
export declare function changeLogWipeReason(db: Database, identity: ChangeLogIdentity): ReseedReason | undefined;
|
|
344
|
+
/**
|
|
345
|
+
* Seeds a valid synthetic transaction at the anchor's resume watermark, making
|
|
346
|
+
* an otherwise empty log serviceable as a catchup boundary for a subscriber
|
|
347
|
+
* that is exactly at that watermark.
|
|
348
|
+
*/
|
|
349
|
+
export declare function seedChangeLogStream(db: Database, anchor: ChangeLogAnchor): void;
|
|
350
|
+
/** Reads the whole meta row. Throws if the log has not been reconciled. */
|
|
351
|
+
export declare function readChangeLogMeta(db: Database): ChangeLogMeta;
|
|
352
|
+
/**
|
|
353
|
+
* `max()` on the primary key's leading column, i.e. an index seek. Null when
|
|
354
|
+
* the log is empty.
|
|
355
|
+
*/
|
|
356
|
+
export declare function readChangeLogHead(db: Database): string | null;
|
|
357
|
+
/**
|
|
358
|
+
* The covered watermark range. Both scalar subqueries seek the watermark
|
|
359
|
+
* index, so unlike a `count()` this does not scan the log. Both bounds are
|
|
360
|
+
* null when it is empty.
|
|
361
|
+
*/
|
|
362
|
+
export declare function readChangeLogBounds(db: Database): ChangeLogBounds;
|
|
363
|
+
export type ChangeLogBounds = {
|
|
364
|
+
readonly minWatermark: string | null;
|
|
365
|
+
readonly headWatermark: string | null;
|
|
366
|
+
};
|
|
367
|
+
export {};
|
|
368
|
+
//# sourceMappingURL=change-log-db.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"change-log-db.d.ts","sourceRoot":"","sources":["../../../../../../zero-cache/src/services/replicator/change-log-db.ts"],"names":[],"mappings":"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"}
|