@rocicorp/zero 1.11.0-canary.2 → 1.11.0-canary.20
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/bin-analyze.js +9 -8
- package/out/analyze-query/src/bin-analyze.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 +54 -1
- 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/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/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/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/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/z2s/src/compiler.js +1 -1
- package/out/z2s/src/sql.d.ts.map +1 -1
- package/out/z2s/src/sql.js +2 -2
- package/out/z2s/src/sql.js.map +1 -1
- package/out/zero/package.js +3 -4
- 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.map +1 -1
- package/out/zero-cache/src/config/normalize.js +26 -2
- package/out/zero-cache/src/config/normalize.js.map +1 -1
- package/out/zero-cache/src/config/zero-config.d.ts +102 -6
- package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
- package/out/zero-cache/src/config/zero-config.js +254 -57
- package/out/zero-cache/src/config/zero-config.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/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/server/change-streamer.d.ts.map +1 -1
- package/out/zero-cache/src/server/change-streamer.js +27 -10
- 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 +79 -15
- 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 +15 -3
- 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/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/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 +204 -18
- 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 +25 -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 +202 -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 +14 -16
- 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 +64 -143
- 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 +37 -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 +53 -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/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 +21 -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 +86 -23
- 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 +100 -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 +43 -0
- 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 +57 -0
- 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 +20 -6
- 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 +66 -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 +154 -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 +2 -0
- 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 +58 -7
- 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-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 +130 -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 +11 -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 +118 -68
- 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 +37 -15
- 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 +51 -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 +132 -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 +1 -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 +19 -8
- 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 +2 -2
- package/out/zero-cache/src/services/change-streamer/storer.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/storer.js +9 -6
- 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 +33 -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 +76 -0
- 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 +17 -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 +19 -3
- package/out/zero-cache/src/services/change-streamer/upstream-acker.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/vfs-watermark-poller.d.ts +5 -0
- package/out/zero-cache/src/services/change-streamer/vfs-watermark-poller.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/vfs-watermark-poller.js +35 -5
- package/out/zero-cache/src/services/change-streamer/vfs-watermark-poller.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 +15 -3
- package/out/zero-cache/src/services/litestream/commands.d.ts.map +1 -1
- package/out/zero-cache/src/services/litestream/commands.js +24 -7
- package/out/zero-cache/src/services/litestream/commands.js.map +1 -1
- package/out/zero-cache/src/services/litestream/config-v5.yml +11 -4
- 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/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 +145 -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 +49 -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 +3 -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 +50 -20
- 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 +96 -6
- package/out/zero-cache/src/services/replicator/replication-status.js.map +1 -1
- package/out/zero-cache/src/services/replicator/replicator.d.ts +2 -1
- package/out/zero-cache/src/services/replicator/replicator.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/replicator.js +2 -2
- package/out/zero-cache/src/services/replicator/replicator.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 +26 -14
- 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/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/cvr-store.d.ts +19 -1
- package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr-store.js +34 -11
- 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 +51 -2
- package/out/zero-cache/src/services/view-syncer/cvr.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr.js +142 -6
- 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 +1 -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 +3 -3
- 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 +50 -2
- 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 +471 -62
- 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 +77 -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 +206 -0
- package/out/zero-cache/src/services/view-syncer/query-stats.js.map +1 -0
- 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 +78 -4
- package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/snapshotter.js +158 -28
- 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 +587 -103
- package/out/zero-cache/src/services/view-syncer/view-syncer.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.map +1 -1
- package/out/zero-cache/src/types/row-key.js +5 -5
- 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 +1 -0
- package/out/zero-cache/src/workers/connect-params.d.ts.map +1 -1
- package/out/zero-cache/src/workers/connect-params.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 +22 -12
- package/out/zero-client/src/client/context.d.ts.map +1 -1
- package/out/zero-client/src/client/context.js +92 -25
- package/out/zero-client/src/client/context.js.map +1 -1
- package/out/zero-client/src/client/custom.js +2 -2
- package/out/zero-client/src/client/custom.js.map +1 -1
- package/out/zero-client/src/client/error.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/mutator-proxy.d.ts.map +1 -1
- package/out/zero-client/src/client/mutator-proxy.js +5 -2
- 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.map +1 -1
- package/out/zero-client/src/client/query-manager.js +44 -11
- package/out/zero-client/src/client/query-manager.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 +83 -46
- package/out/zero-client/src/client/zero.js.map +1 -1
- package/out/zero-client/src/mod.d.ts +1 -0
- 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 +58 -0
- package/out/zero-events/src/status.d.ts.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/down.d.ts +29 -29
- 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 +62 -4
- 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 +1 -0
- package/out/zero-server/src/adapters/pg.d.ts.map +1 -1
- package/out/zero-server/src/adapters/pg.js +8 -2
- 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/custom.d.ts +5 -1
- package/out/zero-server/src/custom.d.ts.map +1 -1
- package/out/zero-server/src/custom.js +6 -3
- 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 +12 -3
- package/out/zero-server/src/process-mutations.d.ts.map +1 -1
- package/out/zero-server/src/process-mutations.js +13 -8
- 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 +2 -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 +33 -2
- 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 +58 -9
- 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/connection-index.d.ts +68 -0
- package/out/zql/src/ivm/connection-index.d.ts.map +1 -0
- package/out/zql/src/ivm/connection-index.js +149 -0
- package/out/zql/src/ivm/connection-index.js.map +1 -0
- 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 +28 -3
- package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
- package/out/zql/src/ivm/memory-source.js +69 -33
- 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 +24 -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 +2 -2
- package/out/zql/src/mutate/mutator-registry.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 +2 -1
- package/out/zql/src/query/measure-push-operator.d.ts.map +1 -1
- package/out/zql/src/query/measure-push-operator.js +33 -4
- 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 +11 -2
- 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 +31 -27
- package/out/zqlite/src/db.js.map +1 -1
- 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/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 +83 -2
- package/out/zqlite/src/table-source.d.ts.map +1 -1
- package/out/zqlite/src/table-source.js +264 -38
- package/out/zqlite/src/table-source.js.map +1 -1
- package/package.json +3 -4
- 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
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { assert, unreachable } from "../../../../shared/src/asserts.js";
|
|
2
|
+
import { getOrInsertComputed } from "../../../../shared/src/map.js";
|
|
3
|
+
import { newArray } from "../../../../shared/src/arrays.js";
|
|
2
4
|
import { must } from "../../../../shared/src/must.js";
|
|
3
5
|
import { h64 } from "../../../../shared/src/hash.js";
|
|
4
6
|
import { Internal, InvalidConnectionRequest, InvalidConnectionRequestBaseCookie, Rehome } from "../../../../zero-protocol/src/error-kind-enum.js";
|
|
@@ -10,12 +12,14 @@ import { manualSpan, startAsyncSpan, startSpan } from "../../../../otel/src/span
|
|
|
10
12
|
import { ZERO_VERSION_COLUMN_NAME } from "../replicator/schema/constants.js";
|
|
11
13
|
import { transformAndHashQuery } from "../../auth/read-authorizer.js";
|
|
12
14
|
import { randInt } from "../../../../shared/src/rand.js";
|
|
13
|
-
import {
|
|
15
|
+
import { LogThrottle } from "../../observability/log-throttle.js";
|
|
16
|
+
import { getOrCreateCounter, getOrCreateLatencyHistogram, getOrCreateNativeHistogram, getOrCreateUpDownCounter, getOrCreateValueHistogram } from "../../observability/metrics.js";
|
|
14
17
|
import { rowIDString } from "../../types/row-key.js";
|
|
15
18
|
import "../replicator/schema/replication-state.js";
|
|
19
|
+
import { planWarningMessage } from "./plan-warnings.js";
|
|
20
|
+
import { queryShape } from "./query-shape.js";
|
|
16
21
|
import { parseSignature } from "./row-set-signature.js";
|
|
17
22
|
import { ResetPipelinesSignal } from "./snapshotter.js";
|
|
18
|
-
import "./pipeline-driver.js";
|
|
19
23
|
import { Subscription } from "../../types/subscription.js";
|
|
20
24
|
import { CustomKeyMap } from "../../../../shared/src/custom-key-map.js";
|
|
21
25
|
import { ttlClockAsNumber, ttlClockFromNumber } from "./ttl-clock.js";
|
|
@@ -25,8 +29,10 @@ import { isAuthErrorBody } from "../../auth/auth.js";
|
|
|
25
29
|
import { ClientHandler, startPoke } from "./client-handler.js";
|
|
26
30
|
import { tracer } from "./tracer.js";
|
|
27
31
|
import { CVRStore, ClientNotFoundError } from "./cvr-store.js";
|
|
28
|
-
import { CVRConfigDrivenUpdater, CVRQueryDrivenUpdater, nextEvictionTime } from "./cvr.js";
|
|
32
|
+
import { CVRConfigDrivenUpdater, CVRQueryDrivenUpdater, classifyQueriesForHydration, nextEvictionTime } from "./cvr.js";
|
|
29
33
|
import { E2EServingLagTracker } from "./e2e-serving-lag.js";
|
|
34
|
+
import { HydrationBudget } from "./hydration-budget.js";
|
|
35
|
+
import { HydrationCircuitBreaker } from "./hydration-circuit-breaker.js";
|
|
30
36
|
import { handleInspect } from "./inspect-handler.js";
|
|
31
37
|
import { QueryCoveringIndex } from "./query-covering.js";
|
|
32
38
|
import { resolver } from "@rocicorp/resolver";
|
|
@@ -50,6 +56,7 @@ function shutdownBeforeInitializationError() {
|
|
|
50
56
|
* use a timer to update the ttlClock every minute.
|
|
51
57
|
*/
|
|
52
58
|
var TTL_CLOCK_INTERVAL = 6e4;
|
|
59
|
+
var slowHydrationLogThrottle = new LogThrottle({ windowMs: 5 * 6e4 });
|
|
53
60
|
var ViewSyncerService = class {
|
|
54
61
|
id;
|
|
55
62
|
createdAtMs = Date.now();
|
|
@@ -61,6 +68,7 @@ var ViewSyncerService = class {
|
|
|
61
68
|
#drainCoordinator;
|
|
62
69
|
#keepaliveMs;
|
|
63
70
|
#slowHydrateThreshold;
|
|
71
|
+
#hydrationCircuitBreaker;
|
|
64
72
|
#lastConnectTime = Date.now();
|
|
65
73
|
/**
|
|
66
74
|
* The TTL clock is used to determine the time at which queries are considered
|
|
@@ -88,14 +96,37 @@ var ViewSyncerService = class {
|
|
|
88
96
|
#lock = new Lock();
|
|
89
97
|
#cvrStore;
|
|
90
98
|
#stopped = resolver();
|
|
99
|
+
/**
|
|
100
|
+
* Set when {@link #cleanup} begins. Lock tasks that were in flight when the
|
|
101
|
+
* view-syncer was stopped may still complete after the timers have been
|
|
102
|
+
* cleared; this flag prevents them from scheduling new timers, which would
|
|
103
|
+
* otherwise outlive the service (and retain everything it references).
|
|
104
|
+
*/
|
|
105
|
+
#shuttingDown = false;
|
|
91
106
|
#initialized = resolver();
|
|
92
107
|
#cvr;
|
|
93
|
-
|
|
108
|
+
/**
|
|
109
|
+
* Indicates whether the query pipelines have completed initial catch-up and
|
|
110
|
+
* hydration with the CVR snapshot, and are ready for steady-state operation.
|
|
111
|
+
*
|
|
112
|
+
* - When `false`: The syncer is in its initial catch-up phase. The replica
|
|
113
|
+
* advances without diffs until it reaches `cvr.version.stateVersion`,
|
|
114
|
+
* after which `#maybeHydratePipelines` hydrates queries.
|
|
115
|
+
* - When `true`: Pipelines are fully populated and in steady-state; replica
|
|
116
|
+
* changes advance incrementally via `#advancePipelines`, and client query
|
|
117
|
+
* updates are processed via `#syncQueryPipelineSet`.
|
|
118
|
+
*
|
|
119
|
+
* Resets to `false` if `#advancePipelines` returns a `ResetPipelinesSignal`
|
|
120
|
+
* and pipelines must be reset and rehydrated, or if a reloaded CVR is ahead
|
|
121
|
+
* of the pipelines (see `#resetPipelinesIfBehindCVR`).
|
|
122
|
+
*/
|
|
123
|
+
#pipelinesHydrated = false;
|
|
94
124
|
#servedVersion = null;
|
|
95
125
|
#e2eServingLagTracker = new E2EServingLagTracker();
|
|
96
126
|
#expiredQueriesTimer = 0;
|
|
97
127
|
#authMaintenanceTimer = 0;
|
|
98
128
|
#setTimeout;
|
|
129
|
+
#now;
|
|
99
130
|
#customQueryTransformer;
|
|
100
131
|
#queryReplacements = /* @__PURE__ */ new Map();
|
|
101
132
|
#activeClients = getOrCreateUpDownCounter("sync", "active-clients", "Number of active sync clients");
|
|
@@ -122,10 +153,64 @@ var ViewSyncerService = class {
|
|
|
122
153
|
#pipelineResets = getOrCreateCounter("sync", "pipeline-resets", "Number of pipeline resets");
|
|
123
154
|
#rowSetSignatureDrifts = getOrCreateCounter("sync", "query.row-set-signature-drifts", "Number of times re-hydration of an unchanged query produced a different row-set signature than what is stored in the CVR (forcing a configVersion bump and full re-execution). Expected to be near-zero in steady state; persistent non-zero values indicate non-deterministic query execution (e.g. Cap operator picking different N-row subsets).");
|
|
124
155
|
#sameHashRehydrationVersionBumps = getOrCreateCounter("sync", "query.same-hash-rehydrations-forced-bump", "Number of times query-set reconciliation forced a configVersion bump for already-gotten same-transformation-hash query rehydration because trackQueries would not otherwise bump. Expected to be near-zero; non-zero values indicate pipeline/CVR row-set drift reached query-set reconciliation.");
|
|
156
|
+
#hydrationBudgetExhaustions = getOrCreateCounter("sync", "hydration_budget_exhaustions", {
|
|
157
|
+
description: "Number of hydration passes that exhaust their budget.",
|
|
158
|
+
unit: "{pass}"
|
|
159
|
+
});
|
|
160
|
+
#hydrationBudgetEvictions = getOrCreateCounter("sync", "hydration_budget_evictions", {
|
|
161
|
+
description: "Number of inactive queries removed after hydration budget exhaustion.",
|
|
162
|
+
unit: "{query}"
|
|
163
|
+
});
|
|
164
|
+
#hydrationBudgetElapsed = getOrCreateValueHistogram("sync", "hydration_budget_elapsed", {
|
|
165
|
+
description: "Elapsed milliseconds when optional query hydration stopped.",
|
|
166
|
+
unit: "ms",
|
|
167
|
+
bucketBoundaries: [
|
|
168
|
+
1,
|
|
169
|
+
2,
|
|
170
|
+
5,
|
|
171
|
+
10,
|
|
172
|
+
20,
|
|
173
|
+
50,
|
|
174
|
+
100,
|
|
175
|
+
200,
|
|
176
|
+
500,
|
|
177
|
+
1e3,
|
|
178
|
+
5e3
|
|
179
|
+
]
|
|
180
|
+
});
|
|
181
|
+
#hydrationBudgetOvershoot = getOrCreateValueHistogram("sync", "hydration_budget_overshoot", {
|
|
182
|
+
description: "Milliseconds elapsed beyond the configured hydration budget.",
|
|
183
|
+
unit: "ms",
|
|
184
|
+
bucketBoundaries: [
|
|
185
|
+
0,
|
|
186
|
+
1,
|
|
187
|
+
2,
|
|
188
|
+
5,
|
|
189
|
+
10,
|
|
190
|
+
20,
|
|
191
|
+
50,
|
|
192
|
+
100,
|
|
193
|
+
200,
|
|
194
|
+
500,
|
|
195
|
+
1e3
|
|
196
|
+
]
|
|
197
|
+
});
|
|
198
|
+
#queryEvictions = getOrCreateCounter("sync", "query_evictions", {
|
|
199
|
+
description: "Number of queries evicted from the CVR ahead of their removal by the client, grouped by reason. Inactive queries are evicted by ttl and hydration-budget; hydration-timeout and hydration-circuit-breaker evict active queries as well.",
|
|
200
|
+
unit: "{query}"
|
|
201
|
+
});
|
|
202
|
+
#hydrationTimeouts = getOrCreateCounter("sync", "hydration_timeouts", {
|
|
203
|
+
description: "Number of query hydrations aborted for exceeding the query hydration timeout.",
|
|
204
|
+
unit: "{query}"
|
|
205
|
+
});
|
|
206
|
+
#hydrationCircuitBreakerRejections = getOrCreateCounter("sync", "hydration_circuit_breaker_rejections", {
|
|
207
|
+
description: "Number of queries rejected without hydration because their hydration circuit breaker was open.",
|
|
208
|
+
unit: "{query}"
|
|
209
|
+
});
|
|
125
210
|
#inspectorDelegate;
|
|
126
211
|
#config;
|
|
127
212
|
#runPriorityOp;
|
|
128
|
-
constructor(config, lc, shard, taskID, clientGroupID, cvrDb, pipelineDriver, versionChanges, drainCoordinator, slowHydrateThreshold, inspectorDelegate, connContextManager, customQueryTransformer, runPriorityOp, keepaliveMs = DEFAULT_KEEPALIVE_MS, setTimeoutFn = setTimeout.bind(globalThis)) {
|
|
213
|
+
constructor(config, lc, shard, taskID, clientGroupID, cvrDb, pipelineDriver, versionChanges, drainCoordinator, slowHydrateThreshold, inspectorDelegate, connContextManager, customQueryTransformer, runPriorityOp, keepaliveMs = DEFAULT_KEEPALIVE_MS, setTimeoutFn = setTimeout.bind(globalThis), now = performance.now.bind(performance)) {
|
|
129
214
|
this.#config = config;
|
|
130
215
|
this.id = clientGroupID;
|
|
131
216
|
this.connContextManager = connContextManager;
|
|
@@ -140,6 +225,8 @@ var ViewSyncerService = class {
|
|
|
140
225
|
this.#customQueryTransformer = customQueryTransformer;
|
|
141
226
|
this.#cvrStore = new CVRStore(lc, cvrDb, shard, taskID, clientGroupID, () => this.#stateChanges.cancel());
|
|
142
227
|
this.#setTimeout = setTimeoutFn;
|
|
228
|
+
this.#now = now;
|
|
229
|
+
this.#hydrationCircuitBreaker = new HydrationCircuitBreaker(config.viewSyncerQueryHydrationTimeoutMs ?? 0, void 0, now);
|
|
143
230
|
this.#runPriorityOp = runPriorityOp;
|
|
144
231
|
this.keepalive();
|
|
145
232
|
}
|
|
@@ -166,11 +253,13 @@ var ViewSyncerService = class {
|
|
|
166
253
|
this.#stateChanges.cancel();
|
|
167
254
|
return;
|
|
168
255
|
}
|
|
256
|
+
let reloaded = false;
|
|
169
257
|
if (!this.#cvr) {
|
|
170
258
|
this.#lc.debug?.("loading cvr");
|
|
171
259
|
this.#cvr = await this.#runPriorityOp(lc, "loading cvr", () => this.#cvrStore.load(lc, this.#lastConnectTime));
|
|
172
260
|
this.#ttlClock = this.#cvr.ttlClock;
|
|
173
261
|
this.#ttlClockBase = Date.now();
|
|
262
|
+
reloaded = true;
|
|
174
263
|
} else {
|
|
175
264
|
const now = Date.now();
|
|
176
265
|
this.#cvr = {
|
|
@@ -179,6 +268,10 @@ var ViewSyncerService = class {
|
|
|
179
268
|
};
|
|
180
269
|
}
|
|
181
270
|
try {
|
|
271
|
+
if (reloaded && this.#resetPipelinesIfBehindCVR(lc, this.#cvr)) {
|
|
272
|
+
const connCtx = this.connContextManager.getBackgroundConnectionContext();
|
|
273
|
+
if (connCtx) await this.#maybeHydratePipelines(lc, this.#cvr, connCtx);
|
|
274
|
+
}
|
|
182
275
|
await fn(lc, this.#cvr);
|
|
183
276
|
} catch (e) {
|
|
184
277
|
this.#cvr = void 0;
|
|
@@ -188,11 +281,47 @@ var ViewSyncerService = class {
|
|
|
188
281
|
}
|
|
189
282
|
});
|
|
190
283
|
}
|
|
284
|
+
/**
|
|
285
|
+
* The CVR is reloaded after an error clears the cached copy. By then another
|
|
286
|
+
* view-syncer may have taken over the client group and flushed the CVR at a
|
|
287
|
+
* version ahead of this instance's hydrated pipelines (e.g. its replica was
|
|
288
|
+
* further ahead). The pipelines can no longer be diffed against the CVR, so
|
|
289
|
+
* reset them and let `#maybeHydratePipelines` rehydrate once the replica has
|
|
290
|
+
* caught up to the CVR.
|
|
291
|
+
*
|
|
292
|
+
* A CVR behind the pipelines is expected (advancements that do not change
|
|
293
|
+
* the CVR are not flushed) and is handled by the normal update path.
|
|
294
|
+
*
|
|
295
|
+
* Returns whether the pipelines were reset.
|
|
296
|
+
*
|
|
297
|
+
* Must be called from within the #lock.
|
|
298
|
+
*/
|
|
299
|
+
#resetPipelinesIfBehindCVR(lc, cvr) {
|
|
300
|
+
if (!this.#pipelinesHydrated) return false;
|
|
301
|
+
const pipelineVersion = this.#pipelines.currentVersion();
|
|
302
|
+
if (pipelineVersion >= cvr.version.stateVersion) return false;
|
|
303
|
+
lc.info?.(`resetting pipelines: pipelines@${pipelineVersion} are behind reloaded cvr@${versionString(cvr.version)}`);
|
|
304
|
+
this.#pipelineResets.add(1, { reason: "behind-cvr" });
|
|
305
|
+
this.#pipelinesHydrated = false;
|
|
306
|
+
this.connContextManager.setSharedRetransformReady(false);
|
|
307
|
+
this.#pipelines.reset(must(cvr.clientSchema, "cvr.clientSchema missing after initialization"));
|
|
308
|
+
return true;
|
|
309
|
+
}
|
|
191
310
|
readyState() {
|
|
192
|
-
return Promise
|
|
311
|
+
return new Promise((resolve, reject) => {
|
|
312
|
+
const unsubscribe = this.#drainCoordinator.onDraining(() => resolve("draining"));
|
|
313
|
+
this.#initialized.promise.then((state) => {
|
|
314
|
+
unsubscribe();
|
|
315
|
+
resolve(state);
|
|
316
|
+
}, (err) => {
|
|
317
|
+
unsubscribe();
|
|
318
|
+
reject(err);
|
|
319
|
+
});
|
|
320
|
+
});
|
|
193
321
|
}
|
|
194
322
|
async run() {
|
|
195
323
|
try {
|
|
324
|
+
this.#scheduleShutdown(this.#keepaliveMs);
|
|
196
325
|
if (await this.readyState() === "draining") {
|
|
197
326
|
this.#lc.debug?.(`draining view-syncer ${this.id} before running`);
|
|
198
327
|
this.stop();
|
|
@@ -213,26 +342,29 @@ var ViewSyncerService = class {
|
|
|
213
342
|
lc.info?.(`resetting CVR: ${message}`);
|
|
214
343
|
throw new ClientNotFoundError(message);
|
|
215
344
|
}
|
|
216
|
-
|
|
345
|
+
let previousQueries;
|
|
346
|
+
if (this.#pipelinesHydrated) {
|
|
217
347
|
const result = await this.#advancePipelines(lc, cvr);
|
|
218
348
|
if (result === "success") return;
|
|
219
349
|
lc.info?.(`resetting pipelines: ${result.message}`);
|
|
220
350
|
this.#pipelineResets.add(1, { reason: result.reason });
|
|
351
|
+
switch (result.reason) {
|
|
352
|
+
case "advancement-timeout":
|
|
353
|
+
case "scalar-subquery":
|
|
354
|
+
case "truncation":
|
|
355
|
+
case "schema-change":
|
|
356
|
+
if (!Object.values(cvr.queries).some((q) => q.type === "client")) previousQueries = new Map(this.#pipelines.queries());
|
|
357
|
+
break;
|
|
358
|
+
case "permissions-change": break;
|
|
359
|
+
default: unreachable(result.reason);
|
|
360
|
+
}
|
|
221
361
|
this.#pipelines.reset(clientSchema);
|
|
222
|
-
this.#
|
|
362
|
+
this.#pipelinesHydrated = false;
|
|
223
363
|
this.connContextManager.setSharedRetransformReady(false);
|
|
224
364
|
}
|
|
225
|
-
const
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
lc.debug?.(`replica@${version} is behind cvr@${cvrVer}`);
|
|
229
|
-
return;
|
|
230
|
-
}
|
|
231
|
-
lc.info?.(`init pipelines@${version} (cvr@${cvrVer})`);
|
|
232
|
-
const driftedQueryIDs = await this.#hydrateUnchangedQueries(lc, cvr);
|
|
233
|
-
await this.#syncQueryPipelineSet(lc, cvr, "missing", void 0, driftedQueryIDs);
|
|
234
|
-
this.#pipelinesSynced = true;
|
|
235
|
-
this.connContextManager.setSharedRetransformReady(true);
|
|
365
|
+
const backgroundConnCtx = this.connContextManager.getBackgroundConnectionContext();
|
|
366
|
+
if (backgroundConnCtx) await this.#maybeHydratePipelines(lc, cvr, backgroundConnCtx, previousQueries);
|
|
367
|
+
else lc.info?.("No validated background connection; deferring pipeline init");
|
|
236
368
|
});
|
|
237
369
|
}
|
|
238
370
|
if (this.#drainCoordinator.shouldDrain()) this.#drainCoordinator.drainNextIn(this.#totalHydrationTimeMs());
|
|
@@ -246,11 +378,66 @@ var ViewSyncerService = class {
|
|
|
246
378
|
this.#stopped.resolve();
|
|
247
379
|
}
|
|
248
380
|
}
|
|
381
|
+
/**
|
|
382
|
+
* Ensures that query pipelines are hydrated and ready for steady-state
|
|
383
|
+
* operation.
|
|
384
|
+
*
|
|
385
|
+
* Preconditions:
|
|
386
|
+
* 1. Must be called from within the `#lock`.
|
|
387
|
+
* 2. The caller must provide an active, validated `ConnectionContext` for
|
|
388
|
+
* evaluating custom query transforms and permissions.
|
|
389
|
+
*
|
|
390
|
+
* Readiness prerequisites:
|
|
391
|
+
* - The underlying `QueryPipelineDriver` must be initialized with the schema
|
|
392
|
+
* (i.e. `this.#pipelines.initialized()` is true).
|
|
393
|
+
* - The SQLite replica must have caught up to at least the CVR's
|
|
394
|
+
* `stateVersion` (`version >= cvr.version.stateVersion`).
|
|
395
|
+
*
|
|
396
|
+
* If either prerequisite is not met, this method returns early as a no-op,
|
|
397
|
+
* waiting for the replica to catch up or the driver to initialize.
|
|
398
|
+
*
|
|
399
|
+
* Once ready:
|
|
400
|
+
* - Hydrates unchanged queries from the CVR snapshot without full row diffing.
|
|
401
|
+
* - Syncs missing, errored, or drifted queries via `#syncQueryPipelineSet`.
|
|
402
|
+
* - Sets `#pipelinesHydrated = true` and enables shared retransformations.
|
|
403
|
+
*/
|
|
404
|
+
async #maybeHydratePipelines(lc, cvr, connCtx, previousQueries) {
|
|
405
|
+
if (!this.#pipelines.initialized()) return;
|
|
406
|
+
let version;
|
|
407
|
+
try {
|
|
408
|
+
version = this.#pipelines.advanceWithoutDiff();
|
|
409
|
+
} catch (e) {
|
|
410
|
+
if (!(e instanceof ResetPipelinesSignal)) throw e;
|
|
411
|
+
lc.info?.(`resetting pipelines: ${e.message}`);
|
|
412
|
+
this.#pipelineResets.add(1, { reason: e.reason });
|
|
413
|
+
this.#pipelines.reset(must(cvr.clientSchema, "cvr.clientSchema missing after initialization"));
|
|
414
|
+
version = this.#pipelines.currentVersion();
|
|
415
|
+
}
|
|
416
|
+
const cvrVer = versionString(cvr.version);
|
|
417
|
+
if (version < cvr.version.stateVersion) {
|
|
418
|
+
lc.debug?.(`replica@${version} is behind cvr@${cvrVer}`);
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
lc.info?.(`init pipelines@${version} (cvr@${cvrVer})`);
|
|
422
|
+
const hydrationBudget = new HydrationBudget(this.#config.viewSyncerHydrationBudgetMs ?? 0, this.#now);
|
|
423
|
+
const hydrationPassStats = {
|
|
424
|
+
activeHydratedQueries: 0,
|
|
425
|
+
inactiveHydratedQueries: 0
|
|
426
|
+
};
|
|
427
|
+
const driftedQueryIDs = await this.#hydrateUnchangedQueries(lc, cvr, connCtx, hydrationPassStats, hydrationBudget, previousQueries);
|
|
428
|
+
await this.#syncQueryPipelineSet(lc, cvr, "missing", connCtx, driftedQueryIDs, hydrationBudget, hydrationPassStats, previousQueries);
|
|
429
|
+
this.#pipelinesHydrated = true;
|
|
430
|
+
this.connContextManager.setSharedRetransformReady(true);
|
|
431
|
+
}
|
|
249
432
|
#removeExpiredQueries = async (lc, cvr) => {
|
|
250
433
|
if (hasExpiredQueries(cvr)) {
|
|
251
434
|
lc = lc.withContext("method", "#removeExpiredQueries");
|
|
252
435
|
lc.debug?.("Queries have expired");
|
|
253
|
-
if (this.#
|
|
436
|
+
if (this.#pipelinesHydrated) {
|
|
437
|
+
const connCtx = this.connContextManager.getBackgroundConnectionContext();
|
|
438
|
+
if (connCtx) await this.#syncQueryPipelineSet(lc, cvr, "missing", connCtx);
|
|
439
|
+
else lc.info?.("No validated background connection to remove expired queries; deferring");
|
|
440
|
+
}
|
|
254
441
|
}
|
|
255
442
|
this.#scheduleExpireEviction(lc, cvr);
|
|
256
443
|
};
|
|
@@ -332,7 +519,14 @@ var ViewSyncerService = class {
|
|
|
332
519
|
return true;
|
|
333
520
|
}
|
|
334
521
|
#shutdownTimer = null;
|
|
522
|
+
#stopShutdownTimer() {
|
|
523
|
+
if (this.#shutdownTimer !== null) {
|
|
524
|
+
clearTimeout(this.#shutdownTimer);
|
|
525
|
+
this.#shutdownTimer = null;
|
|
526
|
+
}
|
|
527
|
+
}
|
|
335
528
|
#scheduleShutdown(delayMs = 0) {
|
|
529
|
+
if (this.#shuttingDown) return;
|
|
336
530
|
this.#shutdownTimer ??= this.#setTimeout(() => {
|
|
337
531
|
this.#shutdownTimer = null;
|
|
338
532
|
this.#runInLockWithCVR(() => {}).catch((e) => this.#stateChanges.fail(e));
|
|
@@ -379,6 +573,7 @@ var ViewSyncerService = class {
|
|
|
379
573
|
*/
|
|
380
574
|
#scheduleAuthMaintenance(lc) {
|
|
381
575
|
this.#stopAuthMaintenanceTimer();
|
|
576
|
+
if (this.#shuttingDown) return;
|
|
382
577
|
const plan = this.connContextManager.planMaintenance();
|
|
383
578
|
if (plan.earliestDeadlineAt === void 0) {
|
|
384
579
|
lc.debug?.("No auth maintenance wakeup scheduled");
|
|
@@ -466,7 +661,7 @@ var ViewSyncerService = class {
|
|
|
466
661
|
}
|
|
467
662
|
lc.debug?.("Auth changed, re-validating and re-transforming queries");
|
|
468
663
|
const connCtx = this.connContextManager.mustGetConnectionContext(selector);
|
|
469
|
-
if (!this.#
|
|
664
|
+
if (!this.#pipelinesHydrated) {
|
|
470
665
|
if (!await this.#validateConnection(connCtx)) return;
|
|
471
666
|
}
|
|
472
667
|
return await this.#handleConfigUpdate(lc, clientID, {}, cvr, "all", void 0, connCtx);
|
|
@@ -484,17 +679,41 @@ var ViewSyncerService = class {
|
|
|
484
679
|
this.#ttlClockBase = now;
|
|
485
680
|
return ttlClock;
|
|
486
681
|
}
|
|
487
|
-
|
|
682
|
+
/**
|
|
683
|
+
* @param patchesPoked Whether patches computed against the updater's CVR
|
|
684
|
+
* have already been poked to clients. If so, the CVR is checked to be
|
|
685
|
+
* current even when the flush has nothing to write: another
|
|
686
|
+
* view-syncer may have already committed identical rows at a newer
|
|
687
|
+
* version, which would otherwise leave this one poking from a stale
|
|
688
|
+
* CVR whose version it cannot advance.
|
|
689
|
+
*/
|
|
690
|
+
#flushUpdater(lc, updater, patchesPoked = false) {
|
|
488
691
|
return startAsyncSpan(tracer, "vs.#flushUpdater", () => this.#runPriorityOp(lc, "flushing cvr", async () => {
|
|
489
692
|
const now = Date.now();
|
|
490
693
|
const ttlClock = this.#getTTLClock(now);
|
|
491
|
-
const { cvr, flushed } = await updater.flush(lc, this.#lastConnectTime, now, ttlClock);
|
|
694
|
+
const { cvr, flushed } = await updater.flush(lc, this.#lastConnectTime, now, ttlClock, patchesPoked);
|
|
492
695
|
if (flushed) this.#startTTLClockInterval(lc);
|
|
493
696
|
return cvr;
|
|
494
697
|
}));
|
|
495
698
|
}
|
|
699
|
+
/**
|
|
700
|
+
* Flushes an updater whose changes have already been poked. If the flush
|
|
701
|
+
* fails (e.g. the CVR was concurrently modified), the poke is cancelled
|
|
702
|
+
* before the error propagates. The error may only fail the client that
|
|
703
|
+
* initiated the operation, and any other client left mid-poke would fail
|
|
704
|
+
* its next pokeStart.
|
|
705
|
+
*/
|
|
706
|
+
async #flushPoked(lc, updater, pokers) {
|
|
707
|
+
try {
|
|
708
|
+
return await this.#flushUpdater(lc, updater, pokers.patchesSent);
|
|
709
|
+
} catch (e) {
|
|
710
|
+
await pokers.cancel();
|
|
711
|
+
throw e;
|
|
712
|
+
}
|
|
713
|
+
}
|
|
496
714
|
#startTTLClockInterval(lc) {
|
|
497
715
|
this.#stopTTLClockInterval();
|
|
716
|
+
if (this.#shuttingDown) return;
|
|
498
717
|
this.#ttlClockInterval = this.#setTimeout(() => {
|
|
499
718
|
this.#updateTTLClockInCVRWithoutLock(lc);
|
|
500
719
|
this.#startTTLClockInterval(lc);
|
|
@@ -523,12 +742,13 @@ var ViewSyncerService = class {
|
|
|
523
742
|
if (cmpVersions(cvr.version, this.#cvr.version) < 0) {
|
|
524
743
|
const newCVR = this.#cvr;
|
|
525
744
|
await startAsyncSpan(tracer, "vs.#updateCVRConfig.pokeClients", async () => {
|
|
526
|
-
const pokers = startPoke(this.#getClients(cvr.version), newCVR.version);
|
|
745
|
+
const pokers = startPoke(lc, this.#getClients(cvr.version), newCVR.version);
|
|
527
746
|
for (const patch of patches) await pokers.addPatch(patch);
|
|
528
747
|
await pokers.end(newCVR.version);
|
|
529
748
|
});
|
|
530
749
|
}
|
|
531
|
-
if (this.#
|
|
750
|
+
if (!this.#pipelinesHydrated) await this.#maybeHydratePipelines(lc, this.#cvr, connCtx);
|
|
751
|
+
else await this.#syncQueryPipelineSet(lc, this.#cvr, customQueryTransformMode, connCtx);
|
|
532
752
|
return this.#cvr;
|
|
533
753
|
}
|
|
534
754
|
/**
|
|
@@ -624,6 +844,7 @@ var ViewSyncerService = class {
|
|
|
624
844
|
#scheduleExpireEviction(lc, cvr) {
|
|
625
845
|
const { ttlClock } = cvr;
|
|
626
846
|
this.#stopExpireTimer();
|
|
847
|
+
if (this.#shuttingDown) return;
|
|
627
848
|
const next = nextEvictionTime(cvr);
|
|
628
849
|
if (next === void 0) {
|
|
629
850
|
lc.debug?.("no inactive queries with ttl");
|
|
@@ -651,7 +872,7 @@ var ViewSyncerService = class {
|
|
|
651
872
|
*
|
|
652
873
|
* This must be called from within the #lock.
|
|
653
874
|
*/
|
|
654
|
-
async #hydrateUnchangedQueries(lc, cvr) {
|
|
875
|
+
async #hydrateUnchangedQueries(lc, cvr, connCtx, hydrationPassStats, hydrationBudget, previousQueries) {
|
|
655
876
|
assert(this.#pipelines.initialized(), "pipelines must be initialized");
|
|
656
877
|
const dbVersion = this.#pipelines.currentVersion();
|
|
657
878
|
const cvrVersion = cvr.version;
|
|
@@ -660,33 +881,34 @@ var ViewSyncerService = class {
|
|
|
660
881
|
return /* @__PURE__ */ new Set();
|
|
661
882
|
}
|
|
662
883
|
const gotQueries = Object.entries(cvr.queries).filter(([_, state]) => state.transformationHash !== void 0);
|
|
884
|
+
const { required: requiredGotQueries } = classifyQueriesForHydration(gotQueries.map(([, query]) => query));
|
|
663
885
|
const customQueries = /* @__PURE__ */ new Map();
|
|
664
886
|
const otherQueries = [];
|
|
665
|
-
|
|
666
|
-
for (const [, query] of gotQueries) {
|
|
667
|
-
if (query.type !== "internal" && Object.values(query.clientState).every(({ inactivatedAt }) => inactivatedAt !== void 0)) {
|
|
668
|
-
inactivatedCount++;
|
|
669
|
-
continue;
|
|
670
|
-
}
|
|
671
|
-
if (query.type === "custom") customQueries.set(query.id, query);
|
|
672
|
-
else otherQueries.push(query);
|
|
673
|
-
}
|
|
887
|
+
const inactivatedCount = gotQueries.length - requiredGotQueries.length;
|
|
674
888
|
const transformedQueries = [];
|
|
889
|
+
for (const query of requiredGotQueries) if (query.type === "custom") {
|
|
890
|
+
const previous = previousQueries?.get(query.id);
|
|
891
|
+
if (previous && previous.transformationHash === query.transformationHash) transformedQueries.push({
|
|
892
|
+
id: query.id,
|
|
893
|
+
transformationHash: previous.transformationHash,
|
|
894
|
+
transformedAst: previous.originalAst ?? previous.transformedAst
|
|
895
|
+
});
|
|
896
|
+
else customQueries.set(query.id, query);
|
|
897
|
+
} else otherQueries.push(query);
|
|
675
898
|
let customErrorCount = 0;
|
|
676
899
|
let customHashMismatchCount = 0;
|
|
677
900
|
let otherHashMismatchCount = 0;
|
|
678
901
|
if (customQueries.size > 0 && !this.#customQueryTransformer) lc.warn?.("Custom/named queries were requested but no `ZERO_QUERY_URL` is configured for Zero Cache.");
|
|
679
|
-
const backgroundContext = this.connContextManager.mustGetBackgroundConnectionContext();
|
|
680
902
|
const customQueryTransformer = this.#customQueryTransformer;
|
|
681
903
|
if (customQueryTransformer && customQueries.size > 0) {
|
|
682
|
-
const transformedCustomQueries = await this.#runPriorityOp(lc, "#hydrateUnchangedQueries transforming custom queries", () => customQueryTransformer.transform(
|
|
683
|
-
if (transformedCustomQueries.kind === "success" && !transformedCustomQueries.cached) this.connContextManager.validateConnection(
|
|
904
|
+
const transformedCustomQueries = await hydrationBudget.excluding(() => this.#runPriorityOp(lc, "#hydrateUnchangedQueries transforming custom queries", () => customQueryTransformer.transform(connCtx, customQueries.values())));
|
|
905
|
+
if (transformedCustomQueries.kind === "success" && !transformedCustomQueries.cached) this.connContextManager.validateConnection(connCtx, connCtx.revision, transformedCustomQueries.validation);
|
|
684
906
|
if (Array.isArray(transformedCustomQueries.result)) for (const q of transformedCustomQueries.result) if ("error" in q) customErrorCount++;
|
|
685
907
|
else if (q.transformationHash !== customQueries.get(q.id)?.transformationHash) customHashMismatchCount++;
|
|
686
908
|
else transformedQueries.push(q);
|
|
687
909
|
}
|
|
688
910
|
for (const q of otherQueries) {
|
|
689
|
-
const transformed = transformAndHashQuery(lc, q.id, q.ast, must(this.#pipelines.currentPermissions()).permissions ?? { tables: {} },
|
|
911
|
+
const transformed = transformAndHashQuery(lc, q.id, q.ast, must(this.#pipelines.currentPermissions()).permissions ?? { tables: {} }, connCtx.auth?.type === "jwt" ? connCtx.auth : void 0, q.type === "internal");
|
|
690
912
|
if (transformed.transformationHash === q.transformationHash) transformedQueries.push(transformed);
|
|
691
913
|
else otherHashMismatchCount++;
|
|
692
914
|
}
|
|
@@ -699,6 +921,10 @@ var ViewSyncerService = class {
|
|
|
699
921
|
for (const { id: queryID, transformationHash, transformedAst } of transformedQueries) {
|
|
700
922
|
const query = cvr.queries[queryID];
|
|
701
923
|
const queryName = query.type === "custom" ? query.name : void 0;
|
|
924
|
+
if (query.type !== "internal" && this.#hydrationCircuitBreaker.isOpen(transformationHash)) {
|
|
925
|
+
lc.info?.(`skipping hydration of ${queryID}: hydration circuit breaker open`);
|
|
926
|
+
continue;
|
|
927
|
+
}
|
|
702
928
|
const covered = queryCoveringIndex ? this.#findQueryCoverageShadowHit(queryCoveringIndex, queryID, transformationHash, transformedAst, queryName) : void 0;
|
|
703
929
|
totalHydratedQueries++;
|
|
704
930
|
if (covered) {
|
|
@@ -707,20 +933,43 @@ var ViewSyncerService = class {
|
|
|
707
933
|
}
|
|
708
934
|
const timer = new TimeSliceTimer(lc);
|
|
709
935
|
let count = 0;
|
|
936
|
+
let timedOut = false;
|
|
710
937
|
await startAsyncSpan(tracer, "vs.#hydrateUnchangedQueries.addQuery", async (span) => {
|
|
711
938
|
span.setAttribute("queryHash", queryID);
|
|
712
939
|
span.setAttribute("transformationHash", transformationHash);
|
|
713
940
|
span.setAttribute("table", transformedAst.table);
|
|
714
941
|
if (queryName !== void 0) span.setAttribute("queryName", queryName);
|
|
715
|
-
for (const change of this.#pipelines.addQuery(transformationHash, queryID, transformedAst, await timer.start(), queryName, "unchanged-query-rehydrate")) if (change === "yield")
|
|
716
|
-
|
|
942
|
+
for (const change of this.#pipelines.addQuery(transformationHash, queryID, transformedAst, await timer.start(), queryName, "unchanged-query-rehydrate")) if (change === "yield") {
|
|
943
|
+
if (query.type !== "internal" && this.#hydrationCircuitBreaker.exceeded(timer.totalElapsed())) {
|
|
944
|
+
timedOut = true;
|
|
945
|
+
await timer.yieldProcess("yield in hydrateUnchangedQueries");
|
|
946
|
+
break;
|
|
947
|
+
}
|
|
948
|
+
await timer.yieldProcess("yield in hydrateUnchangedQueries");
|
|
949
|
+
} else count++;
|
|
717
950
|
});
|
|
718
951
|
const elapsed = timer.totalElapsed();
|
|
952
|
+
if (timedOut) {
|
|
953
|
+
this.#recordHydrationTimeout(lc, {
|
|
954
|
+
id: queryID,
|
|
955
|
+
ast: transformedAst,
|
|
956
|
+
transformationHash,
|
|
957
|
+
name: queryName
|
|
958
|
+
}, elapsed, count);
|
|
959
|
+
continue;
|
|
960
|
+
}
|
|
961
|
+
hydrationPassStats.activeHydratedQueries++;
|
|
719
962
|
this.#hydrations.add(1);
|
|
720
963
|
this.#hydrationTime.recordMs(elapsed);
|
|
721
|
-
this.#addQueryMaterializationServerMetric(
|
|
722
|
-
this.#inspectorDelegate.addQuery(
|
|
964
|
+
this.#addQueryMaterializationServerMetric(queryID, elapsed);
|
|
965
|
+
this.#inspectorDelegate.addQuery(queryID, transformedAst);
|
|
723
966
|
lc.debug?.(`hydrated ${count} rows for ${queryID} (${elapsed} ms)`);
|
|
967
|
+
if (elapsed > this.#slowHydrateThreshold) this.#logSlowHydration(lc, {
|
|
968
|
+
id: queryID,
|
|
969
|
+
ast: transformedAst,
|
|
970
|
+
transformationHash,
|
|
971
|
+
name: queryName
|
|
972
|
+
}, elapsed);
|
|
724
973
|
let drifted = false;
|
|
725
974
|
const storedSigHex = cvr.queries[queryID]?.rowSetSignature;
|
|
726
975
|
if (storedSigHex !== void 0 && storedSigHex !== null) {
|
|
@@ -780,11 +1029,7 @@ var ViewSyncerService = class {
|
|
|
780
1029
|
return;
|
|
781
1030
|
}
|
|
782
1031
|
const appErrorGroups = /* @__PURE__ */ new Map();
|
|
783
|
-
for (const err of errorOrErrors) for (const clientId of getAffectedClientIDs([err.id]))
|
|
784
|
-
const group = appErrorGroups.get(clientId) ?? [];
|
|
785
|
-
group.push(err);
|
|
786
|
-
appErrorGroups.set(clientId, group);
|
|
787
|
-
}
|
|
1032
|
+
for (const err of errorOrErrors) for (const clientId of getAffectedClientIDs([err.id])) getOrInsertComputed(appErrorGroups, clientId, newArray).push(err);
|
|
788
1033
|
for (const [clientId, errors] of appErrorGroups) this.#clients.get(clientId)?.sendQueryTransformApplicationErrors(errors);
|
|
789
1034
|
}
|
|
790
1035
|
#addQueryMaterializationServerMetric(queryID, elapsed) {
|
|
@@ -820,7 +1065,10 @@ var ViewSyncerService = class {
|
|
|
820
1065
|
*
|
|
821
1066
|
* This must be called from within the #lock.
|
|
822
1067
|
*/
|
|
823
|
-
#syncQueryPipelineSet(lc, cvr, customQueryTransformMode, connCtx, driftedQueryIDs = /* @__PURE__ */ new Set()) {
|
|
1068
|
+
#syncQueryPipelineSet(lc, cvr, customQueryTransformMode, connCtx, driftedQueryIDs = /* @__PURE__ */ new Set(), hydrationBudget = new HydrationBudget(this.#config.viewSyncerHydrationBudgetMs ?? 0, this.#now), hydrationPassStats = {
|
|
1069
|
+
activeHydratedQueries: 0,
|
|
1070
|
+
inactiveHydratedQueries: 0
|
|
1071
|
+
}, previousQueries) {
|
|
824
1072
|
return startAsyncSpan(tracer, "vs.#syncQueryPipelineSet", async (span) => {
|
|
825
1073
|
const start = performance.now();
|
|
826
1074
|
span.setAttribute("clientGroupID", this.id);
|
|
@@ -829,38 +1077,45 @@ var ViewSyncerService = class {
|
|
|
829
1077
|
const now = Date.now();
|
|
830
1078
|
const ttlClock = this.#getTTLClock(now);
|
|
831
1079
|
const cvrQueryEntires = Object.entries(cvr.queries);
|
|
832
|
-
const customQueries = /* @__PURE__ */ new Map();
|
|
833
|
-
const otherQueries = [];
|
|
834
1080
|
const transformedQueries = [];
|
|
835
|
-
const
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
});
|
|
843
|
-
for (const { id, query: origQuery } of otherQueries) {
|
|
844
|
-
assert(id === origQuery.id, "query id mismatch");
|
|
845
|
-
const transformed = transformAndHashQuery(lc, origQuery.id, origQuery.ast, must(this.#pipelines.currentPermissions()).permissions ?? { tables: {} }, resolvedConnCtx.auth?.type === "jwt" ? resolvedConnCtx.auth : void 0, origQuery.type === "internal");
|
|
846
|
-
transformedQueries.push({
|
|
847
|
-
id,
|
|
848
|
-
origQuery,
|
|
849
|
-
transformed
|
|
850
|
-
});
|
|
851
|
-
}
|
|
852
|
-
if (customQueries.size > 0 && !this.#customQueryTransformer) lc.warn?.("Custom/named queries were requested but no `ZERO_QUERY_URL` is configured for Zero Cache.");
|
|
853
|
-
let erroredQueryIDs;
|
|
854
|
-
const customQueriesToTransform = customQueryTransformMode === "all" ? [...customQueries.values()] : customQueryTransformMode && [...customQueries.values()].filter((q) => !this.#pipelines.queries().has(q.id));
|
|
1081
|
+
const naturallyExpiredQueryIDs = new Set(cvrQueryEntires.map(([, query]) => query).filter((query) => expired(ttlClock, query)).map((query) => query.id));
|
|
1082
|
+
if (naturallyExpiredQueryIDs.size > 0) this.#queryEvictions.add(naturallyExpiredQueryIDs.size, { reason: "ttl" });
|
|
1083
|
+
const hydrationCandidates = cvrQueryEntires.map(([, query]) => query).filter((query) => !naturallyExpiredQueryIDs.has(query.id));
|
|
1084
|
+
const { required, optional } = classifyQueriesForHydration(hydrationCandidates);
|
|
1085
|
+
const requiredQueryIDs = new Set(required.map((query) => query.id));
|
|
1086
|
+
const optionalToHydrate = hydrationBudget.limitMs === 0 ? optional : optional.filter((query) => query.patchVersion !== void 0);
|
|
1087
|
+
if (!this.#customQueryTransformer && hydrationCandidates.some((query) => query.type === "custom")) lc.warn?.("Custom/named queries were requested but no `ZERO_QUERY_URL` is configured for Zero Cache.");
|
|
855
1088
|
const customQueryTransformer = this.#customQueryTransformer;
|
|
856
|
-
|
|
1089
|
+
const erroredQueryIDs = [];
|
|
1090
|
+
let transformedCustomQueryCount = 0;
|
|
1091
|
+
const transformOtherQueries = (queries) => {
|
|
1092
|
+
for (const origQuery of queries) {
|
|
1093
|
+
if (origQuery.type === "custom") continue;
|
|
1094
|
+
const transformed = transformAndHashQuery(lc, origQuery.id, origQuery.ast, must(this.#pipelines.currentPermissions()).permissions ?? { tables: {} }, connCtx.auth?.type === "jwt" ? connCtx.auth : void 0, origQuery.type === "internal");
|
|
1095
|
+
transformedQueries.push({
|
|
1096
|
+
id: origQuery.id,
|
|
1097
|
+
origQuery,
|
|
1098
|
+
transformed
|
|
1099
|
+
});
|
|
1100
|
+
}
|
|
1101
|
+
};
|
|
1102
|
+
const shouldTransformCustomQuery = (query) => {
|
|
1103
|
+
if (customQueryTransformMode === "all") return true;
|
|
1104
|
+
if (this.#pipelines.queries().has(query.id)) return false;
|
|
1105
|
+
const previous = previousQueries?.get(query.id);
|
|
1106
|
+
if (previous && previous.transformationHash === query.transformationHash) return false;
|
|
1107
|
+
return true;
|
|
1108
|
+
};
|
|
1109
|
+
const transformCustomQueries = async (queries) => {
|
|
1110
|
+
if (!customQueryTransformer || queries.length === 0) return;
|
|
1111
|
+
transformedCustomQueryCount += queries.length;
|
|
857
1112
|
const transformStart = performance.now();
|
|
858
1113
|
let transformedCustomQueries;
|
|
859
1114
|
try {
|
|
860
|
-
transformedCustomQueries = await this.#runPriorityOp(lc, "#syncQueryPipelineSet transforming custom queries", () => customQueryTransformer.transform(
|
|
1115
|
+
transformedCustomQueries = await hydrationBudget.excluding(() => this.#runPriorityOp(lc, "#syncQueryPipelineSet transforming custom queries", () => customQueryTransformer.transform(connCtx, queries)));
|
|
861
1116
|
if (transformedCustomQueries.kind === "failed") throw new ProtocolErrorWithLevel(transformedCustomQueries.result, "warn");
|
|
862
1117
|
else {
|
|
863
|
-
if (!transformedCustomQueries.cached) this.connContextManager.validateConnection(
|
|
1118
|
+
if (!transformedCustomQueries.cached) this.connContextManager.validateConnection(connCtx, connCtx.revision, transformedCustomQueries.validation);
|
|
864
1119
|
this.#queryTransformations.add(1, { result: "success" });
|
|
865
1120
|
}
|
|
866
1121
|
} catch (e) {
|
|
@@ -871,8 +1126,9 @@ var ViewSyncerService = class {
|
|
|
871
1126
|
this.#queryTransformationTime.recordMs(transformDuration);
|
|
872
1127
|
}
|
|
873
1128
|
const successfullyTransformedCustomQueries = /* @__PURE__ */ new Map();
|
|
874
|
-
|
|
875
|
-
|
|
1129
|
+
const customQueryMap = new Map(queries.map((query) => [query.id, query]));
|
|
1130
|
+
erroredQueryIDs.push(...this.#processTransformedCustomQueries(lc, transformedCustomQueries.result, (q) => {
|
|
1131
|
+
const origQuery = customQueryMap.get(q.id);
|
|
876
1132
|
if (origQuery) {
|
|
877
1133
|
successfullyTransformedCustomQueries.set(q.id, q);
|
|
878
1134
|
transformedQueries.push({
|
|
@@ -881,7 +1137,7 @@ var ViewSyncerService = class {
|
|
|
881
1137
|
transformed: q
|
|
882
1138
|
});
|
|
883
1139
|
}
|
|
884
|
-
},
|
|
1140
|
+
}, customQueryMap));
|
|
885
1141
|
for (const [queryID, newTransform] of successfullyTransformedCustomQueries) {
|
|
886
1142
|
const existingTransformHash = cvr.queries[queryID]?.transformationHash;
|
|
887
1143
|
if (existingTransformHash) {
|
|
@@ -894,21 +1150,55 @@ var ViewSyncerService = class {
|
|
|
894
1150
|
} else this.#queryTransformationNoOps.add(1);
|
|
895
1151
|
}
|
|
896
1152
|
}
|
|
1153
|
+
};
|
|
1154
|
+
const queriesToTransform = [...required, ...optionalToHydrate];
|
|
1155
|
+
transformOtherQueries(queriesToTransform);
|
|
1156
|
+
if (customQueryTransformMode === "missing" && previousQueries) {
|
|
1157
|
+
for (const query of queriesToTransform) if (query.type === "custom" && !this.#pipelines.queries().has(query.id)) {
|
|
1158
|
+
const previous = previousQueries.get(query.id);
|
|
1159
|
+
if (previous && previous.transformationHash === query.transformationHash) {
|
|
1160
|
+
this.#queryTransformationNoOps.add(1);
|
|
1161
|
+
transformedQueries.push({
|
|
1162
|
+
id: query.id,
|
|
1163
|
+
origQuery: query,
|
|
1164
|
+
transformed: {
|
|
1165
|
+
id: query.id,
|
|
1166
|
+
transformationHash: previous.transformationHash,
|
|
1167
|
+
transformedAst: previous.originalAst ?? previous.transformedAst
|
|
1168
|
+
}
|
|
1169
|
+
});
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
897
1172
|
}
|
|
898
|
-
|
|
1173
|
+
await transformCustomQueries(queriesToTransform.filter((query) => query.type === "custom" && shouldTransformCustomQuery(query)));
|
|
1174
|
+
const circuitBrokenQueries = transformedQueries.filter(({ id, origQuery, transformed }) => origQuery.type !== "internal" && this.#pipelines.queries().get(id)?.transformationHash !== transformed.transformationHash && this.#hydrationCircuitBreaker.isOpen(transformed.transformationHash)).map(({ id, origQuery, transformed }) => ({
|
|
1175
|
+
id,
|
|
1176
|
+
transformationHash: transformed.transformationHash,
|
|
1177
|
+
name: origQuery.type === "custom" ? origQuery.name : void 0
|
|
1178
|
+
}));
|
|
1179
|
+
if (circuitBrokenQueries.length > 0) this.#rejectCircuitBrokenQueries(lc, cvr, circuitBrokenQueries);
|
|
1180
|
+
const removeQueriesQueryIds = new Set([
|
|
1181
|
+
...naturallyExpiredQueryIDs,
|
|
1182
|
+
...erroredQueryIDs,
|
|
1183
|
+
...circuitBrokenQueries.map(({ id }) => id)
|
|
1184
|
+
]);
|
|
899
1185
|
const addQueries = transformedQueries.map(({ id, origQuery, transformed }) => ({
|
|
900
1186
|
id,
|
|
901
1187
|
ast: transformed.transformedAst,
|
|
902
1188
|
transformationHash: transformed.transformationHash,
|
|
903
1189
|
name: origQuery.type === "custom" ? origQuery.name : void 0
|
|
904
1190
|
})).filter((q) => !removeQueriesQueryIds.has(q.id) && this.#pipelines.queries().get(q.id)?.transformationHash !== q.transformationHash);
|
|
905
|
-
|
|
1191
|
+
const hydrationOrder = new Map([...required, ...optional].map((query, index) => [query.id, index]));
|
|
1192
|
+
addQueries.sort((a, b) => must(hydrationOrder.get(a.id)) - must(hydrationOrder.get(b.id)));
|
|
1193
|
+
const requiredAddQueries = addQueries.filter((query) => requiredQueryIDs.has(query.id));
|
|
1194
|
+
const optionalAddQueries = addQueries.filter((query) => !requiredQueryIDs.has(query.id));
|
|
1195
|
+
lc.info?.(`syncQueryPipelineSet: ${cvrQueryEntires.length} CVR queries, ${transformedCustomQueryCount} custom re-transformed, ${erroredQueryIDs.length} errored, ${circuitBrokenQueries.length} circuit-broken, ${removeQueriesQueryIds.size} to remove, ${addQueries.length} to add`);
|
|
906
1196
|
for (const q of addQueries) {
|
|
907
1197
|
const orig = cvr.queries[q.id];
|
|
908
1198
|
lc.debug?.("ViewSyncer adding query", q.ast, "transformed from", orig.type === "custom" ? orig.name : orig.ast);
|
|
909
1199
|
}
|
|
910
1200
|
if (addQueries.length > 0 || removeQueriesQueryIds.size > 0) {
|
|
911
|
-
await this.#addAndRemoveQueries(lc, cvr,
|
|
1201
|
+
await this.#addAndRemoveQueries(lc, cvr, requiredAddQueries, optionalAddQueries, Array.from(removeQueriesQueryIds, (id) => ({ id })), hydrationBudget, hydrationPassStats, driftedQueryIDs);
|
|
912
1202
|
if (addQueries.length > 0) this.#viewSyncerHydration.recordMs(performance.now() - start);
|
|
913
1203
|
} else await this.#catchupClients(lc, cvr);
|
|
914
1204
|
});
|
|
@@ -941,8 +1231,128 @@ var ViewSyncerService = class {
|
|
|
941
1231
|
record.count++;
|
|
942
1232
|
if (record.count >= THRASH_THRESHOLD) this.#lc.warn?.(`Query thrashing detected for query ${queryID}. ${record.count} replacements in 60s. This may indicate clients with different auth contexts connecting to the same client group.`);
|
|
943
1233
|
}
|
|
944
|
-
|
|
1234
|
+
/**
|
|
1235
|
+
* Records that hydrating `query` was aborted for exceeding the query
|
|
1236
|
+
* hydration timeout, and opens its circuit breaker.
|
|
1237
|
+
*/
|
|
1238
|
+
#recordHydrationTimeout(lc, query, elapsedMs, rowCount) {
|
|
1239
|
+
this.#hydrationCircuitBreaker.trip(query.transformationHash);
|
|
1240
|
+
this.#hydrationTimeouts.add(1);
|
|
1241
|
+
if (!lc.warn) return;
|
|
1242
|
+
const shape = queryShape(query.ast);
|
|
1243
|
+
lc.warn("Query hydration aborted for exceeding the hydration timeout", {
|
|
1244
|
+
clientGroupID: this.id,
|
|
1245
|
+
queryHash: query.id,
|
|
1246
|
+
transformationHash: query.transformationHash,
|
|
1247
|
+
...query.name !== void 0 && { queryName: query.name },
|
|
1248
|
+
queryShape: shape.hash,
|
|
1249
|
+
hydrationTimeoutMs: this.#hydrationCircuitBreaker.timeoutMs,
|
|
1250
|
+
hydrationElapsedMs: elapsedMs,
|
|
1251
|
+
...rowCount !== void 0 && { hydrationRowCount: rowCount },
|
|
1252
|
+
circuitBreakerOpenMs: this.#hydrationCircuitBreaker.openMs,
|
|
1253
|
+
zql: shape.zql
|
|
1254
|
+
});
|
|
1255
|
+
}
|
|
1256
|
+
/**
|
|
1257
|
+
* Logs a hydration that exceeded the slow hydration threshold.
|
|
1258
|
+
*
|
|
1259
|
+
* The query is logged as its {@link queryShape}, with literal values
|
|
1260
|
+
* redacted, and each shape is logged at most once per
|
|
1261
|
+
* {@link SLOW_HYDRATION_LOG_WINDOW_MS}. The next log of a shape reports how
|
|
1262
|
+
* many slow hydrations of it were suppressed in the meantime.
|
|
1263
|
+
*/
|
|
1264
|
+
#logSlowHydration(lc, query, elapsedMs) {
|
|
1265
|
+
if (!lc.warn) return;
|
|
1266
|
+
const stats = this.#pipelines.hydrationStats(query.id);
|
|
1267
|
+
const shape = stats?.shape ?? queryShape(query.ast);
|
|
1268
|
+
const suppressed = slowHydrationLogThrottle.admit(`${query.name ?? ""}:${shape.hash}`);
|
|
1269
|
+
if (suppressed === void 0) return;
|
|
1270
|
+
lc.warn("Slow query materialization", {
|
|
1271
|
+
zeroEvent: "query-slow-hydration",
|
|
1272
|
+
clientGroupID: this.id,
|
|
1273
|
+
queryHash: query.id,
|
|
1274
|
+
transformationHash: query.transformationHash,
|
|
1275
|
+
...query.name !== void 0 && { queryName: query.name },
|
|
1276
|
+
queryShape: shape.hash,
|
|
1277
|
+
hydrationTimeMs: elapsedMs,
|
|
1278
|
+
...stats && {
|
|
1279
|
+
hydrationRowCount: stats.rowCount,
|
|
1280
|
+
hydrationRowsRead: stats.rowsRead
|
|
1281
|
+
},
|
|
1282
|
+
...stats !== void 0 && stats.planWarnings.length > 0 && { planWarnings: stats.planWarnings.map(planWarningMessage) },
|
|
1283
|
+
...suppressed > 0 && { suppressedSinceLastLog: suppressed },
|
|
1284
|
+
zql: shape.zql
|
|
1285
|
+
});
|
|
1286
|
+
}
|
|
1287
|
+
/** Records that `query` was rejected without hydration by its open breaker. */
|
|
1288
|
+
#recordCircuitBreakerRejection(lc, query) {
|
|
1289
|
+
this.#hydrationCircuitBreakerRejections.add(1);
|
|
1290
|
+
lc.warn?.("Query rejected by its open hydration circuit breaker", {
|
|
1291
|
+
clientGroupID: this.id,
|
|
1292
|
+
queryHash: query.id,
|
|
1293
|
+
transformationHash: query.transformationHash,
|
|
1294
|
+
...query.name !== void 0 && { queryName: query.name },
|
|
1295
|
+
hydrationTimeoutMs: this.#hydrationCircuitBreaker.timeoutMs,
|
|
1296
|
+
circuitBreakerOpenMs: this.#hydrationCircuitBreaker.openMs
|
|
1297
|
+
});
|
|
1298
|
+
}
|
|
1299
|
+
/**
|
|
1300
|
+
* Handles queries whose hydration circuit breaker is open: they are counted,
|
|
1301
|
+
* logged, and errored to the affected clients. The caller removes them from
|
|
1302
|
+
* the CVR.
|
|
1303
|
+
*/
|
|
1304
|
+
#rejectCircuitBrokenQueries(lc, cvr, queries) {
|
|
1305
|
+
for (const query of queries) this.#recordCircuitBreakerRejection(lc, query);
|
|
1306
|
+
this.#queryEvictions.add(queries.length, { reason: "hydration-circuit-breaker" });
|
|
1307
|
+
this.#sendHydrationTimeoutErrors(cvr, queries);
|
|
1308
|
+
}
|
|
1309
|
+
/**
|
|
1310
|
+
* Sends a per-query error to every client that desires one of `queries`.
|
|
1311
|
+
* The error goes out as a `transformError` application error, which every
|
|
1312
|
+
* client understands as "this query errored" without affecting the
|
|
1313
|
+
* connection or the client's other queries.
|
|
1314
|
+
*/
|
|
1315
|
+
#sendHydrationTimeoutErrors(cvr, queries) {
|
|
1316
|
+
const timeoutMs = this.#hydrationCircuitBreaker.timeoutMs;
|
|
1317
|
+
const errorsByClient = /* @__PURE__ */ new Map();
|
|
1318
|
+
for (const { id, name } of queries) {
|
|
1319
|
+
const query = cvr.queries[id];
|
|
1320
|
+
if (query === void 0 || query.type === "internal") continue;
|
|
1321
|
+
const error = {
|
|
1322
|
+
error: "app",
|
|
1323
|
+
id,
|
|
1324
|
+
name: name ?? (query.type === "custom" ? query.name : "legacy"),
|
|
1325
|
+
message: `Query hydration exceeded the ${timeoutMs}ms limit (ZERO_VIEW_SYNCER_QUERY_HYDRATION_TIMEOUT_MS) and was aborted`,
|
|
1326
|
+
details: {
|
|
1327
|
+
kind: "HydrationTimeout",
|
|
1328
|
+
timeoutMs
|
|
1329
|
+
}
|
|
1330
|
+
};
|
|
1331
|
+
for (const clientID of Object.keys(query.clientState)) getOrInsertComputed(errorsByClient, clientID, newArray).push(error);
|
|
1332
|
+
}
|
|
1333
|
+
for (const [clientID, errors] of errorsByClient) this.#clients.get(clientID)?.sendQueryTransformApplicationErrors(errors);
|
|
1334
|
+
}
|
|
1335
|
+
#recordHydrationBudgetExhaustion(lc, hydrationBudget, activeHydratedQueries, inactiveHydratedQueries, inactiveEvictedQueryIDs) {
|
|
1336
|
+
const elapsedMs = hydrationBudget.exhaustedAtMs;
|
|
1337
|
+
if (elapsedMs === void 0) return;
|
|
1338
|
+
this.#hydrationBudgetExhaustions.add(1);
|
|
1339
|
+
this.#hydrationBudgetEvictions.add(inactiveEvictedQueryIDs.length);
|
|
1340
|
+
this.#hydrationBudgetElapsed.record(elapsedMs);
|
|
1341
|
+
this.#hydrationBudgetOvershoot.record(Math.max(0, elapsedMs - hydrationBudget.limitMs));
|
|
1342
|
+
if (inactiveEvictedQueryIDs.length > 0) this.#queryEvictions.add(inactiveEvictedQueryIDs.length, { reason: "hydration-budget" });
|
|
1343
|
+
lc.info?.("view-syncer hydration budget exhausted", {
|
|
1344
|
+
clientGroupID: this.id,
|
|
1345
|
+
hydrationBudgetMs: hydrationBudget.limitMs,
|
|
1346
|
+
hydrationElapsedMs: elapsedMs,
|
|
1347
|
+
activeHydratedQueries,
|
|
1348
|
+
inactiveHydratedQueries,
|
|
1349
|
+
inactiveEvictedQueries: inactiveEvictedQueryIDs.length,
|
|
1350
|
+
firstEvictedQueryHash: inactiveEvictedQueryIDs[0] ?? null
|
|
1351
|
+
});
|
|
1352
|
+
}
|
|
1353
|
+
#addAndRemoveQueries(lc, cvr, requiredQueries, optionalQueries, removeQueries, hydrationBudget, hydrationPassStats, driftedQueryIDs = /* @__PURE__ */ new Set()) {
|
|
945
1354
|
return startAsyncSpan(tracer, "vs.#addAndRemoveQueries", async () => {
|
|
1355
|
+
const addQueries = [...requiredQueries, ...optionalQueries];
|
|
946
1356
|
assert(addQueries.length > 0 || removeQueries.length > 0, "Must have queries to add or remove");
|
|
947
1357
|
const start = performance.now();
|
|
948
1358
|
const stateVersion = this.#pipelines.currentVersion();
|
|
@@ -959,7 +1369,9 @@ var ViewSyncerService = class {
|
|
|
959
1369
|
updater.ensureNewVersion();
|
|
960
1370
|
}
|
|
961
1371
|
const { queryPatches, newVersion } = updater.trackQueries(lc, addQueries, removeQueries);
|
|
962
|
-
|
|
1372
|
+
if (hydrationBudget.limitMs !== 0 && optionalQueries.length > 0) assert(cmpVersions(cvr.version, newVersion) < 0, "Optional hydration requires a final poke version before row processing so a removal is actually poked");
|
|
1373
|
+
const clients = this.#getClients();
|
|
1374
|
+
const pokers = startPoke(lc, clients, newVersion);
|
|
963
1375
|
for (const patch of queryPatches) await pokers.addPatch(patch);
|
|
964
1376
|
for (const q of removeQueries) {
|
|
965
1377
|
this.#pipelines.removeQuery(q.id);
|
|
@@ -975,22 +1387,54 @@ var ViewSyncerService = class {
|
|
|
975
1387
|
let totalHydratedQueries = 0;
|
|
976
1388
|
let coveredHydratedQueries = 0;
|
|
977
1389
|
let firstCoveredQuery;
|
|
1390
|
+
const hydratedQueryIDs = [];
|
|
1391
|
+
const budgetEvictedQueryIDs = [];
|
|
1392
|
+
const timedOutQueries = [];
|
|
1393
|
+
const rejectedQueries = [];
|
|
1394
|
+
const circuitBreaker = this.#hydrationCircuitBreaker;
|
|
978
1395
|
const self = this;
|
|
979
1396
|
await yieldProcess(lc);
|
|
980
|
-
function*
|
|
981
|
-
for (
|
|
1397
|
+
function* hydrateQueries(queries, optional, slowHydrateThreshold) {
|
|
1398
|
+
for (let i = 0; i < queries.length; i++) {
|
|
1399
|
+
if (optional && hydrationBudget.exhausted()) {
|
|
1400
|
+
budgetEvictedQueryIDs.push(...queries.slice(i).map((query) => query.id));
|
|
1401
|
+
return;
|
|
1402
|
+
}
|
|
1403
|
+
const q = must(queries[i]);
|
|
982
1404
|
let queryLC = lc.withContext("hash", q.id).withContext("queryHash", q.id).withContext("transformationHash", q.transformationHash);
|
|
983
1405
|
if (q.name !== void 0) queryLC = queryLC.withContext("queryName", q.name);
|
|
984
1406
|
queryLC.debug?.(`adding pipeline for query`, q.ast);
|
|
1407
|
+
const breakable = cvr.queries[q.id]?.type !== "internal";
|
|
1408
|
+
if (breakable && circuitBreaker.isOpen(q.transformationHash)) {
|
|
1409
|
+
rejectedQueries.push(q);
|
|
1410
|
+
self.#recordCircuitBreakerRejection(queryLC, q);
|
|
1411
|
+
continue;
|
|
1412
|
+
}
|
|
985
1413
|
const covered = queryCoveringIndex ? self.#findQueryCoverageShadowHit(queryCoveringIndex, q.id, q.transformationHash, q.ast, q.name) : void 0;
|
|
986
1414
|
totalHydratedQueries++;
|
|
987
1415
|
if (covered) {
|
|
988
1416
|
coveredHydratedQueries++;
|
|
989
1417
|
firstCoveredQuery ??= covered;
|
|
990
1418
|
}
|
|
991
|
-
|
|
1419
|
+
let timedOut = false;
|
|
1420
|
+
for (const change of pipelines.addQuery(q.transformationHash, q.id, q.ast, timer.startWithoutYielding(), q.name, "query-set-sync")) {
|
|
1421
|
+
if (change === "yield" && breakable && circuitBreaker.exceeded(timer.totalElapsed())) {
|
|
1422
|
+
timedOut = true;
|
|
1423
|
+
yield change;
|
|
1424
|
+
break;
|
|
1425
|
+
}
|
|
1426
|
+
yield change;
|
|
1427
|
+
}
|
|
992
1428
|
const elapsed = timer.stop();
|
|
993
1429
|
totalProcessTime += elapsed;
|
|
1430
|
+
if (timedOut) {
|
|
1431
|
+
timedOutQueries.push(q);
|
|
1432
|
+
self.#recordHydrationTimeout(queryLC, q, elapsed);
|
|
1433
|
+
continue;
|
|
1434
|
+
}
|
|
1435
|
+
hydratedQueryIDs.push(q.id);
|
|
1436
|
+
if (optional) hydrationPassStats.inactiveHydratedQueries++;
|
|
1437
|
+
else hydrationPassStats.activeHydratedQueries++;
|
|
994
1438
|
self.#addQueryMaterializationServerMetric(q.id, elapsed);
|
|
995
1439
|
self.#inspectorDelegate.addQuery(q.id, q.ast);
|
|
996
1440
|
queryCoveringIndex?.add(q.id, {
|
|
@@ -998,24 +1442,49 @@ var ViewSyncerService = class {
|
|
|
998
1442
|
transformationHash: q.transformationHash,
|
|
999
1443
|
...q.name !== void 0 && { queryName: q.name }
|
|
1000
1444
|
});
|
|
1001
|
-
if (elapsed > slowHydrateThreshold) queryLC
|
|
1445
|
+
if (elapsed > slowHydrateThreshold) self.#logSlowHydration(queryLC, q, elapsed);
|
|
1002
1446
|
manualSpan(tracer, "vs.addAndConsumeQuery", elapsed, {
|
|
1003
1447
|
hash: q.id,
|
|
1004
1448
|
transformationHash: q.transformationHash,
|
|
1005
1449
|
...q.name !== void 0 && { name: q.name }
|
|
1006
1450
|
});
|
|
1451
|
+
hydrations.add(1);
|
|
1452
|
+
hydrationTime.recordMs(elapsed);
|
|
1007
1453
|
}
|
|
1008
|
-
|
|
1009
|
-
|
|
1454
|
+
}
|
|
1455
|
+
function* generateRowChanges(slowHydrateThreshold) {
|
|
1456
|
+
yield* hydrateQueries(requiredQueries, false, slowHydrateThreshold);
|
|
1457
|
+
yield* hydrateQueries(optionalQueries, true, slowHydrateThreshold);
|
|
1010
1458
|
}
|
|
1011
1459
|
await this.#processChanges(lc, timer, generateRowChanges(this.#slowHydrateThreshold), updater, pokers);
|
|
1460
|
+
const abortedQueries = [...timedOutQueries, ...rejectedQueries];
|
|
1461
|
+
if (abortedQueries.length > 0) {
|
|
1462
|
+
const abortedQueryIDs = abortedQueries.map(({ id }) => id);
|
|
1463
|
+
for (const patch of await updater.abortExecutedQueries(lc, abortedQueryIDs)) await pokers.addPatch(patch);
|
|
1464
|
+
for (const queryID of abortedQueryIDs) {
|
|
1465
|
+
this.#pipelines.removeQuery(queryID);
|
|
1466
|
+
this.#inspectorDelegate.removeQuery(queryID);
|
|
1467
|
+
this.#queryReplacements.delete(queryID);
|
|
1468
|
+
}
|
|
1469
|
+
if (timedOutQueries.length > 0) this.#queryEvictions.add(timedOutQueries.length, { reason: "hydration-timeout" });
|
|
1470
|
+
if (rejectedQueries.length > 0) this.#queryEvictions.add(rejectedQueries.length, { reason: "hydration-circuit-breaker" });
|
|
1471
|
+
this.#sendHydrationTimeoutErrors(cvr, abortedQueries);
|
|
1472
|
+
}
|
|
1473
|
+
for (const patch of updater.removeTrackedQueries(budgetEvictedQueryIDs)) await pokers.addPatch(patch);
|
|
1474
|
+
for (const queryID of budgetEvictedQueryIDs) {
|
|
1475
|
+
this.#pipelines.removeQuery(queryID);
|
|
1476
|
+
this.#inspectorDelegate.removeQuery(queryID);
|
|
1477
|
+
this.#queryReplacements.delete(queryID);
|
|
1478
|
+
}
|
|
1479
|
+
this.#recordHydrationBudgetExhaustion(lc, hydrationBudget, hydrationPassStats.activeHydratedQueries, hydrationPassStats.inactiveHydratedQueries, budgetEvictedQueryIDs);
|
|
1012
1480
|
this.#logQueryCoverageShadowSummary(lc, "add", totalHydratedQueries, coveredHydratedQueries, firstCoveredQuery);
|
|
1013
1481
|
await startAsyncSpan(tracer, "vs.#syncQueryPipelineSet.deleteUnreferencedRows", async () => {
|
|
1014
1482
|
for (const patch of await updater.deleteUnreferencedRows(lc)) await pokers.addPatch(patch);
|
|
1015
1483
|
});
|
|
1016
|
-
this.#cvr = await this.#
|
|
1484
|
+
this.#cvr = await this.#flushPoked(lc, updater, pokers);
|
|
1485
|
+
if (budgetEvictedQueryIDs.length > 0) this.#scheduleExpireEviction(lc, this.#cvr);
|
|
1017
1486
|
const finalVersion = this.#cvr.version;
|
|
1018
|
-
await this.#catchupClients(lc, cvr, finalVersion,
|
|
1487
|
+
await this.#catchupClients(lc, cvr, finalVersion, hydratedQueryIDs, pokers);
|
|
1019
1488
|
await startAsyncSpan(tracer, "vs.#syncQueryPipelineSet.pokeEnd", () => pokers.end(finalVersion));
|
|
1020
1489
|
this.#markVersionServed(stateVersion);
|
|
1021
1490
|
const wallTime = performance.now() - start;
|
|
@@ -1044,7 +1513,7 @@ var ViewSyncerService = class {
|
|
|
1044
1513
|
return startAsyncSpan(tracer, "vs.#catchupClients", async (span) => {
|
|
1045
1514
|
current ??= cvr.version;
|
|
1046
1515
|
const clients = this.#getClients();
|
|
1047
|
-
const pokers = usePokers ?? startPoke(clients, cvr.version);
|
|
1516
|
+
const pokers = usePokers ?? startPoke(lc, clients, cvr.version);
|
|
1048
1517
|
span.setAttribute("numClients", clients.length);
|
|
1049
1518
|
const catchupFrom = clients.map((c) => c.version()).reduce((a, b) => cmpVersions(a, b) < 0 ? a : b, cvr.version);
|
|
1050
1519
|
const rowPatches = this.#cvrStore.catchupRowPatches(lc, catchupFrom, cvr, current, excludeQueryHashes);
|
|
@@ -1156,7 +1625,9 @@ var ViewSyncerService = class {
|
|
|
1156
1625
|
*
|
|
1157
1626
|
* Must be called from within the #lock.
|
|
1158
1627
|
*
|
|
1159
|
-
* Returns
|
|
1628
|
+
* Returns 'success' if changes were successfully processed and poked,
|
|
1629
|
+
* or a `ResetPipelinesSignal` if advancement aborted (e.g. schema change,
|
|
1630
|
+
* timeout) and pipelines need to be reset and rehydrated.
|
|
1160
1631
|
*/
|
|
1161
1632
|
#advancePipelines(lc, cvr) {
|
|
1162
1633
|
return startAsyncSpan(tracer, "vs.#advancePipelines", async (span) => {
|
|
@@ -1164,21 +1635,29 @@ var ViewSyncerService = class {
|
|
|
1164
1635
|
assert(this.#pipelines.initialized(), "pipelines must be initialized (advancePipelines");
|
|
1165
1636
|
const start = performance.now();
|
|
1166
1637
|
const timer = new TimeSliceTimer(lc);
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
lc.debug?.(`applying ${numChanges} to advance to ${version}`);
|
|
1638
|
+
let pokers;
|
|
1639
|
+
let updater;
|
|
1640
|
+
let version;
|
|
1641
|
+
let numChanges = 0;
|
|
1172
1642
|
try {
|
|
1173
|
-
|
|
1643
|
+
const advancement = this.#pipelines.advance(timer);
|
|
1644
|
+
version = advancement.version;
|
|
1645
|
+
numChanges = advancement.numChanges;
|
|
1646
|
+
lc = lc.withContext("newVersion", version);
|
|
1647
|
+
updater = new CVRQueryDrivenUpdater(this.#cvrStore, cvr, version, this.#pipelines.replicaVersion, (queryID) => this.#pipelines.rowSetSignature(queryID));
|
|
1648
|
+
pokers = startPoke(lc, this.#getClients(cvr.version), updater.updatedVersion());
|
|
1649
|
+
lc.debug?.(`applying ${numChanges} to advance to ${version}`);
|
|
1650
|
+
await this.#processChanges(lc, await timer.start(), advancement.changes, updater, pokers);
|
|
1174
1651
|
} catch (e) {
|
|
1175
1652
|
if (e instanceof ResetPipelinesSignal) {
|
|
1176
|
-
await pokers
|
|
1653
|
+
await pokers?.cancel();
|
|
1654
|
+
this.#cvrStore.discardPending();
|
|
1177
1655
|
return e;
|
|
1178
1656
|
}
|
|
1179
1657
|
throw e;
|
|
1180
1658
|
}
|
|
1181
|
-
|
|
1659
|
+
assert(updater && pokers && version !== void 0, "advancement state missing");
|
|
1660
|
+
this.#cvr = await this.#flushPoked(lc, updater, pokers);
|
|
1182
1661
|
const finalVersion = this.#cvr.version;
|
|
1183
1662
|
await startAsyncSpan(tracer, "vs.#advancePipelines.pokeEnd", () => pokers.end(finalVersion));
|
|
1184
1663
|
this.#markVersionServed(version);
|
|
@@ -1198,7 +1677,7 @@ var ViewSyncerService = class {
|
|
|
1198
1677
|
clientID,
|
|
1199
1678
|
wsID: client.wsID
|
|
1200
1679
|
});
|
|
1201
|
-
return handleInspect(lc, body, cvr, client, this.#inspectorDelegate, this.id, this.#cvrStore, this.#config, connCtx);
|
|
1680
|
+
return handleInspect(lc, body, cvr, client, this.#inspectorDelegate, this.id, this, this.#cvrStore, this.#config, connCtx);
|
|
1202
1681
|
};
|
|
1203
1682
|
async #runBackgroundRetransform(lc) {
|
|
1204
1683
|
const attemptRetransform = async (connCtx) => {
|
|
@@ -1285,15 +1764,18 @@ var ViewSyncerService = class {
|
|
|
1285
1764
|
return this.#stopped.promise;
|
|
1286
1765
|
}
|
|
1287
1766
|
async #cleanup(err) {
|
|
1767
|
+
this.#shuttingDown = true;
|
|
1288
1768
|
this.connContextManager.setSharedRetransformReady(false);
|
|
1289
1769
|
this.#stopTTLClockInterval();
|
|
1290
1770
|
this.#stopExpireTimer();
|
|
1291
1771
|
this.#stopAuthMaintenanceTimer();
|
|
1772
|
+
this.#stopShutdownTimer();
|
|
1292
1773
|
this.#customQueryTransformer?.destroy();
|
|
1293
1774
|
for (const client of this.#clients.values()) if (err) client.fail(err);
|
|
1294
1775
|
else client.close(`closed clientGroupID=${this.id}`);
|
|
1295
1776
|
await this.#lock.withLock(() => {});
|
|
1296
1777
|
this.#pipelines.destroy();
|
|
1778
|
+
this.#inspectorDelegate.clearAuthenticated(this.id, this);
|
|
1297
1779
|
}
|
|
1298
1780
|
/**
|
|
1299
1781
|
* Test helper: Manually mark initialization as complete.
|
|
@@ -1329,8 +1811,10 @@ function isTransformFailedError(error) {
|
|
|
1329
1811
|
return error.errorBody.kind === "TransformFailed" && !isAuthErrorBody(error.errorBody);
|
|
1330
1812
|
}
|
|
1331
1813
|
/**
|
|
1332
|
-
* A query must be expired for all clients
|
|
1333
|
-
* expired.
|
|
1814
|
+
* Whether a query's TTL has elapsed. A query must be expired for all clients
|
|
1815
|
+
* in order to be considered expired.
|
|
1816
|
+
*
|
|
1817
|
+
* Exported for testing.
|
|
1334
1818
|
*/
|
|
1335
1819
|
function expired(ttlClock, q) {
|
|
1336
1820
|
if (q.type === "internal") return false;
|