@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
|
@@ -1,31 +1,41 @@
|
|
|
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";
|
|
4
|
+
import { promiseOrAbort } from "../../../../shared/src/promise-race.js";
|
|
3
5
|
import "../change-source/protocol/current/downstream.js";
|
|
4
|
-
import { getOrCreateCounter } from "../../observability/metrics.js";
|
|
6
|
+
import { getOrCreateCounter, getOrCreateLatencyHistogram } from "../../observability/metrics.js";
|
|
5
7
|
import { DEFAULT_MAX_RETRY_DELAY_MS, RunningState, UnrecoverableError } from "../running-state.js";
|
|
6
8
|
import { min } from "../../types/lexi-version.js";
|
|
7
9
|
import { publishCriticalEvent } from "../../observability/events.js";
|
|
8
|
-
import { AutoResetSignal, ensureReplicationConfig, markResetRequired } from "./schema/tables.js";
|
|
9
10
|
import { Subscription } from "../../types/subscription.js";
|
|
11
|
+
import { AutoResetSignal, ensureReplicationConfig, markResetRequired } from "./schema/tables.js";
|
|
10
12
|
import { publishReplicationError, replicationStatusError } from "../replicator/replication-status.js";
|
|
11
13
|
import "./change-streamer.js";
|
|
14
|
+
import { SQLiteChangeLogReader } from "./sqlite-change-log-reader.js";
|
|
15
|
+
import { ChangeLogInitializer, replicaInitializationSource } from "./change-log-initializer.js";
|
|
12
16
|
import { Forwarder } from "./forwarder.js";
|
|
13
|
-
import {
|
|
17
|
+
import { SnapshotReservations } from "./snapshot-reservations.js";
|
|
18
|
+
import { SQLiteChangeLogCatchup } from "./sqlite-change-log-catchup.js";
|
|
19
|
+
import { SQLiteChangeLogComparator } from "./sqlite-change-log-comparator.js";
|
|
20
|
+
import { SQLiteChangeLogPurgeScheduler } from "./sqlite-change-log-purge-scheduler.js";
|
|
21
|
+
import { SQLiteChangeLogReadRouter, inspectSQLiteChangeLog } from "./sqlite-change-log-read-router.js";
|
|
22
|
+
import { SQLiteChangeLogWriter } from "./sqlite-change-log-writer.js";
|
|
14
23
|
import { Storer } from "./storer.js";
|
|
15
24
|
import { Subscriber } from "./subscriber.js";
|
|
25
|
+
import { UpstreamAcker } from "./upstream-acker.js";
|
|
16
26
|
import { resolver } from "@rocicorp/resolver";
|
|
17
27
|
import { getDefaultHighWaterMark } from "node:stream";
|
|
18
28
|
//#region ../zero-cache/src/services/change-streamer/change-streamer-service.ts
|
|
19
29
|
/**
|
|
20
30
|
* Performs initialization and schema migrations to initialize a ChangeStreamerImpl.
|
|
21
31
|
*/
|
|
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);
|
|
32
|
+
async function initializeStreamer(lc, shard, taskID, discoveryAddress, discoveryProtocol, changeDB, changeSource, replicationStatusPublisher, subscriptionState, backupConfig, purgeLock, autoReset, opts, setTimeoutFn = setTimeout) {
|
|
33
|
+
await ensureReplicationConfig(lc, changeDB, subscriptionState, shard, autoReset, purgeLock ?? void 0, setTimeoutFn);
|
|
25
34
|
const { replicaVersion } = subscriptionState;
|
|
26
|
-
return new ChangeStreamerImpl(lc, shard, taskID, discoveryAddress, discoveryProtocol, changeDB, replicaVersion, changeSource, replicationStatusPublisher, purgeLock, autoReset, opts, setTimeoutFn);
|
|
35
|
+
return new ChangeStreamerImpl(lc, shard, taskID, discoveryAddress, discoveryProtocol, changeDB, replicaVersion, changeSource, replicationStatusPublisher, backupConfig, purgeLock, autoReset, opts, setTimeoutFn);
|
|
27
36
|
}
|
|
28
37
|
var REPLICATION_STATUS_ERROR_DELAY_THRESHOLD_MS = 5e3;
|
|
38
|
+
var DEFAULT_CHANGE_LOG_UNAVAILABLE_WARN_THRESHOLD_MS = 6e4;
|
|
29
39
|
/**
|
|
30
40
|
* Upstream-agnostic dispatch of messages in a {@link ChangeStreamMessage} to a
|
|
31
41
|
* {@link Forwarder} and {@link Storer} to execute the forward-store-ack
|
|
@@ -173,30 +183,115 @@ var ChangeStreamerImpl = class {
|
|
|
173
183
|
#source;
|
|
174
184
|
#storer;
|
|
175
185
|
#forwarder;
|
|
186
|
+
#reservations;
|
|
176
187
|
#replicationStatusPublisher;
|
|
188
|
+
#sqliteCatchupOptions;
|
|
189
|
+
#changeLogWriter;
|
|
190
|
+
#purgeScheduler;
|
|
191
|
+
#comparator;
|
|
192
|
+
#acker;
|
|
193
|
+
#initializer;
|
|
194
|
+
#readRouter;
|
|
177
195
|
#autoReset;
|
|
178
196
|
#state;
|
|
179
|
-
#initialWatermarks = /* @__PURE__ */ new Set();
|
|
180
197
|
#serving = resolver();
|
|
181
198
|
#txCounter = getOrCreateCounter("replication", "transactions", "Count of replicated transactions");
|
|
182
199
|
#changeCounter = getOrCreateCounter("replication", "changes", "Count of replicated changes (DML or DDL statements)");
|
|
200
|
+
#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.");
|
|
201
|
+
#catchupRoutes = getOrCreateCounter("replication", "sqlite_change_log.catchup_routes", "Catchup subscriptions by selected source and low-cardinality reason.");
|
|
202
|
+
#reservationDemotions = getOrCreateCounter("replication", "sqlite_change_log.reservation_demotions", "Snapshot reservations demoted from SQLite to PG because the change log could not cover the backup being restored. With PG retired these followers have no fallback, so this is the rate at which one would instead have to wait for a later backup.");
|
|
203
|
+
#reservationConfirmDelays = getOrCreateCounter("replication", "sqlite_change_log.reservation_confirm_delays", "Snapshot reservations whose confirmation was deferred because the selected source's change-log minimum was later than the backup watermark. Counted once per reservation, by that source.");
|
|
183
204
|
#latestStatus;
|
|
205
|
+
#latestLagReportCommitTimeMs = 0;
|
|
206
|
+
#backupWatermark;
|
|
207
|
+
#pgPurgedWatermark = "";
|
|
208
|
+
/**
|
|
209
|
+
* The floor last logged as held back by a laggard. The level-triggered
|
|
210
|
+
* retry re-evaluates every {@link CLEANUP_DELAY_MS}; logging only when the
|
|
211
|
+
* blocking floor moves keeps a stuck subscriber from emitting the same
|
|
212
|
+
* line indefinitely.
|
|
213
|
+
*/
|
|
214
|
+
#loggedBehindWatermark;
|
|
215
|
+
#sqlitePurgeContinuation;
|
|
184
216
|
#purgeLock;
|
|
217
|
+
#pgPurgeScheduled = false;
|
|
218
|
+
#pgPurgeRunning = false;
|
|
219
|
+
#sqlitePurgeScheduled = false;
|
|
220
|
+
#sqlitePurgeRunning = false;
|
|
185
221
|
#stream;
|
|
186
|
-
|
|
222
|
+
#sqliteCatchup;
|
|
223
|
+
#changeLogUnavailableSince;
|
|
224
|
+
#lastForwardedCommitWatermark;
|
|
225
|
+
#transactionForwardStartedAt;
|
|
226
|
+
#currentTransactionCompletion;
|
|
227
|
+
constructor(lc, shard, taskID, discoveryAddress, discoveryProtocol, changeDB, replicaVersion, source, replicationStatusPublisher, backupConfig, initialPurgeLock, autoReset, opts, setTimeoutFn = setTimeout) {
|
|
187
228
|
this.id = `change-streamer`;
|
|
188
229
|
this.#lc = lc.withContext("component", "change-streamer");
|
|
189
230
|
this.#shard = shard;
|
|
190
231
|
this.#changeDB = changeDB;
|
|
191
232
|
this.#replicaVersion = replicaVersion;
|
|
192
233
|
this.#source = source;
|
|
193
|
-
this.#storer = new Storer(lc, shard, taskID, discoveryAddress, discoveryProtocol, changeDB, replicaVersion, (consumed) => this.#
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
234
|
+
this.#storer = new Storer(lc, shard, taskID, discoveryAddress, discoveryProtocol, changeDB, replicaVersion, (consumed) => this.#acker.trackPgChangeLog(consumed[2].watermark), (err) => this.stop(err), opts);
|
|
235
|
+
this.#forwarder = new Forwarder(lc, {
|
|
236
|
+
flowControlConsensusTimeoutProportion: opts.flowControlConsensusTimeoutProportion,
|
|
237
|
+
flowControlSlowSubscriberGracePeriodMs: opts.flowControlSlowSubscriberGracePeriodMs
|
|
238
|
+
});
|
|
239
|
+
const serveOptions = opts.sqliteChangeLogServe;
|
|
240
|
+
const writerOptions = opts.sqliteChangeLogWriter;
|
|
241
|
+
const catchupOptions = opts.sqliteCatchup;
|
|
242
|
+
this.#readRouter = serveOptions && writerOptions && catchupOptions ? new SQLiteChangeLogReadRouter({
|
|
243
|
+
shard,
|
|
244
|
+
readPercent: serveOptions.readPercent,
|
|
245
|
+
coldReadPercent: serveOptions.coldReadPercent,
|
|
246
|
+
retentionMs: serveOptions.retentionMs,
|
|
247
|
+
failureCooldownMs: serveOptions.failureCooldownMs,
|
|
248
|
+
now: serveOptions.now,
|
|
249
|
+
inspect: serveOptions.inspect ?? (() => inspectSQLiteChangeLog(lc, catchupOptions.changeLogFile, writerOptions.identity))
|
|
250
|
+
}) : void 0;
|
|
251
|
+
this.#reservations = backupConfig ? new SnapshotReservations(lc, backupConfig, (taskID) => {
|
|
252
|
+
this.#readRouter?.release(taskID);
|
|
253
|
+
this.#purgeScheduler?.resume(taskID);
|
|
254
|
+
}) : void 0;
|
|
199
255
|
this.#replicationStatusPublisher = replicationStatusPublisher;
|
|
256
|
+
this.#changeLogWriter = opts.sqliteChangeLogWriter ? new SQLiteChangeLogWriter(lc, {
|
|
257
|
+
...opts.sqliteChangeLogWriter,
|
|
258
|
+
onCommit: (watermark) => {
|
|
259
|
+
this.#sqliteCatchup?.onChangeLogCommit(watermark);
|
|
260
|
+
this.#purgeScheduler?.onWriterIdle();
|
|
261
|
+
},
|
|
262
|
+
onDisabled: () => {
|
|
263
|
+
this.#readRouter?.trip(true);
|
|
264
|
+
this.#closeSQLiteCatchup();
|
|
265
|
+
this.#comparator?.stop();
|
|
266
|
+
},
|
|
267
|
+
onRebuilt: () => {
|
|
268
|
+
this.#closeSQLiteCatchup();
|
|
269
|
+
this.#comparator?.invalidate();
|
|
270
|
+
}
|
|
271
|
+
}) : void 0;
|
|
272
|
+
this.#purgeScheduler = opts.sqliteChangeLogPurge && this.#changeLogWriter ? new SQLiteChangeLogPurgeScheduler(lc, () => this.#changeLogWriter?.connection, () => this.#forwarder.getAcks(), opts.sqliteChangeLogPurge) : void 0;
|
|
273
|
+
this.#acker = new UpstreamAcker({
|
|
274
|
+
trackPgChangeLog: true,
|
|
275
|
+
trackBackup: backupConfig?.litestreamVersion === "v5"
|
|
276
|
+
});
|
|
277
|
+
const replicaSource = opts.sqliteChangeLogCompare ? replicaInitializationSource(lc, opts.sqliteChangeLogCompare.replicaFile) : void 0;
|
|
278
|
+
this.#initializer = new ChangeLogInitializer(lc, {
|
|
279
|
+
initFromPgChangeLog: true,
|
|
280
|
+
initFromReplica: replicaSource !== void 0
|
|
281
|
+
}, {
|
|
282
|
+
pgChangeLog: () => this.#storer.getStartStreamInitializationParameters(),
|
|
283
|
+
replica: () => must(replicaSource)(),
|
|
284
|
+
reconcileChangeLog: (resumeFrom, seed) => resumeFrom ? this.#changeLogWriter?.reconcile(resumeFrom) : this.#changeLogWriter?.reconcileFromLog(seed),
|
|
285
|
+
changeLog: () => this.#changeLogWriter?.connection
|
|
286
|
+
});
|
|
287
|
+
this.#sqliteCatchupOptions = opts.sqliteCatchup ? {
|
|
288
|
+
...opts.sqliteCatchup,
|
|
289
|
+
cleanupGuard: opts.sqliteCatchup.cleanupGuard ?? this.#purgeScheduler?.cleanupGuard
|
|
290
|
+
} : void 0;
|
|
291
|
+
this.#comparator = opts.sqliteChangeLogCompare && opts.sqliteChangeLogWriter && opts.sqliteCatchup ? new SQLiteChangeLogComparator(lc, shard, opts.sqliteCatchup.changeLogFile, opts.sqliteChangeLogWriter.identity, this.#storer, {
|
|
292
|
+
setTimeoutFn,
|
|
293
|
+
...opts.sqliteChangeLogCompare
|
|
294
|
+
}) : void 0;
|
|
200
295
|
this.#purgeLock = initialPurgeLock;
|
|
201
296
|
this.#autoReset = autoReset;
|
|
202
297
|
this.#state = new RunningState(this.id, void 0, setTimeoutFn);
|
|
@@ -205,8 +300,11 @@ var ChangeStreamerImpl = class {
|
|
|
205
300
|
async run() {
|
|
206
301
|
this.#lc.info?.("starting change stream");
|
|
207
302
|
this.#forwarder.startProgressMonitor();
|
|
208
|
-
const
|
|
209
|
-
if (
|
|
303
|
+
const lagReportInit = await this.#source.startLagReporter();
|
|
304
|
+
if (lagReportInit) {
|
|
305
|
+
this.#latestStatus.lagReport = { nextSendTimeMs: lagReportInit.nextSendTimeMs };
|
|
306
|
+
this.#latestLagReportCommitTimeMs = lagReportInit.firstCommitTimeMs;
|
|
307
|
+
}
|
|
210
308
|
await this.#storer.assumeOwnership(this.#purgeLock);
|
|
211
309
|
this.#purgeLock = null;
|
|
212
310
|
const flushBytesThreshold = getDefaultHighWaterMark(false);
|
|
@@ -215,19 +313,22 @@ var ChangeStreamerImpl = class {
|
|
|
215
313
|
let watermark = null;
|
|
216
314
|
let unflushedBytes = 0;
|
|
217
315
|
try {
|
|
218
|
-
const { lastWatermark, backfillRequests } = await this.#
|
|
316
|
+
const { lastWatermark, backfillRequests } = await this.#initializer.initialize();
|
|
317
|
+
this.#lastForwardedCommitWatermark = lastWatermark;
|
|
219
318
|
const stream = await this.#source.startStream(lastWatermark, backfillRequests);
|
|
220
319
|
this.#storer.run().catch((e) => stream.changes.cancel(e));
|
|
221
320
|
this.#stream = stream;
|
|
222
321
|
if (this.#state.resetBackoff() > REPLICATION_STATUS_ERROR_DELAY_THRESHOLD_MS) this.#replicationStatusPublisher.publish(this.#lc, "Replicating", `Replicating from ${lastWatermark}`);
|
|
223
322
|
watermark = null;
|
|
323
|
+
this.#acker.reset(stream.acks);
|
|
224
324
|
for await (const change of stream.changes) {
|
|
325
|
+
this.#acker.trackDownstream(change);
|
|
225
326
|
const [type, msg] = change;
|
|
226
327
|
switch (type) {
|
|
227
328
|
case "status":
|
|
228
|
-
if (msg.
|
|
229
|
-
if (msg.lagReport) {
|
|
329
|
+
if (msg.lagReport && msg.lagReport.lastTimings.commitTimeMs >= this.#latestLagReportCommitTimeMs) {
|
|
230
330
|
this.#latestStatus.lagReport = msg.lagReport;
|
|
331
|
+
this.#latestLagReportCommitTimeMs = msg.lagReport.lastTimings.commitTimeMs;
|
|
231
332
|
this.#forwarder.sendStatus(this.#latestStatus);
|
|
232
333
|
}
|
|
233
334
|
continue;
|
|
@@ -247,20 +348,25 @@ var ChangeStreamerImpl = class {
|
|
|
247
348
|
break;
|
|
248
349
|
}
|
|
249
350
|
const json = this.#storer.store(watermark, change);
|
|
351
|
+
this.#changeLogWriter?.write(change, json);
|
|
250
352
|
const entry = [
|
|
251
353
|
watermark,
|
|
252
354
|
change[1].tag,
|
|
253
355
|
json
|
|
254
356
|
];
|
|
255
357
|
unflushedBytes += json.length;
|
|
256
|
-
if (unflushedBytes < flushBytesThreshold)
|
|
257
|
-
|
|
258
|
-
|
|
358
|
+
if (unflushedBytes < flushBytesThreshold) {
|
|
359
|
+
this.#forwarder.forward(entry);
|
|
360
|
+
this.#recordForwardedTransactionBoundary(type, entry[0]);
|
|
361
|
+
} else {
|
|
362
|
+
const forwarded = this.#forwarder.forwardWithFlowControl(entry);
|
|
363
|
+
this.#recordForwardedTransactionBoundary(type, entry[0]);
|
|
364
|
+
await promiseOrAbort(forwarded, stream.changes.signal, this.#state.signal);
|
|
259
365
|
unflushedBytes = 0;
|
|
260
366
|
}
|
|
261
367
|
if (type === "commit" || type === "rollback") watermark = null;
|
|
262
368
|
const readyForMore = this.#storer.readyForMore();
|
|
263
|
-
if (readyForMore) await readyForMore;
|
|
369
|
+
if (readyForMore) await promiseOrAbort(readyForMore, stream.changes.signal, this.#state.signal);
|
|
264
370
|
}
|
|
265
371
|
} catch (e) {
|
|
266
372
|
err = e;
|
|
@@ -271,11 +377,14 @@ var ChangeStreamerImpl = class {
|
|
|
271
377
|
if (watermark) {
|
|
272
378
|
this.#lc.warn?.(`aborting interrupted transaction ${watermark}`);
|
|
273
379
|
this.#storer.abort();
|
|
380
|
+
this.#changeLogWriter?.abort();
|
|
381
|
+
this.#purgeScheduler?.onWriterIdle();
|
|
274
382
|
this.#forwarder.forward([
|
|
275
383
|
watermark,
|
|
276
384
|
"rollback",
|
|
277
385
|
ROLLBACK_JSON
|
|
278
386
|
]);
|
|
387
|
+
this.#recordForwardedTransactionBoundary("rollback", watermark);
|
|
279
388
|
}
|
|
280
389
|
await Promise.all([
|
|
281
390
|
this.#storer.stop(),
|
|
@@ -301,27 +410,135 @@ var ChangeStreamerImpl = class {
|
|
|
301
410
|
default: unreachable(tag);
|
|
302
411
|
}
|
|
303
412
|
}
|
|
304
|
-
subscribe(ctx) {
|
|
413
|
+
async subscribe(ctx) {
|
|
305
414
|
const { protocolVersion, id, mode, replicaVersion, watermark } = ctx;
|
|
306
415
|
if (mode === "serving") this.#serving.resolve();
|
|
307
|
-
|
|
308
|
-
const
|
|
416
|
+
let cleanupSubscriber = () => {};
|
|
417
|
+
const downstream = Subscription.create({ cleanup: () => cleanupSubscriber() });
|
|
418
|
+
const subscriber = new Subscriber(protocolVersion, id, watermark, downstream, () => this.#latestStatus, {});
|
|
419
|
+
const lc = this.#lc.withContext("subscriber", subscriber.id);
|
|
420
|
+
const removeFromForwarder = () => {
|
|
421
|
+
lc.info?.(`removing subscriber ${subscriber.id}`);
|
|
422
|
+
this.#forwarder.remove(subscriber);
|
|
423
|
+
};
|
|
424
|
+
cleanupSubscriber = removeFromForwarder;
|
|
309
425
|
if (replicaVersion !== this.#replicaVersion) {
|
|
310
|
-
|
|
426
|
+
lc.warn?.(`rejecting subscriber at replica version ${replicaVersion}`);
|
|
311
427
|
subscriber.close(1, `current replica version is ${this.#replicaVersion} (requested ${replicaVersion})`);
|
|
312
428
|
} else {
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
429
|
+
lc.info?.(`adding subscriber ${subscriber.id}`);
|
|
430
|
+
const catchupFromPG = () => {
|
|
431
|
+
cleanupSubscriber = removeFromForwarder;
|
|
432
|
+
this.#forwarder.add(subscriber);
|
|
433
|
+
this.#storer.catchup(subscriber, mode);
|
|
434
|
+
};
|
|
435
|
+
const sqliteSelection = this.#selectSQLiteCatchup(lc, ctx);
|
|
436
|
+
if (!sqliteSelection) catchupFromPG();
|
|
437
|
+
else {
|
|
438
|
+
const { catchup, reason, coverage, logWarm } = sqliteSelection;
|
|
439
|
+
cleanupSubscriber = () => catchup.remove(subscriber);
|
|
440
|
+
const registration = await catchup.catchup(subscriber, () => this.#captureRequiredHead(), { logWarm });
|
|
441
|
+
switch (registration.kind) {
|
|
442
|
+
case "registered":
|
|
443
|
+
lc.debug?.(`serving ${ctx.id} from SQLite catchup`, ...coverage ? [{ sqliteChangeLogCoverage: coverage }] : []);
|
|
444
|
+
this.#recordCatchupRoute("sqlite", reason);
|
|
445
|
+
break;
|
|
446
|
+
case "uncovered":
|
|
447
|
+
lc.info?.(`serving ${ctx.id} from PG catchup: subscriber watermark ${ctx.watermark} is below the SQLite change-log minimum ` + registration.minWatermark);
|
|
448
|
+
this.#recordCatchupRoute("pg", "watermark-uncovered");
|
|
449
|
+
catchupFromPG();
|
|
450
|
+
break;
|
|
451
|
+
case "declined":
|
|
452
|
+
lc.error?.(`serving ${ctx.id} from PG catchup: SQLite catchup registration failed`, registration.error);
|
|
453
|
+
this.#recordCatchupRoute("pg", "registration-failed");
|
|
454
|
+
catchupFromPG();
|
|
455
|
+
break;
|
|
456
|
+
case "handled":
|
|
457
|
+
this.#recordCatchupRoute("sqlite", "registration-handled");
|
|
458
|
+
break;
|
|
459
|
+
default: unreachable(registration);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
this.#reservations?.close(ctx.taskID);
|
|
464
|
+
return downstream;
|
|
465
|
+
}
|
|
466
|
+
async startSnapshotReservation(taskID) {
|
|
467
|
+
if (!this.#reservations) throw new Error("backups are not configured");
|
|
468
|
+
const downstream = this.#reservations.open(taskID);
|
|
469
|
+
try {
|
|
470
|
+
await (this.#purgeScheduler?.pause(taskID) ?? promiseVoid);
|
|
471
|
+
if (!this.#reservations.isCurrent(taskID, downstream)) return downstream;
|
|
472
|
+
this.#readRouter?.pin(taskID);
|
|
473
|
+
await this.#confirmReservations();
|
|
474
|
+
return downstream;
|
|
475
|
+
} catch (e) {
|
|
476
|
+
downstream.cancel();
|
|
477
|
+
throw e;
|
|
316
478
|
}
|
|
317
|
-
return Promise.resolve(downstream);
|
|
318
479
|
}
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
this.#
|
|
322
|
-
|
|
480
|
+
trackBackupWatermark(watermark) {
|
|
481
|
+
this.#backupWatermark = watermark;
|
|
482
|
+
this.#acker.trackBackup(watermark);
|
|
483
|
+
this.#requestSQLitePurge("deferred");
|
|
484
|
+
this.#maybeSchedulePGPurge();
|
|
485
|
+
this.#maybeScheduleSQLitePurge();
|
|
486
|
+
this.#confirmReservations().catch((e) => this.#lc.warn?.(`error confirming snapshot reservation`, e));
|
|
323
487
|
}
|
|
324
|
-
async
|
|
488
|
+
async #confirmReservations() {
|
|
489
|
+
const backupWatermark = this.#backupWatermark;
|
|
490
|
+
const reservations = this.#reservations;
|
|
491
|
+
if (backupWatermark === void 0 || !reservations?.confirmationsRequired()) return;
|
|
492
|
+
const pgState = await this.#getChangeLogState();
|
|
493
|
+
for (const taskID of reservations.unconfirmedTaskIDs()) {
|
|
494
|
+
let route = this.#readRouter?.peek(taskID);
|
|
495
|
+
if (this.#readRouter && route === void 0) continue;
|
|
496
|
+
if (route?.source === "sqlite") {
|
|
497
|
+
const coverage = must(route.coverage, "a pinned SQLite route must carry its covered range");
|
|
498
|
+
if (coverage.minWatermark > backupWatermark) {
|
|
499
|
+
this.#lc.info?.(`demoting ${taskID} to PG catchup: SQLite change-log minimum ${coverage.minWatermark} is later than backupWatermark ` + backupWatermark);
|
|
500
|
+
this.#reservationDemotions.add(1);
|
|
501
|
+
route = must(this.#readRouter).demote(taskID);
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
const source = route?.source ?? "pg";
|
|
505
|
+
let minWatermark;
|
|
506
|
+
if (route?.source === "sqlite") minWatermark = must(route.coverage, "a pinned SQLite route must carry its covered range").minWatermark;
|
|
507
|
+
else ({minWatermark} = pgState);
|
|
508
|
+
if (minWatermark <= backupWatermark) reservations.confirmFor(taskID, pgState.replicaVersion, backupWatermark, source);
|
|
509
|
+
else {
|
|
510
|
+
if (reservations.noteConfirmationDelayed(taskID)) this.#reservationConfirmDelays.add(1);
|
|
511
|
+
this.#lc.error?.(`pg change-log minWatermark ${minWatermark} is later than backupWatermark ${backupWatermark}. Delaying confirmation of snapshot reservation until next backup.`);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
#maybeSchedulePGPurge() {
|
|
516
|
+
const backupWatermark = this.#backupWatermark;
|
|
517
|
+
if (this.#pgPurgeScheduled || this.#pgPurgeRunning || backupWatermark === void 0 || this.#pgPurgedWatermark >= backupWatermark) return;
|
|
518
|
+
this.#pgPurgeScheduled = true;
|
|
519
|
+
this.#state.setTimeout(() => {
|
|
520
|
+
this.#pgPurgeScheduled = false;
|
|
521
|
+
this.#pgPurgeRunning = true;
|
|
522
|
+
return this.#purgePGChangeLog().finally(() => {
|
|
523
|
+
this.#pgPurgeRunning = false;
|
|
524
|
+
this.#maybeSchedulePGPurge();
|
|
525
|
+
});
|
|
526
|
+
}, CLEANUP_DELAY_MS);
|
|
527
|
+
}
|
|
528
|
+
#maybeScheduleSQLitePurge() {
|
|
529
|
+
if (this.#sqlitePurgeScheduled || this.#sqlitePurgeRunning || this.#backupWatermark === void 0 || this.#sqlitePurgeContinuation === void 0) return;
|
|
530
|
+
const delay = this.#sqlitePurgeContinuation === "immediate" ? 0 : CLEANUP_DELAY_MS;
|
|
531
|
+
this.#sqlitePurgeScheduled = true;
|
|
532
|
+
this.#state.setTimeout(() => {
|
|
533
|
+
this.#sqlitePurgeScheduled = false;
|
|
534
|
+
this.#sqlitePurgeRunning = true;
|
|
535
|
+
return this.#purgeSQLiteChangeLog().finally(() => {
|
|
536
|
+
this.#sqlitePurgeRunning = false;
|
|
537
|
+
this.#maybeScheduleSQLitePurge();
|
|
538
|
+
});
|
|
539
|
+
}, delay);
|
|
540
|
+
}
|
|
541
|
+
async #getChangeLogState() {
|
|
325
542
|
const minWatermark = await this.#storer.getMinWatermarkForCatchup();
|
|
326
543
|
if (!minWatermark) this.#lc.warn?.(`Unexpected empty changeLog. Resync if "Local replica watermark" errors arise`);
|
|
327
544
|
return {
|
|
@@ -329,45 +546,218 @@ var ChangeStreamerImpl = class {
|
|
|
329
546
|
minWatermark: minWatermark ?? this.#replicaVersion
|
|
330
547
|
};
|
|
331
548
|
}
|
|
549
|
+
#getCleanupFloor() {
|
|
550
|
+
const backupWatermark = this.#backupWatermark;
|
|
551
|
+
assert(backupWatermark !== void 0, "cleanup cannot run without a backup watermark");
|
|
552
|
+
const current = [...this.#forwarder.getAcks(), ...this.#reservations?.getReservedWatermarks() ?? []];
|
|
553
|
+
return {
|
|
554
|
+
backupWatermark,
|
|
555
|
+
purgeWatermark: min(backupWatermark, ...current),
|
|
556
|
+
current
|
|
557
|
+
};
|
|
558
|
+
}
|
|
559
|
+
async #purgePGChangeLog() {
|
|
560
|
+
try {
|
|
561
|
+
const { backupWatermark, purgeWatermark, current } = this.#getCleanupFloor();
|
|
562
|
+
if (purgeWatermark < backupWatermark) {
|
|
563
|
+
if (this.#loggedBehindWatermark !== purgeWatermark) {
|
|
564
|
+
this.#loggedBehindWatermark = purgeWatermark;
|
|
565
|
+
this.#lc.info?.(`At least one client is behind backup ${backupWatermark}`, { watermarks: current });
|
|
566
|
+
}
|
|
567
|
+
} else this.#loggedBehindWatermark = void 0;
|
|
568
|
+
if (purgeWatermark <= this.#pgPurgedWatermark) return;
|
|
569
|
+
this.#lc.info?.(`Purging PG changes before ${purgeWatermark} ...`);
|
|
570
|
+
const start = performance.now();
|
|
571
|
+
const deleted = await this.#storer.purgeRecordsBefore(purgeWatermark);
|
|
572
|
+
const elapsed = (performance.now() - start).toFixed(2);
|
|
573
|
+
this.#lc.info?.(`Purged ${deleted} PG changes before ${purgeWatermark} (${elapsed} ms)`);
|
|
574
|
+
this.#pgPurgedWatermark = purgeWatermark;
|
|
575
|
+
} catch (e) {
|
|
576
|
+
this.#lc.warn?.(`error purging the PG change log`, e);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
async #purgeSQLiteChangeLog() {
|
|
580
|
+
const scheduler = this.#purgeScheduler;
|
|
581
|
+
if (!scheduler) return;
|
|
582
|
+
try {
|
|
583
|
+
const { backupWatermark, purgeWatermark } = this.#getCleanupFloor();
|
|
584
|
+
this.#sqlitePurgeContinuation = void 0;
|
|
585
|
+
if (purgeWatermark < backupWatermark) this.#requestSQLitePurge("deferred");
|
|
586
|
+
const result = await scheduler.purge(purgeWatermark);
|
|
587
|
+
this.#requestSQLitePurge(result.continuation);
|
|
588
|
+
} catch (e) {
|
|
589
|
+
this.#requestSQLitePurge("deferred");
|
|
590
|
+
this.#lc.warn?.(`error purging the SQLite change log`, e);
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
#requestSQLitePurge(continuation) {
|
|
594
|
+
if (!this.#purgeScheduler || continuation === void 0) return;
|
|
595
|
+
if (continuation === "immediate" || this.#sqlitePurgeContinuation === void 0) this.#sqlitePurgeContinuation = continuation;
|
|
596
|
+
}
|
|
597
|
+
async stop(err) {
|
|
598
|
+
this.#state.stop(this.#lc, err);
|
|
599
|
+
this.#stream?.changes.cancel();
|
|
600
|
+
this.#purgeScheduler?.stop();
|
|
601
|
+
this.#comparator?.stop();
|
|
602
|
+
this.#sqliteCatchup?.close();
|
|
603
|
+
this.#changeLogWriter?.close();
|
|
604
|
+
await Promise.allSettled([this.#storer.stop(), this.#source.stop()]);
|
|
605
|
+
}
|
|
606
|
+
#recordForwardedTransactionBoundary(type, watermark) {
|
|
607
|
+
switch (type) {
|
|
608
|
+
case "begin":
|
|
609
|
+
assert(this.#currentTransactionCompletion === void 0, "forwarded begin while a transaction is already in progress");
|
|
610
|
+
this.#currentTransactionCompletion = resolver();
|
|
611
|
+
this.#transactionForwardStartedAt = performance.now();
|
|
612
|
+
break;
|
|
613
|
+
case "commit": {
|
|
614
|
+
const completion = this.#currentTransactionCompletion;
|
|
615
|
+
assert(completion, "forwarded commit without a pending transaction");
|
|
616
|
+
this.#recordTransactionForwardDuration();
|
|
617
|
+
this.#lastForwardedCommitWatermark = watermark;
|
|
618
|
+
this.#currentTransactionCompletion = void 0;
|
|
619
|
+
completion.resolve({
|
|
620
|
+
kind: "committed",
|
|
621
|
+
watermark
|
|
622
|
+
});
|
|
623
|
+
break;
|
|
624
|
+
}
|
|
625
|
+
case "rollback": {
|
|
626
|
+
const completion = this.#currentTransactionCompletion;
|
|
627
|
+
assert(completion, "forwarded rollback without a pending transaction");
|
|
628
|
+
const committed = this.#lastForwardedCommitWatermark;
|
|
629
|
+
assert(committed, "last forwarded commit watermark is not initialized");
|
|
630
|
+
this.#transactionForwardStartedAt = void 0;
|
|
631
|
+
this.#currentTransactionCompletion = void 0;
|
|
632
|
+
completion.resolve({
|
|
633
|
+
kind: "rolled-back",
|
|
634
|
+
watermark: committed
|
|
635
|
+
});
|
|
636
|
+
break;
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
#recordTransactionForwardDuration() {
|
|
641
|
+
const startedAt = this.#transactionForwardStartedAt;
|
|
642
|
+
this.#transactionForwardStartedAt = void 0;
|
|
643
|
+
if (startedAt !== void 0) this.#transactionForwardDuration.recordMs(performance.now() - startedAt, { sqlite_change_log: this.#changeLogWriter?.enabled ? "on" : "off" });
|
|
644
|
+
}
|
|
332
645
|
/**
|
|
333
|
-
*
|
|
334
|
-
*
|
|
335
|
-
*
|
|
646
|
+
* Closes and forgets the cached catchup coordinator, so that a later
|
|
647
|
+
* subscription re-opens the log from scratch rather than reading a handle
|
|
648
|
+
* whose file is gone.
|
|
336
649
|
*/
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
650
|
+
#closeSQLiteCatchup() {
|
|
651
|
+
this.#sqliteCatchup?.close();
|
|
652
|
+
this.#sqliteCatchup = void 0;
|
|
653
|
+
}
|
|
654
|
+
#captureRequiredHead() {
|
|
655
|
+
const committed = this.#lastForwardedCommitWatermark;
|
|
656
|
+
assert(committed, "last forwarded commit watermark is not initialized");
|
|
657
|
+
return this.#currentTransactionCompletion?.promise.then((completion) => completion.watermark) ?? committed;
|
|
658
|
+
}
|
|
659
|
+
#selectSQLiteCatchup(lc, ctx) {
|
|
660
|
+
const opts = this.#sqliteCatchupOptions;
|
|
661
|
+
if (this.#lastForwardedCommitWatermark === void 0 || !opts) {
|
|
662
|
+
this.#recordCatchupRoute("pg", "not-ready");
|
|
663
|
+
return;
|
|
664
|
+
}
|
|
665
|
+
if (ctx.mode !== "serving") {
|
|
666
|
+
lc.info?.(`not serving backup subscriber ${ctx.id} from SQLite catchup`);
|
|
667
|
+
this.#recordCatchupRoute("pg", "ineligible-mode");
|
|
668
|
+
return;
|
|
669
|
+
}
|
|
670
|
+
let route;
|
|
671
|
+
if (this.#readRouter) {
|
|
672
|
+
route = this.#readRouter.consume(ctx.taskID);
|
|
673
|
+
if (route.source === "pg") {
|
|
674
|
+
if (route.reason === "cold-log") lc.info?.(`serving ${ctx.id} from PG catchup: SQLite change log is still warming`, { sqliteChangeLogCoverage: route.coverage });
|
|
675
|
+
else if (route.reason === "log-unavailable") this.#declineSQLiteCatchup(lc, ctx, opts, `${opts.changeLogFile} is unavailable or incompatible`);
|
|
676
|
+
else lc.debug?.(`serving ${ctx.id} from PG catchup: SQLite route ${route.reason}`, ...route.coverage ? [{ sqliteChangeLogCoverage: route.coverage }] : []);
|
|
677
|
+
this.#recordCatchupRoute("pg", route.reason);
|
|
678
|
+
return;
|
|
679
|
+
}
|
|
680
|
+
const coverage = route.coverage;
|
|
681
|
+
assert(coverage, "a SQLite route must carry its covered range");
|
|
682
|
+
if (ctx.watermark < coverage.minWatermark) {
|
|
683
|
+
lc.info?.(`serving ${ctx.id} from PG catchup: subscriber watermark ${ctx.watermark} is below the SQLite change-log minimum ` + coverage.minWatermark, { sqliteChangeLogCoverage: coverage });
|
|
684
|
+
this.#recordCatchupRoute("pg", "watermark-uncovered");
|
|
685
|
+
return;
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
if (!this.#readRouter && !opts.shouldUse?.(ctx)) {
|
|
689
|
+
this.#recordCatchupRoute("pg", "selector");
|
|
341
690
|
return;
|
|
342
691
|
}
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
this.#lc.warn?.("No subscribers to confirm cleanup");
|
|
692
|
+
if (this.#readRouter && opts.shouldUse && !opts.shouldUse(ctx)) {
|
|
693
|
+
this.#recordCatchupRoute("pg", "selector");
|
|
346
694
|
return;
|
|
347
695
|
}
|
|
696
|
+
const catchup = this.#sqliteCatchup ?? this.#openSQLiteCatchup(lc, opts, ctx);
|
|
697
|
+
if (catchup) return {
|
|
698
|
+
catchup,
|
|
699
|
+
reason: route?.reason ?? "selector",
|
|
700
|
+
coverage: route?.coverage,
|
|
701
|
+
logWarm: route === void 0 ? void 0 : route.reason !== "selected-cold"
|
|
702
|
+
};
|
|
703
|
+
else this.#recordCatchupRoute("pg", "log-unavailable");
|
|
704
|
+
}
|
|
705
|
+
#recordCatchupRoute(source, reason) {
|
|
706
|
+
this.#catchupRoutes.add(1, {
|
|
707
|
+
source,
|
|
708
|
+
reason
|
|
709
|
+
});
|
|
710
|
+
}
|
|
711
|
+
/**
|
|
712
|
+
* Opens the change log and, if it can serve, wraps it in the coordinator that
|
|
713
|
+
* subsequent subscriptions reuse.
|
|
714
|
+
*
|
|
715
|
+
* The log may not exist yet -- the writer creates it at the stream loop's
|
|
716
|
+
* first reconcile, and deletes it when it fails soft -- or may exist without
|
|
717
|
+
* content, or may be unreadable. None of those can be allowed to fail a
|
|
718
|
+
* subscription:
|
|
719
|
+
* this is the last point at which PG catchup is still available -- past
|
|
720
|
+
* `Forwarder.add()` the subscriber is committed to SQLite -- so each declines
|
|
721
|
+
* here instead. Neither the failure nor the reader is retained, so a later
|
|
722
|
+
* subscription retries from scratch.
|
|
723
|
+
*/
|
|
724
|
+
#openSQLiteCatchup(lc, opts, ctx) {
|
|
725
|
+
let reader;
|
|
348
726
|
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);
|
|
727
|
+
reader = new SQLiteChangeLogReader(this.#lc, opts.changeLogFile);
|
|
728
|
+
if (reader.plan(ctx.watermark).kind === "not-ready") {
|
|
729
|
+
reader.close();
|
|
730
|
+
this.#declineSQLiteCatchup(lc, ctx, opts, `${opts.changeLogFile} has no changes to serve yet`);
|
|
731
|
+
return;
|
|
359
732
|
}
|
|
360
733
|
} catch (e) {
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
734
|
+
reader?.close();
|
|
735
|
+
this.#declineSQLiteCatchup(lc, ctx, opts, `cannot read ${opts.changeLogFile}`, e);
|
|
736
|
+
return;
|
|
364
737
|
}
|
|
738
|
+
this.#changeLogUnavailableSince = void 0;
|
|
739
|
+
this.#sqliteCatchup = new SQLiteChangeLogCatchup(this.#lc, this.#forwarder, reader, {
|
|
740
|
+
batchSize: opts.readBatchRows,
|
|
741
|
+
barrierTimeoutMs: opts.barrierTimeoutMs,
|
|
742
|
+
barrierPollIntervalMs: opts.barrierPollIntervalMs,
|
|
743
|
+
cleanupGuard: opts.cleanupGuard,
|
|
744
|
+
onFailure: (failure) => {
|
|
745
|
+
this.#lc.warn?.(`temporarily disabling SQLite catchup after ${failure}`);
|
|
746
|
+
this.#readRouter?.trip();
|
|
747
|
+
}
|
|
748
|
+
});
|
|
749
|
+
return this.#sqliteCatchup;
|
|
365
750
|
}
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
751
|
+
/**
|
|
752
|
+
* Reports falling back to PG catchup, tracking how long the log has been
|
|
753
|
+
* unavailable so that a subscription that merely arrived before the writer's
|
|
754
|
+
* first reconcile does not look like an incident.
|
|
755
|
+
*/
|
|
756
|
+
#declineSQLiteCatchup(lc, ctx, opts, reason, error) {
|
|
757
|
+
const now = Date.now();
|
|
758
|
+
this.#changeLogUnavailableSince ??= now;
|
|
759
|
+
const unavailableMs = now - this.#changeLogUnavailableSince;
|
|
760
|
+
lc[unavailableMs >= (opts.notReadyWarnThresholdMs ?? DEFAULT_CHANGE_LOG_UNAVAILABLE_WARN_THRESHOLD_MS) ? "warn" : "debug"]?.(`serving ${ctx.id} from PG catchup: ${reason} (unavailable for ${unavailableMs} ms)`, ...error === void 0 ? [] : [error]);
|
|
371
761
|
}
|
|
372
762
|
};
|
|
373
763
|
var CLEANUP_DELAY_MS = DEFAULT_MAX_RETRY_DELAY_MS * 3;
|