@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
|
@@ -1,31 +1,38 @@
|
|
|
1
|
-
import { unreachable } from "../../../../shared/src/asserts.js";
|
|
1
|
+
import { assert, unreachable } from "../../../../shared/src/asserts.js";
|
|
2
2
|
import { promiseVoid } from "../../../../shared/src/resolved-promises.js";
|
|
3
|
+
import { must } from "../../../../shared/src/must.js";
|
|
3
4
|
import "../change-source/protocol/current/downstream.js";
|
|
4
|
-
import { getOrCreateCounter } from "../../observability/metrics.js";
|
|
5
|
+
import { getOrCreateCounter, getOrCreateLatencyHistogram } from "../../observability/metrics.js";
|
|
5
6
|
import { DEFAULT_MAX_RETRY_DELAY_MS, RunningState, UnrecoverableError } from "../running-state.js";
|
|
6
7
|
import { min } from "../../types/lexi-version.js";
|
|
7
8
|
import { publishCriticalEvent } from "../../observability/events.js";
|
|
8
|
-
import { AutoResetSignal, ensureReplicationConfig, markResetRequired } from "./schema/tables.js";
|
|
9
9
|
import { Subscription } from "../../types/subscription.js";
|
|
10
|
+
import { AutoResetSignal, ensureReplicationConfig, markResetRequired } from "./schema/tables.js";
|
|
10
11
|
import { publishReplicationError, replicationStatusError } from "../replicator/replication-status.js";
|
|
11
12
|
import "./change-streamer.js";
|
|
13
|
+
import { SQLiteChangeLogReader } from "./sqlite-change-log-reader.js";
|
|
14
|
+
import { ChangeLogInitializer, replicaInitializationSource } from "./change-log-initializer.js";
|
|
12
15
|
import { Forwarder } from "./forwarder.js";
|
|
13
|
-
import {
|
|
16
|
+
import { SnapshotReservations } from "./snapshot-reservations.js";
|
|
17
|
+
import { SQLiteChangeLogCatchup } from "./sqlite-change-log-catchup.js";
|
|
18
|
+
import { SQLiteChangeLogPurgeScheduler } from "./sqlite-change-log-purge-scheduler.js";
|
|
19
|
+
import { SQLiteChangeLogWriter } from "./sqlite-change-log-writer.js";
|
|
14
20
|
import { Storer } from "./storer.js";
|
|
15
21
|
import { Subscriber } from "./subscriber.js";
|
|
22
|
+
import { UpstreamAcker } from "./upstream-acker.js";
|
|
16
23
|
import { resolver } from "@rocicorp/resolver";
|
|
17
24
|
import { getDefaultHighWaterMark } from "node:stream";
|
|
18
25
|
//#region ../zero-cache/src/services/change-streamer/change-streamer-service.ts
|
|
19
26
|
/**
|
|
20
27
|
* Performs initialization and schema migrations to initialize a ChangeStreamerImpl.
|
|
21
28
|
*/
|
|
22
|
-
async function initializeStreamer(lc, shard, taskID, discoveryAddress, discoveryProtocol, changeDB, changeSource, replicationStatusPublisher, subscriptionState, purgeLock, autoReset, opts, setTimeoutFn = setTimeout) {
|
|
23
|
-
await
|
|
24
|
-
await ensureReplicationConfig(lc, changeDB, subscriptionState, shard, autoReset, setTimeoutFn);
|
|
29
|
+
async function initializeStreamer(lc, shard, taskID, discoveryAddress, discoveryProtocol, changeDB, changeSource, replicationStatusPublisher, subscriptionState, backupConfig, purgeLock, autoReset, opts, setTimeoutFn = setTimeout) {
|
|
30
|
+
await ensureReplicationConfig(lc, changeDB, subscriptionState, shard, autoReset, purgeLock ?? void 0, setTimeoutFn);
|
|
25
31
|
const { replicaVersion } = subscriptionState;
|
|
26
|
-
return new ChangeStreamerImpl(lc, shard, taskID, discoveryAddress, discoveryProtocol, changeDB, replicaVersion, changeSource, replicationStatusPublisher, purgeLock, autoReset, opts, setTimeoutFn);
|
|
32
|
+
return new ChangeStreamerImpl(lc, shard, taskID, discoveryAddress, discoveryProtocol, changeDB, replicaVersion, changeSource, replicationStatusPublisher, backupConfig, purgeLock, autoReset, opts, setTimeoutFn);
|
|
27
33
|
}
|
|
28
34
|
var REPLICATION_STATUS_ERROR_DELAY_THRESHOLD_MS = 5e3;
|
|
35
|
+
var DEFAULT_CHANGE_LOG_UNAVAILABLE_WARN_THRESHOLD_MS = 6e4;
|
|
29
36
|
/**
|
|
30
37
|
* Upstream-agnostic dispatch of messages in a {@link ChangeStreamMessage} to a
|
|
31
38
|
* {@link Forwarder} and {@link Storer} to execute the forward-store-ack
|
|
@@ -173,30 +180,84 @@ var ChangeStreamerImpl = class {
|
|
|
173
180
|
#source;
|
|
174
181
|
#storer;
|
|
175
182
|
#forwarder;
|
|
183
|
+
#reservations;
|
|
176
184
|
#replicationStatusPublisher;
|
|
185
|
+
#sqliteCatchupOptions;
|
|
186
|
+
#changeLogWriter;
|
|
187
|
+
#purgeScheduler;
|
|
188
|
+
#acker;
|
|
189
|
+
#initializer;
|
|
177
190
|
#autoReset;
|
|
178
191
|
#state;
|
|
179
|
-
#initialWatermarks = /* @__PURE__ */ new Set();
|
|
180
192
|
#serving = resolver();
|
|
181
193
|
#txCounter = getOrCreateCounter("replication", "transactions", "Count of replicated transactions");
|
|
182
194
|
#changeCounter = getOrCreateCounter("replication", "changes", "Count of replicated changes (DML or DDL statements)");
|
|
195
|
+
#transactionForwardDuration = getOrCreateLatencyHistogram("replication", "transaction_forward_duration", "Time from receiving a transaction's `begin` to forwarding its `commit`, i.e. the change-streamer half of forward-to-subscriber latency.");
|
|
183
196
|
#latestStatus;
|
|
197
|
+
#latestLagReportCommitTimeMs = 0;
|
|
198
|
+
#backupWatermark;
|
|
199
|
+
#pgPurgedWatermark = "";
|
|
200
|
+
/**
|
|
201
|
+
* The floor last logged as held back by a laggard. The level-triggered
|
|
202
|
+
* retry re-evaluates every {@link CLEANUP_DELAY_MS}; logging only when the
|
|
203
|
+
* blocking floor moves keeps a stuck subscriber from emitting the same
|
|
204
|
+
* line indefinitely.
|
|
205
|
+
*/
|
|
206
|
+
#loggedBehindWatermark;
|
|
207
|
+
#sqlitePurgeContinuation;
|
|
184
208
|
#purgeLock;
|
|
209
|
+
#pgPurgeScheduled = false;
|
|
210
|
+
#pgPurgeRunning = false;
|
|
211
|
+
#sqlitePurgeScheduled = false;
|
|
212
|
+
#sqlitePurgeRunning = false;
|
|
185
213
|
#stream;
|
|
186
|
-
|
|
214
|
+
#sqliteCatchup;
|
|
215
|
+
#changeLogUnavailableSince;
|
|
216
|
+
#lastForwardedCommitWatermark;
|
|
217
|
+
#transactionForwardStartedAt;
|
|
218
|
+
#currentTransactionCompletion;
|
|
219
|
+
constructor(lc, shard, taskID, discoveryAddress, discoveryProtocol, changeDB, replicaVersion, source, replicationStatusPublisher, backupConfig, initialPurgeLock, autoReset, opts, setTimeoutFn = setTimeout) {
|
|
187
220
|
this.id = `change-streamer`;
|
|
188
221
|
this.#lc = lc.withContext("component", "change-streamer");
|
|
189
222
|
this.#shard = shard;
|
|
190
223
|
this.#changeDB = changeDB;
|
|
191
224
|
this.#replicaVersion = replicaVersion;
|
|
192
225
|
this.#source = source;
|
|
193
|
-
this.#storer = new Storer(lc, shard, taskID, discoveryAddress, discoveryProtocol, changeDB, replicaVersion, (consumed) => this.#
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
this.#
|
|
226
|
+
this.#storer = new Storer(lc, shard, taskID, discoveryAddress, discoveryProtocol, changeDB, replicaVersion, (consumed) => this.#acker.trackPgChangeLog(consumed[2].watermark), (err) => this.stop(err), opts);
|
|
227
|
+
this.#forwarder = new Forwarder(lc, {
|
|
228
|
+
flowControlConsensusTimeoutProportion: opts.flowControlConsensusTimeoutProportion,
|
|
229
|
+
flowControlSlowSubscriberGracePeriodMs: opts.flowControlSlowSubscriberGracePeriodMs
|
|
230
|
+
});
|
|
231
|
+
this.#reservations = backupConfig ? new SnapshotReservations(lc, backupConfig, (taskID) => this.#purgeScheduler?.resume(taskID)) : void 0;
|
|
199
232
|
this.#replicationStatusPublisher = replicationStatusPublisher;
|
|
233
|
+
this.#changeLogWriter = opts.sqliteChangeLogWriter ? new SQLiteChangeLogWriter(lc, {
|
|
234
|
+
...opts.sqliteChangeLogWriter,
|
|
235
|
+
onCommit: (watermark) => {
|
|
236
|
+
this.#sqliteCatchup?.onChangeLogCommit(watermark);
|
|
237
|
+
this.#purgeScheduler?.onWriterIdle();
|
|
238
|
+
},
|
|
239
|
+
onDisabled: () => this.#closeSQLiteCatchup(),
|
|
240
|
+
onRebuilt: () => this.#closeSQLiteCatchup()
|
|
241
|
+
}) : void 0;
|
|
242
|
+
this.#purgeScheduler = opts.sqliteChangeLogPurge && this.#changeLogWriter ? new SQLiteChangeLogPurgeScheduler(lc, () => this.#changeLogWriter?.connection, () => this.#forwarder.getAcks(), opts.sqliteChangeLogPurge) : void 0;
|
|
243
|
+
this.#acker = new UpstreamAcker({
|
|
244
|
+
trackPgChangeLog: true,
|
|
245
|
+
trackBackup: backupConfig?.litestreamVersion === "v5"
|
|
246
|
+
});
|
|
247
|
+
const replicaSource = opts.sqliteChangeLogCompare ? replicaInitializationSource(lc, opts.sqliteChangeLogCompare.replicaFile) : void 0;
|
|
248
|
+
this.#initializer = new ChangeLogInitializer(lc, {
|
|
249
|
+
initFromPgChangeLog: true,
|
|
250
|
+
initFromReplica: replicaSource !== void 0
|
|
251
|
+
}, {
|
|
252
|
+
pgChangeLog: () => this.#storer.getStartStreamInitializationParameters(),
|
|
253
|
+
replica: () => must(replicaSource)(),
|
|
254
|
+
reconcileChangeLog: (resumeFrom, seed) => resumeFrom ? this.#changeLogWriter?.reconcile(resumeFrom) : this.#changeLogWriter?.reconcileFromLog(seed),
|
|
255
|
+
changeLog: () => this.#changeLogWriter?.connection
|
|
256
|
+
});
|
|
257
|
+
this.#sqliteCatchupOptions = opts.sqliteCatchup ? {
|
|
258
|
+
...opts.sqliteCatchup,
|
|
259
|
+
cleanupGuard: opts.sqliteCatchup.cleanupGuard ?? this.#purgeScheduler?.cleanupGuard
|
|
260
|
+
} : void 0;
|
|
200
261
|
this.#purgeLock = initialPurgeLock;
|
|
201
262
|
this.#autoReset = autoReset;
|
|
202
263
|
this.#state = new RunningState(this.id, void 0, setTimeoutFn);
|
|
@@ -205,8 +266,11 @@ var ChangeStreamerImpl = class {
|
|
|
205
266
|
async run() {
|
|
206
267
|
this.#lc.info?.("starting change stream");
|
|
207
268
|
this.#forwarder.startProgressMonitor();
|
|
208
|
-
const
|
|
209
|
-
if (
|
|
269
|
+
const lagReportInit = await this.#source.startLagReporter();
|
|
270
|
+
if (lagReportInit) {
|
|
271
|
+
this.#latestStatus.lagReport = { nextSendTimeMs: lagReportInit.nextSendTimeMs };
|
|
272
|
+
this.#latestLagReportCommitTimeMs = lagReportInit.firstCommitTimeMs;
|
|
273
|
+
}
|
|
210
274
|
await this.#storer.assumeOwnership(this.#purgeLock);
|
|
211
275
|
this.#purgeLock = null;
|
|
212
276
|
const flushBytesThreshold = getDefaultHighWaterMark(false);
|
|
@@ -215,19 +279,22 @@ var ChangeStreamerImpl = class {
|
|
|
215
279
|
let watermark = null;
|
|
216
280
|
let unflushedBytes = 0;
|
|
217
281
|
try {
|
|
218
|
-
const { lastWatermark, backfillRequests } = await this.#
|
|
282
|
+
const { lastWatermark, backfillRequests } = await this.#initializer.initialize();
|
|
283
|
+
this.#lastForwardedCommitWatermark = lastWatermark;
|
|
219
284
|
const stream = await this.#source.startStream(lastWatermark, backfillRequests);
|
|
220
285
|
this.#storer.run().catch((e) => stream.changes.cancel(e));
|
|
221
286
|
this.#stream = stream;
|
|
222
287
|
if (this.#state.resetBackoff() > REPLICATION_STATUS_ERROR_DELAY_THRESHOLD_MS) this.#replicationStatusPublisher.publish(this.#lc, "Replicating", `Replicating from ${lastWatermark}`);
|
|
223
288
|
watermark = null;
|
|
289
|
+
this.#acker.reset(stream.acks);
|
|
224
290
|
for await (const change of stream.changes) {
|
|
291
|
+
this.#acker.trackDownstream(change);
|
|
225
292
|
const [type, msg] = change;
|
|
226
293
|
switch (type) {
|
|
227
294
|
case "status":
|
|
228
|
-
if (msg.
|
|
229
|
-
if (msg.lagReport) {
|
|
295
|
+
if (msg.lagReport && msg.lagReport.lastTimings.commitTimeMs >= this.#latestLagReportCommitTimeMs) {
|
|
230
296
|
this.#latestStatus.lagReport = msg.lagReport;
|
|
297
|
+
this.#latestLagReportCommitTimeMs = msg.lagReport.lastTimings.commitTimeMs;
|
|
231
298
|
this.#forwarder.sendStatus(this.#latestStatus);
|
|
232
299
|
}
|
|
233
300
|
continue;
|
|
@@ -247,20 +314,25 @@ var ChangeStreamerImpl = class {
|
|
|
247
314
|
break;
|
|
248
315
|
}
|
|
249
316
|
const json = this.#storer.store(watermark, change);
|
|
317
|
+
this.#changeLogWriter?.write(change, json);
|
|
250
318
|
const entry = [
|
|
251
319
|
watermark,
|
|
252
320
|
change[1].tag,
|
|
253
321
|
json
|
|
254
322
|
];
|
|
255
323
|
unflushedBytes += json.length;
|
|
256
|
-
if (unflushedBytes < flushBytesThreshold)
|
|
257
|
-
|
|
258
|
-
|
|
324
|
+
if (unflushedBytes < flushBytesThreshold) {
|
|
325
|
+
this.#forwarder.forward(entry);
|
|
326
|
+
this.#recordForwardedTransactionBoundary(type, entry[0]);
|
|
327
|
+
} else {
|
|
328
|
+
const forwarded = this.#forwarder.forwardWithFlowControl(entry);
|
|
329
|
+
this.#recordForwardedTransactionBoundary(type, entry[0]);
|
|
330
|
+
await stream.changes.doneOr(forwarded);
|
|
259
331
|
unflushedBytes = 0;
|
|
260
332
|
}
|
|
261
333
|
if (type === "commit" || type === "rollback") watermark = null;
|
|
262
334
|
const readyForMore = this.#storer.readyForMore();
|
|
263
|
-
if (readyForMore) await readyForMore;
|
|
335
|
+
if (readyForMore) await stream.changes.doneOr(readyForMore);
|
|
264
336
|
}
|
|
265
337
|
} catch (e) {
|
|
266
338
|
err = e;
|
|
@@ -271,11 +343,14 @@ var ChangeStreamerImpl = class {
|
|
|
271
343
|
if (watermark) {
|
|
272
344
|
this.#lc.warn?.(`aborting interrupted transaction ${watermark}`);
|
|
273
345
|
this.#storer.abort();
|
|
346
|
+
this.#changeLogWriter?.abort();
|
|
347
|
+
this.#purgeScheduler?.onWriterIdle();
|
|
274
348
|
this.#forwarder.forward([
|
|
275
349
|
watermark,
|
|
276
350
|
"rollback",
|
|
277
351
|
ROLLBACK_JSON
|
|
278
352
|
]);
|
|
353
|
+
this.#recordForwardedTransactionBoundary("rollback", watermark);
|
|
279
354
|
}
|
|
280
355
|
await Promise.all([
|
|
281
356
|
this.#storer.stop(),
|
|
@@ -301,27 +376,88 @@ var ChangeStreamerImpl = class {
|
|
|
301
376
|
default: unreachable(tag);
|
|
302
377
|
}
|
|
303
378
|
}
|
|
304
|
-
subscribe(ctx) {
|
|
379
|
+
async subscribe(ctx) {
|
|
305
380
|
const { protocolVersion, id, mode, replicaVersion, watermark } = ctx;
|
|
306
381
|
if (mode === "serving") this.#serving.resolve();
|
|
307
|
-
|
|
308
|
-
const
|
|
382
|
+
let cleanupSubscriber = () => {};
|
|
383
|
+
const downstream = Subscription.create({ cleanup: () => cleanupSubscriber() });
|
|
384
|
+
const subscriber = new Subscriber(protocolVersion, id, watermark, downstream, () => this.#latestStatus, {});
|
|
385
|
+
const lc = this.#lc.withContext("subscriber", subscriber.id);
|
|
386
|
+
cleanupSubscriber = () => {
|
|
387
|
+
lc.info?.(`removing subscriber ${subscriber.id}`);
|
|
388
|
+
this.#forwarder.remove(subscriber);
|
|
389
|
+
};
|
|
309
390
|
if (replicaVersion !== this.#replicaVersion) {
|
|
310
|
-
|
|
391
|
+
lc.warn?.(`rejecting subscriber at replica version ${replicaVersion}`);
|
|
311
392
|
subscriber.close(1, `current replica version is ${this.#replicaVersion} (requested ${replicaVersion})`);
|
|
312
393
|
} else {
|
|
313
|
-
|
|
314
|
-
this.#
|
|
315
|
-
|
|
394
|
+
lc.info?.(`adding subscriber ${subscriber.id}`);
|
|
395
|
+
const sqliteCatchup = this.#selectSQLiteCatchup(ctx);
|
|
396
|
+
if (sqliteCatchup) {
|
|
397
|
+
cleanupSubscriber = () => sqliteCatchup.remove(subscriber);
|
|
398
|
+
await sqliteCatchup.catchup(subscriber, () => this.#captureRequiredHead());
|
|
399
|
+
} else {
|
|
400
|
+
this.#forwarder.add(subscriber);
|
|
401
|
+
this.#storer.catchup(subscriber, mode);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
this.#reservations?.close(ctx.taskID);
|
|
405
|
+
return downstream;
|
|
406
|
+
}
|
|
407
|
+
async startSnapshotReservation(taskID) {
|
|
408
|
+
if (!this.#reservations) throw new Error("backups are not configured");
|
|
409
|
+
const downstream = this.#reservations.open(taskID);
|
|
410
|
+
try {
|
|
411
|
+
await (this.#purgeScheduler?.pause(taskID) ?? promiseVoid);
|
|
412
|
+
await this.#confirmReservations();
|
|
413
|
+
return downstream;
|
|
414
|
+
} catch (e) {
|
|
415
|
+
downstream.cancel();
|
|
416
|
+
throw e;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
trackBackupWatermark(watermark) {
|
|
420
|
+
this.#backupWatermark = watermark;
|
|
421
|
+
this.#acker.trackBackup(watermark);
|
|
422
|
+
this.#requestSQLitePurge("deferred");
|
|
423
|
+
this.#maybeSchedulePGPurge();
|
|
424
|
+
this.#maybeScheduleSQLitePurge();
|
|
425
|
+
this.#confirmReservations().catch((e) => this.#lc.warn?.(`error confirming snapshot reservation`, e));
|
|
426
|
+
}
|
|
427
|
+
async #confirmReservations() {
|
|
428
|
+
if (this.#backupWatermark && this.#reservations?.confirmationsRequired()) {
|
|
429
|
+
const { replicaVersion, minWatermark } = await this.#getChangeLogState();
|
|
430
|
+
if (minWatermark <= this.#backupWatermark) this.#reservations?.confirm(replicaVersion, this.#backupWatermark);
|
|
431
|
+
else this.#lc.error?.(`change-log minWatermark ${minWatermark} is later than backupWatermark ${this.#backupWatermark}. Delaying confirmation of snapshot reservation until next backup.`);
|
|
316
432
|
}
|
|
317
|
-
return Promise.resolve(downstream);
|
|
318
433
|
}
|
|
319
|
-
|
|
320
|
-
const
|
|
321
|
-
this.#
|
|
322
|
-
|
|
434
|
+
#maybeSchedulePGPurge() {
|
|
435
|
+
const backupWatermark = this.#backupWatermark;
|
|
436
|
+
if (this.#pgPurgeScheduled || this.#pgPurgeRunning || backupWatermark === void 0 || this.#pgPurgedWatermark >= backupWatermark) return;
|
|
437
|
+
this.#pgPurgeScheduled = true;
|
|
438
|
+
this.#state.setTimeout(() => {
|
|
439
|
+
this.#pgPurgeScheduled = false;
|
|
440
|
+
this.#pgPurgeRunning = true;
|
|
441
|
+
return this.#purgePGChangeLog().finally(() => {
|
|
442
|
+
this.#pgPurgeRunning = false;
|
|
443
|
+
this.#maybeSchedulePGPurge();
|
|
444
|
+
});
|
|
445
|
+
}, CLEANUP_DELAY_MS);
|
|
446
|
+
}
|
|
447
|
+
#maybeScheduleSQLitePurge() {
|
|
448
|
+
if (this.#sqlitePurgeScheduled || this.#sqlitePurgeRunning || this.#backupWatermark === void 0 || this.#sqlitePurgeContinuation === void 0) return;
|
|
449
|
+
const delay = this.#sqlitePurgeContinuation === "immediate" ? 0 : CLEANUP_DELAY_MS;
|
|
450
|
+
this.#sqlitePurgeScheduled = true;
|
|
451
|
+
this.#state.setTimeout(() => {
|
|
452
|
+
this.#sqlitePurgeScheduled = false;
|
|
453
|
+
this.#sqlitePurgeRunning = true;
|
|
454
|
+
return this.#purgeSQLiteChangeLog().finally(() => {
|
|
455
|
+
this.#sqlitePurgeRunning = false;
|
|
456
|
+
this.#maybeScheduleSQLitePurge();
|
|
457
|
+
});
|
|
458
|
+
}, delay);
|
|
323
459
|
}
|
|
324
|
-
async getChangeLogState() {
|
|
460
|
+
async #getChangeLogState() {
|
|
325
461
|
const minWatermark = await this.#storer.getMinWatermarkForCatchup();
|
|
326
462
|
if (!minWatermark) this.#lc.warn?.(`Unexpected empty changeLog. Resync if "Local replica watermark" errors arise`);
|
|
327
463
|
return {
|
|
@@ -329,45 +465,176 @@ var ChangeStreamerImpl = class {
|
|
|
329
465
|
minWatermark: minWatermark ?? this.#replicaVersion
|
|
330
466
|
};
|
|
331
467
|
}
|
|
468
|
+
#getCleanupFloor() {
|
|
469
|
+
const backupWatermark = this.#backupWatermark;
|
|
470
|
+
assert(backupWatermark !== void 0, "cleanup cannot run without a backup watermark");
|
|
471
|
+
const current = [...this.#forwarder.getAcks(), ...this.#reservations?.getReservedWatermarks() ?? []];
|
|
472
|
+
return {
|
|
473
|
+
backupWatermark,
|
|
474
|
+
purgeWatermark: min(backupWatermark, ...current),
|
|
475
|
+
current
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
async #purgePGChangeLog() {
|
|
479
|
+
try {
|
|
480
|
+
const { backupWatermark, purgeWatermark, current } = this.#getCleanupFloor();
|
|
481
|
+
if (purgeWatermark < backupWatermark) {
|
|
482
|
+
if (this.#loggedBehindWatermark !== purgeWatermark) {
|
|
483
|
+
this.#loggedBehindWatermark = purgeWatermark;
|
|
484
|
+
this.#lc.info?.(`At least one client is behind backup ${backupWatermark}`, { watermarks: current });
|
|
485
|
+
}
|
|
486
|
+
} else this.#loggedBehindWatermark = void 0;
|
|
487
|
+
if (purgeWatermark <= this.#pgPurgedWatermark) return;
|
|
488
|
+
this.#lc.info?.(`Purging PG changes before ${purgeWatermark} ...`);
|
|
489
|
+
const start = performance.now();
|
|
490
|
+
const deleted = await this.#storer.purgeRecordsBefore(purgeWatermark);
|
|
491
|
+
const elapsed = (performance.now() - start).toFixed(2);
|
|
492
|
+
this.#lc.info?.(`Purged ${deleted} PG changes before ${purgeWatermark} (${elapsed} ms)`);
|
|
493
|
+
this.#pgPurgedWatermark = purgeWatermark;
|
|
494
|
+
} catch (e) {
|
|
495
|
+
this.#lc.warn?.(`error purging the PG change log`, e);
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
async #purgeSQLiteChangeLog() {
|
|
499
|
+
const scheduler = this.#purgeScheduler;
|
|
500
|
+
if (!scheduler) return;
|
|
501
|
+
try {
|
|
502
|
+
const { backupWatermark, purgeWatermark } = this.#getCleanupFloor();
|
|
503
|
+
this.#sqlitePurgeContinuation = void 0;
|
|
504
|
+
if (purgeWatermark < backupWatermark) this.#requestSQLitePurge("deferred");
|
|
505
|
+
const result = await scheduler.purge(purgeWatermark);
|
|
506
|
+
this.#requestSQLitePurge(result.continuation);
|
|
507
|
+
} catch (e) {
|
|
508
|
+
this.#requestSQLitePurge("deferred");
|
|
509
|
+
this.#lc.warn?.(`error purging the SQLite change log`, e);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
#requestSQLitePurge(continuation) {
|
|
513
|
+
if (!this.#purgeScheduler || continuation === void 0) return;
|
|
514
|
+
if (continuation === "immediate" || this.#sqlitePurgeContinuation === void 0) this.#sqlitePurgeContinuation = continuation;
|
|
515
|
+
}
|
|
516
|
+
async stop(err) {
|
|
517
|
+
this.#state.stop(this.#lc, err);
|
|
518
|
+
this.#stream?.changes.cancel();
|
|
519
|
+
this.#purgeScheduler?.stop();
|
|
520
|
+
this.#sqliteCatchup?.close();
|
|
521
|
+
this.#changeLogWriter?.close();
|
|
522
|
+
await Promise.allSettled([this.#storer.stop(), this.#source.stop()]);
|
|
523
|
+
}
|
|
524
|
+
#recordForwardedTransactionBoundary(type, watermark) {
|
|
525
|
+
switch (type) {
|
|
526
|
+
case "begin":
|
|
527
|
+
assert(this.#currentTransactionCompletion === void 0, "forwarded begin while a transaction is already in progress");
|
|
528
|
+
this.#currentTransactionCompletion = resolver();
|
|
529
|
+
this.#transactionForwardStartedAt = performance.now();
|
|
530
|
+
break;
|
|
531
|
+
case "commit": {
|
|
532
|
+
const completion = this.#currentTransactionCompletion;
|
|
533
|
+
assert(completion, "forwarded commit without a pending transaction");
|
|
534
|
+
this.#recordTransactionForwardDuration();
|
|
535
|
+
this.#lastForwardedCommitWatermark = watermark;
|
|
536
|
+
this.#currentTransactionCompletion = void 0;
|
|
537
|
+
completion.resolve({
|
|
538
|
+
kind: "committed",
|
|
539
|
+
watermark
|
|
540
|
+
});
|
|
541
|
+
break;
|
|
542
|
+
}
|
|
543
|
+
case "rollback": {
|
|
544
|
+
const completion = this.#currentTransactionCompletion;
|
|
545
|
+
assert(completion, "forwarded rollback without a pending transaction");
|
|
546
|
+
const committed = this.#lastForwardedCommitWatermark;
|
|
547
|
+
assert(committed, "last forwarded commit watermark is not initialized");
|
|
548
|
+
this.#transactionForwardStartedAt = void 0;
|
|
549
|
+
this.#currentTransactionCompletion = void 0;
|
|
550
|
+
completion.resolve({
|
|
551
|
+
kind: "rolled-back",
|
|
552
|
+
watermark: committed
|
|
553
|
+
});
|
|
554
|
+
break;
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
#recordTransactionForwardDuration() {
|
|
559
|
+
const startedAt = this.#transactionForwardStartedAt;
|
|
560
|
+
this.#transactionForwardStartedAt = void 0;
|
|
561
|
+
if (startedAt !== void 0) this.#transactionForwardDuration.recordMs(performance.now() - startedAt, { sqlite_change_log: this.#changeLogWriter?.enabled ? "on" : "off" });
|
|
562
|
+
}
|
|
332
563
|
/**
|
|
333
|
-
*
|
|
334
|
-
*
|
|
335
|
-
*
|
|
564
|
+
* Closes and forgets the cached catchup coordinator, so that a later
|
|
565
|
+
* subscription re-opens the log from scratch rather than reading a handle
|
|
566
|
+
* whose file is gone.
|
|
336
567
|
*/
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
568
|
+
#closeSQLiteCatchup() {
|
|
569
|
+
this.#sqliteCatchup?.close();
|
|
570
|
+
this.#sqliteCatchup = void 0;
|
|
571
|
+
}
|
|
572
|
+
#captureRequiredHead() {
|
|
573
|
+
const committed = this.#lastForwardedCommitWatermark;
|
|
574
|
+
assert(committed, "last forwarded commit watermark is not initialized");
|
|
575
|
+
return this.#currentTransactionCompletion?.promise.then((completion) => completion.watermark) ?? committed;
|
|
576
|
+
}
|
|
577
|
+
#selectSQLiteCatchup(ctx) {
|
|
578
|
+
const opts = this.#sqliteCatchupOptions;
|
|
579
|
+
if (this.#lastForwardedCommitWatermark === void 0 || !opts) return;
|
|
580
|
+
if (ctx.mode !== "serving") {
|
|
581
|
+
this.#lc.info?.(`not serving backup subscriber ${ctx.id} from SQLite catchup`);
|
|
341
582
|
return;
|
|
342
583
|
}
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
this.#lc.warn?.("No subscribers to confirm cleanup");
|
|
584
|
+
if (ctx.logsChangeStream) {
|
|
585
|
+
this.#lc.warn?.(`not serving legacy change-log writer ${ctx.id} from SQLite catchup`);
|
|
346
586
|
return;
|
|
347
587
|
}
|
|
588
|
+
if (!opts.shouldUse?.(ctx)) return;
|
|
589
|
+
return this.#sqliteCatchup ?? this.#openSQLiteCatchup(opts, ctx);
|
|
590
|
+
}
|
|
591
|
+
/**
|
|
592
|
+
* Opens the change log and, if it can serve, wraps it in the coordinator that
|
|
593
|
+
* subsequent subscriptions reuse.
|
|
594
|
+
*
|
|
595
|
+
* The log may not exist yet -- the writer creates it at the stream loop's
|
|
596
|
+
* first reconcile, and deletes it when it fails soft -- or may exist without
|
|
597
|
+
* content, or may be unreadable. None of those can be allowed to fail a
|
|
598
|
+
* subscription:
|
|
599
|
+
* this is the last point at which PG catchup is still available -- past
|
|
600
|
+
* `Forwarder.add()` the subscriber is committed to SQLite -- so each declines
|
|
601
|
+
* here instead. Neither the failure nor the reader is retained, so a later
|
|
602
|
+
* subscription retries from scratch.
|
|
603
|
+
*/
|
|
604
|
+
#openSQLiteCatchup(opts, ctx) {
|
|
605
|
+
let reader;
|
|
348
606
|
try {
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
const start = performance.now();
|
|
355
|
-
const deleted = await this.#storer.purgeRecordsBefore(earliestInitial);
|
|
356
|
-
const elapsed = (performance.now() - start).toFixed(2);
|
|
357
|
-
this.#lc.info?.(`Purged ${deleted} changes before ${earliestInitial} (${elapsed} ms)`);
|
|
358
|
-
this.#initialWatermarks.delete(earliestInitial);
|
|
607
|
+
reader = new SQLiteChangeLogReader(this.#lc, opts.changeLogFile);
|
|
608
|
+
if (reader.plan(ctx.watermark).kind === "not-ready") {
|
|
609
|
+
reader.close();
|
|
610
|
+
this.#declineSQLiteCatchup(ctx, opts, `${opts.changeLogFile} has no changes to serve yet`);
|
|
611
|
+
return;
|
|
359
612
|
}
|
|
360
613
|
} catch (e) {
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
614
|
+
reader?.close();
|
|
615
|
+
this.#declineSQLiteCatchup(ctx, opts, `cannot read ${opts.changeLogFile}`, e);
|
|
616
|
+
return;
|
|
364
617
|
}
|
|
618
|
+
this.#changeLogUnavailableSince = void 0;
|
|
619
|
+
this.#sqliteCatchup = new SQLiteChangeLogCatchup(this.#lc, this.#forwarder, reader, {
|
|
620
|
+
batchSize: opts.readBatchRows,
|
|
621
|
+
barrierTimeoutMs: opts.barrierTimeoutMs,
|
|
622
|
+
barrierPollIntervalMs: opts.barrierPollIntervalMs,
|
|
623
|
+
cleanupGuard: opts.cleanupGuard
|
|
624
|
+
});
|
|
625
|
+
return this.#sqliteCatchup;
|
|
365
626
|
}
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
627
|
+
/**
|
|
628
|
+
* Reports falling back to PG catchup, tracking how long the log has been
|
|
629
|
+
* unavailable so that a subscription that merely arrived before the writer's
|
|
630
|
+
* first reconcile does not look like an incident.
|
|
631
|
+
*/
|
|
632
|
+
#declineSQLiteCatchup(ctx, opts, reason, error) {
|
|
633
|
+
const now = Date.now();
|
|
634
|
+
this.#changeLogUnavailableSince ??= now;
|
|
635
|
+
const unavailableMs = now - this.#changeLogUnavailableSince;
|
|
636
|
+
const threshold = opts.notReadyWarnThresholdMs ?? DEFAULT_CHANGE_LOG_UNAVAILABLE_WARN_THRESHOLD_MS;
|
|
637
|
+
this.#lc[unavailableMs >= threshold ? "warn" : "debug"]?.(`serving ${ctx.id} from PG catchup: ${reason} (unavailable for ${unavailableMs} ms)`, ...error === void 0 ? [] : [error]);
|
|
371
638
|
}
|
|
372
639
|
};
|
|
373
640
|
var CLEANUP_DELAY_MS = DEFAULT_MAX_RETRY_DELAY_MS * 3;
|