@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,4 +1,4 @@
|
|
|
1
|
-
import { assert } 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
3
|
import { AbortError } from "../../../../shared/src/abort-error.js";
|
|
4
4
|
import { parse, valita_exports } from "../../../../shared/src/valita.js";
|
|
@@ -8,12 +8,15 @@ import { isDataChange, isSchemaChange } from "../change-source/protocol/current/
|
|
|
8
8
|
import "../change-source/protocol/current/downstream.js";
|
|
9
9
|
import { backfillRequestSchema } from "../change-source/protocol/current/upstream.js";
|
|
10
10
|
import "../change-source/protocol/current.js";
|
|
11
|
+
import { cookieOps } from "../replicator/change-log-cookies.js";
|
|
11
12
|
import "../../types/pg.js";
|
|
12
13
|
import { READONLY, READ_COMMITTED } from "../../db/mode-enum.js";
|
|
13
14
|
import { runTx } from "../../db/run-transaction.js";
|
|
14
|
-
import { AutoResetSignal, markResetRequired } from "./schema/tables.js";
|
|
15
15
|
import { Queue } from "../../../../shared/src/queue.js";
|
|
16
|
+
import { AutoResetSignal, markResetRequired } from "./schema/tables.js";
|
|
16
17
|
import { TransactionPool } from "../../db/transaction-pool.js";
|
|
18
|
+
import { orTimeout } from "../../types/timeout.js";
|
|
19
|
+
import { extractChangeSubstring, reconstructWatermarkedChange, serializeChangeStreamData } from "./change-log-codec.js";
|
|
17
20
|
import { resolver } from "@rocicorp/resolver";
|
|
18
21
|
import "postgres";
|
|
19
22
|
import { getHeapStatistics } from "node:v8";
|
|
@@ -58,15 +61,17 @@ var Storer = class {
|
|
|
58
61
|
#discoveryProtocol;
|
|
59
62
|
#db;
|
|
60
63
|
#replicaVersion;
|
|
61
|
-
#
|
|
64
|
+
#onCommitted;
|
|
62
65
|
#onFatal;
|
|
63
66
|
#queue = new Queue();
|
|
64
67
|
#backPressureThresholdBytes;
|
|
65
68
|
#statementTimeoutMs;
|
|
66
69
|
#changeLogBatchSize;
|
|
70
|
+
#drainTimeoutMs;
|
|
71
|
+
#progressMonitor;
|
|
67
72
|
#approximateQueuedBytes = 0;
|
|
68
73
|
#running = false;
|
|
69
|
-
constructor(lc, shard, taskID, discoveryAddress, discoveryProtocol, db, replicaVersion,
|
|
74
|
+
constructor(lc, shard, taskID, discoveryAddress, discoveryProtocol, db, replicaVersion, onCommitted, onFatal, { backPressureLimitHeapProportion, statementTimeoutMs, changeLogBatchSize, drainTimeoutMs = 3e4 }) {
|
|
70
75
|
this.#lc = lc.withContext("component", "change-log");
|
|
71
76
|
this.#shard = shard;
|
|
72
77
|
this.#taskID = taskID;
|
|
@@ -74,10 +79,12 @@ var Storer = class {
|
|
|
74
79
|
this.#discoveryProtocol = discoveryProtocol;
|
|
75
80
|
this.#db = db;
|
|
76
81
|
this.#replicaVersion = replicaVersion;
|
|
77
|
-
this.#
|
|
82
|
+
this.#onCommitted = onCommitted;
|
|
78
83
|
this.#onFatal = onFatal;
|
|
79
84
|
this.#statementTimeoutMs = statementTimeoutMs;
|
|
80
85
|
this.#changeLogBatchSize = Math.max(1, changeLogBatchSize);
|
|
86
|
+
this.#drainTimeoutMs = drainTimeoutMs;
|
|
87
|
+
this.#progressMonitor = new ProgressMonitor(lc, statementTimeoutMs, onFatal);
|
|
81
88
|
const heapStats = getHeapStatistics();
|
|
82
89
|
this.#backPressureThresholdBytes = (heapStats.heap_size_limit - heapStats.used_heap_size) * backPressureLimitHeapProportion;
|
|
83
90
|
this.#lc.info?.(`Using up to ${(this.#backPressureThresholdBytes / 1024 ** 2).toFixed(2)} MB of --max-old-space-size (~${(heapStats.heap_size_limit / 1024 ** 2).toFixed(2)} MB) to absorb upstream spikes`, { heapStats });
|
|
@@ -85,6 +92,28 @@ var Storer = class {
|
|
|
85
92
|
#cdc(table) {
|
|
86
93
|
return this.#db(`${cdcSchema(this.#shard)}.${table}`);
|
|
87
94
|
}
|
|
95
|
+
/**
|
|
96
|
+
* Bounds a one-off db call (i.e. not part of the main storer loop or the
|
|
97
|
+
* background catchup read, which are tracked by the ProgressMonitor
|
|
98
|
+
* instead) with a plain timeout. This covers calls like
|
|
99
|
+
* {@link assumeOwnership} and {@link getStartStreamInitializationParameters}
|
|
100
|
+
* that are made by the caller *before* {@link run()} -- and thus before the
|
|
101
|
+
* ProgressMonitor's polling starts -- as well as ones made well after,
|
|
102
|
+
* where a continuously-polling watchdog would be overkill for a single
|
|
103
|
+
* bounded db round trip.
|
|
104
|
+
*
|
|
105
|
+
* Does not cancel `promise` on timeout (there is no cancellation mechanism
|
|
106
|
+
* for a postgres.js query); it just stops waiting for it, and swallows a
|
|
107
|
+
* later rejection so it doesn't surface as an unhandled rejection.
|
|
108
|
+
*/
|
|
109
|
+
async #withTimeout(name, promise) {
|
|
110
|
+
const result = await orTimeout(promise, this.#statementTimeoutMs);
|
|
111
|
+
if (result === "timed-out") {
|
|
112
|
+
promise.catch(() => {});
|
|
113
|
+
throw new AbortError(`${name} did not complete within ${this.#statementTimeoutMs}ms`);
|
|
114
|
+
}
|
|
115
|
+
return result;
|
|
116
|
+
}
|
|
88
117
|
async assumeOwnership(purgeLock) {
|
|
89
118
|
const db = this.#db;
|
|
90
119
|
const owner = this.#taskID;
|
|
@@ -93,40 +122,110 @@ var Storer = class {
|
|
|
93
122
|
const addressWithProtocol = ownerProtocol === "ws" ? ownerAddress : `${ownerProtocol}://${ownerAddress}`;
|
|
94
123
|
this.#lc.info?.(`assuming ownership at ${addressWithProtocol}`);
|
|
95
124
|
const start = performance.now();
|
|
96
|
-
await db`UPDATE ${this.#cdc("replicationState")} SET ${db({
|
|
125
|
+
await this.#withTimeout("assume-ownership", db`UPDATE ${this.#cdc("replicationState")} SET ${db({
|
|
97
126
|
owner,
|
|
98
127
|
ownerAddress: addressWithProtocol
|
|
99
|
-
})}
|
|
128
|
+
})}`);
|
|
100
129
|
const elapsed = (performance.now() - start).toFixed(2);
|
|
101
130
|
this.#lc.info?.(`assumed ownership at ${addressWithProtocol} (${elapsed} ms)`);
|
|
102
131
|
if (purgeLock) purgeLock.release();
|
|
103
132
|
}
|
|
133
|
+
/**
|
|
134
|
+
* The whole of what a stream connection starts from: where to resume, what to
|
|
135
|
+
* ask the change source to backfill, and the raw cookie set those requests
|
|
136
|
+
* were derived from.
|
|
137
|
+
*
|
|
138
|
+
* All four statements run in one REPEATABLE READ transaction, so they see one
|
|
139
|
+
* snapshot. That is invariant 15 — the resume watermark and the cookies must
|
|
140
|
+
* come from the same store, read at the same position — and it is why the
|
|
141
|
+
* cookies are read here rather than by a second call: a cookie set paired
|
|
142
|
+
* with a watermark it was not folded to loses every backfill that completed
|
|
143
|
+
* in the interval, and those rows are not replayable from the slot.
|
|
144
|
+
*
|
|
145
|
+
* `cookies` is not `backfillRequests` in another shape. The request list is
|
|
146
|
+
* driven off `backfilling`, so it drops the metadata of every table with no
|
|
147
|
+
* in-flight backfill — correct for starting a stream, lossy as the cookie
|
|
148
|
+
* snapshot that the SQLite change log continues folding onto.
|
|
149
|
+
*/
|
|
104
150
|
async getStartStreamInitializationParameters() {
|
|
105
|
-
const [[{ lastWatermark }], result] = await runTx(this.#db, (sql) => [
|
|
106
|
-
|
|
107
|
-
SELECT
|
|
151
|
+
const [[{ lastWatermark }], result, tableMetadata, backfilling] = await this.#withTimeout("get-stream-params", runTx(this.#db, (sql) => [
|
|
152
|
+
sql`
|
|
153
|
+
SELECT "lastWatermark" FROM ${this.#cdc("replicationState")}`,
|
|
154
|
+
sql`
|
|
155
|
+
SELECT
|
|
108
156
|
json_build_object(
|
|
109
157
|
'schema', b."schema",
|
|
110
158
|
'name', b."table",
|
|
111
159
|
'metadata', t."metadata"
|
|
112
160
|
) as "table",
|
|
113
|
-
json_object_agg(b."column", b."backfill")
|
|
161
|
+
json_object_agg(b."column", b."backfill")
|
|
114
162
|
as "columns"
|
|
115
163
|
FROM ${this.#cdc("backfilling")} as b
|
|
116
164
|
LEFT JOIN ${this.#cdc("tableMetadata")} as t
|
|
117
165
|
ON (b."schema" = t."schema" AND b."table" = t."table")
|
|
118
166
|
GROUP BY b."schema", b."table", t."metadata"
|
|
119
|
-
|
|
167
|
+
`,
|
|
168
|
+
sql`
|
|
169
|
+
SELECT "schema", "table", "metadata" FROM ${this.#cdc("tableMetadata")}
|
|
170
|
+
ORDER BY "schema" COLLATE "C", "table" COLLATE "C"`,
|
|
171
|
+
sql`
|
|
172
|
+
SELECT "schema", "table", "column", "backfill" FROM ${this.#cdc("backfilling")}
|
|
173
|
+
ORDER BY "schema" COLLATE "C", "table" COLLATE "C", "column" COLLATE "C"`
|
|
174
|
+
], { mode: READONLY }));
|
|
120
175
|
return {
|
|
121
176
|
lastWatermark,
|
|
122
|
-
backfillRequests: parse(result, backfillRequestsSchema)
|
|
177
|
+
backfillRequests: parse(result, backfillRequestsSchema),
|
|
178
|
+
cookies: {
|
|
179
|
+
tableMetadata: [...tableMetadata],
|
|
180
|
+
backfilling: [...backfilling]
|
|
181
|
+
}
|
|
123
182
|
};
|
|
124
183
|
}
|
|
125
184
|
async getMinWatermarkForCatchup() {
|
|
126
|
-
const [{ minWatermark }] = await this.#db`
|
|
127
|
-
SELECT min(watermark) as "minWatermark" FROM ${this.#cdc("changeLog")}
|
|
185
|
+
const [{ minWatermark }] = await this.#withTimeout("get-min-watermark", this.#db`
|
|
186
|
+
SELECT min(watermark) as "minWatermark" FROM ${this.#cdc("changeLog")}`);
|
|
128
187
|
return minWatermark;
|
|
129
188
|
}
|
|
189
|
+
/**
|
|
190
|
+
* Returns the retained Postgres catchup bounds.
|
|
191
|
+
* `minWatermark` is the oldest transaction, or `null` for a new replica.
|
|
192
|
+
* `lastWatermark` is the durable head.
|
|
193
|
+
*/
|
|
194
|
+
async getCatchupBounds() {
|
|
195
|
+
const [bounds] = await this.#withTimeout("get-catchup-bounds", this.#db`
|
|
196
|
+
SELECT
|
|
197
|
+
(SELECT min(watermark) FROM ${this.#cdc("changeLog")}) as "minWatermark",
|
|
198
|
+
(SELECT "lastWatermark" FROM ${this.#cdc("replicationState")}) as "lastWatermark"`);
|
|
199
|
+
return bounds;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Lists at most `limit` committed transaction watermarks in
|
|
203
|
+
* `(afterWatermark, throughWatermark]`, in ascending order.
|
|
204
|
+
*/
|
|
205
|
+
async listCommitWatermarks(afterWatermark, throughWatermark, limit) {
|
|
206
|
+
return (await this.#db`
|
|
207
|
+
SELECT watermark FROM ${this.#cdc("changeLog")}
|
|
208
|
+
WHERE precommit IS NOT NULL
|
|
209
|
+
AND watermark > ${afterWatermark}
|
|
210
|
+
AND watermark <= ${throughWatermark}
|
|
211
|
+
ORDER BY watermark
|
|
212
|
+
LIMIT ${limit}`).map(({ watermark }) => watermark);
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Reads `(afterWatermark, throughWatermark]` in stream order and bounded batches.
|
|
216
|
+
* This query matches the subscriber catchup query.
|
|
217
|
+
*
|
|
218
|
+
* Both queries fail when an escaped NUL reaches `change->'tag'`.
|
|
219
|
+
* Postgres cannot convert that value to text.
|
|
220
|
+
*/
|
|
221
|
+
readCatchupRange(afterWatermark, throughWatermark, batchRows = 2e3) {
|
|
222
|
+
assert(Number.isSafeInteger(batchRows) && batchRows > 0, "Postgres change log batch size must be a positive safe integer");
|
|
223
|
+
return this.#db`
|
|
224
|
+
SELECT watermark, change->'tag' as tag, change::text FROM ${this.#cdc("changeLog")}
|
|
225
|
+
WHERE watermark > ${afterWatermark}
|
|
226
|
+
AND watermark <= ${throughWatermark}
|
|
227
|
+
ORDER BY watermark, pos`.cursor(batchRows);
|
|
228
|
+
}
|
|
130
229
|
purgeRecordsBefore(watermark) {
|
|
131
230
|
return runTx(this.#db, async (sql) => {
|
|
132
231
|
await sql`
|
|
@@ -159,7 +258,7 @@ var Storer = class {
|
|
|
159
258
|
* @returns The JSON stringified stream message to be sent downstream.
|
|
160
259
|
*/
|
|
161
260
|
store(watermark, data) {
|
|
162
|
-
const json =
|
|
261
|
+
const json = serializeChangeStreamData(data);
|
|
163
262
|
this.#approximateQueuedBytes += json.length;
|
|
164
263
|
const change = data[1];
|
|
165
264
|
this.#queue.enqueue([
|
|
@@ -173,9 +272,6 @@ var Storer = class {
|
|
|
173
272
|
abort() {
|
|
174
273
|
this.#queue.enqueue(["abort"]);
|
|
175
274
|
}
|
|
176
|
-
status(s) {
|
|
177
|
-
this.#queue.enqueue(s);
|
|
178
|
-
}
|
|
179
275
|
catchup(subscriber, mode) {
|
|
180
276
|
this.#queue.enqueue(["subscriber", {
|
|
181
277
|
subscriber,
|
|
@@ -192,10 +288,12 @@ var Storer = class {
|
|
|
192
288
|
return this.#readyForMore?.promise;
|
|
193
289
|
}
|
|
194
290
|
#maybeReleaseBackPressure() {
|
|
195
|
-
if (this.#readyForMore !== null
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
291
|
+
if (this.#readyForMore !== null) {
|
|
292
|
+
if (this.#approximateQueuedBytes < this.#backPressureThresholdBytes * .8) {
|
|
293
|
+
this.#lc.info?.(`releasing back pressure with ${this.#queue.size()} queued changes (~${(this.#approximateQueuedBytes / 1024 ** 2).toFixed(2)} MB)`);
|
|
294
|
+
this.#readyForMore.resolve();
|
|
295
|
+
this.#readyForMore = null;
|
|
296
|
+
}
|
|
199
297
|
}
|
|
200
298
|
}
|
|
201
299
|
/**
|
|
@@ -235,6 +333,7 @@ var Storer = class {
|
|
|
235
333
|
this.#running = true;
|
|
236
334
|
this.#stopped = stopped;
|
|
237
335
|
this.#lc.info?.("starting storer");
|
|
336
|
+
this.#progressMonitor.start();
|
|
238
337
|
let err;
|
|
239
338
|
try {
|
|
240
339
|
await this.#processQueue();
|
|
@@ -271,9 +370,20 @@ var Storer = class {
|
|
|
271
370
|
async #processQueue() {
|
|
272
371
|
let tx = null;
|
|
273
372
|
let msg;
|
|
373
|
+
let lastTaskDone;
|
|
374
|
+
const nextMessage = async () => {
|
|
375
|
+
lastTaskDone?.();
|
|
376
|
+
lastTaskDone = void 0;
|
|
377
|
+
const entry = await this.#queue.dequeue();
|
|
378
|
+
if (entry !== "stop") lastTaskDone = this.#progressMonitor.trackTask({
|
|
379
|
+
task: "queue-entry",
|
|
380
|
+
type: entry[0]
|
|
381
|
+
});
|
|
382
|
+
return entry;
|
|
383
|
+
};
|
|
274
384
|
const catchupQueue = [];
|
|
275
385
|
try {
|
|
276
|
-
while ((msg = await
|
|
386
|
+
while ((msg = await nextMessage()) !== "stop") {
|
|
277
387
|
const [msgType] = msg;
|
|
278
388
|
switch (msgType) {
|
|
279
389
|
case "ready": {
|
|
@@ -287,9 +397,6 @@ var Storer = class {
|
|
|
287
397
|
else await this.#startCatchup([subscriber]);
|
|
288
398
|
continue;
|
|
289
399
|
}
|
|
290
|
-
case "status":
|
|
291
|
-
this.#onConsumed(msg);
|
|
292
|
-
continue;
|
|
293
400
|
case "abort":
|
|
294
401
|
if (tx) {
|
|
295
402
|
tx.pool.abort();
|
|
@@ -306,10 +413,7 @@ var Storer = class {
|
|
|
306
413
|
const { promise, resolve, reject } = resolver();
|
|
307
414
|
promise.catch(() => {});
|
|
308
415
|
tx = {
|
|
309
|
-
pool: new TransactionPool(this.#lc.withContext("watermark", watermark), {
|
|
310
|
-
mode: READ_COMMITTED,
|
|
311
|
-
statementResponseTimeout: this.#statementTimeoutMs
|
|
312
|
-
}),
|
|
416
|
+
pool: new TransactionPool(this.#lc.withContext("watermark", watermark), { mode: READ_COMMITTED }),
|
|
313
417
|
preCommitWatermark: watermark,
|
|
314
418
|
pos: 0,
|
|
315
419
|
startingReplicationState: promise,
|
|
@@ -356,7 +460,7 @@ var Storer = class {
|
|
|
356
460
|
tx.pool.setDone();
|
|
357
461
|
}
|
|
358
462
|
await tx.pool.done();
|
|
359
|
-
if (tx.ack) this.#
|
|
463
|
+
if (tx.ack) this.#onCommitted([
|
|
360
464
|
"commit",
|
|
361
465
|
change,
|
|
362
466
|
{ watermark }
|
|
@@ -377,9 +481,14 @@ var Storer = class {
|
|
|
377
481
|
}
|
|
378
482
|
async #startCatchup(subs) {
|
|
379
483
|
if (subs.length === 0) return;
|
|
380
|
-
const
|
|
484
|
+
const lc = this.#lc.withContext("pool", "catchup");
|
|
485
|
+
const reader = new TransactionPool(lc, { mode: READONLY });
|
|
381
486
|
reader.run(this.#db);
|
|
382
487
|
let lastWatermark;
|
|
488
|
+
const catchupSnapshotted = this.#progressMonitor.trackTask({
|
|
489
|
+
task: "capture-catchup-snapshot",
|
|
490
|
+
subscribers: subs.map(({ subscriber: s }) => s.id)
|
|
491
|
+
});
|
|
383
492
|
try {
|
|
384
493
|
[{lastWatermark}] = await reader.processReadTask((sql) => sql`
|
|
385
494
|
SELECT "lastWatermark" FROM ${this.#cdc("replicationState")}
|
|
@@ -387,12 +496,22 @@ var Storer = class {
|
|
|
387
496
|
} catch (e) {
|
|
388
497
|
subs.map(({ subscriber }) => subscriber.fail(e));
|
|
389
498
|
throw e;
|
|
499
|
+
} finally {
|
|
500
|
+
catchupSnapshotted();
|
|
390
501
|
}
|
|
391
|
-
Promise.all(subs.map((sub) => this.#catchup(sub, lastWatermark, reader))).finally(() => reader.setDone());
|
|
502
|
+
Promise.all(subs.map((sub) => this.#catchup(lc.withContext("subscriber", sub.subscriber.id), sub, lastWatermark, reader))).finally(() => reader.setDone());
|
|
392
503
|
}
|
|
393
|
-
async #catchup({ subscriber: sub, mode }, lastWatermark, reader) {
|
|
504
|
+
async #catchup(lc, { subscriber: sub, mode }, lastWatermark, reader) {
|
|
505
|
+
let entriesReceived = 0;
|
|
506
|
+
let catchupProgressed = this.#progressMonitor.trackTask({
|
|
507
|
+
task: "catchup",
|
|
508
|
+
subscriber: sub.id,
|
|
509
|
+
entriesReceived
|
|
510
|
+
});
|
|
394
511
|
try {
|
|
512
|
+
lc.info?.(`starting catchup`);
|
|
395
513
|
await reader.processReadTask(async (tx) => {
|
|
514
|
+
lc.info?.(`catching up`);
|
|
396
515
|
const start = Date.now();
|
|
397
516
|
let watermarkFound = sub.watermark === this.#replicaVersion;
|
|
398
517
|
let count = 0;
|
|
@@ -402,100 +521,100 @@ var Storer = class {
|
|
|
402
521
|
WHERE watermark >= ${sub.watermark}
|
|
403
522
|
AND watermark <= ${lastWatermark}
|
|
404
523
|
ORDER BY watermark, pos`.cursor(2e3)) {
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
lastBatchConsumed
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
524
|
+
catchupProgressed();
|
|
525
|
+
entriesReceived += entries.length;
|
|
526
|
+
try {
|
|
527
|
+
const start = performance.now();
|
|
528
|
+
await lastBatchConsumed;
|
|
529
|
+
const elapsed = performance.now() - start;
|
|
530
|
+
if (lastBatchConsumed) lc[elapsed > 100 ? "info" : "debug"]?.(`waited ${elapsed.toFixed(3)} ms for ${sub.id} to consume last batch of catchup entries`);
|
|
531
|
+
for (const entry of entries) if (entry.watermark === sub.watermark) watermarkFound = true;
|
|
532
|
+
else if (watermarkFound) {
|
|
533
|
+
lastBatchConsumed = sub.catchup(reconstructWatermarkedChange(entry));
|
|
534
|
+
count++;
|
|
535
|
+
} else if (mode === "backup") throw new AutoResetSignal(`backup replica at watermark ${sub.watermark} is behind change db: ${entry.watermark})`);
|
|
536
|
+
else {
|
|
537
|
+
lc.warn?.(`rejecting subscriber at watermark ${sub.watermark} (earliest watermark: ${entry.watermark})`);
|
|
538
|
+
sub.close(2, `earliest supported watermark is ${entry.watermark} (requested ${sub.watermark})`);
|
|
539
|
+
return;
|
|
540
|
+
}
|
|
541
|
+
} finally {
|
|
542
|
+
catchupProgressed = this.#progressMonitor.trackTask({
|
|
543
|
+
task: "catchup",
|
|
544
|
+
subscriber: sub.id,
|
|
545
|
+
entriesReceived
|
|
546
|
+
});
|
|
418
547
|
}
|
|
419
548
|
}
|
|
549
|
+
catchupProgressed();
|
|
420
550
|
if (watermarkFound) {
|
|
421
551
|
await lastBatchConsumed;
|
|
422
|
-
|
|
423
|
-
} else
|
|
552
|
+
lc.info?.(`caught up ${sub.id} with ${count} changes (${Date.now() - start} ms)`);
|
|
553
|
+
} else lc.warn?.(`subscriber ${sub.id} at watermark ${sub.watermark} is ahead of the latest durable watermark ${lastWatermark}; waiting for the change DB to catch up`);
|
|
424
554
|
sub.setCaughtUp();
|
|
425
555
|
});
|
|
426
556
|
} catch (err) {
|
|
427
|
-
|
|
557
|
+
lc.error?.(`error while catching up subscriber ${sub.id}`, err);
|
|
428
558
|
if (err instanceof AutoResetSignal) {
|
|
429
559
|
await markResetRequired(this.#db, this.#shard);
|
|
430
560
|
this.#onFatal(err);
|
|
431
561
|
}
|
|
432
562
|
sub.fail(err);
|
|
563
|
+
} finally {
|
|
564
|
+
catchupProgressed();
|
|
433
565
|
}
|
|
434
566
|
}
|
|
435
567
|
/**
|
|
436
568
|
* Returns the db statements necessary to track backfill and table metadata
|
|
437
569
|
* presented in the `change`, if any.
|
|
570
|
+
*
|
|
571
|
+
* This is the Postgres interpreter of {@link cookieOps}, which is also
|
|
572
|
+
* interpreted against the SQLite change log by `ChangeLogCookieWriter`. The
|
|
573
|
+
* two stores have to agree on every transition forever, and the failure mode
|
|
574
|
+
* if they drift is a backfill that is silently never re-requested — so the
|
|
575
|
+
* decision of what a schema change *means* lives in one place and only its
|
|
576
|
+
* transport lives here.
|
|
438
577
|
*/
|
|
439
578
|
#trackBackfillMetadata(sql, change) {
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
}
|
|
447
|
-
case "create-table": {
|
|
448
|
-
const { spec, metadata, backfill } = change;
|
|
449
|
-
if (metadata) stmts.push(this.#upsertTableMetadataStmt(sql, spec, metadata));
|
|
450
|
-
if (backfill) Object.entries(backfill).forEach(([col, backfill]) => {
|
|
451
|
-
stmts.push(this.#upsertColumnBackfillStmt(sql, spec, col, backfill));
|
|
452
|
-
});
|
|
453
|
-
break;
|
|
454
|
-
}
|
|
579
|
+
return cookieOps(change).flatMap((op) => this.#cookieStmts(sql, op));
|
|
580
|
+
}
|
|
581
|
+
#cookieStmts(sql, op) {
|
|
582
|
+
switch (op.op) {
|
|
583
|
+
case "upsert-metadata": return [this.#upsertTableMetadataStmt(sql, op.table, op.metadata)];
|
|
584
|
+
case "upsert-backfill": return [this.#upsertColumnBackfillStmt(sql, op.table, op.column, op.backfill)];
|
|
455
585
|
case "rename-table": {
|
|
456
|
-
const { old } =
|
|
586
|
+
const { old } = op;
|
|
457
587
|
const row = {
|
|
458
|
-
schema:
|
|
459
|
-
table:
|
|
588
|
+
schema: op.new.schema,
|
|
589
|
+
table: op.new.name
|
|
460
590
|
};
|
|
461
|
-
|
|
591
|
+
return [sql`UPDATE ${this.#cdc("tableMetadata")} SET ${sql(row)}
|
|
462
592
|
WHERE "schema" = ${old.schema} AND "table" = ${old.name}`, sql`UPDATE ${this.#cdc("backfilling")} SET ${sql(row)}
|
|
463
|
-
WHERE "schema" = ${old.schema} AND "table" = ${old.name}`
|
|
464
|
-
break;
|
|
593
|
+
WHERE "schema" = ${old.schema} AND "table" = ${old.name}`];
|
|
465
594
|
}
|
|
466
595
|
case "drop-table": {
|
|
467
|
-
const {
|
|
468
|
-
|
|
596
|
+
const { schema, name } = op.table;
|
|
597
|
+
return [sql`DELETE FROM ${this.#cdc("tableMetadata")}
|
|
469
598
|
WHERE "schema" = ${schema} AND "table" = ${name}`, sql`DELETE FROM ${this.#cdc("backfilling")}
|
|
470
|
-
WHERE "schema" = ${schema} AND "table" = ${name}`
|
|
471
|
-
break;
|
|
599
|
+
WHERE "schema" = ${schema} AND "table" = ${name}`];
|
|
472
600
|
}
|
|
473
|
-
case "
|
|
474
|
-
const {
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
break;
|
|
478
|
-
}
|
|
479
|
-
case "update-column": {
|
|
480
|
-
const { table: { schema, name: table }, old: { name: oldName }, new: { name: newName } } = change;
|
|
481
|
-
if (oldName !== newName) stmts.push(sql`UPDATE ${this.#cdc("backfilling")} SET "column" = ${newName}
|
|
482
|
-
WHERE "schema" = ${schema} AND "table" = ${table} AND "column" = ${oldName}`);
|
|
483
|
-
break;
|
|
601
|
+
case "rename-column": {
|
|
602
|
+
const { schema, name: table } = op.table;
|
|
603
|
+
return [sql`UPDATE ${this.#cdc("backfilling")} SET "column" = ${op.new}
|
|
604
|
+
WHERE "schema" = ${schema} AND "table" = ${table} AND "column" = ${op.old}`];
|
|
484
605
|
}
|
|
485
606
|
case "drop-column": {
|
|
486
|
-
const {
|
|
487
|
-
|
|
488
|
-
WHERE "schema" = ${schema} AND "table" = ${name} AND "column" = ${column}`
|
|
489
|
-
break;
|
|
607
|
+
const { schema, name } = op.table;
|
|
608
|
+
return [sql`DELETE FROM ${this.#cdc("backfilling")}
|
|
609
|
+
WHERE "schema" = ${schema} AND "table" = ${name} AND "column" = ${op.column}`];
|
|
490
610
|
}
|
|
491
|
-
case "backfill
|
|
492
|
-
const {
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
WHERE "schema" = ${schema} AND "table" = ${table} AND "column" IN ${sql(cols)}`);
|
|
611
|
+
case "complete-backfill": {
|
|
612
|
+
const { schema, name: table } = op.table;
|
|
613
|
+
return [sql`DELETE FROM ${this.#cdc("backfilling")}
|
|
614
|
+
WHERE "schema" = ${schema} AND "table" = ${table} AND "column" IN ${sql([...op.columns])}`];
|
|
496
615
|
}
|
|
616
|
+
default: unreachable(op);
|
|
497
617
|
}
|
|
498
|
-
return stmts;
|
|
499
618
|
}
|
|
500
619
|
#upsertTableMetadataStmt(sql, { schema, name: table }, metadata) {
|
|
501
620
|
const row = {
|
|
@@ -505,7 +624,7 @@ var Storer = class {
|
|
|
505
624
|
};
|
|
506
625
|
return sql`
|
|
507
626
|
INSERT INTO ${this.#cdc("tableMetadata")} ${sql(row)}
|
|
508
|
-
ON CONFLICT ("schema", "table")
|
|
627
|
+
ON CONFLICT ("schema", "table")
|
|
509
628
|
DO UPDATE SET ${sql(row)};
|
|
510
629
|
`;
|
|
511
630
|
}
|
|
@@ -518,7 +637,7 @@ var Storer = class {
|
|
|
518
637
|
};
|
|
519
638
|
return sql`
|
|
520
639
|
INSERT INTO ${this.#cdc("backfilling")} ${sql(row)}
|
|
521
|
-
ON CONFLICT ("schema", "table", "column")
|
|
640
|
+
ON CONFLICT ("schema", "table", "column")
|
|
522
641
|
DO UPDATE SET ${sql(row)};
|
|
523
642
|
`;
|
|
524
643
|
}
|
|
@@ -533,54 +652,21 @@ var Storer = class {
|
|
|
533
652
|
await promise;
|
|
534
653
|
}
|
|
535
654
|
}
|
|
536
|
-
|
|
655
|
+
/**
|
|
656
|
+
* Stops the storer and waits up to a drain timeout for entries to drain,
|
|
657
|
+
* throwing an exception if it doesn't drain in time, in order to abort
|
|
658
|
+
* the server when PG (or the connection to it) appears to be wedged.
|
|
659
|
+
*/
|
|
660
|
+
async stop() {
|
|
537
661
|
if (this.#running) {
|
|
662
|
+
this.#progressMonitor.stop();
|
|
538
663
|
this.#lc.info?.(`draining ${this.#queue.size()} changeLog entries`);
|
|
664
|
+
this.abort();
|
|
539
665
|
this.#queue.enqueue("stop");
|
|
540
666
|
}
|
|
541
|
-
|
|
667
|
+
if (await orTimeout(this.#stopped, this.#drainTimeoutMs) === "timed-out") throw new AbortError(`changeLog did not drain within ${this.#drainTimeoutMs}ms`);
|
|
542
668
|
}
|
|
543
669
|
};
|
|
544
|
-
/**
|
|
545
|
-
* Extracts the stringified change message from the stringified
|
|
546
|
-
* stream message (e.g. the second tuple element). This optimization
|
|
547
|
-
* facilitates stringifying (and sharing the result of) the stream
|
|
548
|
-
* message exactly once, but storing only the change message substring
|
|
549
|
-
* in the changeLog for backwards compatibility.
|
|
550
|
-
*/
|
|
551
|
-
function extractChangeSubstring(streamMessageJSON, tag) {
|
|
552
|
-
switch (tag) {
|
|
553
|
-
case "begin":
|
|
554
|
-
case "commit": return streamMessageJSON.substring(streamMessageJSON.indexOf(",") + 1, streamMessageJSON.lastIndexOf(","));
|
|
555
|
-
default: return streamMessageJSON.substring(streamMessageJSON.indexOf(",") + 1, streamMessageJSON.lastIndexOf("]"));
|
|
556
|
-
}
|
|
557
|
-
}
|
|
558
|
-
function toDownstream(entry) {
|
|
559
|
-
const { watermark, change } = entry;
|
|
560
|
-
const tag = entry.tag;
|
|
561
|
-
switch (tag) {
|
|
562
|
-
case "begin": return [
|
|
563
|
-
watermark,
|
|
564
|
-
tag,
|
|
565
|
-
`["begin",${change},{"commitWatermark":"${watermark}"}]`
|
|
566
|
-
];
|
|
567
|
-
case "commit": return [
|
|
568
|
-
watermark,
|
|
569
|
-
tag,
|
|
570
|
-
`["commit",${change},{"watermark":"${watermark}"}]`
|
|
571
|
-
];
|
|
572
|
-
case "rollback": return [
|
|
573
|
-
watermark,
|
|
574
|
-
tag,
|
|
575
|
-
`["rollback",${change}]`
|
|
576
|
-
];
|
|
577
|
-
default: return [
|
|
578
|
-
watermark,
|
|
579
|
-
tag,
|
|
580
|
-
`["data",${change}]`
|
|
581
|
-
];
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
670
|
var PurgeLock = class {
|
|
585
671
|
#lc;
|
|
586
672
|
#tx;
|
|
@@ -634,6 +720,65 @@ var PurgeLocker = class {
|
|
|
634
720
|
return new PurgeLock(this.#lc, tx, replicaVersion, watermark);
|
|
635
721
|
}
|
|
636
722
|
};
|
|
723
|
+
/**
|
|
724
|
+
* Periodic monitor for detecting the pathological condition in which a db
|
|
725
|
+
* query hangs forever because of a connection problem, such as a half-closed
|
|
726
|
+
* socket.
|
|
727
|
+
*
|
|
728
|
+
* Use this for db calls that recur or accumulate progress within a single
|
|
729
|
+
* logical operation on the main storer loop (e.g. the queue-processing loop,
|
|
730
|
+
* or a multi-batch catchup read), where "no progress for N ms" is the
|
|
731
|
+
* meaningful signal. For a one-off db call -- including ones made before
|
|
732
|
+
* {@link Storer.run} starts this monitor's polling -- use a plain timeout
|
|
733
|
+
* (see `Storer.#withTimeout`) instead.
|
|
734
|
+
*
|
|
735
|
+
* The failure handler should stop the server. The ProgressMonitor will
|
|
736
|
+
* assume this and stop itself after calling it.
|
|
737
|
+
*
|
|
738
|
+
* Internal to the Storer, but exported for testing.
|
|
739
|
+
*/
|
|
740
|
+
var ProgressMonitor = class {
|
|
741
|
+
#lc;
|
|
742
|
+
#failureThresholdMs;
|
|
743
|
+
#onFailure;
|
|
744
|
+
#taskUpdates = /* @__PURE__ */ new Map();
|
|
745
|
+
#timer;
|
|
746
|
+
constructor(lc, failureThresholdMs, onFailure) {
|
|
747
|
+
this.#lc = lc.withContext("component", "storer-progress-monitor");
|
|
748
|
+
this.#failureThresholdMs = failureThresholdMs;
|
|
749
|
+
this.#onFailure = onFailure;
|
|
750
|
+
}
|
|
751
|
+
start() {
|
|
752
|
+
clearInterval(this.#timer);
|
|
753
|
+
this.#timer = setInterval(() => this.checkTaskProgress(/* @__PURE__ */ new Date()), this.#failureThresholdMs).unref();
|
|
754
|
+
}
|
|
755
|
+
checkTaskProgress(now) {
|
|
756
|
+
for (const [task, lastUpdate] of this.#taskUpdates.entries()) if (now.getTime() - lastUpdate.getTime() >= this.#failureThresholdMs) {
|
|
757
|
+
this.#lc.error?.(`Last task update was more than ${this.#failureThresholdMs}ms ago`, {
|
|
758
|
+
task,
|
|
759
|
+
lastUpdate
|
|
760
|
+
});
|
|
761
|
+
this.#onFailure(/* @__PURE__ */ new Error(`Task failed to progress for over ${this.#failureThresholdMs}ms: ${BigIntJSON.stringify(task)}`));
|
|
762
|
+
this.stop();
|
|
763
|
+
return;
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
/**
|
|
767
|
+
* Starts a task to be tracked.
|
|
768
|
+
*
|
|
769
|
+
* @return a callback to invoke when the task is done.
|
|
770
|
+
*/
|
|
771
|
+
trackTask(task, now = /* @__PURE__ */ new Date()) {
|
|
772
|
+
this.#taskUpdates.set(task, now);
|
|
773
|
+
return () => {
|
|
774
|
+
this.#taskUpdates.delete(task);
|
|
775
|
+
};
|
|
776
|
+
}
|
|
777
|
+
stop() {
|
|
778
|
+
clearInterval(this.#timer);
|
|
779
|
+
this.#taskUpdates.clear();
|
|
780
|
+
}
|
|
781
|
+
};
|
|
637
782
|
//#endregion
|
|
638
783
|
export { PurgeLocker, Storer };
|
|
639
784
|
|