@rocicorp/zero 1.11.0-canary.3 → 1.11.0-canary.30
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/analyze-query/src/analyze-cli.js +4 -4
- package/out/analyze-query/src/analyze-cli.js.map +1 -1
- package/out/analyze-query/src/bin-analyze.js +13 -12
- package/out/analyze-query/src/bin-analyze.js.map +1 -1
- package/out/analyze-query/src/bin-transform.js +1 -1
- package/out/analyze-query/src/bin-transform.js.map +1 -1
- package/out/ast-to-zql/src/ast-to-zql.d.ts +8 -1
- package/out/ast-to-zql/src/ast-to-zql.d.ts.map +1 -1
- package/out/ast-to-zql/src/ast-to-zql.js +25 -25
- package/out/ast-to-zql/src/ast-to-zql.js.map +1 -1
- package/out/otel/src/log-options.d.ts +16 -0
- package/out/otel/src/log-options.d.ts.map +1 -1
- package/out/otel/src/log-options.js +60 -6
- package/out/otel/src/log-options.js.map +1 -1
- package/out/replicache/src/bg-interval.d.ts +2 -1
- package/out/replicache/src/bg-interval.d.ts.map +1 -1
- package/out/replicache/src/bg-interval.js +13 -4
- package/out/replicache/src/bg-interval.js.map +1 -1
- package/out/replicache/src/btree/node.d.ts.map +1 -1
- package/out/replicache/src/btree/node.js +3 -6
- package/out/replicache/src/btree/node.js.map +1 -1
- package/out/replicache/src/dag/gc.d.ts.map +1 -1
- package/out/replicache/src/dag/gc.js +8 -11
- package/out/replicache/src/dag/gc.js.map +1 -1
- package/out/replicache/src/dag/invalid-ref-count-error.d.ts +12 -0
- package/out/replicache/src/dag/invalid-ref-count-error.d.ts.map +1 -0
- package/out/replicache/src/dag/invalid-ref-count-error.js +19 -0
- package/out/replicache/src/dag/invalid-ref-count-error.js.map +1 -0
- package/out/replicache/src/dag/lazy-store.d.ts +17 -4
- package/out/replicache/src/dag/lazy-store.d.ts.map +1 -1
- package/out/replicache/src/dag/lazy-store.js +35 -9
- package/out/replicache/src/dag/lazy-store.js.map +1 -1
- package/out/replicache/src/dag/store-impl.d.ts +12 -2
- package/out/replicache/src/dag/store-impl.d.ts.map +1 -1
- package/out/replicache/src/dag/store-impl.js +29 -9
- package/out/replicache/src/dag/store-impl.js.map +1 -1
- package/out/replicache/src/db/rebase.d.ts +14 -2
- package/out/replicache/src/db/rebase.d.ts.map +1 -1
- package/out/replicache/src/db/rebase.js +27 -5
- package/out/replicache/src/db/rebase.js.map +1 -1
- package/out/replicache/src/get-kv-store-provider.d.ts +1 -1
- package/out/replicache/src/get-kv-store-provider.d.ts.map +1 -1
- package/out/replicache/src/get-kv-store-provider.js +4 -4
- package/out/replicache/src/get-kv-store-provider.js.map +1 -1
- package/out/replicache/src/kv/expo-sqlite/store.d.ts.map +1 -1
- package/out/replicache/src/kv/expo-sqlite/store.js +28 -5
- package/out/replicache/src/kv/expo-sqlite/store.js.map +1 -1
- package/out/replicache/src/kv/idb-store.d.ts +18 -0
- package/out/replicache/src/kv/idb-store.d.ts.map +1 -1
- package/out/replicache/src/kv/idb-store.js +30 -2
- package/out/replicache/src/kv/idb-store.js.map +1 -1
- package/out/replicache/src/kv/mem-fallback-store.d.ts +54 -0
- package/out/replicache/src/kv/mem-fallback-store.d.ts.map +1 -0
- package/out/replicache/src/kv/mem-fallback-store.js +177 -0
- package/out/replicache/src/kv/mem-fallback-store.js.map +1 -0
- package/out/replicache/src/kv/mem-store.d.ts +1 -0
- package/out/replicache/src/kv/mem-store.d.ts.map +1 -1
- package/out/replicache/src/kv/mem-store.js +3 -0
- package/out/replicache/src/kv/mem-store.js.map +1 -1
- package/out/replicache/src/kv/op-sqlite/store.d.ts.map +1 -1
- package/out/replicache/src/kv/op-sqlite/store.js +4 -4
- package/out/replicache/src/kv/op-sqlite/store.js.map +1 -1
- package/out/replicache/src/kv/sqlite-store.d.ts +22 -1
- package/out/replicache/src/kv/sqlite-store.d.ts.map +1 -1
- package/out/replicache/src/kv/sqlite-store.js +159 -14
- package/out/replicache/src/kv/sqlite-store.js.map +1 -1
- package/out/replicache/src/kv/store.d.ts +6 -0
- package/out/replicache/src/kv/store.d.ts.map +1 -1
- package/out/replicache/src/new-client-channel.js.map +1 -1
- package/out/replicache/src/persist/client-gc.d.ts +2 -1
- package/out/replicache/src/persist/client-gc.d.ts.map +1 -1
- package/out/replicache/src/persist/client-gc.js +2 -2
- package/out/replicache/src/persist/client-gc.js.map +1 -1
- package/out/replicache/src/persist/client-group-gc.d.ts +2 -1
- package/out/replicache/src/persist/client-group-gc.d.ts.map +1 -1
- package/out/replicache/src/persist/client-group-gc.js +2 -2
- package/out/replicache/src/persist/client-group-gc.js.map +1 -1
- package/out/replicache/src/persist/clients.d.ts +2 -2
- package/out/replicache/src/persist/collect-idb-databases.d.ts +28 -8
- package/out/replicache/src/persist/collect-idb-databases.d.ts.map +1 -1
- package/out/replicache/src/persist/collect-idb-databases.js +97 -20
- package/out/replicache/src/persist/collect-idb-databases.js.map +1 -1
- package/out/replicache/src/persist/heartbeat.d.ts +2 -1
- package/out/replicache/src/persist/heartbeat.d.ts.map +1 -1
- package/out/replicache/src/persist/heartbeat.js +2 -2
- package/out/replicache/src/persist/heartbeat.js.map +1 -1
- package/out/replicache/src/persist/idb-databases-store-db-name.js +1 -1
- package/out/replicache/src/persist/idb-databases-store-db-name.js.map +1 -1
- package/out/replicache/src/persist/persist.d.ts.map +1 -1
- package/out/replicache/src/persist/persist.js +18 -8
- package/out/replicache/src/persist/persist.js.map +1 -1
- package/out/replicache/src/persist/refresh.js +6 -2
- package/out/replicache/src/persist/refresh.js.map +1 -1
- package/out/replicache/src/replicache-impl.d.ts +85 -3
- package/out/replicache/src/replicache-impl.d.ts.map +1 -1
- package/out/replicache/src/replicache-impl.js +321 -29
- package/out/replicache/src/replicache-impl.js.map +1 -1
- package/out/replicache/src/replicache-options.d.ts +9 -0
- package/out/replicache/src/replicache-options.d.ts.map +1 -1
- package/out/replicache/src/storage-failure.d.ts +37 -0
- package/out/replicache/src/storage-failure.d.ts.map +1 -0
- package/out/replicache/src/storage-failure.js +31 -0
- package/out/replicache/src/storage-failure.js.map +1 -0
- package/out/shared/src/arrays.d.ts +5 -0
- package/out/shared/src/arrays.d.ts.map +1 -1
- package/out/shared/src/arrays.js +8 -10
- package/out/shared/src/arrays.js.map +1 -1
- package/out/shared/src/base64.d.ts +19 -0
- package/out/shared/src/base64.d.ts.map +1 -0
- package/out/shared/src/base64.js +40 -0
- package/out/shared/src/base64.js.map +1 -0
- package/out/shared/src/centroid.d.ts +0 -1
- package/out/shared/src/centroid.d.ts.map +1 -1
- package/out/shared/src/centroid.js +1 -4
- package/out/shared/src/centroid.js.map +1 -1
- package/out/shared/src/error.d.ts +11 -0
- package/out/shared/src/error.d.ts.map +1 -1
- package/out/shared/src/error.js +35 -1
- package/out/shared/src/error.js.map +1 -1
- package/out/shared/src/hash.d.ts.map +1 -1
- package/out/shared/src/hash.js +32 -7
- package/out/shared/src/hash.js.map +1 -1
- package/out/shared/src/iterables.d.ts +2 -0
- package/out/shared/src/iterables.d.ts.map +1 -1
- package/out/shared/src/iterables.js +18 -1
- package/out/shared/src/iterables.js.map +1 -1
- package/out/shared/src/map.d.ts +24 -2
- package/out/shared/src/map.d.ts.map +1 -1
- package/out/shared/src/map.js +18 -4
- package/out/shared/src/map.js.map +1 -1
- package/out/shared/src/options-types.d.ts +2 -2
- package/out/shared/src/options.d.ts.map +1 -1
- package/out/shared/src/options.js +10 -7
- package/out/shared/src/options.js.map +1 -1
- package/out/shared/src/packed-boolean-map.d.ts +7 -0
- package/out/shared/src/packed-boolean-map.d.ts.map +1 -0
- package/out/shared/src/packed-boolean-map.js +36 -0
- package/out/shared/src/packed-boolean-map.js.map +1 -0
- package/out/shared/src/random-values.js +12 -1
- package/out/shared/src/random-values.js.map +1 -1
- package/out/shared/src/ring-buffer.d.ts +10 -0
- package/out/shared/src/ring-buffer.d.ts.map +1 -1
- package/out/shared/src/ring-buffer.js +26 -1
- package/out/shared/src/ring-buffer.js.map +1 -1
- package/out/shared/src/tdigest.d.ts +10 -0
- package/out/shared/src/tdigest.d.ts.map +1 -1
- package/out/shared/src/tdigest.js +147 -63
- package/out/shared/src/tdigest.js.map +1 -1
- package/out/shared/src/valita.d.ts +13 -0
- package/out/shared/src/valita.d.ts.map +1 -1
- package/out/shared/src/valita.js +23 -23
- package/out/shared/src/valita.js.map +1 -1
- package/out/z2s/src/compiler.d.ts.map +1 -1
- package/out/z2s/src/compiler.js +10 -6
- package/out/z2s/src/compiler.js.map +1 -1
- package/out/z2s/src/sql.d.ts.map +1 -1
- package/out/z2s/src/sql.js +9 -5
- package/out/z2s/src/sql.js.map +1 -1
- package/out/zero/package.js +4 -5
- package/out/zero/package.js.map +1 -1
- package/out/zero/src/zero.js +2 -1
- package/out/zero-cache/src/auth/write-authorizer.d.ts.map +1 -1
- package/out/zero-cache/src/auth/write-authorizer.js +1 -0
- package/out/zero-cache/src/auth/write-authorizer.js.map +1 -1
- package/out/zero-cache/src/config/normalize.d.ts +1 -0
- package/out/zero-cache/src/config/normalize.d.ts.map +1 -1
- package/out/zero-cache/src/config/normalize.js +46 -4
- package/out/zero-cache/src/config/normalize.js.map +1 -1
- package/out/zero-cache/src/config/zero-config.d.ts +116 -24
- package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
- package/out/zero-cache/src/config/zero-config.js +409 -157
- package/out/zero-cache/src/config/zero-config.js.map +1 -1
- package/out/zero-cache/src/custom/fetch.d.ts +1 -1
- package/out/zero-cache/src/custom/fetch.d.ts.map +1 -1
- package/out/zero-cache/src/custom/fetch.js.map +1 -1
- package/out/zero-cache/src/db/lite-tables.d.ts.map +1 -1
- package/out/zero-cache/src/db/lite-tables.js +3 -4
- package/out/zero-cache/src/db/lite-tables.js.map +1 -1
- package/out/zero-cache/src/db/migration-lite.d.ts.map +1 -1
- package/out/zero-cache/src/db/migration-lite.js +5 -3
- package/out/zero-cache/src/db/migration-lite.js.map +1 -1
- package/out/zero-cache/src/observability/events.js +4 -1
- package/out/zero-cache/src/observability/events.js.map +1 -1
- package/out/zero-cache/src/observability/log-throttle.d.ts +44 -0
- package/out/zero-cache/src/observability/log-throttle.d.ts.map +1 -0
- package/out/zero-cache/src/observability/log-throttle.js +76 -0
- package/out/zero-cache/src/observability/log-throttle.js.map +1 -0
- package/out/zero-cache/src/observability/metrics.d.ts.map +1 -1
- package/out/zero-cache/src/observability/metrics.js +2 -7
- package/out/zero-cache/src/observability/metrics.js.map +1 -1
- package/out/zero-cache/src/scripts/permissions.d.ts +16 -0
- package/out/zero-cache/src/scripts/permissions.d.ts.map +1 -1
- package/out/zero-cache/src/scripts/permissions.js +3 -3
- package/out/zero-cache/src/scripts/permissions.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 +117 -77
- package/out/zero-cache/src/server/change-streamer.js.map +1 -1
- package/out/zero-cache/src/server/inspector-delegate.d.ts +28 -2
- package/out/zero-cache/src/server/inspector-delegate.d.ts.map +1 -1
- package/out/zero-cache/src/server/inspector-delegate.js +37 -17
- package/out/zero-cache/src/server/inspector-delegate.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 -1
- package/out/zero-cache/src/server/main.js.map +1 -1
- package/out/zero-cache/src/server/mutator.js +2 -0
- package/out/zero-cache/src/server/mutator.js.map +1 -1
- package/out/zero-cache/src/server/reaper.d.ts.map +1 -1
- package/out/zero-cache/src/server/reaper.js +2 -0
- package/out/zero-cache/src/server/reaper.js.map +1 -1
- package/out/zero-cache/src/server/replicator.d.ts +3 -0
- package/out/zero-cache/src/server/replicator.d.ts.map +1 -1
- package/out/zero-cache/src/server/replicator.js +95 -21
- package/out/zero-cache/src/server/replicator.js.map +1 -1
- package/out/zero-cache/src/server/runner/zero-dispatcher.d.ts.map +1 -1
- package/out/zero-cache/src/server/runner/zero-dispatcher.js +5 -0
- package/out/zero-cache/src/server/runner/zero-dispatcher.js.map +1 -1
- package/out/zero-cache/src/server/syncer-assigner.d.ts +14 -0
- package/out/zero-cache/src/server/syncer-assigner.d.ts.map +1 -0
- package/out/zero-cache/src/server/syncer-assigner.js +72 -0
- package/out/zero-cache/src/server/syncer-assigner.js.map +1 -0
- package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
- package/out/zero-cache/src/server/syncer.js +24 -2
- package/out/zero-cache/src/server/syncer.js.map +1 -1
- package/out/zero-cache/src/server/worker-dispatcher.d.ts.map +1 -1
- package/out/zero-cache/src/server/worker-dispatcher.js +21 -4
- package/out/zero-cache/src/server/worker-dispatcher.js.map +1 -1
- package/out/zero-cache/src/services/analyze.d.ts.map +1 -1
- package/out/zero-cache/src/services/analyze.js +11 -9
- package/out/zero-cache/src/services/analyze.js.map +1 -1
- package/out/zero-cache/src/services/change-source/common/backfill-manager.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/common/backfill-manager.js +198 -24
- package/out/zero-cache/src/services/change-source/common/backfill-manager.js.map +1 -1
- package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.js +16 -4
- package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.js.map +1 -1
- package/out/zero-cache/src/services/change-source/common/init-cleanup.d.ts +24 -0
- package/out/zero-cache/src/services/change-source/common/init-cleanup.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-source/common/init-cleanup.js +44 -0
- package/out/zero-cache/src/services/change-source/common/init-cleanup.js.map +1 -0
- package/out/zero-cache/src/services/change-source/common/replica-restore.d.ts +92 -2
- package/out/zero-cache/src/services/change-source/common/replica-restore.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/common/replica-restore.js +27 -10
- package/out/zero-cache/src/services/change-source/common/replica-restore.js.map +1 -1
- package/out/zero-cache/src/services/change-source/common/replica-schema.d.ts +1 -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 +15 -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 +1 -1
- 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 +7 -3
- 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 +9 -0
- 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 +206 -19
- 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-init.d.ts +55 -0
- package/out/zero-cache/src/services/change-source/pg/change-source-init.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-source/pg/change-source-init.js +305 -0
- package/out/zero-cache/src/services/change-source/pg/change-source-init.js.map +1 -0
- package/out/zero-cache/src/services/change-source/pg/change-source.d.ts +31 -18
- 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 +130 -157
- package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts +38 -2
- 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 +55 -21
- 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 +31 -0
- 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 +102 -3
- 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-slot-cleanup-monitor.d.ts +16 -0
- package/out/zero-cache/src/services/change-source/pg/replication-slot-cleanup-monitor.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-source/pg/replication-slot-cleanup-monitor.js +113 -0
- package/out/zero-cache/src/services/change-source/pg/replication-slot-cleanup-monitor.js.map +1 -0
- package/out/zero-cache/src/services/change-source/pg/replication-slots.d.ts +40 -15
- 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 +149 -27
- 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/index-predicate.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/index-predicate.js +68 -8
- package/out/zero-cache/src/services/change-source/pg/schema/index-predicate.js.map +1 -1
- 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 +32 -1
- 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/replica-stage-enum.d.ts +10 -0
- package/out/zero-cache/src/services/change-source/pg/schema/replica-stage-enum.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-source/pg/schema/replica-stage-enum.js +6 -0
- package/out/zero-cache/src/services/change-source/pg/schema/replica-stage-enum.js.map +1 -0
- package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts +50 -27
- 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 +98 -34
- package/out/zero-cache/src/services/change-source/pg/schema/shard.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/backfill-progress.d.ts +68 -0
- package/out/zero-cache/src/services/change-source/protocol/backfill-progress.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-source/protocol/backfill-progress.js +141 -0
- package/out/zero-cache/src/services/change-source/protocol/backfill-progress.js.map +1 -0
- package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts +45 -2
- 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 +10 -1
- 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 +60 -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/upstream.d.ts +23 -10
- package/out/zero-cache/src/services/change-source/protocol/current/upstream.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/upstream.js +17 -7
- package/out/zero-cache/src/services/change-source/protocol/current/upstream.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current.js +2 -1
- package/out/zero-cache/src/services/change-streamer/backfill-state-tracker.d.ts +72 -0
- package/out/zero-cache/src/services/change-streamer/backfill-state-tracker.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/backfill-state-tracker.js +162 -0
- package/out/zero-cache/src/services/change-streamer/backfill-state-tracker.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/backfill-state.d.ts +50 -0
- package/out/zero-cache/src/services/change-streamer/backfill-state.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/backfill-state.js +268 -0
- package/out/zero-cache/src/services/change-streamer/backfill-state.js.map +1 -0
- 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 +6 -17
- 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.map +1 -1
- package/out/zero-cache/src/services/change-streamer/backup-monitor.js +59 -8
- package/out/zero-cache/src/services/change-streamer/backup-monitor.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/broadcast.d.ts +8 -2
- package/out/zero-cache/src/services/change-streamer/broadcast.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/broadcast.js +24 -4
- 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 -4
- package/out/zero-cache/src/services/change-streamer/change-log-codec.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-log-codec.js +28 -8
- package/out/zero-cache/src/services/change-streamer/change-log-codec.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-log-initializer.d.ts +17 -0
- package/out/zero-cache/src/services/change-streamer/change-log-initializer.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-log-initializer.js +44 -1
- package/out/zero-cache/src/services/change-streamer/change-log-initializer.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts +48 -6
- 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 +131 -34
- 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 +22 -0
- 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 +149 -78
- 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 +38 -16
- 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/forwarder.d.ts +3 -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 +36 -5
- package/out/zero-cache/src/services/change-streamer/forwarder.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/litestream-sync-requester.d.ts +53 -0
- package/out/zero-cache/src/services/change-streamer/litestream-sync-requester.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/litestream-sync-requester.js +156 -0
- package/out/zero-cache/src/services/change-streamer/litestream-sync-requester.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/schema/tables.d.ts +58 -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 +107 -16
- package/out/zero-cache/src/services/change-streamer/schema/tables.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/snapshot-message.d.ts +92 -0
- package/out/zero-cache/src/services/change-streamer/snapshot-message.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/snapshot-message.js +42 -0
- package/out/zero-cache/src/services/change-streamer/snapshot-message.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/snapshot-reservations.d.ts +1 -1
- package/out/zero-cache/src/services/change-streamer/snapshot-reservations.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/snapshot-reservations.js +16 -4
- package/out/zero-cache/src/services/change-streamer/snapshot-reservations.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/snapshot.d.ts +7 -69
- package/out/zero-cache/src/services/change-streamer/snapshot.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/snapshot.js +21 -53
- package/out/zero-cache/src/services/change-streamer/snapshot.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.d.ts +6 -1
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.js +27 -9
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/storer.d.ts +95 -4
- package/out/zero-cache/src/services/change-streamer/storer.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/storer.js +293 -83
- package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/subscribe.d.ts +446 -0
- package/out/zero-cache/src/services/change-streamer/subscribe.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/subscribe.js +76 -0
- package/out/zero-cache/src/services/change-streamer/subscribe.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/subscriber.d.ts +58 -1
- package/out/zero-cache/src/services/change-streamer/subscriber.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/subscriber.js +123 -12
- 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 +19 -1
- package/out/zero-cache/src/services/change-streamer/upstream-acker.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/upstream-acker.js +23 -3
- package/out/zero-cache/src/services/change-streamer/upstream-acker.js.map +1 -1
- package/out/zero-cache/src/services/http-service.d.ts +1 -1
- package/out/zero-cache/src/services/http-service.d.ts.map +1 -1
- package/out/zero-cache/src/services/http-service.js.map +1 -1
- package/out/zero-cache/src/services/life-cycle.d.ts.map +1 -1
- package/out/zero-cache/src/services/life-cycle.js +3 -1
- package/out/zero-cache/src/services/life-cycle.js.map +1 -1
- package/out/zero-cache/src/services/litestream/commands.d.ts +34 -3
- package/out/zero-cache/src/services/litestream/commands.d.ts.map +1 -1
- package/out/zero-cache/src/services/litestream/commands.js +121 -35
- package/out/zero-cache/src/services/litestream/commands.js.map +1 -1
- package/out/zero-cache/src/services/litestream/config-v5.yml +6 -7
- package/out/zero-cache/src/services/litestream/litestream-checkpointer.js +51 -24
- package/out/zero-cache/src/services/litestream/litestream-checkpointer.js.map +1 -1
- package/out/zero-cache/src/services/litestream/litestream-controller.d.ts +10 -2
- package/out/zero-cache/src/services/litestream/litestream-controller.d.ts.map +1 -1
- package/out/zero-cache/src/services/litestream/litestream-controller.js +3 -2
- package/out/zero-cache/src/services/litestream/litestream-controller.js.map +1 -1
- package/out/zero-cache/src/services/litestream/restore-progress.d.ts +24 -0
- package/out/zero-cache/src/services/litestream/restore-progress.d.ts.map +1 -0
- package/out/zero-cache/src/services/litestream/restore-progress.js +91 -0
- package/out/zero-cache/src/services/litestream/restore-progress.js.map +1 -0
- package/out/zero-cache/src/services/litestream/wal-keeper.d.ts +33 -0
- package/out/zero-cache/src/services/litestream/wal-keeper.d.ts.map +1 -0
- package/out/zero-cache/src/services/litestream/wal-keeper.js +49 -0
- package/out/zero-cache/src/services/litestream/wal-keeper.js.map +1 -0
- package/out/zero-cache/src/services/mutagen/mutagen.d.ts +5 -0
- package/out/zero-cache/src/services/mutagen/mutagen.d.ts.map +1 -1
- package/out/zero-cache/src/services/mutagen/mutagen.js +7 -1
- package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -1
- package/out/zero-cache/src/services/mutagen/pusher.d.ts.map +1 -1
- package/out/zero-cache/src/services/mutagen/pusher.js +5 -6
- package/out/zero-cache/src/services/mutagen/pusher.js.map +1 -1
- package/out/zero-cache/src/services/plannerz.d.ts +163 -0
- package/out/zero-cache/src/services/plannerz.d.ts.map +1 -0
- package/out/zero-cache/src/services/plannerz.js +267 -0
- package/out/zero-cache/src/services/plannerz.js.map +1 -0
- package/out/zero-cache/src/services/profz.d.ts +30 -0
- package/out/zero-cache/src/services/profz.d.ts.map +1 -0
- package/out/zero-cache/src/services/profz.js +163 -0
- package/out/zero-cache/src/services/profz.js.map +1 -0
- package/out/zero-cache/src/services/replicator/change-log-cookies.js +1 -1
- package/out/zero-cache/src/services/replicator/change-log-cookies.js.map +1 -1
- package/out/zero-cache/src/services/replicator/change-log-stream-writer.d.ts +5 -4
- package/out/zero-cache/src/services/replicator/change-log-stream-writer.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/change-log-stream-writer.js +20 -22
- package/out/zero-cache/src/services/replicator/change-log-stream-writer.js.map +1 -1
- package/out/zero-cache/src/services/replicator/change-processor.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/change-processor.js +51 -5
- package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
- package/out/zero-cache/src/services/replicator/incremental-sync.d.ts +5 -2
- package/out/zero-cache/src/services/replicator/incremental-sync.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/incremental-sync.js +54 -21
- package/out/zero-cache/src/services/replicator/incremental-sync.js.map +1 -1
- package/out/zero-cache/src/services/replicator/replication-status.d.ts +35 -1
- package/out/zero-cache/src/services/replicator/replication-status.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/replication-status.js +99 -8
- package/out/zero-cache/src/services/replicator/replication-status.js.map +1 -1
- package/out/zero-cache/src/services/replicator/replicator.d.ts +4 -1
- package/out/zero-cache/src/services/replicator/replicator.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/replicator.js +5 -2
- package/out/zero-cache/src/services/replicator/replicator.js.map +1 -1
- package/out/zero-cache/src/services/replicator/reporter/recorder.d.ts +16 -1
- package/out/zero-cache/src/services/replicator/reporter/recorder.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/reporter/recorder.js +70 -27
- package/out/zero-cache/src/services/replicator/reporter/recorder.js.map +1 -1
- package/out/zero-cache/src/services/replicator/schema/backfilling.d.ts +23 -2
- package/out/zero-cache/src/services/replicator/schema/backfilling.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/schema/backfilling.js +54 -2
- package/out/zero-cache/src/services/replicator/schema/backfilling.js.map +1 -1
- package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.d.ts +6 -6
- package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.js +19 -14
- package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.js.map +1 -1
- package/out/zero-cache/src/services/replicator/write-worker-client.d.ts +11 -3
- package/out/zero-cache/src/services/replicator/write-worker-client.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/write-worker-client.js.map +1 -1
- package/out/zero-cache/src/services/replicator/write-worker.js +5 -1
- package/out/zero-cache/src/services/replicator/write-worker.js.map +1 -1
- package/out/zero-cache/src/services/run-ast.d.ts +12 -0
- package/out/zero-cache/src/services/run-ast.d.ts.map +1 -1
- package/out/zero-cache/src/services/run-ast.js +42 -22
- package/out/zero-cache/src/services/run-ast.js.map +1 -1
- package/out/zero-cache/src/services/runner.d.ts +2 -1
- package/out/zero-cache/src/services/runner.d.ts.map +1 -1
- package/out/zero-cache/src/services/runner.js +10 -2
- package/out/zero-cache/src/services/runner.js.map +1 -1
- package/out/zero-cache/src/services/statz.d.ts +4 -0
- package/out/zero-cache/src/services/statz.d.ts.map +1 -1
- package/out/zero-cache/src/services/statz.js +22 -5
- package/out/zero-cache/src/services/statz.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/advancement-metrics.d.ts +26 -0
- package/out/zero-cache/src/services/view-syncer/advancement-metrics.d.ts.map +1 -0
- package/out/zero-cache/src/services/view-syncer/advancement-metrics.js +26 -0
- package/out/zero-cache/src/services/view-syncer/advancement-metrics.js.map +1 -0
- package/out/zero-cache/src/services/view-syncer/client-handler.d.ts +19 -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 +42 -30
- package/out/zero-cache/src/services/view-syncer/client-handler.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/connection-context-manager.d.ts +2 -1
- package/out/zero-cache/src/services/view-syncer/connection-context-manager.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/connection-context-manager.js +1 -0
- package/out/zero-cache/src/services/view-syncer/connection-context-manager.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts +27 -2
- 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 +85 -20
- package/out/zero-cache/src/services/view-syncer/cvr-store.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr.d.ts +76 -11
- package/out/zero-cache/src/services/view-syncer/cvr.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr.js +214 -40
- package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/deferred-writes-budget.d.ts +81 -0
- package/out/zero-cache/src/services/view-syncer/deferred-writes-budget.d.ts.map +1 -0
- package/out/zero-cache/src/services/view-syncer/deferred-writes-budget.js +128 -0
- package/out/zero-cache/src/services/view-syncer/deferred-writes-budget.js.map +1 -0
- package/out/zero-cache/src/services/view-syncer/drain-coordinator.d.ts +14 -1
- package/out/zero-cache/src/services/view-syncer/drain-coordinator.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/drain-coordinator.js +30 -4
- package/out/zero-cache/src/services/view-syncer/drain-coordinator.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/hydration-budget.d.ts +33 -0
- package/out/zero-cache/src/services/view-syncer/hydration-budget.d.ts.map +1 -0
- package/out/zero-cache/src/services/view-syncer/hydration-budget.js +62 -0
- package/out/zero-cache/src/services/view-syncer/hydration-budget.js.map +1 -0
- package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.d.ts +51 -0
- package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.d.ts.map +1 -0
- package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.js +78 -0
- package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.js.map +1 -0
- package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts +10 -1
- package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/inspect-handler.js +18 -4
- package/out/zero-cache/src/services/view-syncer/inspect-handler.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts +80 -6
- 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 +658 -195
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/plan-warnings.d.ts +7 -0
- package/out/zero-cache/src/services/view-syncer/plan-warnings.d.ts.map +1 -0
- package/out/zero-cache/src/services/view-syncer/plan-warnings.js +35 -0
- package/out/zero-cache/src/services/view-syncer/plan-warnings.js.map +1 -0
- package/out/zero-cache/src/services/view-syncer/query-covering.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/query-covering.js +2 -6
- package/out/zero-cache/src/services/view-syncer/query-covering.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/query-shape.d.ts +25 -0
- package/out/zero-cache/src/services/view-syncer/query-shape.d.ts.map +1 -0
- package/out/zero-cache/src/services/view-syncer/query-shape.js +28 -0
- package/out/zero-cache/src/services/view-syncer/query-shape.js.map +1 -0
- package/out/zero-cache/src/services/view-syncer/query-stats.d.ts +82 -0
- package/out/zero-cache/src/services/view-syncer/query-stats.d.ts.map +1 -0
- package/out/zero-cache/src/services/view-syncer/query-stats.js +214 -0
- package/out/zero-cache/src/services/view-syncer/query-stats.js.map +1 -0
- package/out/zero-cache/src/services/view-syncer/schema/types.d.ts +2 -107
- package/out/zero-cache/src/services/view-syncer/schema/types.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/schema/types.js +5 -20
- package/out/zero-cache/src/services/view-syncer/schema/types.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/snapshot-row-cache.d.ts +95 -0
- package/out/zero-cache/src/services/view-syncer/snapshot-row-cache.d.ts.map +1 -0
- package/out/zero-cache/src/services/view-syncer/snapshot-row-cache.js +155 -0
- package/out/zero-cache/src/services/view-syncer/snapshot-row-cache.js.map +1 -0
- package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts +96 -14
- package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/snapshotter.js +214 -30
- package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts +11 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.js +566 -107
- package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
- package/out/zero-cache/src/types/pg-data-type.d.ts +2 -0
- package/out/zero-cache/src/types/pg-data-type.d.ts.map +1 -1
- package/out/zero-cache/src/types/pg-data-type.js +6 -1
- package/out/zero-cache/src/types/pg-data-type.js.map +1 -1
- package/out/zero-cache/src/types/pg.d.ts.map +1 -1
- package/out/zero-cache/src/types/pg.js +1 -1
- package/out/zero-cache/src/types/pg.js.map +1 -1
- package/out/zero-cache/src/types/processes.d.ts +39 -0
- package/out/zero-cache/src/types/processes.d.ts.map +1 -1
- package/out/zero-cache/src/types/processes.js +43 -4
- package/out/zero-cache/src/types/processes.js.map +1 -1
- package/out/zero-cache/src/types/profiler.d.ts +12 -0
- package/out/zero-cache/src/types/profiler.d.ts.map +1 -1
- package/out/zero-cache/src/types/profiler.js +46 -1
- package/out/zero-cache/src/types/profiler.js.map +1 -1
- package/out/zero-cache/src/types/row-key.d.ts +1 -15
- package/out/zero-cache/src/types/row-key.d.ts.map +1 -1
- package/out/zero-cache/src/types/row-key.js +6 -8
- package/out/zero-cache/src/types/row-key.js.map +1 -1
- package/out/zero-cache/src/types/streams.d.ts +49 -7
- package/out/zero-cache/src/types/streams.d.ts.map +1 -1
- package/out/zero-cache/src/types/streams.js +190 -58
- package/out/zero-cache/src/types/streams.js.map +1 -1
- package/out/zero-cache/src/types/subscription.d.ts +15 -0
- package/out/zero-cache/src/types/subscription.d.ts.map +1 -1
- package/out/zero-cache/src/types/subscription.js +123 -31
- package/out/zero-cache/src/types/subscription.js.map +1 -1
- package/out/zero-cache/src/types/websocket-handoff.d.ts +1 -1
- package/out/zero-cache/src/types/websocket-handoff.d.ts.map +1 -1
- package/out/zero-cache/src/types/websocket-handoff.js +18 -9
- package/out/zero-cache/src/types/websocket-handoff.js.map +1 -1
- package/out/zero-cache/src/types/ws.d.ts.map +1 -1
- package/out/zero-cache/src/types/ws.js +1 -16
- package/out/zero-cache/src/types/ws.js.map +1 -1
- package/out/zero-cache/src/workers/connect-params.d.ts +18 -1
- package/out/zero-cache/src/workers/connect-params.d.ts.map +1 -1
- package/out/zero-cache/src/workers/connect-params.js +25 -1
- package/out/zero-cache/src/workers/connect-params.js.map +1 -1
- package/out/zero-cache/src/workers/connection.d.ts +4 -4
- package/out/zero-cache/src/workers/connection.d.ts.map +1 -1
- package/out/zero-cache/src/workers/connection.js +8 -8
- package/out/zero-cache/src/workers/connection.js.map +1 -1
- package/out/zero-cache/src/workers/replicator.d.ts.map +1 -1
- package/out/zero-cache/src/workers/replicator.js +15 -7
- package/out/zero-cache/src/workers/replicator.js.map +1 -1
- package/out/zero-cache/src/workers/syncer-ws-message-handler.d.ts.map +1 -1
- package/out/zero-cache/src/workers/syncer-ws-message-handler.js +21 -16
- package/out/zero-cache/src/workers/syncer-ws-message-handler.js.map +1 -1
- package/out/zero-cache/src/workers/syncer.d.ts.map +1 -1
- package/out/zero-cache/src/workers/syncer.js +55 -4
- package/out/zero-cache/src/workers/syncer.js.map +1 -1
- package/out/zero-client/src/client/active-clients-manager.d.ts.map +1 -1
- package/out/zero-client/src/client/active-clients-manager.js +4 -1
- package/out/zero-client/src/client/active-clients-manager.js.map +1 -1
- package/out/zero-client/src/client/connection-manager.d.ts +20 -0
- package/out/zero-client/src/client/connection-manager.d.ts.map +1 -1
- package/out/zero-client/src/client/connection-manager.js +77 -13
- package/out/zero-client/src/client/connection-manager.js.map +1 -1
- package/out/zero-client/src/client/connection-status-enum.d.ts +2 -0
- package/out/zero-client/src/client/connection-status-enum.d.ts.map +1 -1
- package/out/zero-client/src/client/connection-status-enum.js +3 -1
- package/out/zero-client/src/client/connection-status-enum.js.map +1 -1
- package/out/zero-client/src/client/connection.d.ts +6 -0
- package/out/zero-client/src/client/connection.d.ts.map +1 -1
- package/out/zero-client/src/client/connection.js +2 -1
- package/out/zero-client/src/client/connection.js.map +1 -1
- package/out/zero-client/src/client/context.d.ts +23 -13
- package/out/zero-client/src/client/context.d.ts.map +1 -1
- package/out/zero-client/src/client/context.js +94 -26
- package/out/zero-client/src/client/context.js.map +1 -1
- package/out/zero-client/src/client/crud-impl.d.ts.map +1 -1
- package/out/zero-client/src/client/crud-impl.js +1 -1
- package/out/zero-client/src/client/crud-impl.js.map +1 -1
- package/out/zero-client/src/client/custom.d.ts +5 -4
- package/out/zero-client/src/client/custom.d.ts.map +1 -1
- package/out/zero-client/src/client/custom.js +3 -3
- package/out/zero-client/src/client/custom.js.map +1 -1
- package/out/zero-client/src/client/inspector/lazy-inspector.js +1 -1
- package/out/zero-client/src/client/ivm-branch.d.ts.map +1 -1
- package/out/zero-client/src/client/ivm-branch.js +20 -3
- package/out/zero-client/src/client/ivm-branch.js.map +1 -1
- package/out/zero-client/src/client/keys.d.ts.map +1 -1
- package/out/zero-client/src/client/keys.js +19 -1
- package/out/zero-client/src/client/keys.js.map +1 -1
- package/out/zero-client/src/client/make-mutate-property.d.ts +1 -1
- package/out/zero-client/src/client/make-mutate-property.d.ts.map +1 -1
- package/out/zero-client/src/client/make-mutate-property.js.map +1 -1
- package/out/zero-client/src/client/make-replicache-mutators.d.ts.map +1 -1
- package/out/zero-client/src/client/make-replicache-mutators.js +1 -1
- package/out/zero-client/src/client/make-replicache-mutators.js.map +1 -1
- package/out/zero-client/src/client/mutation-tracker.d.ts +2 -2
- package/out/zero-client/src/client/mutation-tracker.d.ts.map +1 -1
- package/out/zero-client/src/client/mutation-tracker.js +3 -7
- package/out/zero-client/src/client/mutation-tracker.js.map +1 -1
- package/out/zero-client/src/client/mutator-proxy.d.ts.map +1 -1
- package/out/zero-client/src/client/mutator-proxy.js +9 -4
- package/out/zero-client/src/client/mutator-proxy.js.map +1 -1
- package/out/zero-client/src/client/options.d.ts +33 -0
- package/out/zero-client/src/client/options.d.ts.map +1 -1
- package/out/zero-client/src/client/options.js.map +1 -1
- package/out/zero-client/src/client/query-manager.d.ts +9 -0
- package/out/zero-client/src/client/query-manager.d.ts.map +1 -1
- package/out/zero-client/src/client/query-manager.js +47 -14
- package/out/zero-client/src/client/query-manager.js.map +1 -1
- package/out/zero-client/src/client/reload-error-handler.js +2 -2
- package/out/zero-client/src/client/reload-error-handler.js.map +1 -1
- package/out/zero-client/src/client/version.js +1 -1
- package/out/zero-client/src/client/zero-rep.d.ts +1 -0
- package/out/zero-client/src/client/zero-rep.d.ts.map +1 -1
- package/out/zero-client/src/client/zero-rep.js +8 -6
- package/out/zero-client/src/client/zero-rep.js.map +1 -1
- package/out/zero-client/src/client/zero.d.ts +18 -3
- package/out/zero-client/src/client/zero.d.ts.map +1 -1
- package/out/zero-client/src/client/zero.js +89 -50
- package/out/zero-client/src/client/zero.js.map +1 -1
- package/out/zero-client/src/mod.d.ts +2 -1
- package/out/zero-client/src/mod.d.ts.map +1 -1
- package/out/zero-client/src/mod.js +1 -0
- package/out/zero-client/src/types/query-result.d.ts +2 -0
- package/out/zero-client/src/types/query-result.d.ts.map +1 -1
- package/out/zero-events/src/status.d.ts +64 -0
- package/out/zero-events/src/status.d.ts.map +1 -1
- package/out/zero-protocol/src/analyze-query-result.d.ts +5 -0
- package/out/zero-protocol/src/analyze-query-result.d.ts.map +1 -1
- package/out/zero-protocol/src/analyze-query-result.js.map +1 -1
- package/out/zero-protocol/src/ast.d.ts.map +1 -1
- package/out/zero-protocol/src/ast.js +13 -14
- package/out/zero-protocol/src/ast.js.map +1 -1
- package/out/zero-protocol/src/connect.d.ts +16 -0
- package/out/zero-protocol/src/connect.d.ts.map +1 -1
- package/out/zero-protocol/src/connect.js +27 -1
- package/out/zero-protocol/src/connect.js.map +1 -1
- package/out/zero-protocol/src/down.d.ts +31 -31
- package/out/zero-protocol/src/feature-flag-enum.d.ts +14 -0
- package/out/zero-protocol/src/feature-flag-enum.d.ts.map +1 -0
- package/out/zero-protocol/src/feature-flag-enum.js +10 -0
- package/out/zero-protocol/src/feature-flag-enum.js.map +1 -0
- package/out/zero-protocol/src/feature-flag.d.ts +5 -0
- package/out/zero-protocol/src/feature-flag.d.ts.map +1 -0
- package/out/zero-protocol/src/inspect-down.d.ts +16 -16
- package/out/zero-protocol/src/poke.d.ts +17 -10
- package/out/zero-protocol/src/poke.d.ts.map +1 -1
- package/out/zero-protocol/src/poke.js +3 -2
- package/out/zero-protocol/src/poke.js.map +1 -1
- package/out/zero-protocol/src/protocol-version.d.ts +30 -6
- package/out/zero-protocol/src/protocol-version.d.ts.map +1 -1
- package/out/zero-protocol/src/protocol-version.js +1 -1
- package/out/zero-protocol/src/protocol-version.js.map +1 -1
- package/out/zero-protocol/src/query-hash.d.ts.map +1 -1
- package/out/zero-protocol/src/query-hash.js +2 -5
- package/out/zero-protocol/src/query-hash.js.map +1 -1
- package/out/zero-react/src/use-query.d.ts +5 -4
- package/out/zero-react/src/use-query.d.ts.map +1 -1
- package/out/zero-react/src/use-query.js +74 -7
- package/out/zero-react/src/use-query.js.map +1 -1
- package/out/zero-react/src/zero.js +1 -0
- package/out/zero-server/src/adapters/drizzle.d.ts +2 -1
- package/out/zero-server/src/adapters/drizzle.d.ts.map +1 -1
- package/out/zero-server/src/adapters/drizzle.js +12 -7
- package/out/zero-server/src/adapters/drizzle.js.map +1 -1
- package/out/zero-server/src/adapters/kysely.d.ts +2 -1
- package/out/zero-server/src/adapters/kysely.d.ts.map +1 -1
- package/out/zero-server/src/adapters/kysely.js +8 -2
- package/out/zero-server/src/adapters/kysely.js.map +1 -1
- package/out/zero-server/src/adapters/pg.d.ts +5 -1
- package/out/zero-server/src/adapters/pg.d.ts.map +1 -1
- package/out/zero-server/src/adapters/pg.js +28 -7
- package/out/zero-server/src/adapters/pg.js.map +1 -1
- package/out/zero-server/src/adapters/postgresjs.d.ts +1 -0
- package/out/zero-server/src/adapters/postgresjs.d.ts.map +1 -1
- package/out/zero-server/src/adapters/postgresjs.js +7 -1
- package/out/zero-server/src/adapters/postgresjs.js.map +1 -1
- package/out/zero-server/src/adapters/prisma.d.ts +3 -2
- package/out/zero-server/src/adapters/prisma.d.ts.map +1 -1
- package/out/zero-server/src/adapters/prisma.js +8 -2
- package/out/zero-server/src/adapters/prisma.js.map +1 -1
- package/out/zero-server/src/closable-db-transaction.d.ts +16 -0
- package/out/zero-server/src/closable-db-transaction.d.ts.map +1 -0
- package/out/zero-server/src/closable-db-transaction.js +31 -0
- package/out/zero-server/src/closable-db-transaction.js.map +1 -0
- package/out/zero-server/src/custom.d.ts +10 -4
- package/out/zero-server/src/custom.d.ts.map +1 -1
- package/out/zero-server/src/custom.js +15 -6
- package/out/zero-server/src/custom.js.map +1 -1
- package/out/zero-server/src/logging.d.ts +2 -2
- package/out/zero-server/src/logging.d.ts.map +1 -1
- package/out/zero-server/src/logging.js +2 -2
- package/out/zero-server/src/logging.js.map +1 -1
- package/out/zero-server/src/mod.d.ts +1 -1
- package/out/zero-server/src/mod.d.ts.map +1 -1
- package/out/zero-server/src/pg-query-executor.d.ts +2 -2
- package/out/zero-server/src/pg-query-executor.d.ts.map +1 -1
- package/out/zero-server/src/pg-query-executor.js +2 -2
- package/out/zero-server/src/pg-query-executor.js.map +1 -1
- package/out/zero-server/src/process-mutations.d.ts +25 -4
- package/out/zero-server/src/process-mutations.d.ts.map +1 -1
- package/out/zero-server/src/process-mutations.js +103 -52
- package/out/zero-server/src/process-mutations.js.map +1 -1
- package/out/zero-server/src/push-processor.d.ts +8 -2
- package/out/zero-server/src/push-processor.d.ts.map +1 -1
- package/out/zero-server/src/push-processor.js +12 -4
- package/out/zero-server/src/push-processor.js.map +1 -1
- package/out/zero-server/src/schema.d.ts +2 -2
- package/out/zero-server/src/schema.d.ts.map +1 -1
- package/out/zero-server/src/schema.js +3 -2
- package/out/zero-server/src/schema.js.map +1 -1
- package/out/zero-server/src/zql-database.d.ts +21 -1
- package/out/zero-server/src/zql-database.d.ts.map +1 -1
- package/out/zero-server/src/zql-database.js +61 -24
- package/out/zero-server/src/zql-database.js.map +1 -1
- package/out/zero-solid/src/solid-view.d.ts +17 -0
- package/out/zero-solid/src/solid-view.d.ts.map +1 -1
- package/out/zero-solid/src/solid-view.js +39 -1
- package/out/zero-solid/src/solid-view.js.map +1 -1
- package/out/zero-solid/src/use-query.js +1 -2
- package/out/zero-solid/src/use-query.js.map +1 -1
- package/out/zero-solid/src/zero.js +1 -0
- package/out/zql/src/builder/builder.d.ts +25 -0
- package/out/zql/src/builder/builder.d.ts.map +1 -1
- package/out/zql/src/builder/builder.js +69 -19
- package/out/zql/src/builder/builder.js.map +1 -1
- package/out/zql/src/builder/correlated-predicate-pushdown.d.ts +43 -0
- package/out/zql/src/builder/correlated-predicate-pushdown.d.ts.map +1 -0
- package/out/zql/src/builder/correlated-predicate-pushdown.js +161 -0
- package/out/zql/src/builder/correlated-predicate-pushdown.js.map +1 -0
- package/out/zql/src/builder/debug-delegate.d.ts +6 -1
- package/out/zql/src/builder/debug-delegate.d.ts.map +1 -1
- package/out/zql/src/builder/debug-delegate.js +14 -2
- package/out/zql/src/builder/debug-delegate.js.map +1 -1
- package/out/zql/src/ivm/array-view.d.ts +29 -0
- package/out/zql/src/ivm/array-view.d.ts.map +1 -1
- package/out/zql/src/ivm/array-view.js +74 -16
- package/out/zql/src/ivm/array-view.js.map +1 -1
- package/out/zql/src/ivm/cap.d.ts +2 -1
- package/out/zql/src/ivm/cap.d.ts.map +1 -1
- package/out/zql/src/ivm/cap.js +14 -4
- package/out/zql/src/ivm/cap.js.map +1 -1
- package/out/zql/src/ivm/data.d.ts.map +1 -1
- package/out/zql/src/ivm/data.js +8 -3
- package/out/zql/src/ivm/data.js.map +1 -1
- package/out/zql/src/ivm/deferred-input.d.ts.map +1 -1
- package/out/zql/src/ivm/deferred-input.js +3 -2
- package/out/zql/src/ivm/deferred-input.js.map +1 -1
- package/out/zql/src/ivm/exists.d.ts +3 -1
- package/out/zql/src/ivm/exists.d.ts.map +1 -1
- package/out/zql/src/ivm/exists.js +4 -1
- package/out/zql/src/ivm/exists.js.map +1 -1
- package/out/zql/src/ivm/fan-in.d.ts +6 -2
- package/out/zql/src/ivm/fan-in.d.ts.map +1 -1
- package/out/zql/src/ivm/fan-in.js +13 -5
- package/out/zql/src/ivm/fan-in.js.map +1 -1
- package/out/zql/src/ivm/fan-out.d.ts +5 -2
- package/out/zql/src/ivm/fan-out.d.ts.map +1 -1
- package/out/zql/src/ivm/fan-out.js +4 -0
- package/out/zql/src/ivm/fan-out.js.map +1 -1
- package/out/zql/src/ivm/filter-operators.d.ts +8 -6
- package/out/zql/src/ivm/filter-operators.d.ts.map +1 -1
- package/out/zql/src/ivm/filter-operators.js +19 -8
- package/out/zql/src/ivm/filter-operators.js.map +1 -1
- package/out/zql/src/ivm/filter.d.ts +5 -2
- package/out/zql/src/ivm/filter.d.ts.map +1 -1
- package/out/zql/src/ivm/filter.js +10 -4
- package/out/zql/src/ivm/filter.js.map +1 -1
- package/out/zql/src/ivm/flipped-join.d.ts +9 -4
- package/out/zql/src/ivm/flipped-join.d.ts.map +1 -1
- package/out/zql/src/ivm/flipped-join.js +97 -46
- package/out/zql/src/ivm/flipped-join.js.map +1 -1
- package/out/zql/src/ivm/join-index-tap.d.ts +33 -0
- package/out/zql/src/ivm/join-index-tap.d.ts.map +1 -0
- package/out/zql/src/ivm/join-index-tap.js +70 -0
- package/out/zql/src/ivm/join-index-tap.js.map +1 -0
- package/out/zql/src/ivm/join-index.d.ts +35 -0
- package/out/zql/src/ivm/join-index.d.ts.map +1 -0
- package/out/zql/src/ivm/join-index.js +141 -0
- package/out/zql/src/ivm/join-index.js.map +1 -0
- package/out/zql/src/ivm/join-utils.d.ts +6 -0
- package/out/zql/src/ivm/join-utils.d.ts.map +1 -1
- package/out/zql/src/ivm/join-utils.js +22 -1
- package/out/zql/src/ivm/join-utils.js.map +1 -1
- package/out/zql/src/ivm/join.d.ts +19 -1
- package/out/zql/src/ivm/join.d.ts.map +1 -1
- package/out/zql/src/ivm/join.js +107 -15
- package/out/zql/src/ivm/join.js.map +1 -1
- package/out/zql/src/ivm/maybe-split-and-push-edit-change.d.ts +1 -1
- package/out/zql/src/ivm/maybe-split-and-push-edit-change.d.ts.map +1 -1
- package/out/zql/src/ivm/maybe-split-and-push-edit-change.js +6 -4
- package/out/zql/src/ivm/maybe-split-and-push-edit-change.js.map +1 -1
- package/out/zql/src/ivm/memory-source.d.ts +29 -4
- package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
- package/out/zql/src/ivm/memory-source.js +70 -34
- package/out/zql/src/ivm/memory-source.js.map +1 -1
- package/out/zql/src/ivm/memory-storage.d.ts +1 -0
- package/out/zql/src/ivm/memory-storage.d.ts.map +1 -1
- package/out/zql/src/ivm/memory-storage.js +1 -0
- package/out/zql/src/ivm/memory-storage.js.map +1 -1
- package/out/zql/src/ivm/operator.d.ts +45 -10
- package/out/zql/src/ivm/operator.d.ts.map +1 -1
- package/out/zql/src/ivm/operator.js +9 -4
- package/out/zql/src/ivm/operator.js.map +1 -1
- package/out/zql/src/ivm/push-accumulated.d.ts +6 -1
- package/out/zql/src/ivm/push-accumulated.d.ts.map +1 -1
- package/out/zql/src/ivm/push-accumulated.js +47 -2
- package/out/zql/src/ivm/push-accumulated.js.map +1 -1
- package/out/zql/src/ivm/skip.d.ts +2 -1
- package/out/zql/src/ivm/skip.d.ts.map +1 -1
- package/out/zql/src/ivm/skip.js +3 -0
- package/out/zql/src/ivm/skip.js.map +1 -1
- package/out/zql/src/ivm/take-gate.d.ts +57 -0
- package/out/zql/src/ivm/take-gate.d.ts.map +1 -0
- package/out/zql/src/ivm/take-gate.js +106 -0
- package/out/zql/src/ivm/take-gate.js.map +1 -0
- package/out/zql/src/ivm/take.d.ts +8 -2
- package/out/zql/src/ivm/take.d.ts.map +1 -1
- package/out/zql/src/ivm/take.js +139 -103
- package/out/zql/src/ivm/take.js.map +1 -1
- package/out/zql/src/ivm/union-fan-in.d.ts +3 -0
- package/out/zql/src/ivm/union-fan-in.d.ts.map +1 -1
- package/out/zql/src/ivm/union-fan-in.js +63 -10
- package/out/zql/src/ivm/union-fan-in.js.map +1 -1
- package/out/zql/src/ivm/union-fan-out.d.ts +2 -1
- package/out/zql/src/ivm/union-fan-out.d.ts.map +1 -1
- package/out/zql/src/ivm/union-fan-out.js +5 -0
- package/out/zql/src/ivm/union-fan-out.js.map +1 -1
- package/out/zql/src/ivm/view-apply-change.d.ts.map +1 -1
- package/out/zql/src/ivm/view-apply-change.js +9 -4
- package/out/zql/src/ivm/view-apply-change.js.map +1 -1
- package/out/zql/src/ivm/view.d.ts +15 -0
- package/out/zql/src/ivm/view.d.ts.map +1 -1
- package/out/zql/src/mutate/custom.d.ts +53 -1
- package/out/zql/src/mutate/custom.d.ts.map +1 -1
- package/out/zql/src/mutate/custom.js.map +1 -1
- package/out/zql/src/mutate/mutator-registry.d.ts.map +1 -1
- package/out/zql/src/mutate/mutator-registry.js +3 -3
- package/out/zql/src/mutate/mutator-registry.js.map +1 -1
- package/out/zql/src/mutate/mutator.d.ts +2 -2
- package/out/zql/src/mutate/mutator.d.ts.map +1 -1
- package/out/zql/src/mutate/mutator.js.map +1 -1
- package/out/zql/src/planner/planner-builder.d.ts +23 -3
- package/out/zql/src/planner/planner-builder.d.ts.map +1 -1
- package/out/zql/src/planner/planner-builder.js +34 -17
- package/out/zql/src/planner/planner-builder.js.map +1 -1
- package/out/zql/src/planner/planner-connection.d.ts +58 -2
- package/out/zql/src/planner/planner-connection.d.ts.map +1 -1
- package/out/zql/src/planner/planner-connection.js +103 -11
- package/out/zql/src/planner/planner-connection.js.map +1 -1
- package/out/zql/src/planner/planner-debug.d.ts.map +1 -1
- package/out/zql/src/planner/planner-debug.js +3 -8
- package/out/zql/src/planner/planner-debug.js.map +1 -1
- package/out/zql/src/planner/planner-graph.d.ts +10 -0
- package/out/zql/src/planner/planner-graph.d.ts.map +1 -1
- package/out/zql/src/planner/planner-graph.js +14 -0
- package/out/zql/src/planner/planner-graph.js.map +1 -1
- package/out/zql/src/planner/planner-source.d.ts +2 -2
- package/out/zql/src/planner/planner-source.d.ts.map +1 -1
- package/out/zql/src/planner/planner-source.js +2 -2
- package/out/zql/src/planner/planner-source.js.map +1 -1
- package/out/zql/src/planner/planner-warnings.d.ts +83 -0
- package/out/zql/src/planner/planner-warnings.d.ts.map +1 -0
- package/out/zql/src/planner/planner-warnings.js +78 -0
- package/out/zql/src/planner/planner-warnings.js.map +1 -0
- package/out/zql/src/query/measure-push-operator.d.ts +9 -2
- package/out/zql/src/query/measure-push-operator.d.ts.map +1 -1
- package/out/zql/src/query/measure-push-operator.js +52 -5
- package/out/zql/src/query/measure-push-operator.js.map +1 -1
- package/out/zql/src/query/query-delegate-base.d.ts +4 -2
- package/out/zql/src/query/query-delegate-base.d.ts.map +1 -1
- package/out/zql/src/query/query-delegate-base.js +66 -33
- package/out/zql/src/query/query-delegate-base.js.map +1 -1
- package/out/zql/src/query/query-delegate.d.ts +33 -6
- package/out/zql/src/query/query-delegate.d.ts.map +1 -1
- package/out/zql/src/query/query-impl.d.ts +1 -0
- package/out/zql/src/query/query-impl.d.ts.map +1 -1
- package/out/zql/src/query/query-impl.js +6 -23
- package/out/zql/src/query/query-impl.js.map +1 -1
- package/out/zql/src/query/query-transitions.d.ts.map +1 -1
- package/out/zql/src/query/query-transitions.js +2 -5
- package/out/zql/src/query/query-transitions.js.map +1 -1
- package/out/zql/src/query/query.d.ts +22 -5
- package/out/zql/src/query/query.d.ts.map +1 -1
- package/out/zql/src/query/runnable-query-impl.d.ts +1 -0
- package/out/zql/src/query/runnable-query-impl.d.ts.map +1 -1
- package/out/zql/src/query/runnable-query-impl.js +2 -10
- package/out/zql/src/query/runnable-query-impl.js.map +1 -1
- package/out/zql/src/query/typed-view.d.ts +1 -1
- package/out/zql/src/query/typed-view.d.ts.map +1 -1
- package/out/zqlite/src/database-storage.d.ts.map +1 -1
- package/out/zqlite/src/database-storage.js +9 -1
- package/out/zqlite/src/database-storage.js.map +1 -1
- package/out/zqlite/src/db.d.ts +9 -1
- package/out/zqlite/src/db.d.ts.map +1 -1
- package/out/zqlite/src/db.js +62 -30
- package/out/zqlite/src/db.js.map +1 -1
- package/out/zqlite/src/index-usage.d.ts +19 -0
- package/out/zqlite/src/index-usage.d.ts.map +1 -0
- package/out/zqlite/src/index-usage.js +49 -0
- package/out/zqlite/src/index-usage.js.map +1 -0
- package/out/zqlite/src/pending-delta.d.ts +110 -0
- package/out/zqlite/src/pending-delta.d.ts.map +1 -0
- package/out/zqlite/src/pending-delta.js +278 -0
- package/out/zqlite/src/pending-delta.js.map +1 -0
- package/out/zqlite/src/query-builder.d.ts +17 -1
- package/out/zqlite/src/query-builder.d.ts.map +1 -1
- package/out/zqlite/src/query-builder.js +111 -20
- package/out/zqlite/src/query-builder.js.map +1 -1
- package/out/zqlite/src/query-delegate.d.ts.map +1 -1
- package/out/zqlite/src/query-delegate.js +10 -7
- package/out/zqlite/src/query-delegate.js.map +1 -1
- package/out/zqlite/src/resolve-scalar-subqueries.d.ts +3 -1
- package/out/zqlite/src/resolve-scalar-subqueries.d.ts.map +1 -1
- package/out/zqlite/src/resolve-scalar-subqueries.js +1 -0
- package/out/zqlite/src/resolve-scalar-subqueries.js.map +1 -1
- package/out/zqlite/src/sqlite-cost-model.d.ts.map +1 -1
- package/out/zqlite/src/sqlite-cost-model.js +52 -1
- package/out/zqlite/src/sqlite-cost-model.js.map +1 -1
- package/out/zqlite/src/sqlite-stat-fanout.d.ts.map +1 -1
- package/out/zqlite/src/sqlite-stat-fanout.js +5 -31
- package/out/zqlite/src/sqlite-stat-fanout.js.map +1 -1
- package/out/zqlite/src/sqlite-stat4-sample.d.ts +37 -0
- package/out/zqlite/src/sqlite-stat4-sample.d.ts.map +1 -0
- package/out/zqlite/src/sqlite-stat4-sample.js +61 -0
- package/out/zqlite/src/sqlite-stat4-sample.js.map +1 -0
- package/out/zqlite/src/table-source.d.ts +87 -2
- package/out/zqlite/src/table-source.d.ts.map +1 -1
- package/out/zqlite/src/table-source.js +276 -42
- package/out/zqlite/src/table-source.js.map +1 -1
- package/package.json +4 -5
- package/out/replicache/src/kv/idb-store-with-mem-fallback.d.ts +0 -25
- package/out/replicache/src/kv/idb-store-with-mem-fallback.d.ts.map +0 -1
- package/out/replicache/src/kv/idb-store-with-mem-fallback.js +0 -83
- package/out/replicache/src/kv/idb-store-with-mem-fallback.js.map +0 -1
- package/out/zero-cache/src/services/change-streamer/vfs-watermark-poller.d.ts +0 -29
- package/out/zero-cache/src/services/change-streamer/vfs-watermark-poller.d.ts.map +0 -1
- package/out/zero-cache/src/services/change-streamer/vfs-watermark-poller.js +0 -154
- package/out/zero-cache/src/services/change-streamer/vfs-watermark-poller.js.map +0 -1
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
snapshot:
|
|
2
2
|
interval: ${ZERO_LITESTREAM_SNAPSHOT_BACKUP_INTERVAL_HOURS}h
|
|
3
3
|
retention: ${ZERO_LITESTREAM_SNAPSHOT_RETENTION_INTERVAL_HOURS}h
|
|
4
|
+
mode: compaction
|
|
4
5
|
|
|
5
|
-
# Retain raw L0 files well past worst-case restore
|
|
6
|
-
# compaction can't delete a file an in-progress
|
|
6
|
+
# Retain raw L0 files well past the worst-case restore or snapshot-compaction
|
|
7
|
+
# duration, so continuous compaction can't delete a file that an in-progress
|
|
8
|
+
# restore or compaction snapshot still needs.
|
|
7
9
|
l0-retention: 1h
|
|
8
10
|
l0-retention-check-interval: 5m
|
|
9
11
|
|
|
@@ -25,11 +27,7 @@ validation:
|
|
|
25
27
|
|
|
26
28
|
dbs:
|
|
27
29
|
- path: ${ZERO_REPLICA_FILE}
|
|
28
|
-
|
|
29
|
-
# is checked to create new l0 files and/or checkpoint the wal. The
|
|
30
|
-
# application will also explicitly trigger a "/sync" if the wal reaches
|
|
31
|
-
# ZERO_LITESTREAM_FORCE_CHECKPOINT_THRESHOLD_MB.
|
|
32
|
-
monitor-interval: ${ZERO_LITESTREAM_INCREMENTAL_BACKUP_INTERVAL_SECONDS}s
|
|
30
|
+
monitor-interval: ${ZERO_LITESTREAM_MONITOR_INTERVAL_SECONDS}s
|
|
33
31
|
min-checkpoint-page-count: ${ZERO_LITESTREAM_MIN_CHECKPOINT_PAGE_COUNT}
|
|
34
32
|
truncate-page-n: ${ZERO_LITESTREAM_TRUNCATE_PAGE_N}
|
|
35
33
|
replica:
|
|
@@ -45,6 +43,7 @@ dbs:
|
|
|
45
43
|
logging:
|
|
46
44
|
level: ${ZERO_LITESTREAM_LOG_LEVEL}
|
|
47
45
|
type: ${ZERO_LOG_FORMAT}
|
|
46
|
+
stderr: true # output logs to stderr so that command output can be parsed from stdout
|
|
48
47
|
|
|
49
48
|
addr: localhost:${LITESTREAM_PORT}
|
|
50
49
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { AbortError } from "../../../../shared/src/abort-error.js";
|
|
2
2
|
import { RunningState } from "../running-state.js";
|
|
3
3
|
//#region ../zero-cache/src/services/litestream/litestream-checkpointer.ts
|
|
4
|
-
var
|
|
4
|
+
var SOFT_CHECKPOINT_WAIT_MS = 1e4;
|
|
5
|
+
var LITESTREAM_SYNC_TIMEOUT_MS = 5 * 6e4;
|
|
5
6
|
var PAUSE_POLL_INTERVAL_MS = 1e3;
|
|
6
7
|
var PAUSE_LOG_INTERVAL_POLLS = 30;
|
|
7
8
|
/**
|
|
@@ -13,11 +14,17 @@ var PAUSE_LOG_INTERVAL_POLLS = 30;
|
|
|
13
14
|
* - Soft (`checkpointThresholdPages`): after each committed transaction,
|
|
14
15
|
* once the un-checkpointed WAL backlog reaches the threshold, force an
|
|
15
16
|
* immediate litestream sync (which seals the WAL to LTX and attempts
|
|
16
|
-
* litestream's own PASSIVE checkpoint)
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
17
|
+
* litestream's own PASSIVE checkpoint) and block the write path until it
|
|
18
|
+
* completes, but only up to {@link SOFT_CHECKPOINT_WAIT_MS}. Waiting is the
|
|
19
|
+
* backpressure: it throttles upstream reads to litestream's WAL-seal rate
|
|
20
|
+
* and, in the common case, gives litestream a window to checkpoint without
|
|
21
|
+
* writer interference. A single sync is kept in flight at a time
|
|
22
|
+
* (`#pendingSync`): if one is still running when the budget elapses, the
|
|
23
|
+
* writer proceeds and the next commit waits for that sync rather than
|
|
24
|
+
* issuing (and orphaning) another. Backs off by a full threshold's worth of
|
|
25
|
+
* WAL growth whenever an attempt fails to drain the WAL (e.g. litestream
|
|
26
|
+
* is mid-snapshot and its checkpoints are being skipped), so repeated
|
|
27
|
+
* failures don't reattempt on every commit.
|
|
21
28
|
* - Hard (`walMaxPages`, optional): if the WAL still exceeds this cap after
|
|
22
29
|
* a soft attempt, pause (block the caller) polling litestream until the
|
|
23
30
|
* WAL drains below it. This is the fail-safe against unbounded WAL growth
|
|
@@ -33,8 +40,9 @@ var LitestreamCheckpointer = class {
|
|
|
33
40
|
#maxWalPages;
|
|
34
41
|
#state = new RunningState("litestream-checkpointer");
|
|
35
42
|
#nextWalThreshold;
|
|
43
|
+
#pendingSync;
|
|
36
44
|
constructor(lc, db, litestream, config) {
|
|
37
|
-
this.#lc = lc.withContext("litestream-checkpointer");
|
|
45
|
+
this.#lc = lc.withContext("component", "litestream-checkpointer");
|
|
38
46
|
this.#db = db;
|
|
39
47
|
this.#litestream = litestream;
|
|
40
48
|
this.#attemptChunk = config.checkpointThresholdPages;
|
|
@@ -55,26 +63,47 @@ var LitestreamCheckpointer = class {
|
|
|
55
63
|
* that litestream's (disabled) truncate-page-n would have served.
|
|
56
64
|
*/
|
|
57
65
|
async maybeCheckpoint() {
|
|
58
|
-
|
|
66
|
+
let walPages = this.#getNumWalPages();
|
|
59
67
|
if (walPages < this.#nextWalThreshold) return;
|
|
68
|
+
this.#pendingSync ??= this.#sync(walPages);
|
|
69
|
+
await this.#waitFor(this.#pendingSync, SOFT_CHECKPOINT_WAIT_MS);
|
|
70
|
+
walPages = this.#getNumWalPages();
|
|
71
|
+
if (this.#maxWalPages !== void 0 && walPages > this.#maxWalPages) walPages = await this.#pauseUntilWalDrained(this.#maxWalPages);
|
|
72
|
+
this.#nextWalThreshold = walPages + this.#attemptChunk;
|
|
73
|
+
}
|
|
74
|
+
async #waitFor(p, timeoutMs) {
|
|
75
|
+
if (await Promise.race([p, this.#state.sleep(timeoutMs).then(() => "timed-out")]) === "timed-out") this.#lc.warn?.(`timed out waiting for /sync result (${timeoutMs}ms)`);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Runs a single litestream sync, logs its outcome, and clears
|
|
79
|
+
* {@link #pendingSync} when it settles. Never rejects: sync failures and
|
|
80
|
+
* post-sync bookkeeping errors (e.g. the db being closed during shutdown)
|
|
81
|
+
* are caught and logged, so the shared promise can be awaited from multiple
|
|
82
|
+
* places without risking an unhandled rejection.
|
|
83
|
+
*/
|
|
84
|
+
async #sync(walPagesBefore) {
|
|
60
85
|
const start = performance.now();
|
|
61
86
|
let result;
|
|
62
87
|
let err;
|
|
63
88
|
try {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
89
|
+
try {
|
|
90
|
+
result = await this.#litestream.sync({
|
|
91
|
+
wait: false,
|
|
92
|
+
timeoutMs: LITESTREAM_SYNC_TIMEOUT_MS
|
|
93
|
+
}, this.#state.signal);
|
|
94
|
+
} catch (e) {
|
|
95
|
+
err = e;
|
|
96
|
+
}
|
|
97
|
+
const elapsed = performance.now() - start;
|
|
98
|
+
const newWalPages = this.#getNumWalPages();
|
|
99
|
+
if (newWalPages < this.#nextWalThreshold) this.#lc.info?.(`checkpointed ${walPagesBefore} -> ${newWalPages} wal pages (${elapsed.toFixed(2)} ms)`, result);
|
|
100
|
+
else if (result) this.#lc.warn?.(`checkpoint skipped ${walPagesBefore} -> ${newWalPages}. a snapshot may be in progress (${elapsed.toFixed(2)} ms)`, result);
|
|
101
|
+
else this.#lc.warn?.(`checkpoint failed ${walPagesBefore} -> ${newWalPages} (${elapsed.toFixed(2)} ms)`, err);
|
|
68
102
|
} catch (e) {
|
|
69
|
-
|
|
103
|
+
this.#lc.warn?.("litestream-checkpointer sync post-processing failed", e);
|
|
104
|
+
} finally {
|
|
105
|
+
this.#pendingSync = void 0;
|
|
70
106
|
}
|
|
71
|
-
const elapsed = performance.now() - start;
|
|
72
|
-
let newWalPages = this.#getNumWalPages();
|
|
73
|
-
if (newWalPages < this.#nextWalThreshold) this.#lc.info?.(`checkpointed ${walPages} -> ${newWalPages} wal pages (${elapsed.toFixed(2)} ms)`, result);
|
|
74
|
-
else if (result) this.#lc.warn?.(`checkpoint skipped ${walPages} -> ${newWalPages}. a snapshot may be in progress (${elapsed.toFixed(2)} ms)`, result);
|
|
75
|
-
else this.#lc.warn?.(`checkpoint failed ${walPages} -> ${newWalPages} (${elapsed.toFixed(2)} ms)`, err);
|
|
76
|
-
if (this.#maxWalPages !== void 0 && newWalPages > this.#maxWalPages) newWalPages = await this.#pauseUntilWalDrained(this.#maxWalPages);
|
|
77
|
-
this.#nextWalThreshold = newWalPages + this.#attemptChunk;
|
|
78
107
|
}
|
|
79
108
|
async #pauseUntilWalDrained(maxWalPages) {
|
|
80
109
|
for (let i = 0; this.#state.shouldRun(); i++) {
|
|
@@ -85,10 +114,8 @@ var LitestreamCheckpointer = class {
|
|
|
85
114
|
}
|
|
86
115
|
if (i % PAUSE_LOG_INTERVAL_POLLS === 0) this.#lc.warn?.(`waiting for litestream to successfully checkpoint ${walPages} wal pages`);
|
|
87
116
|
await this.#state.sleep(PAUSE_POLL_INTERVAL_MS);
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
timeoutMs: LITESTREAM_SYNC_TIMEOUT_MS
|
|
91
|
-
}, this.#state.signal).catch((e) => this.#lc.warn?.(`litestream /sync failed`, e));
|
|
117
|
+
this.#pendingSync ??= this.#sync(this.#getNumWalPages());
|
|
118
|
+
await this.#pendingSync;
|
|
92
119
|
}
|
|
93
120
|
throw new AbortError("litestream-controller stopped");
|
|
94
121
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"litestream-checkpointer.js","names":["#lc","#db","#litestream","#attemptChunk","#maxWalPages","#state","#nextWalThreshold","#getNumWalPages","#pauseUntilWalDrained"],"sources":["../../../../../../zero-cache/src/services/litestream/litestream-checkpointer.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {AbortError} from '../../../../shared/src/abort-error.ts';\nimport type {Database} from '../../../../zqlite/src/db.ts';\nimport type {ForceCheckpointConfig} from '../replicator/write-worker-client.ts';\nimport {RunningState} from '../running-state.ts';\nimport type {\n LitestreamController,\n SyncResponse,\n} from './litestream-controller.ts';\n\nconst LITESTREAM_SYNC_TIMEOUT_MS = 10_000;\nconst PAUSE_POLL_INTERVAL_MS = 1_000;\nconst PAUSE_LOG_INTERVAL_POLLS = 30;\n\n/**\n * Forces litestream to checkpoint the WAL from the write path, so a sustained\n * high write rate can't grow the WAL until litestream's own blocking TRUNCATE\n * checkpoint locks the db (see ReplicationPauseCheckpointConfig).\n *\n * Two tiers:\n * - Soft (`checkpointThresholdPages`): after each committed transaction,\n * once the un-checkpointed WAL backlog reaches the threshold, force an\n * immediate litestream sync (which seals the WAL to LTX and attempts\n * litestream's own PASSIVE checkpoint). Non-blocking beyond the sync call\n * itself. Backs off by a full threshold's worth of WAL growth whenever an\n * attempt fails to drain the WAL (e.g. litestream is mid-snapshot and its\n * checkpoints are being skipped), so repeated failures don't reattempt on\n * every commit.\n * - Hard (`walMaxPages`, optional): if the WAL still exceeds this cap after\n * a soft attempt, pause (block the caller) polling litestream until the\n * WAL drains below it. This is the fail-safe against unbounded WAL growth\n * when litestream structurally cannot checkpoint — e.g. an in-progress\n * snapshot holds litestream's checkpoint lock for its full duration, so\n * neither PASSIVE nor TRUNCATE checkpoints can run until it completes.\n */\nexport class LitestreamCheckpointer {\n readonly #lc: LogContext;\n readonly #db: Database;\n readonly #litestream: LitestreamController;\n readonly #attemptChunk: number;\n readonly #maxWalPages: number | undefined;\n readonly #state = new RunningState('litestream-checkpointer');\n #nextWalThreshold: number;\n\n constructor(\n lc: LogContext,\n db: Database,\n litestream: LitestreamController,\n config: ForceCheckpointConfig,\n ) {\n this.#lc = lc.withContext('litestream-checkpointer');\n this.#db = db;\n this.#litestream = litestream;\n this.#attemptChunk = config.checkpointThresholdPages;\n this.#nextWalThreshold = config.checkpointThresholdPages;\n this.#maxWalPages = config.maxWalPages;\n }\n\n #getNumWalPages(): number {\n // wal_checkpoint(NOOP) reads WAL status without doing any work: `log` is\n // the current WAL frame count and `checkpointed` is how many of those\n // frames are already applied to the main db, so `log - checkpointed` is\n // the un-checkpointed backlog that a forced sync would actually drain.\n // (Both reset once litestream restarts the WAL.)\n const [{log, checkpointed}] = this.#db.pragma<{\n log: number;\n checkpointed: number;\n }>('wal_checkpoint(NOOP)');\n return log - checkpointed;\n }\n\n /**\n * Call after a committed transaction. No-ops unless the WAL has grown to\n * at least the current threshold, in which case it triggers a litestream\n * sync to perform a checkpoint. Assuming that snapshots are disabled, the\n * checkpoint always succeeds. In the case where the server is configured to\n * perform snapshots and checkpoints fail, the \"emergency break\"\n * {@link #pauseUntilWalDrained()} option provides the disk use protection\n * that litestream's (disabled) truncate-page-n would have served.\n */\n async maybeCheckpoint(): Promise<void> {\n const walPages = this.#getNumWalPages();\n if (walPages < this.#nextWalThreshold) {\n return;\n }\n\n const start = performance.now();\n let result: SyncResponse | undefined;\n let err: unknown;\n try {\n result = await this.#litestream.sync(\n {\n wait: false,\n timeoutMs: LITESTREAM_SYNC_TIMEOUT_MS,\n },\n this.#state.signal,\n );\n } catch (e) {\n err = e;\n }\n\n const elapsed = performance.now() - start;\n let newWalPages = this.#getNumWalPages();\n if (newWalPages < this.#nextWalThreshold) {\n this.#lc.info?.(\n `checkpointed ${walPages} -> ${newWalPages} wal pages (${elapsed.toFixed(2)} ms)`,\n result,\n );\n } else if (result) {\n this.#lc.warn?.(\n `checkpoint skipped ${walPages} -> ${newWalPages}. a snapshot may be in progress (${elapsed.toFixed(2)} ms)`,\n result,\n );\n } else {\n this.#lc.warn?.(\n `checkpoint failed ${walPages} -> ${newWalPages} (${elapsed.toFixed(2)} ms)`,\n err,\n );\n }\n\n if (this.#maxWalPages !== undefined && newWalPages > this.#maxWalPages) {\n // Emergency brake when best-effort checkpoints are being skipped\n // (i.e. during a snapshot) and the WAL is approaching disk capacity.\n // Pausing replication is favorable to litestream's truncate-page-n\n // because the latter involves re-encoding the database under the lock\n // (https://github.com/benbjohnson/litestream/issues/1332), which would\n // incur the full latency of an additional snapshot.\n newWalPages = await this.#pauseUntilWalDrained(this.#maxWalPages);\n }\n\n // In the common case where checkpoints are successful, this is always\n // just `attemptChunk`. When a checkpoint doesn't drain the WAL (e.g.\n // litestream is performing a snapshot), wait for another chunk of growth\n // before the next attempt.\n this.#nextWalThreshold = newWalPages + this.#attemptChunk;\n }\n\n async #pauseUntilWalDrained(maxWalPages: number): Promise<number> {\n for (let i = 0; this.#state.shouldRun(); i++) {\n const walPages = this.#getNumWalPages();\n if (walPages < maxWalPages) {\n this.#lc.info?.(\n `wal size (${walPages} pages) is under the max limit of ${maxWalPages}`,\n );\n return walPages;\n }\n\n // Log every 30 seconds.\n if (i % PAUSE_LOG_INTERVAL_POLLS === 0) {\n this.#lc.warn?.(\n `waiting for litestream to successfully checkpoint ${walPages} wal pages`,\n );\n }\n await this.#state.sleep(PAUSE_POLL_INTERVAL_MS);\n await this.#litestream\n .sync(\n {wait: false, timeoutMs: LITESTREAM_SYNC_TIMEOUT_MS},\n this.#state.signal,\n )\n .catch(e => this.#lc.warn?.(`litestream /sync failed`, e));\n }\n throw new AbortError('litestream-controller stopped');\n }\n\n /** Releases the underlying litestream controller's connection. */\n close(): void {\n this.#litestream.close();\n this.#state.stop(this.#lc);\n }\n}\n"],"mappings":";;;AAUA,IAAM,6BAA6B;AACnC,IAAM,yBAAyB;AAC/B,IAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;AAuBjC,IAAa,yBAAb,MAAoC;CAClC;CACA;CACA;CACA;CACA;CACA,SAAkB,IAAI,aAAa,yBAAyB;CAC5D;CAEA,YACE,IACA,IACA,YACA,QACA;EACA,KAAKA,MAAM,GAAG,YAAY,yBAAyB;EACnD,KAAKC,MAAM;EACX,KAAKC,cAAc;EACnB,KAAKC,gBAAgB,OAAO;EAC5B,KAAKG,oBAAoB,OAAO;EAChC,KAAKF,eAAe,OAAO;CAC7B;CAEA,kBAA0B;EAMxB,MAAM,CAAC,EAAC,KAAK,kBAAiB,KAAKH,IAAI,OAGpC,sBAAsB;EACzB,OAAO,MAAM;CACf;;;;;;;;;;CAWA,MAAM,kBAAiC;EACrC,MAAM,WAAW,KAAKM,gBAAgB;EACtC,IAAI,WAAW,KAAKD,mBAClB;EAGF,MAAM,QAAQ,YAAY,IAAI;EAC9B,IAAI;EACJ,IAAI;EACJ,IAAI;GACF,SAAS,MAAM,KAAKJ,YAAY,KAC9B;IACE,MAAM;IACN,WAAW;GACb,GACA,KAAKG,OAAO,MACd;EACF,SAAS,GAAG;GACV,MAAM;EACR;EAEA,MAAM,UAAU,YAAY,IAAI,IAAI;EACpC,IAAI,cAAc,KAAKE,gBAAgB;EACvC,IAAI,cAAc,KAAKD,mBACrB,KAAKN,IAAI,OACP,gBAAgB,SAAS,MAAM,YAAY,cAAc,QAAQ,QAAQ,CAAC,EAAE,OAC5E,MACF;OACK,IAAI,QACT,KAAKA,IAAI,OACP,sBAAsB,SAAS,MAAM,YAAY,mCAAmC,QAAQ,QAAQ,CAAC,EAAE,OACvG,MACF;OAEA,KAAKA,IAAI,OACP,qBAAqB,SAAS,MAAM,YAAY,IAAI,QAAQ,QAAQ,CAAC,EAAE,OACvE,GACF;EAGF,IAAI,KAAKI,iBAAiB,KAAA,KAAa,cAAc,KAAKA,cAOxD,cAAc,MAAM,KAAKI,sBAAsB,KAAKJ,YAAY;EAOlE,KAAKE,oBAAoB,cAAc,KAAKH;CAC9C;CAEA,MAAMK,sBAAsB,aAAsC;EAChE,KAAK,IAAI,IAAI,GAAG,KAAKH,OAAO,UAAU,GAAG,KAAK;GAC5C,MAAM,WAAW,KAAKE,gBAAgB;GACtC,IAAI,WAAW,aAAa;IAC1B,KAAKP,IAAI,OACP,aAAa,SAAS,oCAAoC,aAC5D;IACA,OAAO;GACT;GAGA,IAAI,IAAI,6BAA6B,GACnC,KAAKA,IAAI,OACP,qDAAqD,SAAS,WAChE;GAEF,MAAM,KAAKK,OAAO,MAAM,sBAAsB;GAC9C,MAAM,KAAKH,YACR,KACC;IAAC,MAAM;IAAO,WAAW;GAA0B,GACnD,KAAKG,OAAO,MACd,EACC,OAAM,MAAK,KAAKL,IAAI,OAAO,2BAA2B,CAAC,CAAC;EAC7D;EACA,MAAM,IAAI,WAAW,+BAA+B;CACtD;;CAGA,QAAc;EACZ,KAAKE,YAAY,MAAM;EACvB,KAAKG,OAAO,KAAK,KAAKL,GAAG;CAC3B;AACF"}
|
|
1
|
+
{"version":3,"file":"litestream-checkpointer.js","names":["#lc","#db","#litestream","#attemptChunk","#maxWalPages","#state","#nextWalThreshold","#getNumWalPages","#pendingSync","#sync","#waitFor","#pauseUntilWalDrained"],"sources":["../../../../../../zero-cache/src/services/litestream/litestream-checkpointer.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {AbortError} from '../../../../shared/src/abort-error.ts';\nimport type {Database} from '../../../../zqlite/src/db.ts';\nimport type {ForceCheckpointConfig} from '../replicator/write-worker-client.ts';\nimport {RunningState} from '../running-state.ts';\nimport type {\n LitestreamController,\n SyncResponse,\n} from './litestream-controller.ts';\n\n// How long the soft path blocks the write path waiting for an in-flight sync\n// before letting the writer proceed. This is a backpressure knob, *not* a\n// request timeout: letting it elapse leaves the sync running (see #pendingSync)\n// rather than abandoning it. In normal operation litestream seals + runs its\n// PASSIVE checkpoint well within this budget; a sync that regularly exceeds it\n// indicates a litestream-side problem to fix (e.g. unintended snapshot), not a\n// value to raise.\nexport const SOFT_CHECKPOINT_WAIT_MS = 10_000;\n// Liveness bound on the /sync request itself, well above the soft wait budget.\n// It exists only to recover from a genuinely wedged litestream (so #pendingSync\n// can't hang forever).\nconst LITESTREAM_SYNC_TIMEOUT_MS = 5 * 60_000;\nconst PAUSE_POLL_INTERVAL_MS = 1_000;\nconst PAUSE_LOG_INTERVAL_POLLS = 30;\n\n/**\n * Forces litestream to checkpoint the WAL from the write path, so a sustained\n * high write rate can't grow the WAL until litestream's own blocking TRUNCATE\n * checkpoint locks the db (see ReplicationPauseCheckpointConfig).\n *\n * Two tiers:\n * - Soft (`checkpointThresholdPages`): after each committed transaction,\n * once the un-checkpointed WAL backlog reaches the threshold, force an\n * immediate litestream sync (which seals the WAL to LTX and attempts\n * litestream's own PASSIVE checkpoint) and block the write path until it\n * completes, but only up to {@link SOFT_CHECKPOINT_WAIT_MS}. Waiting is the\n * backpressure: it throttles upstream reads to litestream's WAL-seal rate\n * and, in the common case, gives litestream a window to checkpoint without\n * writer interference. A single sync is kept in flight at a time\n * (`#pendingSync`): if one is still running when the budget elapses, the\n * writer proceeds and the next commit waits for that sync rather than\n * issuing (and orphaning) another. Backs off by a full threshold's worth of\n * WAL growth whenever an attempt fails to drain the WAL (e.g. litestream\n * is mid-snapshot and its checkpoints are being skipped), so repeated\n * failures don't reattempt on every commit.\n * - Hard (`walMaxPages`, optional): if the WAL still exceeds this cap after\n * a soft attempt, pause (block the caller) polling litestream until the\n * WAL drains below it. This is the fail-safe against unbounded WAL growth\n * when litestream structurally cannot checkpoint — e.g. an in-progress\n * snapshot holds litestream's checkpoint lock for its full duration, so\n * neither PASSIVE nor TRUNCATE checkpoints can run until it completes.\n */\nexport class LitestreamCheckpointer {\n readonly #lc: LogContext;\n readonly #db: Database;\n readonly #litestream: LitestreamController;\n readonly #attemptChunk: number;\n readonly #maxWalPages: number | undefined;\n readonly #state = new RunningState('litestream-checkpointer');\n #nextWalThreshold: number;\n #pendingSync: Promise<void> | undefined;\n\n constructor(\n lc: LogContext,\n db: Database,\n litestream: LitestreamController,\n config: ForceCheckpointConfig,\n ) {\n this.#lc = lc.withContext('component', 'litestream-checkpointer');\n this.#db = db;\n this.#litestream = litestream;\n this.#attemptChunk = config.checkpointThresholdPages;\n this.#nextWalThreshold = config.checkpointThresholdPages;\n this.#maxWalPages = config.maxWalPages;\n }\n\n #getNumWalPages(): number {\n // wal_checkpoint(NOOP) reads WAL status without doing any work: `log` is\n // the current WAL frame count and `checkpointed` is how many of those\n // frames are already applied to the main db, so `log - checkpointed` is\n // the un-checkpointed backlog that a forced sync would actually drain.\n // (Both reset once litestream restarts the WAL.)\n const [{log, checkpointed}] = this.#db.pragma<{\n log: number;\n checkpointed: number;\n }>('wal_checkpoint(NOOP)');\n return log - checkpointed;\n }\n\n /**\n * Call after a committed transaction. No-ops unless the WAL has grown to\n * at least the current threshold, in which case it triggers a litestream\n * sync to perform a checkpoint. Assuming that snapshots are disabled, the\n * checkpoint always succeeds. In the case where the server is configured to\n * perform snapshots and checkpoints fail, the \"emergency break\"\n * {@link #pauseUntilWalDrained()} option provides the disk use protection\n * that litestream's (disabled) truncate-page-n would have served.\n */\n async maybeCheckpoint(): Promise<void> {\n let walPages = this.#getNumWalPages();\n if (walPages < this.#nextWalThreshold) {\n return;\n }\n\n // Single-flight: reuse the outstanding sync if one is already running.\n this.#pendingSync ??= this.#sync(walPages);\n\n // Soft backpressure: block the write path until the sync completes, but no\n // longer than the wait budget. Letting the budget elapse lets the writer\n // proceed *without* cancelling the sync (it keeps running, tracked by\n // #pendingSync); unbounded WAL growth is caught by the hard cap below.\n await this.#waitFor(this.#pendingSync, SOFT_CHECKPOINT_WAIT_MS);\n\n walPages = this.#getNumWalPages();\n if (this.#maxWalPages !== undefined && walPages > this.#maxWalPages) {\n // Emergency brake when best-effort checkpoints are being skipped\n // (i.e. during a snapshot) and the WAL is approaching disk capacity.\n // Pausing replication is favorable to litestream's truncate-page-n\n // because the latter involves re-encoding the database under the lock\n // (https://github.com/benbjohnson/litestream/issues/1332), which would\n // incur the full latency of an additional snapshot.\n walPages = await this.#pauseUntilWalDrained(this.#maxWalPages);\n }\n\n // In the common case where checkpoints are successful, this is always\n // just `attemptChunk`. When a checkpoint doesn't drain the WAL (e.g.\n // litestream is performing a snapshot), wait for another chunk of growth\n // before the next attempt.\n this.#nextWalThreshold = walPages + this.#attemptChunk;\n }\n\n async #waitFor(p: Promise<void>, timeoutMs: number): Promise<void> {\n const result = await Promise.race([\n p,\n this.#state.sleep(timeoutMs).then(() => 'timed-out' as const),\n ]);\n if (result === 'timed-out') {\n this.#lc.warn?.(`timed out waiting for /sync result (${timeoutMs}ms)`);\n }\n }\n\n /**\n * Runs a single litestream sync, logs its outcome, and clears\n * {@link #pendingSync} when it settles. Never rejects: sync failures and\n * post-sync bookkeeping errors (e.g. the db being closed during shutdown)\n * are caught and logged, so the shared promise can be awaited from multiple\n * places without risking an unhandled rejection.\n */\n async #sync(walPagesBefore: number): Promise<void> {\n const start = performance.now();\n let result: SyncResponse | undefined;\n let err: unknown;\n try {\n try {\n result = await this.#litestream.sync(\n {wait: false, timeoutMs: LITESTREAM_SYNC_TIMEOUT_MS},\n this.#state.signal,\n );\n } catch (e) {\n err = e;\n }\n\n const elapsed = performance.now() - start;\n const newWalPages = this.#getNumWalPages();\n if (newWalPages < this.#nextWalThreshold) {\n this.#lc.info?.(\n `checkpointed ${walPagesBefore} -> ${newWalPages} wal pages (${elapsed.toFixed(2)} ms)`,\n result,\n );\n } else if (result) {\n this.#lc.warn?.(\n `checkpoint skipped ${walPagesBefore} -> ${newWalPages}. a snapshot may be in progress (${elapsed.toFixed(2)} ms)`,\n result,\n );\n } else {\n this.#lc.warn?.(\n `checkpoint failed ${walPagesBefore} -> ${newWalPages} (${elapsed.toFixed(2)} ms)`,\n err,\n );\n }\n } catch (e) {\n this.#lc.warn?.('litestream-checkpointer sync post-processing failed', e);\n } finally {\n this.#pendingSync = undefined;\n }\n }\n\n async #pauseUntilWalDrained(maxWalPages: number): Promise<number> {\n for (let i = 0; this.#state.shouldRun(); i++) {\n const walPages = this.#getNumWalPages();\n if (walPages < maxWalPages) {\n this.#lc.info?.(\n `wal size (${walPages} pages) is under the max limit of ${maxWalPages}`,\n );\n return walPages;\n }\n\n // Log every 30 seconds.\n if (i % PAUSE_LOG_INTERVAL_POLLS === 0) {\n this.#lc.warn?.(\n `waiting for litestream to successfully checkpoint ${walPages} wal pages`,\n );\n }\n await this.#state.sleep(PAUSE_POLL_INTERVAL_MS);\n // Single-flight: reuse the outstanding sync if one is already running.\n this.#pendingSync ??= this.#sync(this.#getNumWalPages());\n // await the full liveness timeout configured in #sync()\n await this.#pendingSync;\n }\n throw new AbortError('litestream-controller stopped');\n }\n\n /** Releases the underlying litestream controller's connection. */\n close(): void {\n this.#litestream.close();\n this.#state.stop(this.#lc);\n }\n}\n"],"mappings":";;;AAiBA,IAAa,0BAA0B;AAIvC,IAAM,6BAA6B,IAAI;AACvC,IAAM,yBAAyB;AAC/B,IAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BjC,IAAa,yBAAb,MAAoC;CAClC;CACA;CACA;CACA;CACA;CACA,SAAkB,IAAI,aAAa,yBAAyB;CAC5D;CACA;CAEA,YACE,IACA,IACA,YACA,QACA;EACA,KAAKA,MAAM,GAAG,YAAY,aAAa,yBAAyB;EAChE,KAAKC,MAAM;EACX,KAAKC,cAAc;EACnB,KAAKC,gBAAgB,OAAO;EAC5B,KAAKG,oBAAoB,OAAO;EAChC,KAAKF,eAAe,OAAO;CAC7B;CAEA,kBAA0B;EAMxB,MAAM,CAAC,EAAC,KAAK,kBAAiB,KAAKH,IAAI,OAGpC,sBAAsB;EACzB,OAAO,MAAM;CACf;;;;;;;;;;CAWA,MAAM,kBAAiC;EACrC,IAAI,WAAW,KAAKM,gBAAgB;EACpC,IAAI,WAAW,KAAKD,mBAClB;EAIF,KAAKE,iBAAiB,KAAKC,MAAM,QAAQ;EAMzC,MAAM,KAAKC,SAAS,KAAKF,cAAc,uBAAuB;EAE9D,WAAW,KAAKD,gBAAgB;EAChC,IAAI,KAAKH,iBAAiB,KAAA,KAAa,WAAW,KAAKA,cAOrD,WAAW,MAAM,KAAKO,sBAAsB,KAAKP,YAAY;EAO/D,KAAKE,oBAAoB,WAAW,KAAKH;CAC3C;CAEA,MAAMO,SAAS,GAAkB,WAAkC;EAKjE,IAAI,MAJiB,QAAQ,KAAK,CAChC,GACA,KAAKL,OAAO,MAAM,SAAS,EAAE,WAAW,WAAoB,CAC9D,CAAC,MACc,aACb,KAAKL,IAAI,OAAO,uCAAuC,UAAU,IAAI;CAEzE;;;;;;;;CASA,MAAMS,MAAM,gBAAuC;EACjD,MAAM,QAAQ,YAAY,IAAI;EAC9B,IAAI;EACJ,IAAI;EACJ,IAAI;GACF,IAAI;IACF,SAAS,MAAM,KAAKP,YAAY,KAC9B;KAAC,MAAM;KAAO,WAAW;IAA0B,GACnD,KAAKG,OAAO,MACd;GACF,SAAS,GAAG;IACV,MAAM;GACR;GAEA,MAAM,UAAU,YAAY,IAAI,IAAI;GACpC,MAAM,cAAc,KAAKE,gBAAgB;GACzC,IAAI,cAAc,KAAKD,mBACrB,KAAKN,IAAI,OACP,gBAAgB,eAAe,MAAM,YAAY,cAAc,QAAQ,QAAQ,CAAC,EAAE,OAClF,MACF;QACK,IAAI,QACT,KAAKA,IAAI,OACP,sBAAsB,eAAe,MAAM,YAAY,mCAAmC,QAAQ,QAAQ,CAAC,EAAE,OAC7G,MACF;QAEA,KAAKA,IAAI,OACP,qBAAqB,eAAe,MAAM,YAAY,IAAI,QAAQ,QAAQ,CAAC,EAAE,OAC7E,GACF;EAEJ,SAAS,GAAG;GACV,KAAKA,IAAI,OAAO,uDAAuD,CAAC;EAC1E,UAAU;GACR,KAAKQ,eAAe,KAAA;EACtB;CACF;CAEA,MAAMG,sBAAsB,aAAsC;EAChE,KAAK,IAAI,IAAI,GAAG,KAAKN,OAAO,UAAU,GAAG,KAAK;GAC5C,MAAM,WAAW,KAAKE,gBAAgB;GACtC,IAAI,WAAW,aAAa;IAC1B,KAAKP,IAAI,OACP,aAAa,SAAS,oCAAoC,aAC5D;IACA,OAAO;GACT;GAGA,IAAI,IAAI,6BAA6B,GACnC,KAAKA,IAAI,OACP,qDAAqD,SAAS,WAChE;GAEF,MAAM,KAAKK,OAAO,MAAM,sBAAsB;GAE9C,KAAKG,iBAAiB,KAAKC,MAAM,KAAKF,gBAAgB,CAAC;GAEvD,MAAM,KAAKC;EACb;EACA,MAAM,IAAI,WAAW,+BAA+B;CACtD;;CAGA,QAAc;EACZ,KAAKN,YAAY,MAAM;EACvB,KAAKG,OAAO,KAAK,KAAKL,GAAG;CAC3B;AACF"}
|
|
@@ -28,9 +28,17 @@ export type SyncOptions = {
|
|
|
28
28
|
* returning without waiting on the backup store. Use false on the write path
|
|
29
29
|
* where the goal is to keep the WAL small, not to durably back it up.
|
|
30
30
|
*/
|
|
31
|
-
wait?: boolean;
|
|
31
|
+
wait?: boolean | undefined;
|
|
32
32
|
/** Overall request timeout in milliseconds. Defaults to 30s. */
|
|
33
|
-
timeoutMs?: number;
|
|
33
|
+
timeoutMs?: number | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* Server-side deadline in seconds, sent as litestream's `timeout`. When set,
|
|
36
|
+
* litestream ends the request itself (with an error response) once it
|
|
37
|
+
* elapses. Set it below {@link timeoutMs} so that litestream, rather than
|
|
38
|
+
* the client, ends a slow request. (litestream defaults to 30s when `wait`
|
|
39
|
+
* is set, and to no deadline otherwise.)
|
|
40
|
+
*/
|
|
41
|
+
serverTimeoutSeconds?: number | undefined;
|
|
34
42
|
};
|
|
35
43
|
/**
|
|
36
44
|
* IPC client for the litestream control server. litestream serves an HTTP API
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"litestream-controller.d.ts","sourceRoot":"","sources":["../../../../../../zero-cache/src/services/litestream/litestream-controller.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAEjD;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAEhE;AAID,qEAAqE;AACrE,MAAM,MAAM,YAAY,GAAG;IACzB;;;;OAIG;IACH,MAAM,EAAE,QAAQ,GAAG,cAAc,GAAG,WAAW,CAAC;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"litestream-controller.d.ts","sourceRoot":"","sources":["../../../../../../zero-cache/src/services/litestream/litestream-controller.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAEjD;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAEhE;AAID,qEAAqE;AACrE,MAAM,MAAM,YAAY,GAAG;IACzB;;;;OAIG;IACH,MAAM,EAAE,QAAQ,GAAG,cAAc,GAAG,WAAW,CAAC;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAE3B,gEAAgE;IAChE,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAE/B;;;;;;OAMG;IACH,oBAAoB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3C,CAAC;AAEF;;;;;;;;;GASG;AACH,qBAAa,oBAAoB;;IAM/B;;;;;;OAMG;IACH,YACE,EAAE,EAAE,UAAU,EACd,WAAW,EAAE,MAAM,EACnB,UAAU,SAAoC,EAQ/C;IAED;;;;;;;;;;OAUG;IACG,IAAI,CACR,IAAI,GAAE,WAAgB,EACtB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,YAAY,CAAC,CAkBvB;IAED,iDAAiD;IACjD,KAAK,IAAI,IAAI,CAEZ;CA4DF"}
|
|
@@ -56,10 +56,11 @@ var LitestreamController = class {
|
|
|
56
56
|
* than blocking application progress on it.
|
|
57
57
|
*/
|
|
58
58
|
async sync(opts = {}, signal) {
|
|
59
|
-
const { wait = false, timeoutMs = DEFAULT_REQUEST_TIMEOUT_MS } = opts;
|
|
59
|
+
const { wait = false, timeoutMs = DEFAULT_REQUEST_TIMEOUT_MS, serverTimeoutSeconds } = opts;
|
|
60
60
|
const result = await this.#post("/sync", {
|
|
61
61
|
path: this.#replicaFile,
|
|
62
|
-
wait
|
|
62
|
+
wait,
|
|
63
|
+
...serverTimeoutSeconds ? { timeout: serverTimeoutSeconds } : {}
|
|
63
64
|
}, timeoutMs, signal);
|
|
64
65
|
this.#lc.debug?.("litestream sync", result);
|
|
65
66
|
return result;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"litestream-controller.js","names":["#lc","#replicaFile","#socketPath","#agent","#post"],"sources":["../../../../../../zero-cache/src/services/litestream/litestream-controller.ts"],"sourcesContent":["import type {IncomingMessage} from 'node:http';\nimport {Agent, request} from 'node:http';\nimport {json as readJSON} from 'node:stream/consumers';\nimport type {LogContext} from '@rocicorp/logger';\n\n/**\n * Path of the litestream control socket, derived from the replica file's\n * directory. The socket must live on a filesystem the (non-root) runtime user\n * can write — the replica directory is guaranteed writable since litestream\n * writes the replica there — so it must NOT default to a root-owned location\n * like /var/run. Kept in sync with config-v5.yml's `socket.path`, which is set\n * from `ZERO_LITESTREAM_SOCKET_PATH` (see getLitestream() in commands.ts).\n */\nexport function litestreamSocketPath(replicaFile: string): string {\n return `${replicaFile}.sock`;\n}\n\nconst DEFAULT_REQUEST_TIMEOUT_MS = 30_000;\n\n/** Response body from litestream's `POST /sync` control endpoint. */\nexport type SyncResponse = {\n /**\n * `synced` when `wait` was true and the upload completed, `synced_local`\n * when the WAL was sealed locally without waiting on the remote replica, or\n * `no_change` when there was nothing to sync.\n */\n status: 'synced' | 'synced_local' | 'no_change';\n path: string;\n txid: number;\n replicated_txid: number;\n};\n\nexport type SyncOptions = {\n /**\n * When true, block until the sealed WAL has been uploaded to the remote\n * replica (litestream's SyncAndWait). When false (the default), litestream\n * only seals the WAL into local LTX files and runs its checkpoint thresholds,\n * returning without waiting on the backup store. Use false on the write path\n * where the goal is to keep the WAL small, not to durably back it up.\n */\n wait?: boolean;\n\n /** Overall request timeout in milliseconds. Defaults to 30s. */\n timeoutMs?: number;\n};\n\n/**\n * IPC client for the litestream control server. litestream serves an HTTP API\n * over a Unix domain socket (enabled via the `socket:` block in config-v5.yml);\n * because zero-cache runs litestream as a subprocess in the same container, the\n * socket is reachable directly on the local filesystem.\n *\n * A single keep-alive connection is held open and reused across calls, so a\n * high-frequency caller (e.g. write-path backpressure) does not pay a\n * connect/handshake per request.\n */\nexport class LitestreamController {\n readonly #lc: LogContext;\n readonly #replicaFile: string;\n readonly #socketPath: string;\n readonly #agent: Agent;\n\n /**\n * @param replicaFile Path of the replica database litestream is managing —\n * the same value passed to litestream as `ZERO_REPLICA_FILE`. This is the\n * `path` litestream matches control requests against.\n * @param socketPath Path of the control socket; defaults to the path derived\n * from `replicaFile`, matching config-v5.yml's `socket.path`.\n */\n constructor(\n lc: LogContext,\n replicaFile: string,\n socketPath = litestreamSocketPath(replicaFile),\n ) {\n this.#lc = lc.withContext('component', 'litestream-controller');\n this.#replicaFile = replicaFile;\n this.#socketPath = socketPath;\n // keepAlive with a single socket keeps one warm connection to the control\n // socket that is reused across calls.\n this.#agent = new Agent({keepAlive: true, maxSockets: 1});\n }\n\n /**\n * Forces litestream to sync the WAL into LTX files immediately and run its\n * checkpoint thresholds, instead of waiting for the next monitor-interval\n * tick. The checkpoint itself is still litestream's usual (non-blocking)\n * PASSIVE attempt, so it is skipped if the database is busy — call this once\n * writes are quiesced.\n *\n * Best-effort: callers should tolerate rejection (e.g. ECONNREFUSED/ENOENT\n * while litestream is restarting or before it has created the socket) rather\n * than blocking application progress on it.\n */\n async sync(\n opts: SyncOptions = {},\n signal?: AbortSignal,\n ): Promise<SyncResponse> {\n const {wait = false
|
|
1
|
+
{"version":3,"file":"litestream-controller.js","names":["#lc","#replicaFile","#socketPath","#agent","#post"],"sources":["../../../../../../zero-cache/src/services/litestream/litestream-controller.ts"],"sourcesContent":["import type {IncomingMessage} from 'node:http';\nimport {Agent, request} from 'node:http';\nimport {json as readJSON} from 'node:stream/consumers';\nimport type {LogContext} from '@rocicorp/logger';\n\n/**\n * Path of the litestream control socket, derived from the replica file's\n * directory. The socket must live on a filesystem the (non-root) runtime user\n * can write — the replica directory is guaranteed writable since litestream\n * writes the replica there — so it must NOT default to a root-owned location\n * like /var/run. Kept in sync with config-v5.yml's `socket.path`, which is set\n * from `ZERO_LITESTREAM_SOCKET_PATH` (see getLitestream() in commands.ts).\n */\nexport function litestreamSocketPath(replicaFile: string): string {\n return `${replicaFile}.sock`;\n}\n\nconst DEFAULT_REQUEST_TIMEOUT_MS = 30_000;\n\n/** Response body from litestream's `POST /sync` control endpoint. */\nexport type SyncResponse = {\n /**\n * `synced` when `wait` was true and the upload completed, `synced_local`\n * when the WAL was sealed locally without waiting on the remote replica, or\n * `no_change` when there was nothing to sync.\n */\n status: 'synced' | 'synced_local' | 'no_change';\n path: string;\n txid: number;\n replicated_txid: number;\n};\n\nexport type SyncOptions = {\n /**\n * When true, block until the sealed WAL has been uploaded to the remote\n * replica (litestream's SyncAndWait). When false (the default), litestream\n * only seals the WAL into local LTX files and runs its checkpoint thresholds,\n * returning without waiting on the backup store. Use false on the write path\n * where the goal is to keep the WAL small, not to durably back it up.\n */\n wait?: boolean | undefined;\n\n /** Overall request timeout in milliseconds. Defaults to 30s. */\n timeoutMs?: number | undefined;\n\n /**\n * Server-side deadline in seconds, sent as litestream's `timeout`. When set,\n * litestream ends the request itself (with an error response) once it\n * elapses. Set it below {@link timeoutMs} so that litestream, rather than\n * the client, ends a slow request. (litestream defaults to 30s when `wait`\n * is set, and to no deadline otherwise.)\n */\n serverTimeoutSeconds?: number | undefined;\n};\n\n/**\n * IPC client for the litestream control server. litestream serves an HTTP API\n * over a Unix domain socket (enabled via the `socket:` block in config-v5.yml);\n * because zero-cache runs litestream as a subprocess in the same container, the\n * socket is reachable directly on the local filesystem.\n *\n * A single keep-alive connection is held open and reused across calls, so a\n * high-frequency caller (e.g. write-path backpressure) does not pay a\n * connect/handshake per request.\n */\nexport class LitestreamController {\n readonly #lc: LogContext;\n readonly #replicaFile: string;\n readonly #socketPath: string;\n readonly #agent: Agent;\n\n /**\n * @param replicaFile Path of the replica database litestream is managing —\n * the same value passed to litestream as `ZERO_REPLICA_FILE`. This is the\n * `path` litestream matches control requests against.\n * @param socketPath Path of the control socket; defaults to the path derived\n * from `replicaFile`, matching config-v5.yml's `socket.path`.\n */\n constructor(\n lc: LogContext,\n replicaFile: string,\n socketPath = litestreamSocketPath(replicaFile),\n ) {\n this.#lc = lc.withContext('component', 'litestream-controller');\n this.#replicaFile = replicaFile;\n this.#socketPath = socketPath;\n // keepAlive with a single socket keeps one warm connection to the control\n // socket that is reused across calls.\n this.#agent = new Agent({keepAlive: true, maxSockets: 1});\n }\n\n /**\n * Forces litestream to sync the WAL into LTX files immediately and run its\n * checkpoint thresholds, instead of waiting for the next monitor-interval\n * tick. The checkpoint itself is still litestream's usual (non-blocking)\n * PASSIVE attempt, so it is skipped if the database is busy — call this once\n * writes are quiesced.\n *\n * Best-effort: callers should tolerate rejection (e.g. ECONNREFUSED/ENOENT\n * while litestream is restarting or before it has created the socket) rather\n * than blocking application progress on it.\n */\n async sync(\n opts: SyncOptions = {},\n signal?: AbortSignal,\n ): Promise<SyncResponse> {\n const {\n wait = false,\n timeoutMs = DEFAULT_REQUEST_TIMEOUT_MS,\n serverTimeoutSeconds,\n } = opts;\n const result = await this.#post<SyncResponse>(\n '/sync',\n {\n path: this.#replicaFile,\n wait,\n ...(serverTimeoutSeconds ? {timeout: serverTimeoutSeconds} : {}),\n },\n timeoutMs,\n signal,\n );\n this.#lc.debug?.('litestream sync', result);\n return result;\n }\n\n /** Releases the pooled keep-alive connection. */\n close(): void {\n this.#agent.destroy();\n }\n\n // Note: Uses ye'old node:http for its unix socketPath support.\n // fetch() would have less boiler-plate, but it would require importing\n // the `unidici` package to provide a fetch Agent that supports sockets.\n #post<T>(\n path: string,\n body: unknown,\n timeoutMs: number,\n signal?: AbortSignal,\n ): Promise<T> {\n const payload = JSON.stringify(body);\n return new Promise<T>((resolve, reject) => {\n const req = request(\n {\n socketPath: this.#socketPath,\n method: 'POST',\n path,\n agent: this.#agent,\n timeout: timeoutMs,\n headers: {\n 'content-type': 'application/json',\n 'content-length': Buffer.byteLength(payload),\n },\n signal,\n },\n (res: IncomingMessage) => {\n const status = res.statusCode ?? 0;\n // litestream's success and error responses are both always JSON\n // (writeJSON / writeJSONError in server.go).\n readJSON(res).then(\n body => {\n if (status < 200 || status >= 300) {\n reject(\n new Error(\n `litestream ${path} failed: ${status} ${JSON.stringify(body)}`,\n ),\n );\n } else {\n resolve(body as T);\n }\n },\n (e: unknown) =>\n reject(\n new Error(`litestream ${path} returned invalid JSON`, {\n cause: e,\n }),\n ),\n );\n },\n );\n req.on('timeout', () =>\n req.destroy(\n new Error(`litestream ${path} timed out after ${timeoutMs}ms`),\n ),\n );\n req.on('error', reject);\n req.end(payload);\n });\n }\n}\n"],"mappings":";;;;;;;;;;;AAaA,SAAgB,qBAAqB,aAA6B;CAChE,OAAO,GAAG,YAAY;AACxB;AAEA,IAAM,6BAA6B;;;;;;;;;;;AAgDnC,IAAa,uBAAb,MAAkC;CAChC;CACA;CACA;CACA;;;;;;;;CASA,YACE,IACA,aACA,aAAa,qBAAqB,WAAW,GAC7C;EACA,KAAKA,MAAM,GAAG,YAAY,aAAa,uBAAuB;EAC9D,KAAKC,eAAe;EACpB,KAAKC,cAAc;EAGnB,KAAKC,SAAS,IAAI,MAAM;GAAC,WAAW;GAAM,YAAY;EAAC,CAAC;CAC1D;;;;;;;;;;;;CAaA,MAAM,KACJ,OAAoB,CAAC,GACrB,QACuB;EACvB,MAAM,EACJ,OAAO,OACP,YAAY,4BACZ,yBACE;EACJ,MAAM,SAAS,MAAM,KAAKC,MACxB,SACA;GACE,MAAM,KAAKH;GACX;GACA,GAAI,uBAAuB,EAAC,SAAS,qBAAoB,IAAI,CAAC;EAChE,GACA,WACA,MACF;EACA,KAAKD,IAAI,QAAQ,mBAAmB,MAAM;EAC1C,OAAO;CACT;;CAGA,QAAc;EACZ,KAAKG,OAAO,QAAQ;CACtB;CAKA,MACE,MACA,MACA,WACA,QACY;EACZ,MAAM,UAAU,KAAK,UAAU,IAAI;EACnC,OAAO,IAAI,SAAY,SAAS,WAAW;GACzC,MAAM,MAAM,QACV;IACE,YAAY,KAAKD;IACjB,QAAQ;IACR;IACA,OAAO,KAAKC;IACZ,SAAS;IACT,SAAS;KACP,gBAAgB;KAChB,kBAAkB,OAAO,WAAW,OAAO;IAC7C;IACA;GACF,IACC,QAAyB;IACxB,MAAM,SAAS,IAAI,cAAc;IAGjC,KAAS,GAAG,EAAE,MACZ,SAAQ;KACN,IAAI,SAAS,OAAO,UAAU,KAC5B,uBACE,IAAI,MACF,cAAc,KAAK,WAAW,OAAO,GAAG,KAAK,UAAU,IAAI,GAC7D,CACF;UAEA,QAAQ,IAAS;IAErB,IACC,MACC,OACE,IAAI,MAAM,cAAc,KAAK,yBAAyB,EACpD,OAAO,EACT,CAAC,CACH,CACJ;GACF,CACF;GACA,IAAI,GAAG,iBACL,IAAI,wBACF,IAAI,MAAM,cAAc,KAAK,mBAAmB,UAAU,GAAG,CAC/D,CACF;GACA,IAAI,GAAG,SAAS,MAAM;GACtB,IAAI,IAAI,OAAO;EACjB,CAAC;CACH;AACF"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { LogContext } from '@rocicorp/logger';
|
|
2
|
+
import type { ViewSyncerStatusEvent } from '../../../../zero-events/src/status.ts';
|
|
3
|
+
type PublishFn = (lc: LogContext, event: ViewSyncerStatusEvent) => void;
|
|
4
|
+
/**
|
|
5
|
+
* Publishes the progress of a view-syncer's litestream restore.
|
|
6
|
+
*
|
|
7
|
+
* `litestream restore` writes the database page by page into
|
|
8
|
+
* `<replica>.tmp` and renames it to the replica when it is done, so the
|
|
9
|
+
* size of the temporary file is the number of bytes restored so far.
|
|
10
|
+
*/
|
|
11
|
+
export declare class RestoreProgressReporter {
|
|
12
|
+
#private;
|
|
13
|
+
constructor(lc: LogContext, replicaFile: string, publishFn?: PublishFn);
|
|
14
|
+
/**
|
|
15
|
+
* Publishes a `Restoring` event now and then every `intervalMs` while the
|
|
16
|
+
* number of restored bytes changes, until {@link stop} or {@link done}.
|
|
17
|
+
*/
|
|
18
|
+
start(totalBytes: number | undefined, intervalMs?: number): void;
|
|
19
|
+
stop(): void;
|
|
20
|
+
/** Publishes a `Restored` event with the size of the restored replica. */
|
|
21
|
+
done(): void;
|
|
22
|
+
}
|
|
23
|
+
export {};
|
|
24
|
+
//# sourceMappingURL=restore-progress.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"restore-progress.d.ts","sourceRoot":"","sources":["../../../../../../zero-cache/src/services/litestream/restore-progress.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EAGV,qBAAqB,EACtB,MAAM,uCAAuC,CAAC;AAK/C,KAAK,SAAS,GAAG,CAAC,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,qBAAqB,KAAK,IAAI,CAAC;AAExE;;;;;;GAMG;AACH,qBAAa,uBAAuB;;IAUlC,YACE,EAAE,EAAE,UAAU,EACd,WAAW,EAAE,MAAM,EACnB,SAAS,GAAE,SAAwB,EAKpC;IAED;;;OAGG;IACH,KAAK,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,EAAE,UAAU,SAAsB,QAcrE;IAED,IAAI,SAGH;IAED,0EAA0E;IAC1E,IAAI,SAGH;CA2CF"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { publishEvent } from "../../observability/events.js";
|
|
2
|
+
import { statSync } from "node:fs";
|
|
3
|
+
//#region ../zero-cache/src/services/litestream/restore-progress.ts
|
|
4
|
+
var PUBLISH_INTERVAL_MS = 5e3;
|
|
5
|
+
/**
|
|
6
|
+
* Publishes the progress of a view-syncer's litestream restore.
|
|
7
|
+
*
|
|
8
|
+
* `litestream restore` writes the database page by page into
|
|
9
|
+
* `<replica>.tmp` and renames it to the replica when it is done, so the
|
|
10
|
+
* size of the temporary file is the number of bytes restored so far.
|
|
11
|
+
*/
|
|
12
|
+
var RestoreProgressReporter = class {
|
|
13
|
+
#lc;
|
|
14
|
+
#replicaFile;
|
|
15
|
+
#publishFn;
|
|
16
|
+
#start = performance.now();
|
|
17
|
+
#totalBytes;
|
|
18
|
+
#lastBytes;
|
|
19
|
+
#sawTempFile = false;
|
|
20
|
+
#timer;
|
|
21
|
+
constructor(lc, replicaFile, publishFn = publishEvent) {
|
|
22
|
+
this.#lc = lc;
|
|
23
|
+
this.#replicaFile = replicaFile;
|
|
24
|
+
this.#publishFn = publishFn;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Publishes a `Restoring` event now and then every `intervalMs` while the
|
|
28
|
+
* number of restored bytes changes, until {@link stop} or {@link done}.
|
|
29
|
+
*/
|
|
30
|
+
start(totalBytes, intervalMs = PUBLISH_INTERVAL_MS) {
|
|
31
|
+
this.stop();
|
|
32
|
+
this.#start = performance.now();
|
|
33
|
+
if (totalBytes !== this.#totalBytes) {
|
|
34
|
+
this.#lastBytes = void 0;
|
|
35
|
+
this.#totalBytes = totalBytes;
|
|
36
|
+
}
|
|
37
|
+
this.#sawTempFile = false;
|
|
38
|
+
this.#update(0);
|
|
39
|
+
this.#timer = setInterval(() => this.#check(), intervalMs);
|
|
40
|
+
}
|
|
41
|
+
stop() {
|
|
42
|
+
clearInterval(this.#timer);
|
|
43
|
+
this.#timer = void 0;
|
|
44
|
+
}
|
|
45
|
+
/** Publishes a `Restored` event with the size of the restored replica. */
|
|
46
|
+
done() {
|
|
47
|
+
this.stop();
|
|
48
|
+
this.#publish("Restored", fileSize(this.#replicaFile) ?? 0);
|
|
49
|
+
}
|
|
50
|
+
#check() {
|
|
51
|
+
const tempBytes = fileSize(`${this.#replicaFile}.tmp`);
|
|
52
|
+
if (tempBytes !== void 0) {
|
|
53
|
+
this.#sawTempFile = true;
|
|
54
|
+
this.#update(tempBytes);
|
|
55
|
+
} else if (this.#sawTempFile) this.#update(fileSize(this.#replicaFile) ?? 0);
|
|
56
|
+
}
|
|
57
|
+
#update(bytes) {
|
|
58
|
+
if (bytes !== this.#lastBytes) {
|
|
59
|
+
this.#lastBytes = bytes;
|
|
60
|
+
this.#publish("Restoring", bytes);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
#publish(stage, bytes) {
|
|
64
|
+
const restoreStatus = {
|
|
65
|
+
bytes,
|
|
66
|
+
totalBytes: this.#totalBytes,
|
|
67
|
+
elapsedMs: Math.round(performance.now() - this.#start)
|
|
68
|
+
};
|
|
69
|
+
const event = {
|
|
70
|
+
type: "zero/events/status/view-syncer/v1",
|
|
71
|
+
component: "view-syncer",
|
|
72
|
+
status: "OK",
|
|
73
|
+
stage,
|
|
74
|
+
description: stage === "Restoring" ? "Restoring replica from backup" : "Restored replica from backup",
|
|
75
|
+
time: (/* @__PURE__ */ new Date()).toISOString(),
|
|
76
|
+
state: { restoreStatus }
|
|
77
|
+
};
|
|
78
|
+
this.#publishFn(this.#lc, event);
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
function fileSize(file) {
|
|
82
|
+
try {
|
|
83
|
+
return statSync(file).size;
|
|
84
|
+
} catch {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
//#endregion
|
|
89
|
+
export { RestoreProgressReporter };
|
|
90
|
+
|
|
91
|
+
//# sourceMappingURL=restore-progress.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"restore-progress.js","names":["#lc","#replicaFile","#publishFn","#start","#totalBytes","#lastBytes","#sawTempFile","#update","#timer","#check","#publish"],"sources":["../../../../../../zero-cache/src/services/litestream/restore-progress.ts"],"sourcesContent":["import {statSync} from 'node:fs';\nimport type {LogContext} from '@rocicorp/logger';\nimport type {\n RestoreStatus,\n ViewSyncerStage,\n ViewSyncerStatusEvent,\n} from '../../../../zero-events/src/status.ts';\nimport {publishEvent} from '../../observability/events.ts';\n\nconst PUBLISH_INTERVAL_MS = 5000;\n\ntype PublishFn = (lc: LogContext, event: ViewSyncerStatusEvent) => void;\n\n/**\n * Publishes the progress of a view-syncer's litestream restore.\n *\n * `litestream restore` writes the database page by page into\n * `<replica>.tmp` and renames it to the replica when it is done, so the\n * size of the temporary file is the number of bytes restored so far.\n */\nexport class RestoreProgressReporter {\n readonly #lc: LogContext;\n readonly #replicaFile: string;\n readonly #publishFn: PublishFn;\n #start = performance.now();\n #totalBytes: number | undefined;\n #lastBytes: number | undefined;\n #sawTempFile = false;\n #timer: NodeJS.Timeout | undefined;\n\n constructor(\n lc: LogContext,\n replicaFile: string,\n publishFn: PublishFn = publishEvent,\n ) {\n this.#lc = lc;\n this.#replicaFile = replicaFile;\n this.#publishFn = publishFn;\n }\n\n /**\n * Publishes a `Restoring` event now and then every `intervalMs` while the\n * number of restored bytes changes, until {@link stop} or {@link done}.\n */\n start(totalBytes: number | undefined, intervalMs = PUBLISH_INTERVAL_MS) {\n this.stop();\n // Measure the restore itself, not the wait for a restorable backup.\n this.#start = performance.now();\n if (totalBytes !== this.#totalBytes) {\n // Publish the new total even if the restored bytes are unchanged.\n this.#lastBytes = undefined;\n this.#totalBytes = totalBytes;\n }\n // Start from 0 rather than checking now: a `.tmp` left behind by an\n // interrupted restore is only deleted when the restore starts.\n this.#sawTempFile = false;\n this.#update(0);\n this.#timer = setInterval(() => this.#check(), intervalMs);\n }\n\n stop() {\n clearInterval(this.#timer);\n this.#timer = undefined;\n }\n\n /** Publishes a `Restored` event with the size of the restored replica. */\n done() {\n this.stop();\n this.#publish('Restored', fileSize(this.#replicaFile) ?? 0);\n }\n\n #check() {\n const tempBytes = fileSize(`${this.#replicaFile}.tmp`);\n if (tempBytes !== undefined) {\n this.#sawTempFile = true;\n this.#update(tempBytes);\n } else if (this.#sawTempFile) {\n // litestream renames `.tmp` to the replica before its post-restore\n // integrity check, so once `.tmp` is gone the replica holds the bytes.\n // Before `.tmp` appears, an existing replica is not restore progress\n // (it may be invalid and about to be deleted).\n this.#update(fileSize(this.#replicaFile) ?? 0);\n }\n }\n\n #update(bytes: number) {\n if (bytes !== this.#lastBytes) {\n this.#lastBytes = bytes;\n this.#publish('Restoring', bytes);\n }\n }\n\n #publish(stage: ViewSyncerStage, bytes: number) {\n const restoreStatus: RestoreStatus = {\n bytes,\n totalBytes: this.#totalBytes,\n elapsedMs: Math.round(performance.now() - this.#start),\n };\n const event: ViewSyncerStatusEvent = {\n type: 'zero/events/status/view-syncer/v1',\n component: 'view-syncer',\n status: 'OK',\n stage,\n description:\n stage === 'Restoring'\n ? 'Restoring replica from backup'\n : 'Restored replica from backup',\n time: new Date().toISOString(),\n state: {restoreStatus},\n };\n this.#publishFn(this.#lc, event);\n }\n}\n\nfunction fileSize(file: string): number | undefined {\n try {\n return statSync(file).size;\n } catch {\n return undefined;\n }\n}\n"],"mappings":";;;AASA,IAAM,sBAAsB;;;;;;;;AAW5B,IAAa,0BAAb,MAAqC;CACnC;CACA;CACA;CACA,SAAS,YAAY,IAAI;CACzB;CACA;CACA,eAAe;CACf;CAEA,YACE,IACA,aACA,YAAuB,cACvB;EACA,KAAKA,MAAM;EACX,KAAKC,eAAe;EACpB,KAAKC,aAAa;CACpB;;;;;CAMA,MAAM,YAAgC,aAAa,qBAAqB;EACtE,KAAK,KAAK;EAEV,KAAKC,SAAS,YAAY,IAAI;EAC9B,IAAI,eAAe,KAAKC,aAAa;GAEnC,KAAKC,aAAa,KAAA;GAClB,KAAKD,cAAc;EACrB;EAGA,KAAKE,eAAe;EACpB,KAAKC,QAAQ,CAAC;EACd,KAAKC,SAAS,kBAAkB,KAAKC,OAAO,GAAG,UAAU;CAC3D;CAEA,OAAO;EACL,cAAc,KAAKD,MAAM;EACzB,KAAKA,SAAS,KAAA;CAChB;;CAGA,OAAO;EACL,KAAK,KAAK;EACV,KAAKE,SAAS,YAAY,SAAS,KAAKT,YAAY,KAAK,CAAC;CAC5D;CAEA,SAAS;EACP,MAAM,YAAY,SAAS,GAAG,KAAKA,aAAa,KAAK;EACrD,IAAI,cAAc,KAAA,GAAW;GAC3B,KAAKK,eAAe;GACpB,KAAKC,QAAQ,SAAS;EACxB,OAAO,IAAI,KAAKD,cAKd,KAAKC,QAAQ,SAAS,KAAKN,YAAY,KAAK,CAAC;CAEjD;CAEA,QAAQ,OAAe;EACrB,IAAI,UAAU,KAAKI,YAAY;GAC7B,KAAKA,aAAa;GAClB,KAAKK,SAAS,aAAa,KAAK;EAClC;CACF;CAEA,SAAS,OAAwB,OAAe;EAC9C,MAAM,gBAA+B;GACnC;GACA,YAAY,KAAKN;GACjB,WAAW,KAAK,MAAM,YAAY,IAAI,IAAI,KAAKD,MAAM;EACvD;EACA,MAAM,QAA+B;GACnC,MAAM;GACN,WAAW;GACX,QAAQ;GACR;GACA,aACE,UAAU,cACN,kCACA;GACN,uBAAM,IAAI,KAAK,GAAE,YAAY;GAC7B,OAAO,EAAC,cAAa;EACvB;EACA,KAAKD,WAAW,KAAKF,KAAK,KAAK;CACjC;AACF;AAEA,SAAS,SAAS,MAAkC;CAClD,IAAI;EACF,OAAO,SAAS,IAAI,EAAE;CACxB,QAAQ;EACN;CACF;AACF"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { LogContext } from '@rocicorp/logger';
|
|
2
|
+
import type { Database } from '../../../../zqlite/src/db.ts';
|
|
3
|
+
/**
|
|
4
|
+
* Keeps the WAL of a replica intact until `litestream replicate` has attached
|
|
5
|
+
* to it, when the backup continues from the local litestream state (see
|
|
6
|
+
* `ResumableBackup`), e.g. after a forking `litestream restore`.
|
|
7
|
+
*
|
|
8
|
+
* Litestream needs its latest local L0 file to correspond to the state of
|
|
9
|
+
* the WAL to continue replication from it rather than creating a new snapshot.
|
|
10
|
+
* Normally, the last connection to close a database checkpoints and deletes
|
|
11
|
+
* its WAL, which loses the salt and makes litestream fall back to the
|
|
12
|
+
* snapshot. The keeper prevents that because every connection holds a SHARED
|
|
13
|
+
* lock on the database file while it is open in WAL mode, so while the keeper
|
|
14
|
+
* is open, no other connection's close can be the last one.
|
|
15
|
+
*
|
|
16
|
+
* While the keeper is held, nothing can change the journal mode or take an
|
|
17
|
+
* exclusive lock on the replica, as those fail with SQLITE_BUSY. The backup
|
|
18
|
+
* replicator keeps a replica that is already in 'wal' mode as is, and skips
|
|
19
|
+
* a due VACUUM (see `setupReplica`). Incremental schema migrations run in WAL
|
|
20
|
+
* mode (see `runSchemaMigrations`).
|
|
21
|
+
*/
|
|
22
|
+
export declare class WalKeeper {
|
|
23
|
+
#private;
|
|
24
|
+
/**
|
|
25
|
+
* Takes ownership of `db`, an open connection to the replica, which it
|
|
26
|
+
* closes when released.
|
|
27
|
+
*/
|
|
28
|
+
constructor(lc: LogContext, db: Database);
|
|
29
|
+
get held(): boolean;
|
|
30
|
+
/** Closes the keeper connection. Idempotent. */
|
|
31
|
+
release(reason: string): void;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=wal-keeper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wal-keeper.d.ts","sourceRoot":"","sources":["../../../../../../zero-cache/src/services/litestream/wal-keeper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,8BAA8B,CAAC;AAE3D;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,SAAS;;IAIpB;;;OAGG;IACH,YAAY,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,QAAQ,EAMvC;IAED,IAAI,IAAI,IAAI,OAAO,CAElB;IAED,gDAAgD;IAChD,OAAO,CAAC,MAAM,EAAE,MAAM,QAMrB;CACF"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
//#region ../zero-cache/src/services/litestream/wal-keeper.ts
|
|
2
|
+
/**
|
|
3
|
+
* Keeps the WAL of a replica intact until `litestream replicate` has attached
|
|
4
|
+
* to it, when the backup continues from the local litestream state (see
|
|
5
|
+
* `ResumableBackup`), e.g. after a forking `litestream restore`.
|
|
6
|
+
*
|
|
7
|
+
* Litestream needs its latest local L0 file to correspond to the state of
|
|
8
|
+
* the WAL to continue replication from it rather than creating a new snapshot.
|
|
9
|
+
* Normally, the last connection to close a database checkpoints and deletes
|
|
10
|
+
* its WAL, which loses the salt and makes litestream fall back to the
|
|
11
|
+
* snapshot. The keeper prevents that because every connection holds a SHARED
|
|
12
|
+
* lock on the database file while it is open in WAL mode, so while the keeper
|
|
13
|
+
* is open, no other connection's close can be the last one.
|
|
14
|
+
*
|
|
15
|
+
* While the keeper is held, nothing can change the journal mode or take an
|
|
16
|
+
* exclusive lock on the replica, as those fail with SQLITE_BUSY. The backup
|
|
17
|
+
* replicator keeps a replica that is already in 'wal' mode as is, and skips
|
|
18
|
+
* a due VACUUM (see `setupReplica`). Incremental schema migrations run in WAL
|
|
19
|
+
* mode (see `runSchemaMigrations`).
|
|
20
|
+
*/
|
|
21
|
+
var WalKeeper = class {
|
|
22
|
+
#lc;
|
|
23
|
+
#db;
|
|
24
|
+
/**
|
|
25
|
+
* Takes ownership of `db`, an open connection to the replica, which it
|
|
26
|
+
* closes when released.
|
|
27
|
+
*/
|
|
28
|
+
constructor(lc, db) {
|
|
29
|
+
this.#lc = lc.withContext("component", "wal-keeper");
|
|
30
|
+
db.prepare("SELECT count(*) FROM sqlite_master").get();
|
|
31
|
+
this.#db = db;
|
|
32
|
+
this.#lc.info?.(`holding the restored WAL of ${db.name}`);
|
|
33
|
+
}
|
|
34
|
+
get held() {
|
|
35
|
+
return this.#db !== null;
|
|
36
|
+
}
|
|
37
|
+
/** Closes the keeper connection. Idempotent. */
|
|
38
|
+
release(reason) {
|
|
39
|
+
if (this.#db) {
|
|
40
|
+
this.#lc.info?.(`releasing the restored WAL: ${reason}`);
|
|
41
|
+
this.#db.close();
|
|
42
|
+
this.#db = null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
//#endregion
|
|
47
|
+
export { WalKeeper };
|
|
48
|
+
|
|
49
|
+
//# sourceMappingURL=wal-keeper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wal-keeper.js","names":["#lc","#db"],"sources":["../../../../../../zero-cache/src/services/litestream/wal-keeper.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport type {Database} from '../../../../zqlite/src/db.ts';\n\n/**\n * Keeps the WAL of a replica intact until `litestream replicate` has attached\n * to it, when the backup continues from the local litestream state (see\n * `ResumableBackup`), e.g. after a forking `litestream restore`.\n *\n * Litestream needs its latest local L0 file to correspond to the state of\n * the WAL to continue replication from it rather than creating a new snapshot.\n * Normally, the last connection to close a database checkpoints and deletes\n * its WAL, which loses the salt and makes litestream fall back to the\n * snapshot. The keeper prevents that because every connection holds a SHARED\n * lock on the database file while it is open in WAL mode, so while the keeper\n * is open, no other connection's close can be the last one.\n *\n * While the keeper is held, nothing can change the journal mode or take an\n * exclusive lock on the replica, as those fail with SQLITE_BUSY. The backup\n * replicator keeps a replica that is already in 'wal' mode as is, and skips\n * a due VACUUM (see `setupReplica`). Incremental schema migrations run in WAL\n * mode (see `runSchemaMigrations`).\n */\nexport class WalKeeper {\n readonly #lc: LogContext;\n #db: Database | null;\n\n /**\n * Takes ownership of `db`, an open connection to the replica, which it\n * closes when released.\n */\n constructor(lc: LogContext, db: Database) {\n this.#lc = lc.withContext('component', 'wal-keeper');\n // The SHARED lock is taken by the first read (if no read has taken it).\n db.prepare('SELECT count(*) FROM sqlite_master').get();\n this.#db = db;\n this.#lc.info?.(`holding the restored WAL of ${db.name}`);\n }\n\n get held(): boolean {\n return this.#db !== null;\n }\n\n /** Closes the keeper connection. Idempotent. */\n release(reason: string) {\n if (this.#db) {\n this.#lc.info?.(`releasing the restored WAL: ${reason}`);\n this.#db.close();\n this.#db = null;\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAsBA,IAAa,YAAb,MAAuB;CACrB;CACA;;;;;CAMA,YAAY,IAAgB,IAAc;EACxC,KAAKA,MAAM,GAAG,YAAY,aAAa,YAAY;EAEnD,GAAG,QAAQ,oCAAoC,EAAE,IAAI;EACrD,KAAKC,MAAM;EACX,KAAKD,IAAI,OAAO,+BAA+B,GAAG,MAAM;CAC1D;CAEA,IAAI,OAAgB;EAClB,OAAO,KAAKC,QAAQ;CACtB;;CAGA,QAAQ,QAAgB;EACtB,IAAI,KAAKA,KAAK;GACZ,KAAKD,IAAI,OAAO,+BAA+B,QAAQ;GACvD,KAAKC,IAAI,MAAM;GACf,KAAKA,MAAM;EACb;CACF;AACF"}
|
|
@@ -14,6 +14,11 @@ export type MutationError = [
|
|
|
14
14
|
desc: string
|
|
15
15
|
];
|
|
16
16
|
export interface Mutagen extends RefCountedService {
|
|
17
|
+
/**
|
|
18
|
+
* Callers must hold a {@link ref} for the duration of a push (i.e. across
|
|
19
|
+
* all of its mutations). The service stops, closing its replica handle,
|
|
20
|
+
* when its ref count drops to zero.
|
|
21
|
+
*/
|
|
17
22
|
processMutation(mutation: Mutation, authData: JWTPayload | undefined, customMutatorsEnabled: boolean): Promise<MutationError | undefined>;
|
|
18
23
|
}
|
|
19
24
|
export declare class MutagenService implements Mutagen, Service {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mutagen.d.ts","sourceRoot":"","sources":["../../../../../../zero-cache/src/services/mutagen/mutagen.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAEjD,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,MAAM,CAAC;AACrC,OAAO,QAAQ,MAAM,UAAU,CAAC;AAGhC,OAAO,EAAC,SAAS,EAAC,MAAM,6CAA6C,CAAC;AAOtE,OAAO,EACL,KAAK,YAAY,EAEjB,KAAK,QAAQ,EACb,KAAK,QAAQ,EAEb,KAAK,QAAQ,EACd,MAAM,2CAA2C,CAAC;AAKnD,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,4CAA4C,CAAC;AAEhF,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAC,KAAK,UAAU,EAAC,MAAM,6BAA6B,CAAC;AAK5D,OAAO,KAAK,EAAC,UAAU,EAAE,mBAAmB,EAAC,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAiB,KAAK,OAAO,EAAC,MAAM,uBAAuB,CAAC;AAEnE,OAAO,KAAK,EAAC,iBAAiB,EAAE,OAAO,EAAC,MAAM,eAAe,CAAC;AAK9D,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,SAAS,CAAC,cAAc,GAAG,SAAS,CAAC,mBAAmB;IAC9D,IAAI,EAAE,MAAM;CACb,CAAC;AAEF,MAAM,WAAW,OAAQ,SAAQ,iBAAiB;IAChD,eAAe,CACb,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,UAAU,GAAG,SAAS,EAChC,qBAAqB,EAAE,OAAO,GAC7B,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAAC;CACvC;AAED,qBAAa,cAAe,YAAW,OAAO,EAAE,OAAO;;IACrD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAiBpB,YACE,EAAE,EAAE,UAAU,EACd,KAAK,EAAE,OAAO,EACd,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,UAAU,EACpB,MAAM,EAAE,UAAU,EAClB,iBAAiB,EAAE,eAAe,EAwBnC;IAED,GAAG,SAGF;IAED,KAAK,SAMJ;IAED,OAAO,IAAI,OAAO,CAEjB;IAED,eAAe,CACb,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,UAAU,GAAG,SAAS,EAChC,qBAAqB,UAAQ,GAC5B,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAqBpC;IAED,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,CAEnB;IAED,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"mutagen.d.ts","sourceRoot":"","sources":["../../../../../../zero-cache/src/services/mutagen/mutagen.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAEjD,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,MAAM,CAAC;AACrC,OAAO,QAAQ,MAAM,UAAU,CAAC;AAGhC,OAAO,EAAC,SAAS,EAAC,MAAM,6CAA6C,CAAC;AAOtE,OAAO,EACL,KAAK,YAAY,EAEjB,KAAK,QAAQ,EACb,KAAK,QAAQ,EAEb,KAAK,QAAQ,EACd,MAAM,2CAA2C,CAAC;AAKnD,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,4CAA4C,CAAC;AAEhF,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAC,KAAK,UAAU,EAAC,MAAM,6BAA6B,CAAC;AAK5D,OAAO,KAAK,EAAC,UAAU,EAAE,mBAAmB,EAAC,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAiB,KAAK,OAAO,EAAC,MAAM,uBAAuB,CAAC;AAEnE,OAAO,KAAK,EAAC,iBAAiB,EAAE,OAAO,EAAC,MAAM,eAAe,CAAC;AAK9D,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,SAAS,CAAC,cAAc,GAAG,SAAS,CAAC,mBAAmB;IAC9D,IAAI,EAAE,MAAM;CACb,CAAC;AAEF,MAAM,WAAW,OAAQ,SAAQ,iBAAiB;IAChD;;;;OAIG;IACH,eAAe,CACb,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,UAAU,GAAG,SAAS,EAChC,qBAAqB,EAAE,OAAO,GAC7B,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAAC;CACvC;AAED,qBAAa,cAAe,YAAW,OAAO,EAAE,OAAO;;IACrD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAiBpB,YACE,EAAE,EAAE,UAAU,EACd,KAAK,EAAE,OAAO,EACd,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,UAAU,EACpB,MAAM,EAAE,UAAU,EAClB,iBAAiB,EAAE,eAAe,EAwBnC;IAED,GAAG,SAGF;IAED,KAAK,SAMJ;IAED,OAAO,IAAI,OAAO,CAEjB;IAED,eAAe,CACb,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,UAAU,GAAG,SAAS,EAChC,qBAAqB,UAAQ,GAC5B,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAqBpC;IAED,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,CAEnB;IAED,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAiBpB;CACF;AAID,wBAAsB,eAAe,CACnC,EAAE,EAAE,UAAU,EACd,QAAQ,EAAE,UAAU,GAAG,SAAS,EAChC,EAAE,EAAE,UAAU,EACd,KAAK,EAAE,OAAO,EACd,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,QAAQ,EAClB,eAAe,EAAE,eAAe,EAChC,SAAS,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,EAAE,cAAc;AACtD,qBAAqB,UAAQ,GAC5B,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAwIpC;AAED,wBAAsB,qBAAqB,CACzC,EAAE,EAAE,UAAU,EACd,EAAE,EAAE,mBAAmB,EACvB,QAAQ,EAAE,UAAU,GAAG,SAAS,EAChC,KAAK,EAAE,OAAO,EACd,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,YAAY,EACtB,SAAS,EAAE,OAAO,EAClB,UAAU,EAAE,eAAe,iBAgE5B;AAED,wBAAgB,YAAY,CAC1B,EAAE,EAAE,QAAQ,CAAC,cAAc,EAC3B,MAAM,EAAE,QAAQ,GACf,QAAQ,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,CAKvC;AAED,wBAAgB,YAAY,CAC1B,EAAE,EAAE,QAAQ,CAAC,cAAc,EAC3B,GAAG,EAAE,QAAQ,GACZ,QAAQ,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,CAOvC"}
|
|
@@ -63,8 +63,14 @@ var MutagenService = class {
|
|
|
63
63
|
}
|
|
64
64
|
stop() {
|
|
65
65
|
if (this.#isStopped) return this.#stopped.promise;
|
|
66
|
-
this.#writeAuthorizer.destroy();
|
|
67
66
|
this.#isStopped = true;
|
|
67
|
+
try {
|
|
68
|
+
this.#writeAuthorizer.destroy();
|
|
69
|
+
} catch (e) {
|
|
70
|
+
this.#lc.error?.("error destroying write authorizer storage", e);
|
|
71
|
+
} finally {
|
|
72
|
+
this.#replica.close({ optimize: false });
|
|
73
|
+
}
|
|
68
74
|
this.#stopped.resolve();
|
|
69
75
|
return this.#stopped.promise;
|
|
70
76
|
}
|