@rocicorp/zero 0.25.0-canary.0 → 0.25.0-canary.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/out/analyze-query/src/bin-analyze.js +268 -257
- package/out/analyze-query/src/bin-analyze.js.map +1 -1
- package/out/analyze-query/src/bin-transform.js +31 -23
- package/out/analyze-query/src/bin-transform.js.map +1 -1
- package/out/analyze-query/src/explain-queries.js +13 -16
- package/out/analyze-query/src/explain-queries.js.map +1 -1
- package/out/analyze-query/src/run-ast.d.ts +3 -2
- package/out/analyze-query/src/run-ast.d.ts.map +1 -1
- package/out/analyze-query/src/run-ast.js +79 -73
- package/out/analyze-query/src/run-ast.js.map +1 -1
- package/out/ast-to-zql/src/ast-to-zql.js +146 -180
- package/out/ast-to-zql/src/ast-to-zql.js.map +1 -1
- package/out/ast-to-zql/src/bin.js +51 -54
- package/out/ast-to-zql/src/bin.js.map +1 -1
- package/out/ast-to-zql/src/format.js +15 -14
- package/out/ast-to-zql/src/format.js.map +1 -1
- package/out/datadog/src/datadog-log-sink.js +223 -0
- package/out/datadog/src/datadog-log-sink.js.map +1 -0
- package/out/otel/src/enabled.js +15 -15
- package/out/otel/src/enabled.js.map +1 -1
- package/out/otel/src/log-options.js +36 -31
- package/out/otel/src/log-options.js.map +1 -1
- package/out/otel/src/maybe-time.js +14 -11
- package/out/otel/src/maybe-time.js.map +1 -1
- package/out/otel/src/span.js +30 -27
- package/out/otel/src/span.js.map +1 -1
- package/out/otel/src/test-log-config.js +10 -7
- package/out/otel/src/test-log-config.js.map +1 -1
- package/out/otel/src/version.js +5 -2
- package/out/otel/src/version.js.map +1 -1
- package/out/replicache/src/async-iterable-to-array.js +11 -0
- package/out/replicache/src/async-iterable-to-array.js.map +1 -0
- package/out/replicache/src/bg-interval.js +38 -0
- package/out/replicache/src/bg-interval.js.map +1 -0
- package/out/replicache/src/btree/diff.js +8 -0
- package/out/replicache/src/btree/diff.js.map +1 -0
- package/out/replicache/src/btree/node.js +400 -0
- package/out/replicache/src/btree/node.js.map +1 -0
- package/out/replicache/src/btree/read.d.ts +3 -2
- package/out/replicache/src/btree/read.d.ts.map +1 -1
- package/out/replicache/src/btree/read.js +266 -0
- package/out/replicache/src/btree/read.js.map +1 -0
- package/out/replicache/src/btree/splice.js +83 -0
- package/out/replicache/src/btree/splice.js.map +1 -0
- package/out/replicache/src/btree/write.d.ts +1 -1
- package/out/replicache/src/btree/write.d.ts.map +1 -1
- package/out/replicache/src/btree/write.js +163 -0
- package/out/replicache/src/btree/write.js.map +1 -0
- package/out/replicache/src/call-default-fetch.js +34 -0
- package/out/replicache/src/call-default-fetch.js.map +1 -0
- package/out/replicache/src/connection-loop-delegates.js +34 -0
- package/out/replicache/src/connection-loop-delegates.js.map +1 -0
- package/out/replicache/src/connection-loop.js +251 -0
- package/out/replicache/src/connection-loop.js.map +1 -0
- package/out/replicache/src/cookies.js +40 -0
- package/out/replicache/src/cookies.js.map +1 -0
- package/out/replicache/src/dag/chunk.js +59 -0
- package/out/replicache/src/dag/chunk.js.map +1 -0
- package/out/replicache/src/dag/gc.js +117 -0
- package/out/replicache/src/dag/gc.js.map +1 -0
- package/out/replicache/src/dag/key.js +20 -0
- package/out/replicache/src/dag/key.js.map +1 -0
- package/out/replicache/src/dag/lazy-store.d.ts +3 -2
- package/out/replicache/src/dag/lazy-store.d.ts.map +1 -1
- package/out/replicache/src/dag/lazy-store.js +515 -0
- package/out/replicache/src/dag/lazy-store.js.map +1 -0
- package/out/replicache/src/dag/store-impl.js +183 -0
- package/out/replicache/src/dag/store-impl.js.map +1 -0
- package/out/replicache/src/dag/store.js +27 -0
- package/out/replicache/src/dag/store.js.map +1 -0
- package/out/replicache/src/dag/visitor.js +22 -0
- package/out/replicache/src/dag/visitor.js.map +1 -0
- package/out/replicache/src/db/commit.js +358 -0
- package/out/replicache/src/db/commit.js.map +1 -0
- package/out/replicache/src/db/index-operation-enum.js +7 -0
- package/out/replicache/src/db/index-operation-enum.js.map +1 -0
- package/out/replicache/src/db/index.js +134 -0
- package/out/replicache/src/db/index.js.map +1 -0
- package/out/replicache/src/db/meta-type-enum.js +7 -0
- package/out/replicache/src/db/meta-type-enum.js.map +1 -0
- package/out/replicache/src/db/read.d.ts +3 -2
- package/out/replicache/src/db/read.d.ts.map +1 -1
- package/out/replicache/src/db/read.js +72 -0
- package/out/replicache/src/db/read.js.map +1 -0
- package/out/replicache/src/db/rebase.d.ts +2 -2
- package/out/replicache/src/db/rebase.d.ts.map +1 -1
- package/out/replicache/src/db/rebase.js +85 -0
- package/out/replicache/src/db/rebase.js.map +1 -0
- package/out/replicache/src/db/write.d.ts +2 -1
- package/out/replicache/src/db/write.d.ts.map +1 -1
- package/out/replicache/src/db/write.js +296 -0
- package/out/replicache/src/db/write.js.map +1 -0
- package/out/replicache/src/deleted-clients.js +104 -0
- package/out/replicache/src/deleted-clients.js.map +1 -0
- package/out/replicache/src/error-responses.js +34 -0
- package/out/replicache/src/error-responses.js.map +1 -0
- package/out/replicache/src/format-version-enum.js +11 -0
- package/out/replicache/src/format-version-enum.js.map +1 -0
- package/out/{chunk-EZM3XBAB.js → replicache/src/frozen-json.js} +8 -75
- package/out/replicache/src/frozen-json.js.map +1 -0
- package/out/replicache/src/get-default-puller.js +61 -0
- package/out/replicache/src/get-default-puller.js.map +1 -0
- package/out/replicache/src/get-default-pusher.js +39 -0
- package/out/replicache/src/get-default-pusher.js.map +1 -0
- package/out/replicache/src/get-kv-store-provider.js +23 -0
- package/out/replicache/src/get-kv-store-provider.js.map +1 -0
- package/out/replicache/src/hash.js +38 -0
- package/out/replicache/src/hash.js.map +1 -0
- package/out/replicache/src/http-request-info.js +10 -0
- package/out/replicache/src/http-request-info.js.map +1 -0
- package/out/replicache/src/http-status-unauthorized.js +5 -0
- package/out/replicache/src/http-status-unauthorized.js.map +1 -0
- package/out/replicache/src/index-defs.js +32 -0
- package/out/replicache/src/index-defs.js.map +1 -0
- package/out/replicache/src/invoke-kind-enum.js +7 -0
- package/out/replicache/src/invoke-kind-enum.js.map +1 -0
- package/out/{chunk-ZZXMKAAG.js → replicache/src/kv/expo-sqlite/store.js} +8 -16
- package/out/replicache/src/kv/expo-sqlite/store.js.map +1 -0
- package/out/replicache/src/kv/idb-store-with-mem-fallback.js +80 -0
- package/out/replicache/src/kv/idb-store-with-mem-fallback.js.map +1 -0
- package/out/replicache/src/kv/idb-store.js +183 -0
- package/out/replicache/src/kv/idb-store.js.map +1 -0
- package/out/replicache/src/kv/mem-store.js +51 -0
- package/out/replicache/src/kv/mem-store.js.map +1 -0
- package/out/{op-sqlite.js → replicache/src/kv/op-sqlite/store.js} +7 -18
- package/out/replicache/src/kv/op-sqlite/store.js.map +1 -0
- package/out/replicache/src/kv/op-sqlite/types.js +6 -0
- package/out/replicache/src/kv/op-sqlite/types.js.map +1 -0
- package/out/replicache/src/kv/read-impl.js +27 -0
- package/out/replicache/src/kv/read-impl.js.map +1 -0
- package/out/replicache/src/kv/sqlite-store.d.ts.map +1 -1
- package/out/{chunk-ECUMGQGC.js → replicache/src/kv/sqlite-store.js} +27 -21
- package/out/replicache/src/kv/sqlite-store.js.map +1 -0
- package/out/{chunk-ASRS2LFV.js → replicache/src/kv/throw-if-closed.js} +4 -6
- package/out/replicache/src/kv/throw-if-closed.js.map +1 -0
- package/out/replicache/src/kv/write-impl-base.js +57 -0
- package/out/replicache/src/kv/write-impl-base.js.map +1 -0
- package/out/replicache/src/kv/write-impl.js +30 -0
- package/out/replicache/src/kv/write-impl.js.map +1 -0
- package/out/replicache/src/lazy.js +13 -0
- package/out/replicache/src/lazy.js.map +1 -0
- package/out/replicache/src/log-options.d.ts +1 -1
- package/out/replicache/src/log-options.d.ts.map +1 -1
- package/out/replicache/src/log-options.js +9 -0
- package/out/replicache/src/log-options.js.map +1 -0
- package/out/replicache/src/make-idb-name.js +13 -0
- package/out/replicache/src/make-idb-name.js.map +1 -0
- package/out/replicache/src/new-client-channel.js +51 -0
- package/out/replicache/src/new-client-channel.js.map +1 -0
- package/out/replicache/src/on-persist-channel.js +36 -0
- package/out/replicache/src/on-persist-channel.js.map +1 -0
- package/out/replicache/src/patch-operation.js +42 -0
- package/out/replicache/src/patch-operation.js.map +1 -0
- package/out/replicache/src/pending-mutations.js +16 -0
- package/out/replicache/src/pending-mutations.js.map +1 -0
- package/out/replicache/src/persist/client-gc.js +58 -0
- package/out/replicache/src/persist/client-gc.js.map +1 -0
- package/out/replicache/src/persist/client-group-gc.js +43 -0
- package/out/replicache/src/persist/client-group-gc.js.map +1 -0
- package/out/replicache/src/persist/client-groups.js +184 -0
- package/out/replicache/src/persist/client-groups.js.map +1 -0
- package/out/replicache/src/persist/clients.d.ts +3 -2
- package/out/replicache/src/persist/clients.d.ts.map +1 -1
- package/out/replicache/src/persist/clients.js +353 -0
- package/out/replicache/src/persist/clients.js.map +1 -0
- package/out/replicache/src/persist/collect-idb-databases.d.ts +3 -3
- package/out/replicache/src/persist/collect-idb-databases.d.ts.map +1 -1
- package/out/replicache/src/persist/collect-idb-databases.js +188 -0
- package/out/replicache/src/persist/collect-idb-databases.js.map +1 -0
- package/out/replicache/src/persist/gather-mem-only-visitor.js +27 -0
- package/out/replicache/src/persist/gather-mem-only-visitor.js.map +1 -0
- package/out/replicache/src/persist/gather-not-cached-visitor.js +37 -0
- package/out/replicache/src/persist/gather-not-cached-visitor.js.map +1 -0
- package/out/replicache/src/persist/heartbeat.js +48 -0
- package/out/replicache/src/persist/heartbeat.js.map +1 -0
- package/out/replicache/src/persist/idb-databases-store-db-name.js +14 -0
- package/out/replicache/src/persist/idb-databases-store-db-name.js.map +1 -0
- package/out/replicache/src/persist/idb-databases-store.js +92 -0
- package/out/replicache/src/persist/idb-databases-store.js.map +1 -0
- package/out/replicache/src/persist/make-client-id.js +12 -0
- package/out/replicache/src/persist/make-client-id.js.map +1 -0
- package/out/replicache/src/persist/persist.d.ts +2 -2
- package/out/replicache/src/persist/persist.d.ts.map +1 -1
- package/out/replicache/src/persist/persist.js +183 -0
- package/out/replicache/src/persist/persist.js.map +1 -0
- package/out/replicache/src/persist/refresh.d.ts +4 -3
- package/out/replicache/src/persist/refresh.d.ts.map +1 -1
- package/out/replicache/src/persist/refresh.js +198 -0
- package/out/replicache/src/persist/refresh.js.map +1 -0
- package/out/replicache/src/process-scheduler.js +96 -0
- package/out/replicache/src/process-scheduler.js.map +1 -0
- package/out/replicache/src/pusher.js +33 -0
- package/out/replicache/src/pusher.js.map +1 -0
- package/out/replicache/src/replicache-impl.d.ts +1 -1
- package/out/replicache/src/replicache-impl.d.ts.map +1 -1
- package/out/replicache/src/replicache-impl.js +1200 -0
- package/out/replicache/src/replicache-impl.js.map +1 -0
- package/out/replicache/src/replicache-options.d.ts +4 -3
- package/out/replicache/src/replicache-options.d.ts.map +1 -1
- package/out/replicache/src/report-error.js +6 -0
- package/out/replicache/src/report-error.js.map +1 -0
- package/out/replicache/src/request-idle.js +13 -0
- package/out/replicache/src/request-idle.js.map +1 -0
- package/out/replicache/src/scan-iterator.js +146 -0
- package/out/replicache/src/scan-iterator.js.map +1 -0
- package/out/replicache/src/scan-options.js +45 -0
- package/out/replicache/src/scan-options.js.map +1 -0
- package/out/replicache/src/set-interval-with-signal.js +12 -0
- package/out/replicache/src/set-interval-with-signal.js.map +1 -0
- package/out/replicache/src/subscriptions.js +355 -0
- package/out/replicache/src/subscriptions.js.map +1 -0
- package/out/replicache/src/sync/diff.d.ts +3 -2
- package/out/replicache/src/sync/diff.d.ts.map +1 -1
- package/out/replicache/src/sync/diff.js +72 -0
- package/out/replicache/src/sync/diff.js.map +1 -0
- package/out/replicache/src/sync/handle-pull-response-result-type-enum.js +9 -0
- package/out/replicache/src/sync/handle-pull-response-result-type-enum.js.map +1 -0
- package/out/replicache/src/sync/ids.js +9 -0
- package/out/replicache/src/sync/ids.js.map +1 -0
- package/out/replicache/src/sync/patch.js +49 -0
- package/out/replicache/src/sync/patch.js.map +1 -0
- package/out/replicache/src/sync/pull-error.js +16 -0
- package/out/replicache/src/sync/pull-error.js.map +1 -0
- package/out/replicache/src/sync/pull.d.ts +3 -2
- package/out/replicache/src/sync/pull.d.ts.map +1 -1
- package/out/replicache/src/sync/pull.js +301 -0
- package/out/replicache/src/sync/pull.js.map +1 -0
- package/out/replicache/src/sync/push.js +88 -0
- package/out/replicache/src/sync/push.js.map +1 -0
- package/out/replicache/src/sync/request-id.js +20 -0
- package/out/replicache/src/sync/request-id.js.map +1 -0
- package/out/replicache/src/sync/sync-head-name.js +5 -0
- package/out/replicache/src/sync/sync-head-name.js.map +1 -0
- package/out/replicache/src/to-error.js +10 -0
- package/out/replicache/src/to-error.js.map +1 -0
- package/out/replicache/src/transaction-closed-error.js +19 -0
- package/out/replicache/src/transaction-closed-error.js.map +1 -0
- package/out/replicache/src/transactions.js +152 -0
- package/out/replicache/src/transactions.js.map +1 -0
- package/out/replicache/src/version.js +5 -0
- package/out/replicache/src/version.js.map +1 -0
- package/out/replicache/src/with-transactions.js +28 -0
- package/out/replicache/src/with-transactions.js.map +1 -0
- package/out/shared/src/abort-error.js +6 -3
- package/out/shared/src/abort-error.js.map +1 -1
- package/out/shared/src/arrays.js +45 -43
- package/out/shared/src/arrays.js.map +1 -1
- package/out/shared/src/asserts.js +64 -68
- package/out/shared/src/asserts.js.map +1 -1
- package/out/shared/src/bigint-json.js +38 -42
- package/out/shared/src/bigint-json.js.map +1 -1
- package/out/shared/src/binary-search.js +18 -29
- package/out/shared/src/binary-search.js.map +1 -1
- package/out/shared/src/broadcast-channel.js +24 -0
- package/out/shared/src/broadcast-channel.js.map +1 -0
- package/out/shared/src/browser-env.js +25 -0
- package/out/shared/src/browser-env.js.map +1 -0
- package/out/shared/src/btree-set.js +464 -507
- package/out/shared/src/btree-set.js.map +1 -1
- package/out/shared/src/cache.js +34 -38
- package/out/shared/src/cache.js.map +1 -1
- package/out/shared/src/centroid.js +24 -24
- package/out/shared/src/centroid.js.map +1 -1
- package/out/shared/src/config.js +6 -3
- package/out/shared/src/config.js.map +1 -1
- package/out/shared/src/custom-key-map.js +58 -64
- package/out/shared/src/custom-key-map.js.map +1 -1
- package/out/shared/src/custom-key-set.js +51 -57
- package/out/shared/src/custom-key-set.js.map +1 -1
- package/out/shared/src/deep-clone.js +46 -0
- package/out/shared/src/deep-clone.js.map +1 -0
- package/out/shared/src/deep-merge.d.ts +24 -4
- package/out/shared/src/deep-merge.d.ts.map +1 -1
- package/out/shared/src/deep-merge.js +27 -0
- package/out/shared/src/deep-merge.js.map +1 -0
- package/out/shared/src/document-visible.js +74 -0
- package/out/shared/src/document-visible.js.map +1 -0
- package/out/shared/src/dotenv.js +5 -7
- package/out/shared/src/dotenv.js.map +1 -1
- package/out/shared/src/error.d.ts +4 -0
- package/out/shared/src/error.d.ts.map +1 -0
- package/out/shared/src/error.js +71 -0
- package/out/shared/src/error.js.map +1 -0
- package/out/shared/src/has-own.js +5 -3
- package/out/shared/src/has-own.js.map +1 -1
- package/out/shared/src/hash.js +15 -14
- package/out/shared/src/hash.js.map +1 -1
- package/out/shared/src/iterables.js +71 -73
- package/out/shared/src/iterables.js.map +1 -1
- package/out/shared/src/json-schema.js +30 -33
- package/out/shared/src/json-schema.js.map +1 -1
- package/out/shared/src/json.js +128 -143
- package/out/shared/src/json.js.map +1 -1
- package/out/shared/src/logging-test-utils.js +12 -19
- package/out/shared/src/logging-test-utils.js.map +1 -1
- package/out/shared/src/logging.d.ts.map +1 -1
- package/out/shared/src/logging.js +99 -83
- package/out/shared/src/logging.js.map +1 -1
- package/out/shared/src/must.js +9 -7
- package/out/shared/src/must.js.map +1 -1
- package/out/shared/src/navigator.js +5 -0
- package/out/shared/src/navigator.js.map +1 -0
- package/out/shared/src/object-traversal.d.ts +19 -0
- package/out/shared/src/object-traversal.d.ts.map +1 -0
- package/out/shared/src/object-traversal.js +27 -0
- package/out/shared/src/object-traversal.js.map +1 -0
- package/out/shared/src/objects.js +21 -22
- package/out/shared/src/objects.js.map +1 -1
- package/out/shared/src/options.d.ts +3 -1
- package/out/shared/src/options.d.ts.map +1 -1
- package/out/shared/src/options.js +289 -318
- package/out/shared/src/options.js.map +1 -1
- package/out/shared/src/parse-big-int.js +12 -10
- package/out/shared/src/parse-big-int.js.map +1 -1
- package/out/shared/src/promise-race.d.ts +17 -0
- package/out/shared/src/promise-race.d.ts.map +1 -0
- package/out/shared/src/promise-race.js +20 -0
- package/out/shared/src/promise-race.js.map +1 -0
- package/out/shared/src/queue.js +119 -122
- package/out/shared/src/queue.js.map +1 -1
- package/out/shared/src/rand.js +8 -10
- package/out/shared/src/rand.js.map +1 -1
- package/out/shared/src/random-uint64.js +9 -0
- package/out/shared/src/random-uint64.js.map +1 -0
- package/out/shared/src/random-values.js +13 -0
- package/out/shared/src/random-values.js.map +1 -0
- package/out/shared/src/resolved-promises.js +12 -9
- package/out/shared/src/resolved-promises.js.map +1 -1
- package/out/shared/src/sentinels.js +13 -6
- package/out/shared/src/sentinels.js.map +1 -1
- package/out/shared/src/set-utils.js +63 -62
- package/out/shared/src/set-utils.js.map +1 -1
- package/out/shared/src/size-of-value.js +58 -0
- package/out/shared/src/size-of-value.js.map +1 -0
- package/out/shared/src/sleep.js +45 -53
- package/out/shared/src/sleep.js.map +1 -1
- package/out/shared/src/string-compare.js +12 -9
- package/out/shared/src/string-compare.js.map +1 -1
- package/out/shared/src/subscribable.js +34 -0
- package/out/shared/src/subscribable.js.map +1 -0
- package/out/shared/src/tdigest-schema.js +7 -7
- package/out/shared/src/tdigest-schema.js.map +1 -1
- package/out/shared/src/tdigest.js +247 -271
- package/out/shared/src/tdigest.js.map +1 -1
- package/out/shared/src/valita.js +195 -207
- package/out/shared/src/valita.js.map +1 -1
- package/out/z2s/src/compiler.d.ts +3 -3
- package/out/z2s/src/compiler.d.ts.map +1 -1
- package/out/z2s/src/compiler.js +438 -311
- package/out/z2s/src/compiler.js.map +1 -1
- package/out/z2s/src/sql.d.ts +1 -1
- package/out/z2s/src/sql.d.ts.map +1 -1
- package/out/z2s/src/sql.js +186 -218
- package/out/z2s/src/sql.js.map +1 -1
- package/out/zero/package.json.js +9 -0
- package/out/zero/package.json.js.map +1 -0
- package/out/zero/src/adapters/drizzle.js +5 -2
- package/out/zero/src/adapters/drizzle.js.map +1 -1
- package/out/zero/src/adapters/pg.js +7 -2
- package/out/zero/src/adapters/pg.js.map +1 -1
- package/out/zero/src/adapters/postgresjs.js +7 -2
- package/out/zero/src/adapters/postgresjs.js.map +1 -1
- package/out/zero/src/analyze-query.js +1 -1
- package/out/zero/src/analyze-query.js.map +1 -1
- package/out/zero/src/ast-to-zql.js +1 -1
- package/out/zero/src/ast-to-zql.js.map +1 -1
- package/out/zero/src/build-schema.js +3 -5
- package/out/zero/src/build-schema.js.map +1 -1
- package/out/zero/src/change-protocol/v0.js +5 -3
- package/out/zero/src/change-protocol/v0.js.map +1 -1
- package/out/zero/src/cli.js +2 -2
- package/out/zero/src/cli.js.map +1 -1
- package/out/zero/src/deploy-permissions.js +1 -1
- package/out/zero/src/deploy-permissions.js.map +1 -1
- package/out/zero/src/expo-sqlite.js +5 -0
- package/out/zero/src/expo-sqlite.js.map +1 -0
- package/out/zero/src/op-sqlite.js +5 -0
- package/out/zero/src/op-sqlite.js.map +1 -0
- package/out/zero/src/pg.js +29 -3
- package/out/zero/src/pg.js.map +1 -1
- package/out/zero/src/react-native.js +13 -0
- package/out/zero/src/react-native.js.map +1 -0
- package/out/zero/src/react.js +17 -0
- package/out/zero/src/react.js.map +1 -0
- package/out/zero/src/server.js +25 -3
- package/out/zero/src/server.js.map +1 -1
- package/out/zero/src/solid.js +15 -0
- package/out/zero/src/solid.js.map +1 -0
- package/out/zero/src/sqlite.js +7 -0
- package/out/zero/src/sqlite.js.map +1 -0
- package/out/zero/src/transform-query.js +1 -1
- package/out/zero/src/transform-query.js.map +1 -1
- package/out/zero/src/zero-cache-dev.js +133 -105
- package/out/zero/src/zero-cache-dev.js.map +1 -1
- package/out/zero/src/zero-out.d.ts +3 -0
- package/out/zero/src/zero-out.d.ts.map +1 -0
- package/out/zero/src/zero-out.js +13 -0
- package/out/zero/src/zero-out.js.map +1 -0
- package/out/zero/src/zero.js +67 -0
- package/out/zero/src/zero.js.map +1 -0
- package/out/zero/src/zqlite.js +11 -3
- package/out/zero/src/zqlite.js.map +1 -1
- package/out/zero-cache/src/auth/jwt.d.ts +3 -0
- package/out/zero-cache/src/auth/jwt.d.ts.map +1 -1
- package/out/zero-cache/src/auth/jwt.js +33 -38
- package/out/zero-cache/src/auth/jwt.js.map +1 -1
- package/out/zero-cache/src/auth/load-permissions.d.ts +1 -1
- package/out/zero-cache/src/auth/load-permissions.d.ts.map +1 -1
- package/out/zero-cache/src/auth/load-permissions.js +61 -45
- package/out/zero-cache/src/auth/load-permissions.js.map +1 -1
- package/out/zero-cache/src/auth/read-authorizer.js +79 -91
- package/out/zero-cache/src/auth/read-authorizer.js.map +1 -1
- package/out/zero-cache/src/auth/write-authorizer.d.ts +4 -3
- package/out/zero-cache/src/auth/write-authorizer.d.ts.map +1 -1
- package/out/zero-cache/src/auth/write-authorizer.js +387 -328
- package/out/zero-cache/src/auth/write-authorizer.js.map +1 -1
- package/out/zero-cache/src/config/network.js +42 -45
- package/out/zero-cache/src/config/network.js.map +1 -1
- package/out/zero-cache/src/config/normalize.js +86 -83
- package/out/zero-cache/src/config/normalize.js.map +1 -1
- package/out/zero-cache/src/config/zero-config.d.ts +39 -0
- package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
- package/out/zero-cache/src/config/zero-config.js +704 -646
- package/out/zero-cache/src/config/zero-config.js.map +1 -1
- package/out/zero-cache/src/custom/fetch.d.ts +5 -3
- package/out/zero-cache/src/custom/fetch.d.ts.map +1 -1
- package/out/zero-cache/src/custom/fetch.js +171 -86
- package/out/zero-cache/src/custom/fetch.js.map +1 -1
- package/out/zero-cache/src/custom-queries/transform-query.d.ts +11 -8
- package/out/zero-cache/src/custom-queries/transform-query.d.ts.map +1 -1
- package/out/zero-cache/src/custom-queries/transform-query.js +101 -108
- package/out/zero-cache/src/custom-queries/transform-query.js.map +1 -1
- package/out/zero-cache/src/db/create.d.ts +4 -0
- package/out/zero-cache/src/db/create.d.ts.map +1 -1
- package/out/zero-cache/src/db/create.js +33 -39
- package/out/zero-cache/src/db/create.js.map +1 -1
- package/out/zero-cache/src/db/delete-lite-db.js +9 -6
- package/out/zero-cache/src/db/delete-lite-db.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 +150 -174
- package/out/zero-cache/src/db/lite-tables.js.map +1 -1
- package/out/zero-cache/src/db/migration-lite.js +170 -165
- package/out/zero-cache/src/db/migration-lite.js.map +1 -1
- package/out/zero-cache/src/db/migration.js +157 -137
- package/out/zero-cache/src/db/migration.js.map +1 -1
- package/out/zero-cache/src/db/mode-enum.d.ts +2 -0
- package/out/zero-cache/src/db/mode-enum.d.ts.map +1 -1
- package/out/zero-cache/src/db/mode-enum.js +9 -3
- package/out/zero-cache/src/db/mode-enum.js.map +1 -1
- package/out/zero-cache/src/db/pg-copy.js +51 -90
- package/out/zero-cache/src/db/pg-copy.js.map +1 -1
- package/out/zero-cache/src/db/pg-to-lite.d.ts +10 -0
- package/out/zero-cache/src/db/pg-to-lite.d.ts.map +1 -1
- package/out/zero-cache/src/db/pg-to-lite.js +116 -96
- package/out/zero-cache/src/db/pg-to-lite.js.map +1 -1
- package/out/zero-cache/src/db/pg-type-parser.js +27 -39
- package/out/zero-cache/src/db/pg-type-parser.js.map +1 -1
- package/out/zero-cache/src/db/postgres-replica-identity-enum.js +11 -6
- package/out/zero-cache/src/db/postgres-replica-identity-enum.js.map +1 -1
- package/out/zero-cache/src/db/postgres-type-class-enum.js +17 -9
- package/out/zero-cache/src/db/postgres-type-class-enum.js.map +1 -1
- package/out/zero-cache/src/db/specs.d.ts +12 -18
- package/out/zero-cache/src/db/specs.d.ts.map +1 -1
- package/out/zero-cache/src/db/specs.js +66 -40
- package/out/zero-cache/src/db/specs.js.map +1 -1
- package/out/zero-cache/src/db/statements.d.ts +1 -1
- package/out/zero-cache/src/db/statements.d.ts.map +1 -1
- package/out/zero-cache/src/db/statements.js +59 -52
- package/out/zero-cache/src/db/statements.js.map +1 -1
- package/out/zero-cache/src/db/transaction-pool.d.ts +1 -1
- package/out/zero-cache/src/db/transaction-pool.d.ts.map +1 -1
- package/out/zero-cache/src/db/transaction-pool.js +375 -501
- package/out/zero-cache/src/db/transaction-pool.js.map +1 -1
- package/out/zero-cache/src/db/warmup.js +25 -12
- package/out/zero-cache/src/db/warmup.js.map +1 -1
- package/out/zero-cache/src/observability/events.js +71 -82
- package/out/zero-cache/src/observability/events.js.map +1 -1
- package/out/zero-cache/src/observability/metrics.js +54 -32
- package/out/zero-cache/src/observability/metrics.js.map +1 -1
- package/out/zero-cache/src/scripts/decommission.d.ts +50 -0
- package/out/zero-cache/src/scripts/decommission.d.ts.map +1 -0
- package/out/zero-cache/src/scripts/decommission.js +55 -0
- package/out/zero-cache/src/scripts/decommission.js.map +1 -0
- package/out/zero-cache/src/scripts/deploy-permissions.js +128 -118
- package/out/zero-cache/src/scripts/deploy-permissions.js.map +1 -1
- package/out/zero-cache/src/scripts/permissions.d.ts +1 -1
- package/out/zero-cache/src/scripts/permissions.d.ts.map +1 -1
- package/out/zero-cache/src/scripts/permissions.js +108 -100
- package/out/zero-cache/src/scripts/permissions.js.map +1 -1
- package/out/zero-cache/src/server/anonymous-otel-start.js +410 -366
- package/out/zero-cache/src/server/anonymous-otel-start.js.map +1 -1
- package/out/zero-cache/src/server/change-streamer.d.ts.map +1 -1
- package/out/zero-cache/src/server/change-streamer.js +105 -64
- package/out/zero-cache/src/server/change-streamer.js.map +1 -1
- package/out/zero-cache/src/server/inspector-delegate.d.ts.map +1 -1
- package/out/zero-cache/src/server/inspector-delegate.js +113 -105
- package/out/zero-cache/src/server/inspector-delegate.js.map +1 -1
- package/out/zero-cache/src/server/logging.d.ts +1 -1
- package/out/zero-cache/src/server/logging.d.ts.map +1 -1
- package/out/zero-cache/src/server/logging.js +26 -19
- package/out/zero-cache/src/server/logging.js.map +1 -1
- package/out/zero-cache/src/server/main.d.ts.map +1 -1
- package/out/zero-cache/src/server/main.js +137 -120
- package/out/zero-cache/src/server/main.js.map +1 -1
- package/out/zero-cache/src/server/mutator.js +19 -0
- package/out/zero-cache/src/server/mutator.js.map +1 -0
- package/out/zero-cache/src/server/otel-diag-logger.d.ts +1 -1
- package/out/zero-cache/src/server/otel-diag-logger.d.ts.map +1 -1
- package/out/zero-cache/src/server/otel-diag-logger.js +67 -70
- package/out/zero-cache/src/server/otel-diag-logger.js.map +1 -1
- package/out/zero-cache/src/server/otel-log-sink.js +40 -41
- package/out/zero-cache/src/server/otel-log-sink.js.map +1 -1
- package/out/zero-cache/src/server/otel-start.d.ts +1 -1
- package/out/zero-cache/src/server/otel-start.d.ts.map +1 -1
- package/out/zero-cache/src/server/otel-start.js +57 -68
- package/out/zero-cache/src/server/otel-start.js.map +1 -1
- package/out/zero-cache/src/server/reaper.js +34 -26
- package/out/zero-cache/src/server/reaper.js.map +1 -1
- package/out/zero-cache/src/server/replicator.js +53 -31
- package/out/zero-cache/src/server/replicator.js.map +1 -1
- package/out/zero-cache/src/server/runner/main.js +6 -4
- package/out/zero-cache/src/server/runner/main.js.map +1 -1
- package/out/zero-cache/src/server/runner/run-worker.d.ts.map +1 -1
- package/out/zero-cache/src/server/runner/run-worker.js +46 -50
- package/out/zero-cache/src/server/runner/run-worker.js.map +1 -1
- package/out/zero-cache/src/server/runner/runtime.js +33 -32
- package/out/zero-cache/src/server/runner/runtime.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 +28 -22
- package/out/zero-cache/src/server/runner/zero-dispatcher.js.map +1 -1
- package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
- package/out/zero-cache/src/server/syncer.js +124 -63
- package/out/zero-cache/src/server/syncer.js.map +1 -1
- package/out/zero-cache/src/server/worker-dispatcher.d.ts +1 -1
- package/out/zero-cache/src/server/worker-dispatcher.d.ts.map +1 -1
- package/out/zero-cache/src/server/worker-dispatcher.js +112 -106
- package/out/zero-cache/src/server/worker-dispatcher.js.map +1 -1
- package/out/zero-cache/src/server/worker-urls.d.ts +7 -0
- package/out/zero-cache/src/server/worker-urls.d.ts.map +1 -0
- package/out/zero-cache/src/server/worker-urls.js +21 -0
- package/out/zero-cache/src/server/worker-urls.js.map +1 -0
- package/out/zero-cache/src/services/analyze.d.ts +4 -9
- package/out/zero-cache/src/services/analyze.d.ts.map +1 -1
- package/out/zero-cache/src/services/analyze.js +104 -120
- package/out/zero-cache/src/services/analyze.js.map +1 -1
- package/out/zero-cache/src/services/change-source/column-metadata.d.ts +10 -3
- package/out/zero-cache/src/services/change-source/column-metadata.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/column-metadata.js +154 -144
- package/out/zero-cache/src/services/change-source/column-metadata.js.map +1 -1
- package/out/zero-cache/src/services/change-source/custom/change-source.d.ts +1 -1
- package/out/zero-cache/src/services/change-source/custom/change-source.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/custom/change-source.js +197 -171
- package/out/zero-cache/src/services/change-source/custom/change-source.js.map +1 -1
- package/out/zero-cache/src/services/change-source/custom/sync-schema.js +11 -3
- package/out/zero-cache/src/services/change-source/custom/sync-schema.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/change-source.d.ts +1 -1
- 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 +601 -621
- package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/decommission.js +24 -23
- package/out/zero-cache/src/services/change-source/pg/decommission.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts +1 -1
- package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/initial-sync.js +327 -284
- package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/logical-replication/binary-reader.d.ts +2 -3
- package/out/zero-cache/src/services/change-source/pg/logical-replication/binary-reader.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/logical-replication/binary-reader.js +61 -69
- package/out/zero-cache/src/services/change-source/pg/logical-replication/binary-reader.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/logical-replication/pgoutput-parser.js +247 -257
- package/out/zero-cache/src/services/change-source/pg/logical-replication/pgoutput-parser.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js +127 -119
- package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/lsn.js +20 -19
- package/out/zero-cache/src/services/change-source/pg/lsn.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/ddl.d.ts +25 -25
- package/out/zero-cache/src/services/change-source/pg/schema/ddl.js +96 -119
- package/out/zero-cache/src/services/change-source/pg/schema/ddl.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/init.js +138 -117
- 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/published.d.ts +10 -10
- package/out/zero-cache/src/services/change-source/pg/schema/published.js +67 -74
- package/out/zero-cache/src/services/change-source/pg/schema/published.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts +5 -5
- package/out/zero-cache/src/services/change-source/pg/schema/shard.js +199 -188
- package/out/zero-cache/src/services/change-source/pg/schema/shard.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/validation.js +53 -38
- package/out/zero-cache/src/services/change-source/pg/schema/validation.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/sync-schema.js +11 -3
- package/out/zero-cache/src/services/change-source/pg/sync-schema.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/control.js +9 -19
- package/out/zero-cache/src/services/change-source/protocol/current/control.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts +16 -16
- package/out/zero-cache/src/services/change-source/protocol/current/data.js +143 -116
- 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 +24 -24
- package/out/zero-cache/src/services/change-source/protocol/current/downstream.js +29 -19
- package/out/zero-cache/src/services/change-source/protocol/current/downstream.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/path.js +5 -20
- package/out/zero-cache/src/services/change-source/protocol/current/path.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/status.js +12 -13
- package/out/zero-cache/src/services/change-source/protocol/current/status.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/upstream.d.ts +1 -1
- 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 +5 -4
- 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 +35 -7
- package/out/zero-cache/src/services/change-source/protocol/current.js.map +1 -1
- package/out/zero-cache/src/services/change-source/replica-schema.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/replica-schema.js +67 -37
- package/out/zero-cache/src/services/change-source/replica-schema.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/backup-monitor.d.ts +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 +139 -157
- package/out/zero-cache/src/services/change-streamer/backup-monitor.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts +14 -4
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +213 -141
- 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 +1 -1
- 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 +235 -349
- 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 +13 -9
- 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 +24 -22
- package/out/zero-cache/src/services/change-streamer/change-streamer.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/error-type-enum.js +9 -4
- package/out/zero-cache/src/services/change-streamer/error-type-enum.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/forwarder.d.ts +1 -1
- package/out/zero-cache/src/services/change-streamer/forwarder.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/forwarder.js +53 -57
- package/out/zero-cache/src/services/change-streamer/forwarder.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/replica-monitor.d.ts +16 -0
- package/out/zero-cache/src/services/change-streamer/replica-monitor.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/replica-monitor.js +48 -0
- package/out/zero-cache/src/services/change-streamer/replica-monitor.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/schema/init.js +82 -68
- package/out/zero-cache/src/services/change-streamer/schema/init.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/schema/tables.d.ts +2 -2
- 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 +93 -78
- package/out/zero-cache/src/services/change-streamer/schema/tables.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/snapshot.d.ts +58 -0
- package/out/zero-cache/src/services/change-streamer/snapshot.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/snapshot.js +28 -18
- package/out/zero-cache/src/services/change-streamer/snapshot.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/storer.d.ts +3 -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 +309 -353
- package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/subscriber.d.ts +3 -2
- package/out/zero-cache/src/services/change-streamer/subscriber.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/subscriber.js +85 -87
- package/out/zero-cache/src/services/change-streamer/subscriber.js.map +1 -1
- package/out/zero-cache/src/services/heapz.js +21 -25
- package/out/zero-cache/src/services/heapz.js.map +1 -1
- package/out/zero-cache/src/services/http-service.d.ts +6 -5
- package/out/zero-cache/src/services/http-service.d.ts.map +1 -1
- package/out/zero-cache/src/services/http-service.js +61 -59
- package/out/zero-cache/src/services/http-service.js.map +1 -1
- package/out/zero-cache/src/services/life-cycle.d.ts +1 -1
- package/out/zero-cache/src/services/life-cycle.d.ts.map +1 -1
- package/out/zero-cache/src/services/life-cycle.js +216 -255
- package/out/zero-cache/src/services/life-cycle.js.map +1 -1
- package/out/zero-cache/src/services/limiter/sliding-window-limiter.js +76 -130
- package/out/zero-cache/src/services/limiter/sliding-window-limiter.js.map +1 -1
- package/out/zero-cache/src/services/litestream/commands.d.ts +1 -1
- package/out/zero-cache/src/services/litestream/commands.d.ts.map +1 -1
- package/out/zero-cache/src/services/litestream/commands.js +201 -154
- package/out/zero-cache/src/services/litestream/commands.js.map +1 -1
- package/out/zero-cache/src/services/mutagen/error.js +11 -6
- package/out/zero-cache/src/services/mutagen/error.js.map +1 -1
- package/out/zero-cache/src/services/mutagen/mutagen.d.ts +2 -1
- package/out/zero-cache/src/services/mutagen/mutagen.d.ts.map +1 -1
- package/out/zero-cache/src/services/mutagen/mutagen.js +272 -266
- package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -1
- package/out/zero-cache/src/services/mutagen/pusher.d.ts +221 -25
- package/out/zero-cache/src/services/mutagen/pusher.d.ts.map +1 -1
- package/out/zero-cache/src/services/mutagen/pusher.js +356 -332
- package/out/zero-cache/src/services/mutagen/pusher.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 +483 -497
- package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
- package/out/zero-cache/src/services/replicator/incremental-sync.d.ts +1 -1
- package/out/zero-cache/src/services/replicator/incremental-sync.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/incremental-sync.js +97 -97
- package/out/zero-cache/src/services/replicator/incremental-sync.js.map +1 -1
- package/out/zero-cache/src/services/replicator/notifier.js +28 -52
- package/out/zero-cache/src/services/replicator/notifier.js.map +1 -1
- package/out/zero-cache/src/services/replicator/replication-status.js +100 -83
- package/out/zero-cache/src/services/replicator/replication-status.js.map +1 -1
- package/out/zero-cache/src/services/replicator/replicator.d.ts +1 -1
- package/out/zero-cache/src/services/replicator/replicator.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/replicator.js +33 -26
- package/out/zero-cache/src/services/replicator/replicator.js.map +1 -1
- package/out/zero-cache/src/services/replicator/schema/change-log.d.ts +1 -1
- package/out/zero-cache/src/services/replicator/schema/change-log.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/schema/change-log.js +74 -86
- package/out/zero-cache/src/services/replicator/schema/change-log.js.map +1 -1
- package/out/zero-cache/src/services/replicator/schema/constants.js +5 -7
- package/out/zero-cache/src/services/replicator/schema/constants.js.map +1 -1
- package/out/zero-cache/src/services/replicator/schema/replication-state.d.ts +2 -2
- package/out/zero-cache/src/services/replicator/schema/replication-state.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/schema/replication-state.js +70 -74
- package/out/zero-cache/src/services/replicator/schema/replication-state.js.map +1 -1
- package/out/zero-cache/src/services/run-ast.d.ts +9 -3
- package/out/zero-cache/src/services/run-ast.d.ts.map +1 -1
- package/out/zero-cache/src/services/run-ast.js +87 -78
- package/out/zero-cache/src/services/run-ast.js.map +1 -1
- package/out/zero-cache/src/services/runner.d.ts +1 -1
- package/out/zero-cache/src/services/runner.d.ts.map +1 -1
- package/out/zero-cache/src/services/runner.js +40 -40
- package/out/zero-cache/src/services/runner.js.map +1 -1
- package/out/zero-cache/src/services/running-state.d.ts +1 -1
- package/out/zero-cache/src/services/running-state.d.ts.map +1 -1
- package/out/zero-cache/src/services/running-state.js +122 -119
- package/out/zero-cache/src/services/running-state.js.map +1 -1
- package/out/zero-cache/src/services/statz.js +184 -162
- package/out/zero-cache/src/services/statz.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/active-users-gauge.js +40 -39
- package/out/zero-cache/src/services/view-syncer/active-users-gauge.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/client-handler.d.ts +3 -1
- 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 +307 -294
- package/out/zero-cache/src/services/view-syncer/client-handler.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/client-schema.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/client-schema.js +81 -80
- package/out/zero-cache/src/services/view-syncer/client-schema.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr-purger.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr-purger.js +84 -94
- package/out/zero-cache/src/services/view-syncer/cvr-purger.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts +6 -8
- 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 +655 -603
- 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 +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr.js +633 -693
- package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/drain-coordinator.d.ts +1 -0
- 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 +38 -55
- package/out/zero-cache/src/services/view-syncer/drain-coordinator.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts +2 -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 +175 -85
- 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 +15 -14
- 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 +535 -449
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/row-record-cache.d.ts +1 -1
- package/out/zero-cache/src/services/view-syncer/row-record-cache.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/row-record-cache.js +229 -277
- package/out/zero-cache/src/services/view-syncer/row-record-cache.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/schema/cvr.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/schema/cvr.js +57 -122
- package/out/zero-cache/src/services/view-syncer/schema/cvr.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/schema/init.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/schema/init.js +177 -131
- package/out/zero-cache/src/services/view-syncer/schema/init.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/schema/types.d.ts +4 -4
- package/out/zero-cache/src/services/view-syncer/schema/types.js +265 -257
- package/out/zero-cache/src/services/view-syncer/schema/types.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts +3 -3
- package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/snapshotter.js +295 -338
- package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/ttl-clock.js +13 -7
- package/out/zero-cache/src/services/view-syncer/ttl-clock.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts +10 -3
- 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 +1510 -1250
- package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
- package/out/zero-cache/src/types/error-with-level.d.ts +9 -0
- package/out/zero-cache/src/types/error-with-level.d.ts.map +1 -0
- package/out/zero-cache/src/types/error-with-level.js +33 -0
- package/out/zero-cache/src/types/error-with-level.js.map +1 -0
- package/out/zero-cache/src/types/http.js +27 -14
- package/out/zero-cache/src/types/http.js.map +1 -1
- package/out/zero-cache/src/types/lexi-version.js +46 -31
- package/out/zero-cache/src/types/lexi-version.js.map +1 -1
- package/out/zero-cache/src/types/lite.d.ts +15 -13
- package/out/zero-cache/src/types/lite.d.ts.map +1 -1
- package/out/zero-cache/src/types/lite.js +119 -114
- package/out/zero-cache/src/types/lite.js.map +1 -1
- package/out/zero-cache/src/types/names.js +6 -3
- package/out/zero-cache/src/types/names.js.map +1 -1
- package/out/zero-cache/src/types/pg-data-type.d.ts +73 -0
- package/out/zero-cache/src/types/pg-data-type.d.ts.map +1 -0
- package/out/zero-cache/src/types/pg-data-type.js +82 -0
- package/out/zero-cache/src/types/pg-data-type.js.map +1 -0
- package/out/zero-cache/src/types/pg-types.js +17 -72
- package/out/zero-cache/src/types/pg-types.js.map +1 -1
- package/out/zero-cache/src/types/pg.d.ts +2 -74
- package/out/zero-cache/src/types/pg.d.ts.map +1 -1
- package/out/zero-cache/src/types/pg.js +212 -309
- package/out/zero-cache/src/types/pg.js.map +1 -1
- package/out/zero-cache/src/types/processes.d.ts +2 -2
- package/out/zero-cache/src/types/processes.d.ts.map +1 -1
- package/out/zero-cache/src/types/processes.js +95 -143
- package/out/zero-cache/src/types/processes.js.map +1 -1
- package/out/zero-cache/src/types/profiler.js +29 -30
- package/out/zero-cache/src/types/profiler.js.map +1 -1
- package/out/zero-cache/src/types/row-key.js +30 -68
- package/out/zero-cache/src/types/row-key.js.map +1 -1
- package/out/zero-cache/src/types/schema-versions.d.ts +7 -3
- package/out/zero-cache/src/types/schema-versions.d.ts.map +1 -1
- package/out/zero-cache/src/types/schema-versions.js +26 -18
- package/out/zero-cache/src/types/schema-versions.js.map +1 -1
- package/out/zero-cache/src/types/shards.js +50 -36
- package/out/zero-cache/src/types/shards.js.map +1 -1
- package/out/zero-cache/src/types/sql.js +9 -13
- package/out/zero-cache/src/types/sql.js.map +1 -1
- package/out/zero-cache/src/types/streams.d.ts +1 -1
- package/out/zero-cache/src/types/streams.d.ts.map +1 -1
- package/out/zero-cache/src/types/streams.js +246 -245
- package/out/zero-cache/src/types/streams.js.map +1 -1
- package/out/zero-cache/src/types/strings.js +14 -11
- package/out/zero-cache/src/types/strings.js.map +1 -1
- package/out/zero-cache/src/types/subscription.d.ts +17 -2
- package/out/zero-cache/src/types/subscription.d.ts.map +1 -1
- package/out/zero-cache/src/types/subscription.js +202 -225
- package/out/zero-cache/src/types/subscription.js.map +1 -1
- package/out/zero-cache/src/types/url-params.js +35 -30
- package/out/zero-cache/src/types/url-params.js.map +1 -1
- package/out/zero-cache/src/types/websocket-handoff.d.ts +7 -6
- package/out/zero-cache/src/types/websocket-handoff.d.ts.map +1 -1
- package/out/zero-cache/src/types/websocket-handoff.js +68 -74
- package/out/zero-cache/src/types/websocket-handoff.js.map +1 -1
- package/out/zero-cache/src/types/ws.js +56 -59
- package/out/zero-cache/src/types/ws.js.map +1 -1
- package/out/zero-cache/src/workers/connect-params.js +44 -40
- package/out/zero-cache/src/workers/connect-params.js.map +1 -1
- package/out/zero-cache/src/workers/connection.d.ts +6 -1
- package/out/zero-cache/src/workers/connection.d.ts.map +1 -1
- package/out/zero-cache/src/workers/connection.js +283 -227
- package/out/zero-cache/src/workers/connection.js.map +1 -1
- package/out/zero-cache/src/workers/mutator.js +24 -0
- package/out/zero-cache/src/workers/mutator.js.map +1 -0
- package/out/zero-cache/src/workers/replicator.d.ts +1 -1
- package/out/zero-cache/src/workers/replicator.d.ts.map +1 -1
- package/out/zero-cache/src/workers/replicator.js +103 -106
- package/out/zero-cache/src/workers/replicator.js.map +1 -1
- package/out/zero-cache/src/workers/syncer-ws-message-handler.d.ts.map +1 -1
- package/out/zero-cache/src/workers/syncer-ws-message-handler.js +179 -141
- package/out/zero-cache/src/workers/syncer-ws-message-handler.js.map +1 -1
- package/out/zero-cache/src/workers/syncer.d.ts +3 -3
- package/out/zero-cache/src/workers/syncer.d.ts.map +1 -1
- package/out/zero-cache/src/workers/syncer.js +195 -154
- package/out/zero-cache/src/workers/syncer.js.map +1 -1
- package/out/zero-client/src/client/active-clients-manager.js +199 -0
- package/out/zero-client/src/client/active-clients-manager.js.map +1 -0
- package/out/zero-client/src/client/bindings.d.ts +43 -0
- package/out/zero-client/src/client/bindings.d.ts.map +1 -0
- package/out/zero-client/src/client/bindings.js +33 -0
- package/out/zero-client/src/client/bindings.js.map +1 -0
- package/out/zero-client/src/client/client-error-kind-enum.d.ts +14 -6
- package/out/zero-client/src/client/client-error-kind-enum.d.ts.map +1 -1
- package/out/zero-client/src/client/client-error-kind-enum.js +29 -0
- package/out/zero-client/src/client/client-error-kind-enum.js.map +1 -0
- package/out/zero-client/src/client/connection-manager.d.ts +70 -22
- package/out/zero-client/src/client/connection-manager.d.ts.map +1 -1
- package/out/zero-client/src/client/connection-manager.js +310 -0
- package/out/zero-client/src/client/connection-manager.js.map +1 -0
- package/out/zero-client/src/client/connection-status-enum.d.ts +4 -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 +15 -0
- package/out/zero-client/src/client/connection-status-enum.js.map +1 -0
- package/out/zero-client/src/client/connection.d.ts +96 -0
- package/out/zero-client/src/client/connection.d.ts.map +1 -0
- package/out/zero-client/src/client/connection.js +103 -0
- package/out/zero-client/src/client/connection.js.map +1 -0
- package/out/zero-client/src/client/context.d.ts +9 -10
- package/out/zero-client/src/client/context.d.ts.map +1 -1
- package/out/zero-client/src/client/context.js +104 -0
- package/out/zero-client/src/client/context.js.map +1 -0
- package/out/zero-client/src/client/crud.d.ts +8 -6
- package/out/zero-client/src/client/crud.d.ts.map +1 -1
- package/out/zero-client/src/client/crud.js +225 -0
- package/out/zero-client/src/client/crud.js.map +1 -0
- package/out/zero-client/src/client/custom.d.ts +48 -25
- package/out/zero-client/src/client/custom.d.ts.map +1 -1
- package/out/zero-client/src/client/custom.js +128 -0
- package/out/zero-client/src/client/custom.js.map +1 -0
- package/out/zero-client/src/client/delete-clients-manager.d.ts +2 -2
- package/out/zero-client/src/client/delete-clients-manager.d.ts.map +1 -1
- package/out/zero-client/src/client/delete-clients-manager.js +71 -0
- package/out/zero-client/src/client/delete-clients-manager.js.map +1 -0
- package/out/zero-client/src/client/enable-analytics.js +18 -0
- package/out/zero-client/src/client/enable-analytics.js.map +1 -0
- package/out/zero-client/src/client/error.d.ts +62 -22
- package/out/zero-client/src/client/error.d.ts.map +1 -1
- package/out/zero-client/src/client/error.js +148 -0
- package/out/zero-client/src/client/error.js.map +1 -0
- package/out/zero-client/src/client/http-string.js +11 -0
- package/out/zero-client/src/client/http-string.js.map +1 -0
- package/out/zero-client/src/client/inspector/client-group.js +27 -0
- package/out/zero-client/src/client/inspector/client-group.js.map +1 -0
- package/out/zero-client/src/client/inspector/client.js +28 -0
- package/out/zero-client/src/client/inspector/client.js.map +1 -0
- package/out/zero-client/src/client/inspector/html-dialog-prompt.d.ts.map +1 -1
- package/out/zero-client/src/client/inspector/html-dialog-prompt.js +77 -0
- package/out/zero-client/src/client/inspector/html-dialog-prompt.js.map +1 -0
- package/out/zero-client/src/client/inspector/inspector.d.ts +8 -3
- package/out/zero-client/src/client/inspector/inspector.d.ts.map +1 -1
- package/out/zero-client/src/client/inspector/inspector.js +54 -0
- package/out/zero-client/src/client/inspector/inspector.js.map +1 -0
- package/out/zero-client/src/client/inspector/lazy-inspector.d.ts +4 -1
- package/out/zero-client/src/client/inspector/lazy-inspector.d.ts.map +1 -1
- package/out/zero-client/src/client/inspector/lazy-inspector.js +243 -0
- package/out/zero-client/src/client/inspector/lazy-inspector.js.map +1 -0
- package/out/zero-client/src/client/inspector/query.d.ts.map +1 -1
- package/out/zero-client/src/client/inspector/query.js +82 -0
- package/out/zero-client/src/client/inspector/query.js.map +1 -0
- package/out/zero-client/src/client/ivm-branch.d.ts +6 -6
- package/out/zero-client/src/client/ivm-branch.d.ts.map +1 -1
- package/out/zero-client/src/client/ivm-branch.js +149 -0
- package/out/zero-client/src/client/ivm-branch.js.map +1 -0
- package/out/zero-client/src/client/keys.js +45 -0
- package/out/zero-client/src/client/keys.js.map +1 -0
- package/out/zero-client/src/client/log-options.js +60 -0
- package/out/zero-client/src/client/log-options.js.map +1 -0
- package/out/zero-client/src/client/make-mutate-property.d.ts +43 -0
- package/out/zero-client/src/client/make-mutate-property.d.ts.map +1 -0
- package/out/zero-client/src/client/make-mutate-property.js +38 -0
- package/out/zero-client/src/client/make-mutate-property.js.map +1 -0
- package/out/zero-client/src/client/make-replicache-mutators.d.ts +34 -0
- package/out/zero-client/src/client/make-replicache-mutators.d.ts.map +1 -0
- package/out/zero-client/src/client/make-replicache-mutators.js +103 -0
- package/out/zero-client/src/client/make-replicache-mutators.js.map +1 -0
- package/out/zero-client/src/client/metric-name-enum.js +15 -0
- package/out/zero-client/src/client/metric-name-enum.js.map +1 -0
- package/out/zero-client/src/client/metrics.d.ts +11 -2
- package/out/zero-client/src/client/metrics.d.ts.map +1 -1
- package/out/zero-client/src/client/metrics.js +249 -0
- package/out/zero-client/src/client/metrics.js.map +1 -0
- package/out/zero-client/src/client/mutation-tracker.d.ts +15 -6
- package/out/zero-client/src/client/mutation-tracker.d.ts.map +1 -1
- package/out/zero-client/src/client/mutation-tracker.js +363 -0
- package/out/zero-client/src/client/mutation-tracker.js.map +1 -0
- package/out/zero-client/src/client/mutator-proxy.d.ts +15 -0
- package/out/zero-client/src/client/mutator-proxy.d.ts.map +1 -0
- package/out/zero-client/src/client/mutator-proxy.js +132 -0
- package/out/zero-client/src/client/mutator-proxy.js.map +1 -0
- package/out/zero-client/src/client/options.d.ts +83 -26
- package/out/zero-client/src/client/options.d.ts.map +1 -1
- package/out/zero-client/src/client/options.js +11 -0
- package/out/zero-client/src/client/options.js.map +1 -0
- package/out/zero-client/src/client/query-manager.d.ts +13 -5
- package/out/zero-client/src/client/query-manager.d.ts.map +1 -1
- package/out/zero-client/src/client/query-manager.js +377 -0
- package/out/zero-client/src/client/query-manager.js.map +1 -0
- package/out/zero-client/src/client/reload-error-handler.d.ts +4 -4
- package/out/zero-client/src/client/reload-error-handler.d.ts.map +1 -1
- package/out/zero-client/src/client/reload-error-handler.js +114 -0
- package/out/zero-client/src/client/reload-error-handler.js.map +1 -0
- package/out/zero-client/src/client/server-option.js +64 -0
- package/out/zero-client/src/client/server-option.js.map +1 -0
- package/out/zero-client/src/client/update-needed-reason-type-enum.js +9 -0
- package/out/zero-client/src/client/update-needed-reason-type-enum.js.map +1 -0
- package/out/zero-client/src/client/version.js +5 -0
- package/out/zero-client/src/client/version.js.map +1 -0
- package/out/zero-client/src/client/zero-poke-handler.d.ts +4 -4
- package/out/zero-client/src/client/zero-poke-handler.d.ts.map +1 -1
- package/out/zero-client/src/client/zero-poke-handler.js +303 -0
- package/out/zero-client/src/client/zero-poke-handler.js.map +1 -0
- package/out/zero-client/src/client/zero-rep.d.ts +6 -3
- package/out/zero-client/src/client/zero-rep.d.ts.map +1 -1
- package/out/zero-client/src/client/zero-rep.js +72 -0
- package/out/zero-client/src/client/zero-rep.js.map +1 -0
- package/out/zero-client/src/client/zero.d.ts +125 -25
- package/out/zero-client/src/client/zero.d.ts.map +1 -1
- package/out/zero-client/src/client/zero.js +1759 -0
- package/out/zero-client/src/client/zero.js.map +1 -0
- package/out/zero-client/src/mod.d.ts +24 -10
- package/out/zero-client/src/mod.d.ts.map +1 -1
- package/out/zero-client/src/types/query-result.d.ts +24 -0
- package/out/zero-client/src/types/query-result.d.ts.map +1 -0
- package/out/zero-client/src/util/nanoid.js +21 -0
- package/out/zero-client/src/util/nanoid.js.map +1 -0
- package/out/zero-client/src/util/socket.js +7 -0
- package/out/zero-client/src/util/socket.js.map +1 -0
- package/out/zero-protocol/src/analyze-query-result.d.ts +237 -0
- package/out/zero-protocol/src/analyze-query-result.d.ts.map +1 -1
- package/out/zero-protocol/src/analyze-query-result.js +159 -24
- package/out/zero-protocol/src/analyze-query-result.js.map +1 -1
- package/out/zero-protocol/src/application-error.d.ts +27 -0
- package/out/zero-protocol/src/application-error.d.ts.map +1 -0
- package/out/zero-protocol/src/application-error.js +38 -0
- package/out/zero-protocol/src/application-error.js.map +1 -0
- package/out/zero-protocol/src/ast.d.ts +2 -2
- package/out/zero-protocol/src/ast.js +296 -277
- package/out/zero-protocol/src/ast.js.map +1 -1
- package/out/zero-protocol/src/change-desired-queries.d.ts +2 -2
- package/out/zero-protocol/src/change-desired-queries.js +11 -7
- package/out/zero-protocol/src/change-desired-queries.js.map +1 -1
- package/out/zero-protocol/src/client-schema.d.ts +2 -2
- package/out/zero-protocol/src/client-schema.d.ts.map +1 -1
- package/out/zero-protocol/src/client-schema.js +40 -26
- package/out/zero-protocol/src/client-schema.js.map +1 -1
- package/out/zero-protocol/src/close-connection.js +11 -18
- package/out/zero-protocol/src/close-connection.js.map +1 -1
- package/out/zero-protocol/src/connect.d.ts +4 -4
- package/out/zero-protocol/src/connect.d.ts.map +1 -1
- package/out/zero-protocol/src/connect.js +50 -51
- package/out/zero-protocol/src/connect.js.map +1 -1
- package/out/zero-protocol/src/custom-queries.d.ts +56 -53
- package/out/zero-protocol/src/custom-queries.d.ts.map +1 -1
- package/out/zero-protocol/src/custom-queries.js +63 -39
- package/out/zero-protocol/src/custom-queries.js.map +1 -1
- package/out/zero-protocol/src/data.js +9 -4
- package/out/zero-protocol/src/data.js.map +1 -1
- package/out/zero-protocol/src/delete-clients.js +16 -9
- package/out/zero-protocol/src/delete-clients.js.map +1 -1
- package/out/zero-protocol/src/down.d.ts +114 -16
- package/out/zero-protocol/src/down.d.ts.map +1 -1
- package/out/zero-protocol/src/down.js +20 -4
- package/out/zero-protocol/src/down.js.map +1 -1
- package/out/zero-protocol/src/error-kind-enum.d.ts +65 -0
- package/out/zero-protocol/src/error-kind-enum.d.ts.map +1 -1
- package/out/zero-protocol/src/error-kind-enum.js +41 -21
- package/out/zero-protocol/src/error-kind-enum.js.map +1 -1
- package/out/zero-protocol/src/error-origin-enum.d.ts +7 -0
- package/out/zero-protocol/src/error-origin-enum.d.ts.map +1 -0
- package/out/zero-protocol/src/error-origin-enum.js +9 -0
- package/out/zero-protocol/src/error-origin-enum.js.map +1 -0
- package/out/zero-protocol/src/error-origin.d.ts +5 -0
- package/out/zero-protocol/src/error-origin.d.ts.map +1 -0
- package/out/zero-protocol/src/error-reason-enum.d.ts +15 -0
- package/out/zero-protocol/src/error-reason-enum.d.ts.map +1 -0
- package/out/zero-protocol/src/error-reason-enum.js +17 -0
- package/out/zero-protocol/src/error-reason-enum.js.map +1 -0
- package/out/zero-protocol/src/error-reason.d.ts +5 -0
- package/out/zero-protocol/src/error-reason.d.ts.map +1 -0
- package/out/zero-protocol/src/error.d.ts +182 -2
- package/out/zero-protocol/src/error.d.ts.map +1 -1
- package/out/zero-protocol/src/error.js +157 -26
- package/out/zero-protocol/src/error.js.map +1 -1
- package/out/zero-protocol/src/inspect-down.d.ts +318 -18
- package/out/zero-protocol/src/inspect-down.d.ts.map +1 -1
- package/out/zero-protocol/src/inspect-down.js +72 -54
- package/out/zero-protocol/src/inspect-down.js.map +1 -1
- package/out/zero-protocol/src/inspect-up.d.ts +10 -6
- package/out/zero-protocol/src/inspect-up.d.ts.map +1 -1
- package/out/zero-protocol/src/inspect-up.js +39 -26
- package/out/zero-protocol/src/inspect-up.js.map +1 -1
- package/out/zero-protocol/src/mutation-id.d.ts +7 -0
- package/out/zero-protocol/src/mutation-id.d.ts.map +1 -0
- package/out/zero-protocol/src/mutation-id.js +10 -0
- package/out/zero-protocol/src/mutation-id.js.map +1 -0
- package/out/zero-protocol/src/mutation-type-enum.js +7 -3
- package/out/zero-protocol/src/mutation-type-enum.js.map +1 -1
- package/out/zero-protocol/src/mutations-patch.d.ts +6 -3
- package/out/zero-protocol/src/mutations-patch.d.ts.map +1 -1
- package/out/zero-protocol/src/mutations-patch.js +18 -18
- package/out/zero-protocol/src/mutations-patch.js.map +1 -1
- package/out/zero-protocol/src/ping.js +9 -4
- package/out/zero-protocol/src/ping.js.map +1 -1
- package/out/zero-protocol/src/poke.d.ts +2 -0
- package/out/zero-protocol/src/poke.d.ts.map +1 -1
- package/out/zero-protocol/src/poke.js +55 -72
- package/out/zero-protocol/src/poke.js.map +1 -1
- package/out/zero-protocol/src/pong.js +9 -4
- package/out/zero-protocol/src/pong.js.map +1 -1
- package/out/zero-protocol/src/primary-key.js +19 -5
- package/out/zero-protocol/src/primary-key.js.map +1 -1
- package/out/zero-protocol/src/protocol-version.d.ts +2 -2
- package/out/zero-protocol/src/protocol-version.d.ts.map +1 -1
- package/out/zero-protocol/src/protocol-version.js +7 -56
- package/out/zero-protocol/src/protocol-version.js.map +1 -1
- package/out/zero-protocol/src/pull.js +26 -19
- package/out/zero-protocol/src/pull.js.map +1 -1
- package/out/zero-protocol/src/push.d.ts +145 -13
- package/out/zero-protocol/src/push.d.ts.map +1 -1
- package/out/zero-protocol/src/push.js +182 -157
- package/out/zero-protocol/src/push.js.map +1 -1
- package/out/zero-protocol/src/queries-patch.d.ts +3 -3
- package/out/zero-protocol/src/queries-patch.js +29 -22
- package/out/zero-protocol/src/queries-patch.js.map +1 -1
- package/out/zero-protocol/src/query-hash.js +18 -14
- package/out/zero-protocol/src/query-hash.js.map +1 -1
- package/out/zero-protocol/src/row-patch.js +29 -20
- package/out/zero-protocol/src/row-patch.js.map +1 -1
- package/out/zero-protocol/src/up.d.ts +6 -5
- package/out/zero-protocol/src/up.d.ts.map +1 -1
- package/out/zero-protocol/src/up.js +18 -4
- package/out/zero-protocol/src/up.js.map +1 -1
- package/out/zero-protocol/src/version.js +9 -4
- package/out/zero-protocol/src/version.js.map +1 -1
- package/out/zero-react/src/components/inspector.d.ts +5 -3
- package/out/zero-react/src/components/inspector.d.ts.map +1 -1
- package/out/{inspector-IU2HG74I.js → zero-react/src/components/inspector.js} +4 -9
- package/out/zero-react/src/components/inspector.js.map +1 -0
- package/out/{chunk-VZOYWIRW.js → zero-react/src/components/mark-icon.js} +3 -5
- package/out/zero-react/src/components/mark-icon.js.map +1 -0
- package/out/zero-react/src/components/zero-inspector.d.ts +5 -3
- package/out/zero-react/src/components/zero-inspector.d.ts.map +1 -1
- package/out/zero-react/src/components/zero-inspector.js +44 -0
- package/out/zero-react/src/components/zero-inspector.js.map +1 -0
- package/out/zero-react/src/mod.d.ts +6 -3
- package/out/zero-react/src/mod.d.ts.map +1 -1
- package/out/zero-react/src/use-query.d.ts +11 -28
- package/out/zero-react/src/use-query.d.ts.map +1 -1
- package/out/zero-react/src/use-query.js +286 -0
- package/out/zero-react/src/use-query.js.map +1 -0
- package/out/zero-react/src/use-zero-connection-state.d.ts +9 -0
- package/out/zero-react/src/use-zero-connection-state.d.ts.map +1 -0
- package/out/zero-react/src/use-zero-connection-state.js +14 -0
- package/out/zero-react/src/use-zero-connection-state.js.map +1 -0
- package/out/zero-react/src/use-zero-online.d.ts +2 -0
- package/out/zero-react/src/use-zero-online.d.ts.map +1 -1
- package/out/zero-react/src/use-zero-online.js +14 -0
- package/out/zero-react/src/use-zero-online.js.map +1 -0
- package/out/zero-react/src/zero-provider.d.ts +21 -7
- package/out/zero-react/src/zero-provider.d.ts.map +1 -1
- package/out/zero-react/src/zero-provider.js +61 -0
- package/out/zero-react/src/zero-provider.js.map +1 -0
- package/out/zero-schema/src/builder/relationship-builder.js +22 -19
- package/out/zero-schema/src/builder/relationship-builder.js.map +1 -1
- package/out/zero-schema/src/builder/schema-builder.d.ts +1 -3
- package/out/zero-schema/src/builder/schema-builder.d.ts.map +1 -1
- package/out/zero-schema/src/builder/schema-builder.js +81 -71
- package/out/zero-schema/src/builder/schema-builder.js.map +1 -1
- package/out/zero-schema/src/builder/table-builder.js +117 -116
- package/out/zero-schema/src/builder/table-builder.js.map +1 -1
- package/out/zero-schema/src/compiled-permissions.js +23 -19
- package/out/zero-schema/src/compiled-permissions.js.map +1 -1
- package/out/zero-schema/src/name-mapper.js +43 -38
- package/out/zero-schema/src/name-mapper.js.map +1 -1
- package/out/zero-schema/src/permissions.d.ts +9 -9
- package/out/zero-schema/src/permissions.d.ts.map +1 -1
- package/out/{chunk-BJ2CGCME.js → zero-schema/src/permissions.js} +16 -173
- package/out/zero-schema/src/permissions.js.map +1 -0
- package/out/zero-schema/src/schema-config.d.ts +1 -1
- package/out/zero-schema/src/schema-config.d.ts.map +1 -1
- package/out/zero-schema/src/schema-config.js +35 -51
- package/out/zero-schema/src/schema-config.js.map +1 -1
- package/out/zero-server/src/adapters/drizzle.d.ts +2 -2
- package/out/zero-server/src/adapters/drizzle.d.ts.map +1 -1
- package/out/zero-server/src/adapters/drizzle.js +84 -97
- package/out/zero-server/src/adapters/drizzle.js.map +1 -1
- package/out/zero-server/src/adapters/pg.d.ts +8 -2
- package/out/zero-server/src/adapters/pg.d.ts.map +1 -1
- package/out/zero-server/src/adapters/pg.js +54 -74
- package/out/zero-server/src/adapters/pg.js.map +1 -1
- package/out/zero-server/src/adapters/postgresjs.d.ts +7 -2
- package/out/zero-server/src/adapters/postgresjs.d.ts.map +1 -1
- package/out/zero-server/src/adapters/postgresjs.js +40 -54
- package/out/zero-server/src/adapters/postgresjs.js.map +1 -1
- package/out/zero-server/src/custom.d.ts +14 -18
- package/out/zero-server/src/custom.d.ts.map +1 -1
- package/out/zero-server/src/custom.js +185 -105
- package/out/zero-server/src/custom.js.map +1 -1
- package/out/zero-server/src/logging.js +7 -4
- package/out/zero-server/src/logging.js.map +1 -1
- package/out/zero-server/src/mod.d.ts +5 -4
- package/out/zero-server/src/mod.d.ts.map +1 -1
- package/out/zero-server/src/pg-query-executor.d.ts +11 -0
- package/out/zero-server/src/pg-query-executor.d.ts.map +1 -0
- package/out/zero-server/src/pg-query-executor.js +20 -0
- package/out/zero-server/src/pg-query-executor.js.map +1 -0
- package/out/zero-server/src/process-mutations.d.ts +11 -15
- package/out/zero-server/src/process-mutations.d.ts.map +1 -1
- package/out/zero-server/src/process-mutations.js +341 -163
- package/out/zero-server/src/process-mutations.js.map +1 -1
- package/out/zero-server/src/push-processor.d.ts +5 -3
- package/out/zero-server/src/push-processor.d.ts.map +1 -1
- package/out/zero-server/src/push-processor.js +48 -32
- package/out/zero-server/src/push-processor.js.map +1 -1
- package/out/zero-server/src/queries/process-queries.d.ts +66 -4
- package/out/zero-server/src/queries/process-queries.d.ts.map +1 -1
- package/out/zero-server/src/queries/process-queries.js +101 -27
- package/out/zero-server/src/queries/process-queries.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 +137 -125
- package/out/zero-server/src/schema.js.map +1 -1
- package/out/zero-server/src/zql-database.d.ts +9 -6
- package/out/zero-server/src/zql-database.d.ts.map +1 -1
- package/out/zero-server/src/zql-database.js +68 -51
- package/out/zero-server/src/zql-database.js.map +1 -1
- package/out/zero-solid/src/mod.d.ts +10 -2
- package/out/zero-solid/src/mod.d.ts.map +1 -1
- package/out/zero-solid/src/solid-view.d.ts +3 -23
- package/out/zero-solid/src/solid-view.d.ts.map +1 -1
- package/out/{solid.js → zero-solid/src/solid-view.js} +54 -167
- package/out/zero-solid/src/solid-view.js.map +1 -0
- package/out/zero-solid/src/use-query.d.ts +7 -6
- package/out/zero-solid/src/use-query.d.ts.map +1 -1
- package/out/zero-solid/src/use-query.js +57 -0
- package/out/zero-solid/src/use-query.js.map +1 -0
- package/out/zero-solid/src/use-zero-connection-state.d.ts +10 -0
- package/out/zero-solid/src/use-zero-connection-state.d.ts.map +1 -0
- package/out/zero-solid/src/use-zero-connection-state.js +17 -0
- package/out/zero-solid/src/use-zero-connection-state.js.map +1 -0
- package/out/zero-solid/src/use-zero-online.d.ts +1 -7
- package/out/zero-solid/src/use-zero-online.d.ts.map +1 -1
- package/out/zero-solid/src/use-zero-online.js +15 -0
- package/out/zero-solid/src/use-zero-online.js.map +1 -0
- package/out/zero-solid/src/use-zero.d.ts +24 -7
- package/out/zero-solid/src/use-zero.d.ts.map +1 -1
- package/out/zero-solid/src/use-zero.js +70 -0
- package/out/zero-solid/src/use-zero.js.map +1 -0
- package/out/zero-types/src/default-types.d.ts +38 -0
- package/out/zero-types/src/default-types.d.ts.map +1 -0
- package/out/zero-types/src/format.js +7 -4
- package/out/zero-types/src/format.js.map +1 -1
- package/out/zero-types/src/name-mapper.js +43 -40
- package/out/zero-types/src/name-mapper.js.map +1 -1
- package/out/zero-types/src/server-schema.d.ts.map +1 -0
- package/out/zql/src/builder/builder.d.ts +11 -2
- package/out/zql/src/builder/builder.d.ts.map +1 -1
- package/out/zql/src/builder/builder.js +487 -424
- package/out/zql/src/builder/builder.js.map +1 -1
- package/out/zql/src/builder/debug-delegate.d.ts +4 -0
- package/out/zql/src/builder/debug-delegate.d.ts.map +1 -1
- package/out/zql/src/builder/debug-delegate.js +68 -47
- package/out/zql/src/builder/debug-delegate.js.map +1 -1
- package/out/zql/src/builder/filter.js +132 -138
- package/out/zql/src/builder/filter.js.map +1 -1
- package/out/zql/src/builder/like.js +44 -51
- package/out/zql/src/builder/like.js.map +1 -1
- package/out/zql/src/error.d.ts +5 -0
- package/out/zql/src/error.d.ts.map +1 -1
- package/out/zql/src/error.js +18 -6
- package/out/zql/src/error.js.map +1 -1
- package/out/zql/src/ivm/array-view.js +86 -92
- package/out/zql/src/ivm/array-view.js.map +1 -1
- package/out/zql/src/ivm/constraint.js +74 -127
- package/out/zql/src/ivm/constraint.js.map +1 -1
- package/out/zql/src/ivm/data.d.ts +1 -1
- package/out/zql/src/ivm/data.d.ts.map +1 -1
- package/out/zql/src/ivm/data.js +59 -85
- package/out/zql/src/ivm/data.js.map +1 -1
- package/out/zql/src/ivm/exists.js +236 -243
- package/out/zql/src/ivm/exists.js.map +1 -1
- package/out/zql/src/ivm/fan-in.js +50 -51
- package/out/zql/src/ivm/fan-in.js.map +1 -1
- package/out/zql/src/ivm/fan-out.js +48 -50
- package/out/zql/src/ivm/fan-out.js.map +1 -1
- package/out/zql/src/ivm/filter-operators.js +87 -87
- package/out/zql/src/ivm/filter-operators.js.map +1 -1
- package/out/zql/src/ivm/filter-push.d.ts +1 -1
- package/out/zql/src/ivm/filter-push.d.ts.map +1 -1
- package/out/zql/src/ivm/filter-push.js +26 -23
- package/out/zql/src/ivm/filter-push.js.map +1 -1
- package/out/zql/src/ivm/filter.js +30 -32
- package/out/zql/src/ivm/filter.js.map +1 -1
- package/out/zql/src/ivm/flipped-join.js +343 -326
- package/out/zql/src/ivm/flipped-join.js.map +1 -1
- package/out/zql/src/ivm/join-utils.js +85 -79
- package/out/zql/src/ivm/join-utils.js.map +1 -1
- package/out/zql/src/ivm/join.js +287 -207
- package/out/zql/src/ivm/join.js.map +1 -1
- package/out/zql/src/ivm/maybe-split-and-push-edit-change.js +26 -24
- package/out/zql/src/ivm/maybe-split-and-push-edit-change.js.map +1 -1
- package/out/zql/src/ivm/memory-source.d.ts +4 -4
- package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
- package/out/zql/src/ivm/memory-source.js +471 -489
- package/out/zql/src/ivm/memory-source.js.map +1 -1
- package/out/zql/src/ivm/memory-storage.js +32 -31
- package/out/zql/src/ivm/memory-storage.js.map +1 -1
- package/out/zql/src/ivm/operator.js +8 -9
- package/out/zql/src/ivm/operator.js.map +1 -1
- package/out/zql/src/ivm/push-accumulated.js +236 -305
- package/out/zql/src/ivm/push-accumulated.js.map +1 -1
- package/out/zql/src/ivm/skip.js +92 -106
- package/out/zql/src/ivm/skip.js.map +1 -1
- package/out/zql/src/ivm/source.d.ts +4 -2
- package/out/zql/src/ivm/source.d.ts.map +1 -1
- package/out/zql/src/ivm/stream.js +20 -16
- package/out/zql/src/ivm/stream.js.map +1 -1
- package/out/zql/src/ivm/take.d.ts +1 -1
- package/out/zql/src/ivm/take.d.ts.map +1 -1
- package/out/zql/src/ivm/take.js +502 -456
- package/out/zql/src/ivm/take.js.map +1 -1
- package/out/zql/src/ivm/union-fan-in.js +156 -134
- package/out/zql/src/ivm/union-fan-in.js.map +1 -1
- package/out/zql/src/ivm/union-fan-out.js +46 -45
- package/out/zql/src/ivm/union-fan-out.js.map +1 -1
- package/out/zql/src/ivm/view-apply-change.js +246 -216
- package/out/zql/src/ivm/view-apply-change.js.map +1 -1
- package/out/zql/src/ivm/view.d.ts +3 -2
- package/out/zql/src/ivm/view.d.ts.map +1 -1
- package/out/zql/src/mutate/custom.d.ts +26 -11
- package/out/zql/src/mutate/custom.d.ts.map +1 -1
- package/out/zql/src/mutate/custom.js +15 -7
- package/out/zql/src/mutate/custom.js.map +1 -1
- package/out/zql/src/mutate/mutator-registry.d.ts +93 -0
- package/out/zql/src/mutate/mutator-registry.d.ts.map +1 -0
- package/out/zql/src/mutate/mutator-registry.js +93 -0
- package/out/zql/src/mutate/mutator-registry.js.map +1 -0
- package/out/zql/src/mutate/mutator.d.ts +79 -0
- package/out/zql/src/mutate/mutator.d.ts.map +1 -0
- package/out/zql/src/mutate/mutator.js +31 -0
- package/out/zql/src/mutate/mutator.js.map +1 -0
- package/out/zql/src/planner/planner-builder.d.ts +15 -0
- package/out/zql/src/planner/planner-builder.d.ts.map +1 -0
- package/out/zql/src/planner/planner-builder.js +271 -0
- package/out/zql/src/planner/planner-builder.js.map +1 -0
- package/out/zql/src/planner/planner-connection.d.ts +124 -0
- package/out/zql/src/planner/planner-connection.d.ts.map +1 -0
- package/out/zql/src/planner/planner-connection.js +215 -0
- package/out/zql/src/planner/planner-connection.js.map +1 -0
- package/out/zql/src/planner/planner-constraint.d.ts +14 -0
- package/out/zql/src/planner/planner-constraint.d.ts.map +1 -0
- package/out/zql/src/planner/planner-constraint.js +9 -0
- package/out/zql/src/planner/planner-constraint.js.map +1 -0
- package/out/zql/src/planner/planner-debug.d.ts +143 -0
- package/out/zql/src/planner/planner-debug.d.ts.map +1 -0
- package/out/zql/src/planner/planner-debug.js +242 -0
- package/out/zql/src/planner/planner-debug.js.map +1 -0
- package/out/zql/src/planner/planner-fan-in.d.ts +39 -0
- package/out/zql/src/planner/planner-fan-in.d.ts.map +1 -0
- package/out/zql/src/planner/planner-fan-in.js +165 -0
- package/out/zql/src/planner/planner-fan-in.js.map +1 -0
- package/out/zql/src/planner/planner-fan-out.d.ts +23 -0
- package/out/zql/src/planner/planner-fan-out.d.ts.map +1 -0
- package/out/zql/src/planner/planner-fan-out.js +76 -0
- package/out/zql/src/planner/planner-fan-out.js.map +1 -0
- package/out/zql/src/planner/planner-graph.d.ts +102 -0
- package/out/zql/src/planner/planner-graph.d.ts.map +1 -0
- package/out/zql/src/planner/planner-graph.js +346 -0
- package/out/zql/src/planner/planner-graph.js.map +1 -0
- package/out/zql/src/planner/planner-join.d.ts +140 -0
- package/out/zql/src/planner/planner-join.d.ts.map +1 -0
- package/out/zql/src/planner/planner-join.js +244 -0
- package/out/zql/src/planner/planner-join.js.map +1 -0
- package/out/zql/src/planner/planner-node.d.ts +53 -0
- package/out/zql/src/planner/planner-node.d.ts.map +1 -0
- package/out/zql/src/planner/planner-node.js +8 -0
- package/out/zql/src/planner/planner-node.js.map +1 -0
- package/out/zql/src/planner/planner-source.d.ts +11 -0
- package/out/zql/src/planner/planner-source.d.ts.map +1 -0
- package/out/zql/src/planner/planner-source.js +24 -0
- package/out/zql/src/planner/planner-source.js.map +1 -0
- package/out/zql/src/planner/planner-terminus.d.ts +17 -0
- package/out/zql/src/planner/planner-terminus.d.ts.map +1 -0
- package/out/zql/src/planner/planner-terminus.js +29 -0
- package/out/zql/src/planner/planner-terminus.js.map +1 -0
- package/out/zql/src/query/complete-ordering.d.ts +5 -0
- package/out/zql/src/query/complete-ordering.d.ts.map +1 -0
- package/out/zql/src/query/complete-ordering.js +71 -0
- package/out/zql/src/query/complete-ordering.js.map +1 -0
- package/out/zql/src/query/create-builder.d.ts +7 -0
- package/out/zql/src/query/create-builder.d.ts.map +1 -0
- package/out/zql/src/query/create-builder.js +44 -0
- package/out/zql/src/query/create-builder.js.map +1 -0
- package/out/zql/src/query/error.d.ts +4 -0
- package/out/zql/src/query/error.d.ts.map +1 -0
- package/out/zql/src/query/error.js +13 -0
- package/out/zql/src/query/error.js.map +1 -0
- package/out/zql/src/query/escape-like.js +7 -0
- package/out/zql/src/query/escape-like.js.map +1 -0
- package/out/zql/src/query/expression.d.ts +5 -5
- package/out/zql/src/query/expression.d.ts.map +1 -1
- package/out/zql/src/query/expression.js +153 -151
- package/out/zql/src/query/expression.js.map +1 -1
- package/out/zql/src/query/measure-push-operator.js +42 -35
- package/out/zql/src/query/measure-push-operator.js.map +1 -1
- package/out/zql/src/query/metrics-delegate.js +9 -5
- package/out/zql/src/query/metrics-delegate.js.map +1 -1
- package/out/zql/src/query/named.d.ts +21 -12
- package/out/zql/src/query/named.d.ts.map +1 -1
- package/out/zql/src/query/named.js +47 -57
- package/out/zql/src/query/named.js.map +1 -1
- package/out/zql/src/query/query-delegate-base.d.ts +114 -0
- package/out/zql/src/query/query-delegate-base.d.ts.map +1 -0
- package/out/zql/src/query/query-delegate-base.js +120 -0
- package/out/zql/src/query/query-delegate-base.js.map +1 -0
- package/out/zql/src/query/query-delegate.d.ts +30 -7
- package/out/zql/src/query/query-delegate.d.ts.map +1 -1
- package/out/zql/src/query/query-impl.d.ts +29 -50
- package/out/zql/src/query/query-impl.d.ts.map +1 -1
- package/out/zql/src/query/query-impl.js +514 -453
- package/out/zql/src/query/query-impl.js.map +1 -1
- package/out/zql/src/query/query-internals.d.ts +68 -0
- package/out/zql/src/query/query-internals.d.ts.map +1 -0
- package/out/zql/src/query/query-internals.js +11 -0
- package/out/zql/src/query/query-internals.js.map +1 -0
- package/out/zql/src/query/query-registry.d.ts +163 -0
- package/out/zql/src/query/query-registry.d.ts.map +1 -0
- package/out/zql/src/query/query-registry.js +123 -0
- package/out/zql/src/query/query-registry.js.map +1 -0
- package/out/zql/src/query/query.d.ts +54 -250
- package/out/zql/src/query/query.d.ts.map +1 -1
- package/out/zql/src/query/schema-query.d.ts +6 -0
- package/out/zql/src/query/schema-query.d.ts.map +1 -0
- package/out/zql/src/query/static-query.d.ts +7 -16
- package/out/zql/src/query/static-query.d.ts.map +1 -1
- package/out/zql/src/query/static-query.js +44 -31
- package/out/zql/src/query/static-query.js.map +1 -1
- package/out/zql/src/query/ttl.js +69 -62
- package/out/zql/src/query/ttl.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/zql/src/query/validate-input.d.ts +15 -0
- package/out/zql/src/query/validate-input.d.ts.map +1 -0
- package/out/zql/src/query/validate-input.js +24 -0
- package/out/zql/src/query/validate-input.js.map +1 -0
- package/out/zqlite/src/database-storage.d.ts +1 -1
- package/out/zqlite/src/database-storage.d.ts.map +1 -1
- package/out/zqlite/src/database-storage.js +99 -102
- package/out/zqlite/src/database-storage.js.map +1 -1
- package/out/zqlite/src/db.d.ts +2 -1
- package/out/zqlite/src/db.d.ts.map +1 -1
- package/out/zqlite/src/db.js +241 -192
- package/out/zqlite/src/db.js.map +1 -1
- package/out/zqlite/src/explain-queries.js +13 -16
- package/out/zqlite/src/explain-queries.js.map +1 -1
- package/out/zqlite/src/internal/sql.js +15 -10
- package/out/zqlite/src/internal/sql.js.map +1 -1
- package/out/zqlite/src/internal/statement-cache.js +86 -110
- package/out/zqlite/src/internal/statement-cache.js.map +1 -1
- package/out/zqlite/src/query-builder.js +172 -143
- package/out/zqlite/src/query-builder.js.map +1 -1
- package/out/zqlite/src/query-delegate.d.ts +6 -20
- package/out/zqlite/src/query-delegate.d.ts.map +1 -1
- package/out/zqlite/src/query-delegate.js +56 -70
- package/out/zqlite/src/query-delegate.js.map +1 -1
- package/out/zqlite/src/sqlite-cost-model.d.ts +17 -0
- package/out/zqlite/src/sqlite-cost-model.d.ts.map +1 -0
- package/out/zqlite/src/sqlite-cost-model.js +110 -0
- package/out/zqlite/src/sqlite-cost-model.js.map +1 -0
- package/out/zqlite/src/sqlite-stat-fanout.d.ts +121 -0
- package/out/zqlite/src/sqlite-stat-fanout.d.ts.map +1 -0
- package/out/zqlite/src/sqlite-stat-fanout.js +301 -0
- package/out/zqlite/src/sqlite-stat-fanout.js.map +1 -0
- package/out/zqlite/src/table-source.d.ts +10 -5
- package/out/zqlite/src/table-source.d.ts.map +1 -1
- package/out/zqlite/src/table-source.js +424 -311
- package/out/zqlite/src/table-source.js.map +1 -1
- package/package.json +30 -29
- package/out/chunk-424PT5DM.js +0 -23
- package/out/chunk-424PT5DM.js.map +0 -7
- package/out/chunk-4RB4OYLQ.js +0 -4125
- package/out/chunk-4RB4OYLQ.js.map +0 -7
- package/out/chunk-AFADJQ2O.js +0 -1
- package/out/chunk-AFADJQ2O.js.map +0 -7
- package/out/chunk-ASRS2LFV.js.map +0 -7
- package/out/chunk-BJ2CGCME.js.map +0 -7
- package/out/chunk-ECUMGQGC.js.map +0 -7
- package/out/chunk-EZM3XBAB.js.map +0 -7
- package/out/chunk-MXPHMVU7.js +0 -16350
- package/out/chunk-MXPHMVU7.js.map +0 -7
- package/out/chunk-VZOYWIRW.js.map +0 -7
- package/out/chunk-ZZXMKAAG.js.map +0 -7
- package/out/expo-sqlite.js +0 -11
- package/out/expo-sqlite.js.map +0 -7
- package/out/inspector-IU2HG74I.js.map +0 -7
- package/out/lazy-inspector-2SW772W4.js +0 -574
- package/out/lazy-inspector-2SW772W4.js.map +0 -7
- package/out/op-sqlite.js.map +0 -7
- package/out/react-native.js +0 -25
- package/out/react-native.js.map +0 -7
- package/out/react.js +0 -448
- package/out/react.js.map +0 -7
- package/out/shared/src/enum.js +0 -2
- package/out/shared/src/enum.js.map +0 -1
- package/out/shared/src/expand.js +0 -2
- package/out/shared/src/expand.js.map +0 -1
- package/out/shared/src/immutable.js +0 -2
- package/out/shared/src/immutable.js.map +0 -1
- package/out/shared/src/types.js +0 -2
- package/out/shared/src/types.js.map +0 -1
- package/out/shared/src/writable.js +0 -2
- package/out/shared/src/writable.js.map +0 -1
- package/out/solid.js.map +0 -7
- package/out/sqlite.js +0 -15
- package/out/sqlite.js.map +0 -7
- package/out/zero/package.json +0 -192
- package/out/zero/src/server/change-streamer.js +0 -2
- package/out/zero/src/server/change-streamer.js.map +0 -1
- package/out/zero/src/server/main.js +0 -2
- package/out/zero/src/server/main.js.map +0 -1
- package/out/zero/src/server/reaper.js +0 -2
- package/out/zero/src/server/reaper.js.map +0 -1
- package/out/zero/src/server/replicator.js +0 -2
- package/out/zero/src/server/replicator.js.map +0 -1
- package/out/zero/src/server/runner/main.js +0 -2
- package/out/zero/src/server/runner/main.js.map +0 -1
- package/out/zero/src/server/syncer.js +0 -2
- package/out/zero/src/server/syncer.js.map +0 -1
- package/out/zero-cache/src/services/change-source/pg/logical-replication/pgoutput.types.js +0 -4
- package/out/zero-cache/src/services/change-source/pg/logical-replication/pgoutput.types.js.map +0 -1
- package/out/zero-cache/src/services/change-source/protocol/mod.js +0 -5
- package/out/zero-cache/src/services/change-source/protocol/mod.js.map +0 -1
- package/out/zero-cache/src/services/service.js +0 -2
- package/out/zero-cache/src/services/service.js.map +0 -1
- package/out/zero-cache/src/services/view-syncer/key-columns.d.ts +0 -32
- package/out/zero-cache/src/services/view-syncer/key-columns.d.ts.map +0 -1
- package/out/zero-cache/src/services/view-syncer/key-columns.js +0 -73
- package/out/zero-cache/src/services/view-syncer/key-columns.js.map +0 -1
- package/out/zero-cache/src/types/error-for-client.d.ts +0 -23
- package/out/zero-cache/src/types/error-for-client.d.ts.map +0 -1
- package/out/zero-cache/src/types/error-for-client.js +0 -28
- package/out/zero-cache/src/types/error-for-client.js.map +0 -1
- package/out/zero-cache/src/types/satisfies.js +0 -2
- package/out/zero-cache/src/types/satisfies.js.map +0 -1
- package/out/zero-client/src/client/on-error.d.ts +0 -15
- package/out/zero-client/src/client/on-error.d.ts.map +0 -1
- package/out/zero-client/src/client/ping-result-enum.d.ts +0 -5
- package/out/zero-client/src/client/ping-result-enum.d.ts.map +0 -1
- package/out/zero-client/src/client/zero-log-context.d.ts +0 -7
- package/out/zero-client/src/client/zero-log-context.d.ts.map +0 -1
- package/out/zero-events/src/index.js +0 -2
- package/out/zero-events/src/index.js.map +0 -1
- package/out/zero-events/src/json.js +0 -2
- package/out/zero-events/src/json.js.map +0 -1
- package/out/zero-events/src/status.js +0 -3
- package/out/zero-events/src/status.js.map +0 -1
- package/out/zero-pg/src/mod.js +0 -6
- package/out/zero-pg/src/mod.js.map +0 -1
- package/out/zero-protocol/src/error-kind.js +0 -3
- package/out/zero-protocol/src/error-kind.js.map +0 -1
- package/out/zero-schema/src/server-schema.d.ts.map +0 -1
- package/out/zero-schema/src/server-schema.js +0 -2
- package/out/zero-schema/src/server-schema.js.map +0 -1
- package/out/zero-schema/src/table-schema.js +0 -7
- package/out/zero-schema/src/table-schema.js.map +0 -1
- package/out/zero-server/src/mod.js +0 -8
- package/out/zero-server/src/mod.js.map +0 -1
- package/out/zero-server/src/query.d.ts +0 -22
- package/out/zero-server/src/query.d.ts.map +0 -1
- package/out/zero-server/src/query.js +0 -61
- package/out/zero-server/src/query.js.map +0 -1
- package/out/zero-types/src/schema-value.js +0 -2
- package/out/zero-types/src/schema-value.js.map +0 -1
- package/out/zero-types/src/schema.js +0 -2
- package/out/zero-types/src/schema.js.map +0 -1
- package/out/zero.js +0 -69
- package/out/zero.js.map +0 -7
- package/out/zql/src/ivm/change.js +0 -2
- package/out/zql/src/ivm/change.js.map +0 -1
- package/out/zql/src/ivm/default-format.js +0 -2
- package/out/zql/src/ivm/default-format.js.map +0 -1
- package/out/zql/src/ivm/schema.js +0 -2
- package/out/zql/src/ivm/schema.js.map +0 -1
- package/out/zql/src/ivm/source.js +0 -2
- package/out/zql/src/ivm/source.js.map +0 -1
- package/out/zql/src/ivm/view.js +0 -2
- package/out/zql/src/ivm/view.js.map +0 -1
- package/out/zql/src/query/query-delegate.js +0 -2
- package/out/zql/src/query/query-delegate.js.map +0 -1
- package/out/zql/src/query/query.js +0 -9
- package/out/zql/src/query/query.js.map +0 -1
- package/out/zql/src/query/typed-view.js +0 -2
- package/out/zql/src/query/typed-view.js.map +0 -1
- package/out/zqlite/src/mod.js +0 -5
- package/out/zqlite/src/mod.js.map +0 -1
- /package/out/{zero-schema → zero-types}/src/server-schema.d.ts +0 -0
|
@@ -1,1335 +1,1595 @@
|
|
|
1
|
-
import { trace } from
|
|
2
|
-
import { Lock } from
|
|
3
|
-
import { resolver } from
|
|
4
|
-
import {
|
|
1
|
+
import { trace } from "@opentelemetry/api";
|
|
2
|
+
import { Lock } from "@rocicorp/lock";
|
|
3
|
+
import { resolver } from "@rocicorp/resolver";
|
|
4
|
+
import { startSpan, startAsyncSpan, manualSpan } from "../../../../otel/src/span.js";
|
|
5
5
|
import { version } from "../../../../otel/src/version.js";
|
|
6
6
|
import { assert, unreachable } from "../../../../shared/src/asserts.js";
|
|
7
7
|
import { stringify } from "../../../../shared/src/bigint-json.js";
|
|
8
8
|
import { CustomKeyMap } from "../../../../shared/src/custom-key-map.js";
|
|
9
|
-
import { wrapIterable } from "../../../../shared/src/iterables.js";
|
|
10
9
|
import { must } from "../../../../shared/src/must.js";
|
|
11
10
|
import { randInt } from "../../../../shared/src/rand.js";
|
|
12
|
-
import {
|
|
11
|
+
import { Rehome, ClientNotFound, InvalidConnectionRequest, TransformFailed, Unauthorized, InvalidConnectionRequestBaseCookie } from "../../../../zero-protocol/src/error-kind-enum.js";
|
|
12
|
+
import { ZeroCache } from "../../../../zero-protocol/src/error-origin-enum.js";
|
|
13
|
+
import { ProtocolError } from "../../../../zero-protocol/src/error.js";
|
|
13
14
|
import { clampTTL, MAX_TTL_MS } from "../../../../zql/src/query/ttl.js";
|
|
14
|
-
import { transformAndHashQuery
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import { InspectorDelegate } from "../../server/inspector-delegate.js";
|
|
18
|
-
import { ErrorForClient, getLogLevel } from "../../types/error-for-client.js";
|
|
15
|
+
import { transformAndHashQuery } from "../../auth/read-authorizer.js";
|
|
16
|
+
import { getOrCreateUpDownCounter, getOrCreateCounter, getOrCreateHistogram } from "../../observability/metrics.js";
|
|
17
|
+
import { ProtocolErrorWithLevel, getLogLevel } from "../../types/error-with-level.js";
|
|
19
18
|
import { rowIDString } from "../../types/row-key.js";
|
|
20
19
|
import { Subscription } from "../../types/subscription.js";
|
|
21
|
-
import
|
|
22
|
-
import {
|
|
20
|
+
import "../replicator/schema/replication-state.js";
|
|
21
|
+
import { startPoke, ClientHandler } from "./client-handler.js";
|
|
23
22
|
import { CVRStore } from "./cvr-store.js";
|
|
24
|
-
import { CVRConfigDrivenUpdater,
|
|
23
|
+
import { CVRConfigDrivenUpdater, nextEvictionTime, CVRQueryDrivenUpdater } from "./cvr.js";
|
|
25
24
|
import { handleInspect } from "./inspect-handler.js";
|
|
26
|
-
import
|
|
27
|
-
import
|
|
25
|
+
import "../../../../shared/src/config.js";
|
|
26
|
+
import "compare-utf8";
|
|
27
|
+
import "../../../../zero-protocol/src/ast.js";
|
|
28
|
+
import "../../../../zero-protocol/src/data.js";
|
|
29
|
+
import "@rocicorp/zero-sqlite3";
|
|
30
|
+
import "../../../../zqlite/src/internal/sql.js";
|
|
31
|
+
import "../../../../shared/src/btree-set.js";
|
|
32
|
+
import "../../../../shared/src/valita.js";
|
|
33
|
+
import "../../../../zero-schema/src/compiled-permissions.js";
|
|
34
|
+
import "../../../../zero-protocol/src/primary-key.js";
|
|
35
|
+
import { ZERO_VERSION_COLUMN_NAME } from "../replicator/schema/constants.js";
|
|
36
|
+
import "../../types/pg-data-type.js";
|
|
37
|
+
import "../../db/specs.js";
|
|
28
38
|
import { ResetPipelinesSignal } from "./snapshotter.js";
|
|
29
|
-
import {
|
|
30
|
-
|
|
31
|
-
const
|
|
32
|
-
const
|
|
39
|
+
import { versionString, cmpVersions, EMPTY_CVR_VERSION, versionToCookie, versionFromString } from "./schema/types.js";
|
|
40
|
+
import { ttlClockFromNumber, ttlClockAsNumber } from "./ttl-clock.js";
|
|
41
|
+
const tracer = trace.getTracer("view-syncer", version);
|
|
42
|
+
const PROTOCOL_VERSION_ATTR = "protocol.version";
|
|
43
|
+
const DEFAULT_KEEPALIVE_MS = 5e3;
|
|
33
44
|
function randomID() {
|
|
34
|
-
|
|
45
|
+
return randInt(1, Number.MAX_SAFE_INTEGER).toString(36);
|
|
35
46
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
constructor(config, lc, shard, taskID, clientGroupID, cvrDb, upstreamDb, pipelineDriver, versionChanges, drainCoordinator, slowHydrateThreshold, inspectorDelegate, customQueryTransformer, keepaliveMs = DEFAULT_KEEPALIVE_MS, setTimeoutFn = setTimeout.bind(globalThis)) {
|
|
121
|
-
const { getQueries: pullConfig } = config;
|
|
122
|
-
this.#config = config;
|
|
123
|
-
this.id = clientGroupID;
|
|
124
|
-
this.#shard = shard;
|
|
125
|
-
this.#queryConfig = pullConfig;
|
|
126
|
-
this.#lc = lc;
|
|
127
|
-
this.#pipelines = pipelineDriver;
|
|
128
|
-
this.#stateChanges = versionChanges;
|
|
129
|
-
this.#drainCoordinator = drainCoordinator;
|
|
130
|
-
this.#keepaliveMs = keepaliveMs;
|
|
131
|
-
this.#slowHydrateThreshold = slowHydrateThreshold;
|
|
132
|
-
this.#inspectorDelegate = inspectorDelegate;
|
|
133
|
-
this.#customQueryTransformer = customQueryTransformer;
|
|
134
|
-
this.#cvrStore = new CVRStore(lc, cvrDb, upstreamDb, shard, taskID, clientGroupID,
|
|
135
|
-
// On failure, cancel the #stateChanges subscription. The run()
|
|
136
|
-
// loop will then await #cvrStore.flushed() which rejects if necessary.
|
|
137
|
-
() => this.#stateChanges.cancel());
|
|
138
|
-
this.#setTimeout = setTimeoutFn;
|
|
139
|
-
// Wait for the first connection to init.
|
|
140
|
-
this.keepalive();
|
|
47
|
+
const TTL_CLOCK_INTERVAL = 6e4;
|
|
48
|
+
const TTL_TIMER_HYSTERESIS = 50;
|
|
49
|
+
class ViewSyncerService {
|
|
50
|
+
id;
|
|
51
|
+
#shard;
|
|
52
|
+
#lc;
|
|
53
|
+
#pipelines;
|
|
54
|
+
#stateChanges;
|
|
55
|
+
#drainCoordinator;
|
|
56
|
+
#keepaliveMs;
|
|
57
|
+
#slowHydrateThreshold;
|
|
58
|
+
#queryConfig;
|
|
59
|
+
userQueryURL;
|
|
60
|
+
// The ViewSyncerService is only started in response to a connection,
|
|
61
|
+
// so #lastConnectTime is always initialized to now(). This is necessary
|
|
62
|
+
// to handle race conditions in which, e.g. the replica is ready and the
|
|
63
|
+
// CVR is accessed before the first connection sends a request.
|
|
64
|
+
//
|
|
65
|
+
// Note: It is fine to update this variable outside of the lock.
|
|
66
|
+
#lastConnectTime = Date.now();
|
|
67
|
+
/**
|
|
68
|
+
* The TTL clock is used to determine the time at which queries are considered
|
|
69
|
+
* expired.
|
|
70
|
+
*/
|
|
71
|
+
#ttlClock;
|
|
72
|
+
/**
|
|
73
|
+
* The base time for the TTL clock. This is used to compute the current TTL
|
|
74
|
+
* clock value. The first time a connection is made, this is set to the
|
|
75
|
+
* current time. On subsequent connections, the TTL clock is computed as the
|
|
76
|
+
* difference between the current time and this base time.
|
|
77
|
+
*
|
|
78
|
+
* Every time we write the ttlClock this is update to the current time. That
|
|
79
|
+
* way we can compute how much time has passed since the last time we set the
|
|
80
|
+
* ttlClock. When we set the ttlClock we just increment it by the amount of
|
|
81
|
+
* time that has passed since the last time we set it.
|
|
82
|
+
*/
|
|
83
|
+
#ttlClockBase = Date.now();
|
|
84
|
+
/**
|
|
85
|
+
* We update the ttlClock every minute to ensure that it is not too much
|
|
86
|
+
* out of sync with the current time.
|
|
87
|
+
*/
|
|
88
|
+
#ttlClockInterval = 0;
|
|
89
|
+
// Note: It is okay to add/remove clients without acquiring the lock.
|
|
90
|
+
#clients = /* @__PURE__ */ new Map();
|
|
91
|
+
// Serialize on this lock for:
|
|
92
|
+
// (1) storage or database-dependent operations
|
|
93
|
+
// (2) updating member variables.
|
|
94
|
+
#lock = new Lock();
|
|
95
|
+
#cvrStore;
|
|
96
|
+
#stopped = resolver();
|
|
97
|
+
#initialized = resolver();
|
|
98
|
+
#cvr;
|
|
99
|
+
#pipelinesSynced = false;
|
|
100
|
+
// DEPRECATED: remove `authData` in favor of forwarding
|
|
101
|
+
// auth and cookie headers directly
|
|
102
|
+
#authData;
|
|
103
|
+
// Not sure why lint can't see that this is used?
|
|
104
|
+
// oxlint-disable-next-line no-unused-private-class-members
|
|
105
|
+
#httpCookie;
|
|
106
|
+
#expiredQueriesTimer = 0;
|
|
107
|
+
#setTimeout;
|
|
108
|
+
#customQueryTransformer;
|
|
109
|
+
// Track query replacements for thrashing detection
|
|
110
|
+
#queryReplacements = /* @__PURE__ */ new Map();
|
|
111
|
+
#activeClients = getOrCreateUpDownCounter(
|
|
112
|
+
"sync",
|
|
113
|
+
"active-clients",
|
|
114
|
+
"Number of active sync clients"
|
|
115
|
+
);
|
|
116
|
+
#hydrations = getOrCreateCounter(
|
|
117
|
+
"sync",
|
|
118
|
+
"hydration",
|
|
119
|
+
"Number of query hydrations"
|
|
120
|
+
);
|
|
121
|
+
#hydrationTime = getOrCreateHistogram("sync", "hydration-time", {
|
|
122
|
+
description: "Time to hydrate a query.",
|
|
123
|
+
unit: "s"
|
|
124
|
+
});
|
|
125
|
+
#transactionAdvanceTime = getOrCreateHistogram(
|
|
126
|
+
"sync",
|
|
127
|
+
"advance-time",
|
|
128
|
+
{
|
|
129
|
+
description: "Time to advance all queries for a given client group after applying a new transaction to the replica.",
|
|
130
|
+
unit: "s"
|
|
141
131
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
132
|
+
);
|
|
133
|
+
#queryTransformations = getOrCreateCounter(
|
|
134
|
+
"sync",
|
|
135
|
+
"query.transformations",
|
|
136
|
+
"Number of query transformations performed"
|
|
137
|
+
);
|
|
138
|
+
#queryTransformationTime = getOrCreateHistogram(
|
|
139
|
+
"sync",
|
|
140
|
+
"query.transformation-time",
|
|
141
|
+
{
|
|
142
|
+
description: "Time to transform custom queries via API server",
|
|
143
|
+
unit: "s"
|
|
148
144
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
145
|
+
);
|
|
146
|
+
#queryTransformationHashChanges = getOrCreateCounter(
|
|
147
|
+
"sync",
|
|
148
|
+
"query.transformation-hash-changes",
|
|
149
|
+
"Number of times query transformation hash changed"
|
|
150
|
+
);
|
|
151
|
+
#queryTransformationNoOps = getOrCreateCounter(
|
|
152
|
+
"sync",
|
|
153
|
+
"query.transformation-no-ops",
|
|
154
|
+
"Number of times query transformation resulted in no-op (hash unchanged)"
|
|
155
|
+
);
|
|
156
|
+
#inspectorDelegate;
|
|
157
|
+
#config;
|
|
158
|
+
constructor(config, lc, shard, taskID, clientGroupID, cvrDb, upstreamDb, pipelineDriver, versionChanges, drainCoordinator, slowHydrateThreshold, inspectorDelegate, customQueryTransformer, keepaliveMs = DEFAULT_KEEPALIVE_MS, setTimeoutFn = setTimeout.bind(globalThis)) {
|
|
159
|
+
const queryConfig = config.query?.url ? config.query : config.getQueries;
|
|
160
|
+
this.#config = config;
|
|
161
|
+
this.id = clientGroupID;
|
|
162
|
+
this.#shard = shard;
|
|
163
|
+
this.#queryConfig = queryConfig;
|
|
164
|
+
this.#lc = lc;
|
|
165
|
+
this.#pipelines = pipelineDriver;
|
|
166
|
+
this.#stateChanges = versionChanges;
|
|
167
|
+
this.#drainCoordinator = drainCoordinator;
|
|
168
|
+
this.#keepaliveMs = keepaliveMs;
|
|
169
|
+
this.#slowHydrateThreshold = slowHydrateThreshold;
|
|
170
|
+
this.#inspectorDelegate = inspectorDelegate;
|
|
171
|
+
this.#customQueryTransformer = customQueryTransformer;
|
|
172
|
+
this.#cvrStore = new CVRStore(
|
|
173
|
+
lc,
|
|
174
|
+
cvrDb,
|
|
175
|
+
upstreamDb,
|
|
176
|
+
shard,
|
|
177
|
+
taskID,
|
|
178
|
+
clientGroupID,
|
|
179
|
+
// On failure, cancel the #stateChanges subscription. The run()
|
|
180
|
+
// loop will then await #cvrStore.flushed() which rejects if necessary.
|
|
181
|
+
() => this.#stateChanges.cancel()
|
|
182
|
+
);
|
|
183
|
+
this.#setTimeout = setTimeoutFn;
|
|
184
|
+
this.keepalive();
|
|
185
|
+
}
|
|
186
|
+
#getHeaderOptions(forwardCookie) {
|
|
187
|
+
return {
|
|
188
|
+
apiKey: this.#queryConfig.apiKey,
|
|
189
|
+
token: this.#authData?.raw,
|
|
190
|
+
cookie: forwardCookie ? this.#httpCookie : void 0
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
#runInLockWithCVR(fn) {
|
|
194
|
+
const rid = randomID();
|
|
195
|
+
this.#lc.debug?.("about to acquire lock for cvr ", rid);
|
|
196
|
+
return this.#lock.withLock(async () => {
|
|
197
|
+
this.#lc.debug?.("acquired lock in #runInLockWithCVR ", rid);
|
|
198
|
+
const lc = this.#lc.withContext("lock", rid);
|
|
199
|
+
if (!this.#stateChanges.active) {
|
|
200
|
+
this.#lc.debug?.("state changes are inactive");
|
|
201
|
+
clearTimeout(this.#expiredQueriesTimer);
|
|
202
|
+
throw new ProtocolErrorWithLevel({
|
|
203
|
+
kind: Rehome,
|
|
204
|
+
message: "Reconnect required",
|
|
205
|
+
origin: ZeroCache
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
if (await this.#checkForShutdownConditionsInLock()) {
|
|
209
|
+
this.#lc.info?.(`closing clientGroupID=${this.id}`);
|
|
210
|
+
this.#stateChanges.cancel();
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
if (!this.#cvr) {
|
|
214
|
+
this.#lc.debug?.("loading CVR");
|
|
215
|
+
this.#cvr = await this.#cvrStore.load(lc, this.#lastConnectTime);
|
|
216
|
+
this.#ttlClock = this.#cvr.ttlClock;
|
|
217
|
+
this.#ttlClockBase = Date.now();
|
|
218
|
+
} else {
|
|
219
|
+
const now = Date.now();
|
|
220
|
+
this.#cvr = {
|
|
221
|
+
...this.#cvr,
|
|
222
|
+
ttlClock: this.#getTTLClock(now)
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
try {
|
|
226
|
+
await fn(lc, this.#cvr);
|
|
227
|
+
} catch (e) {
|
|
228
|
+
this.#cvr = void 0;
|
|
229
|
+
throw e;
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
readyState() {
|
|
234
|
+
return Promise.race([
|
|
235
|
+
this.#initialized.promise,
|
|
236
|
+
this.#drainCoordinator.draining
|
|
237
|
+
]);
|
|
238
|
+
}
|
|
239
|
+
async run() {
|
|
240
|
+
try {
|
|
241
|
+
if (await this.readyState() === "draining") {
|
|
242
|
+
this.#lc.debug?.(`draining view-syncer ${this.id} before running`);
|
|
243
|
+
void this.stop();
|
|
244
|
+
}
|
|
245
|
+
for await (const { state } of this.#stateChanges) {
|
|
246
|
+
if (this.#drainCoordinator.shouldDrain()) {
|
|
247
|
+
this.#lc.debug?.(`draining view-syncer ${this.id} (elective)`);
|
|
248
|
+
break;
|
|
249
|
+
}
|
|
250
|
+
assert(state === "version-ready", "state should be version-ready");
|
|
251
|
+
await this.#runInLockWithCVR(async (lc, cvr) => {
|
|
252
|
+
const clientSchema = must(
|
|
253
|
+
cvr.clientSchema,
|
|
254
|
+
"cvr.clientSchema missing after initialization"
|
|
255
|
+
);
|
|
256
|
+
if (!this.#pipelines.initialized()) {
|
|
257
|
+
this.#pipelines.init(clientSchema);
|
|
258
|
+
}
|
|
259
|
+
if (cvr.replicaVersion !== null && cvr.version.stateVersion !== "00" && this.#pipelines.replicaVersion < cvr.replicaVersion) {
|
|
260
|
+
const message = `Cannot sync from older replica: CVR=${cvr.replicaVersion}, DB=${this.#pipelines.replicaVersion}`;
|
|
261
|
+
lc.info?.(`resetting CVR: ${message}`);
|
|
262
|
+
throw new ProtocolErrorWithLevel({
|
|
263
|
+
kind: ClientNotFound,
|
|
264
|
+
message,
|
|
265
|
+
origin: ZeroCache
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
if (this.#pipelinesSynced) {
|
|
269
|
+
const result = await this.#advancePipelines(lc, cvr);
|
|
270
|
+
if (result === "success") {
|
|
271
|
+
return;
|
|
187
272
|
}
|
|
273
|
+
lc.info?.(`resetting pipelines: ${result.message}`);
|
|
274
|
+
this.#pipelines.reset(clientSchema);
|
|
275
|
+
}
|
|
276
|
+
const version2 = this.#pipelines.advanceWithoutDiff();
|
|
277
|
+
const cvrVer = versionString(cvr.version);
|
|
278
|
+
if (version2 < cvr.version.stateVersion) {
|
|
279
|
+
lc.debug?.(`replica@${version2} is behind cvr@${cvrVer}`);
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
lc.info?.(`init pipelines@${version2} (cvr@${cvrVer})`);
|
|
283
|
+
await this.#hydrateUnchangedQueries(lc, cvr);
|
|
284
|
+
await this.#syncQueryPipelineSet(lc, cvr);
|
|
285
|
+
this.#pipelinesSynced = true;
|
|
188
286
|
});
|
|
287
|
+
}
|
|
288
|
+
if (this.#drainCoordinator.shouldDrain()) {
|
|
289
|
+
this.#drainCoordinator.drainNextIn(this.#totalHydrationTimeMs());
|
|
290
|
+
}
|
|
291
|
+
this.#cleanup();
|
|
292
|
+
} catch (e) {
|
|
293
|
+
this.#lc[getLogLevel(e)]?.(
|
|
294
|
+
`stopping view-syncer ${this.id}: ${String(e)}`,
|
|
295
|
+
e
|
|
296
|
+
);
|
|
297
|
+
this.#cleanup(e);
|
|
298
|
+
} finally {
|
|
299
|
+
await this.#cvrStore.flushed(this.#lc).catch((e) => this.#lc[getLogLevel(e)]?.(e));
|
|
300
|
+
this.#lc.info?.(`view-syncer ${this.id} finished`);
|
|
301
|
+
this.#stopped.resolve();
|
|
189
302
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
await this.#runInLockWithCVR(async (lc, cvr) => {
|
|
199
|
-
if (!this.#pipelines.initialized()) {
|
|
200
|
-
// On the first version-ready signal, connect to the replica.
|
|
201
|
-
this.#pipelines.init(cvr.clientSchema);
|
|
202
|
-
}
|
|
203
|
-
if (cvr.replicaVersion !== null &&
|
|
204
|
-
cvr.version.stateVersion !== '00' &&
|
|
205
|
-
this.#pipelines.replicaVersion < cvr.replicaVersion) {
|
|
206
|
-
const message = `Cannot sync from older replica: CVR=${cvr.replicaVersion}, DB=${this.#pipelines.replicaVersion}`;
|
|
207
|
-
lc.info?.(`resetting CVR: ${message}`);
|
|
208
|
-
throw new ErrorForClient({ kind: ErrorKind.ClientNotFound, message });
|
|
209
|
-
}
|
|
210
|
-
if (this.#pipelinesSynced) {
|
|
211
|
-
const result = await this.#advancePipelines(lc, cvr);
|
|
212
|
-
if (result === 'success') {
|
|
213
|
-
return;
|
|
214
|
-
}
|
|
215
|
-
lc.info?.(`resetting pipelines: ${result.message}`);
|
|
216
|
-
this.#pipelines.reset(cvr.clientSchema);
|
|
217
|
-
}
|
|
218
|
-
// Advance the snapshot to the current version.
|
|
219
|
-
const version = this.#pipelines.advanceWithoutDiff();
|
|
220
|
-
const cvrVer = versionString(cvr.version);
|
|
221
|
-
if (version < cvr.version.stateVersion) {
|
|
222
|
-
lc.debug?.(`replica@${version} is behind cvr@${cvrVer}`);
|
|
223
|
-
return; // Wait for the next advancement.
|
|
224
|
-
}
|
|
225
|
-
// stateVersion is at or beyond CVR version for the first time.
|
|
226
|
-
lc.info?.(`init pipelines@${version} (cvr@${cvrVer})`);
|
|
227
|
-
await this.#hydrateUnchangedQueries(lc, cvr);
|
|
228
|
-
await this.#syncQueryPipelineSet(lc, cvr);
|
|
229
|
-
this.#pipelinesSynced = true;
|
|
230
|
-
});
|
|
231
|
-
}
|
|
232
|
-
// If this view-syncer exited due to an elective or forced drain,
|
|
233
|
-
// set the next drain timeout.
|
|
234
|
-
if (this.#drainCoordinator.shouldDrain()) {
|
|
235
|
-
this.#drainCoordinator.drainNextIn(this.#totalHydrationTimeMs());
|
|
236
|
-
}
|
|
237
|
-
this.#cleanup();
|
|
238
|
-
}
|
|
239
|
-
catch (e) {
|
|
240
|
-
this.#lc[getLogLevel(e)]?.(`stopping view-syncer: ${String(e)}`, e);
|
|
241
|
-
this.#cleanup(e);
|
|
242
|
-
}
|
|
243
|
-
finally {
|
|
244
|
-
// Always wait for the cvrStore to flush, regardless of how the service
|
|
245
|
-
// was stopped.
|
|
246
|
-
await this.#cvrStore
|
|
247
|
-
.flushed(this.#lc)
|
|
248
|
-
.catch(e => this.#lc[getLogLevel(e)]?.(e));
|
|
249
|
-
this.#lc.info?.('view-syncer stopped');
|
|
250
|
-
this.#stopped.resolve();
|
|
251
|
-
}
|
|
303
|
+
}
|
|
304
|
+
// must be called from within #lock
|
|
305
|
+
#removeExpiredQueries = async (lc, cvr) => {
|
|
306
|
+
if (hasExpiredQueries(cvr)) {
|
|
307
|
+
lc = lc.withContext("method", "#removeExpiredQueries");
|
|
308
|
+
lc.debug?.("Queries have expired");
|
|
309
|
+
await this.#syncQueryPipelineSet(lc, cvr);
|
|
310
|
+
this.#pipelinesSynced = true;
|
|
252
311
|
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
312
|
+
this.#scheduleExpireEviction(lc, cvr);
|
|
313
|
+
};
|
|
314
|
+
#totalHydrationTimeMs() {
|
|
315
|
+
return this.#pipelines.totalHydrationTimeMs();
|
|
316
|
+
}
|
|
317
|
+
#keepAliveUntil = 0;
|
|
318
|
+
/**
|
|
319
|
+
* Guarantees that the ViewSyncer will remain running for at least
|
|
320
|
+
* its configured `keepaliveMs`. This is called when establishing a
|
|
321
|
+
* new connection to ensure that its associated ViewSyncer isn't
|
|
322
|
+
* shutdown before it receives the connection.
|
|
323
|
+
*
|
|
324
|
+
* @return `true` if the ViewSyncer will stay alive, `false` if the
|
|
325
|
+
* ViewSyncer is shutting down.
|
|
326
|
+
*/
|
|
327
|
+
keepalive() {
|
|
328
|
+
if (!this.#stateChanges.active) {
|
|
329
|
+
return false;
|
|
269
330
|
}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
331
|
+
this.#keepAliveUntil = Date.now() + this.#keepaliveMs;
|
|
332
|
+
return true;
|
|
333
|
+
}
|
|
334
|
+
// oxlint-disable-next-line no-unused-private-class-members -- False positive, used in #scheduleShutdown
|
|
335
|
+
#shutdownTimer = null;
|
|
336
|
+
#scheduleShutdown(delayMs = 0) {
|
|
337
|
+
this.#shutdownTimer ??= this.#setTimeout(() => {
|
|
338
|
+
this.#shutdownTimer = null;
|
|
339
|
+
void this.#runInLockWithCVR(() => {
|
|
340
|
+
}).catch(
|
|
341
|
+
(e) => (
|
|
342
|
+
// If an error occurs (e.g. ownership change), propagate the error
|
|
343
|
+
// to the main run() loop via the #stateChanges Subscription.
|
|
344
|
+
this.#stateChanges.fail(e)
|
|
345
|
+
)
|
|
346
|
+
);
|
|
347
|
+
}, delayMs);
|
|
348
|
+
}
|
|
349
|
+
async #checkForShutdownConditionsInLock() {
|
|
350
|
+
if (this.#clients.size > 0) {
|
|
351
|
+
return false;
|
|
286
352
|
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
this.#shutdownTimer = null;
|
|
292
|
-
// All lock tasks check for shutdown so that queued work is immediately
|
|
293
|
-
// canceled when clients disconnect. Queue an empty task to ensure that
|
|
294
|
-
// this check happens.
|
|
295
|
-
void this.#runInLockWithCVR(() => { }).catch(e =>
|
|
296
|
-
// If an error occurs (e.g. ownership change), propagate the error
|
|
297
|
-
// to the main run() loop via the #stateChanges Subscription.
|
|
298
|
-
this.#stateChanges.fail(e));
|
|
299
|
-
}, delayMs);
|
|
353
|
+
await this.#cvrStore.flushed(this.#lc);
|
|
354
|
+
if (Date.now() <= this.#keepAliveUntil) {
|
|
355
|
+
this.#scheduleShutdown(this.#keepaliveMs);
|
|
356
|
+
return false;
|
|
300
357
|
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
358
|
+
return this.#clients.size === 0;
|
|
359
|
+
}
|
|
360
|
+
#deleteClientDueToDisconnect(clientID, client) {
|
|
361
|
+
const c = this.#clients.get(clientID);
|
|
362
|
+
if (c === client) {
|
|
363
|
+
this.#clients.delete(clientID);
|
|
364
|
+
if (this.#clients.size === 0) {
|
|
365
|
+
if (this.#ttlClock !== void 0) {
|
|
366
|
+
this.#updateTTLClockInCVRWithoutLock(this.#lc);
|
|
304
367
|
}
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
await this.#cvrStore.flushed(this.#lc);
|
|
309
|
-
if (Date.now() <= this.#keepAliveUntil) {
|
|
310
|
-
this.#scheduleShutdown(this.#keepaliveMs); // check again later
|
|
311
|
-
return false;
|
|
312
|
-
}
|
|
313
|
-
// If no clients have connected while waiting for the row flush, shutdown.
|
|
314
|
-
return this.#clients.size === 0;
|
|
368
|
+
this.#stopExpireTimer();
|
|
369
|
+
this.#scheduleShutdown();
|
|
370
|
+
}
|
|
315
371
|
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
372
|
+
}
|
|
373
|
+
#stopExpireTimer() {
|
|
374
|
+
this.#lc.debug?.("Stopping expired queries timer");
|
|
375
|
+
clearTimeout(this.#expiredQueriesTimer);
|
|
376
|
+
this.#expiredQueriesTimer = 0;
|
|
377
|
+
}
|
|
378
|
+
initConnection(ctx, initConnectionMessage) {
|
|
379
|
+
this.#lc.debug?.("viewSyncer.initConnection");
|
|
380
|
+
return startSpan(tracer, "vs.initConnection", () => {
|
|
381
|
+
const {
|
|
382
|
+
clientID,
|
|
383
|
+
wsID,
|
|
384
|
+
baseCookie,
|
|
385
|
+
schemaVersion,
|
|
386
|
+
tokenData,
|
|
387
|
+
httpCookie,
|
|
388
|
+
protocolVersion
|
|
389
|
+
} = ctx;
|
|
390
|
+
this.#authData = pickToken(this.#lc, this.#authData, tokenData);
|
|
391
|
+
this.#lc.debug?.(
|
|
392
|
+
`Picked auth token: ${JSON.stringify(this.#authData?.decoded)}`
|
|
393
|
+
);
|
|
394
|
+
this.#httpCookie = httpCookie;
|
|
395
|
+
const [, { userQueryURL }] = initConnectionMessage;
|
|
396
|
+
if (this.userQueryURL === void 0) {
|
|
397
|
+
this.userQueryURL = userQueryURL;
|
|
398
|
+
} else {
|
|
399
|
+
if (this.userQueryURL !== userQueryURL) {
|
|
400
|
+
this.#lc.warn?.(
|
|
401
|
+
"Client provided different query parameters than client group",
|
|
402
|
+
{
|
|
403
|
+
clientID,
|
|
404
|
+
clientURL: userQueryURL,
|
|
405
|
+
clientGroupURL: this.userQueryURL
|
|
332
406
|
}
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
const lc = this.#lc.withContext("clientID", clientID).withContext("wsID", wsID);
|
|
411
|
+
const downstream = Subscription.create({
|
|
412
|
+
cleanup: (_, err) => {
|
|
413
|
+
err ? lc[getLogLevel(err)]?.(`client closed with error`, err) : lc.info?.("client closed");
|
|
414
|
+
this.#deleteClientDueToDisconnect(clientID, newClient);
|
|
415
|
+
this.#activeClients.add(-1, {
|
|
416
|
+
[PROTOCOL_VERSION_ATTR]: protocolVersion
|
|
417
|
+
});
|
|
333
418
|
}
|
|
419
|
+
});
|
|
420
|
+
this.#activeClients.add(1, {
|
|
421
|
+
[PROTOCOL_VERSION_ATTR]: protocolVersion
|
|
422
|
+
});
|
|
423
|
+
if (this.#clients.size === 0) {
|
|
424
|
+
const now = Date.now();
|
|
425
|
+
this.#ttlClockBase = now;
|
|
426
|
+
}
|
|
427
|
+
const newClient = new ClientHandler(
|
|
428
|
+
lc,
|
|
429
|
+
this.id,
|
|
430
|
+
clientID,
|
|
431
|
+
wsID,
|
|
432
|
+
this.#shard,
|
|
433
|
+
baseCookie,
|
|
434
|
+
schemaVersion,
|
|
435
|
+
downstream
|
|
436
|
+
);
|
|
437
|
+
this.#clients.get(clientID)?.close(`replaced by wsID: ${wsID}`);
|
|
438
|
+
this.#clients.set(clientID, newClient);
|
|
439
|
+
void this.#runInLockForClient(
|
|
440
|
+
ctx,
|
|
441
|
+
initConnectionMessage,
|
|
442
|
+
async (lc2, clientID2, msg, cvr) => {
|
|
443
|
+
if (cvr.clientSchema === null && !msg.clientSchema) {
|
|
444
|
+
throw new ProtocolErrorWithLevel({
|
|
445
|
+
kind: InvalidConnectionRequest,
|
|
446
|
+
message: "The initConnection message for a new client group must include client schema.",
|
|
447
|
+
origin: ZeroCache
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
await this.#handleConfigUpdate(lc2, clientID2, msg, cvr);
|
|
451
|
+
this.#initialized.resolve("initialized");
|
|
452
|
+
},
|
|
453
|
+
newClient
|
|
454
|
+
).catch((e) => newClient.fail(e));
|
|
455
|
+
return downstream;
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
async changeDesiredQueries(ctx, msg) {
|
|
459
|
+
await this.#runInLockForClient(ctx, msg, this.#handleConfigUpdate);
|
|
460
|
+
}
|
|
461
|
+
async deleteClients(ctx, msg) {
|
|
462
|
+
await this.#runInLockForClient(
|
|
463
|
+
ctx,
|
|
464
|
+
[msg[0], { deleted: msg[1] }],
|
|
465
|
+
this.#handleConfigUpdate
|
|
466
|
+
);
|
|
467
|
+
}
|
|
468
|
+
#getTTLClock(now) {
|
|
469
|
+
const delta = now - this.#ttlClockBase;
|
|
470
|
+
assert(this.#ttlClock !== void 0, "ttlClock should be defined");
|
|
471
|
+
const ttlClock = ttlClockFromNumber(
|
|
472
|
+
ttlClockAsNumber(this.#ttlClock) + delta
|
|
473
|
+
);
|
|
474
|
+
assert(
|
|
475
|
+
ttlClockAsNumber(ttlClock) <= now,
|
|
476
|
+
"ttlClock should be less than or equal to now"
|
|
477
|
+
);
|
|
478
|
+
this.#ttlClock = ttlClock;
|
|
479
|
+
this.#ttlClockBase = now;
|
|
480
|
+
return ttlClock;
|
|
481
|
+
}
|
|
482
|
+
async #flushUpdater(lc, updater) {
|
|
483
|
+
const now = Date.now();
|
|
484
|
+
const ttlClock = this.#getTTLClock(now);
|
|
485
|
+
const { cvr, flushed } = await updater.flush(
|
|
486
|
+
lc,
|
|
487
|
+
this.#lastConnectTime,
|
|
488
|
+
now,
|
|
489
|
+
ttlClock
|
|
490
|
+
);
|
|
491
|
+
if (flushed) {
|
|
492
|
+
this.#startTTLClockInterval(lc);
|
|
334
493
|
}
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
494
|
+
return cvr;
|
|
495
|
+
}
|
|
496
|
+
#startTTLClockInterval(lc) {
|
|
497
|
+
this.#stopTTLClockInterval();
|
|
498
|
+
this.#ttlClockInterval = this.#setTimeout(() => {
|
|
499
|
+
this.#updateTTLClockInCVRWithoutLock(lc);
|
|
500
|
+
this.#startTTLClockInterval(lc);
|
|
501
|
+
}, TTL_CLOCK_INTERVAL);
|
|
502
|
+
}
|
|
503
|
+
#stopTTLClockInterval() {
|
|
504
|
+
clearTimeout(this.#ttlClockInterval);
|
|
505
|
+
this.#ttlClockInterval = 0;
|
|
506
|
+
}
|
|
507
|
+
#updateTTLClockInCVRWithoutLock(lc) {
|
|
508
|
+
lc.debug?.("Syncing ttlClock");
|
|
509
|
+
const now = Date.now();
|
|
510
|
+
const ttlClock = this.#getTTLClock(now);
|
|
511
|
+
this.#cvrStore.updateTTLClock(ttlClock, now).catch((e) => {
|
|
512
|
+
lc.error?.("failed to update TTL clock", e);
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
async #updateCVRConfig(lc, cvr, clientID, fn) {
|
|
516
|
+
const updater = new CVRConfigDrivenUpdater(
|
|
517
|
+
this.#cvrStore,
|
|
518
|
+
cvr,
|
|
519
|
+
this.#shard
|
|
520
|
+
);
|
|
521
|
+
updater.ensureClient(clientID);
|
|
522
|
+
const patches = fn(updater);
|
|
523
|
+
this.#cvr = await this.#flushUpdater(lc, updater);
|
|
524
|
+
if (cmpVersions(cvr.version, this.#cvr.version) < 0) {
|
|
525
|
+
const newCVR = this.#cvr;
|
|
526
|
+
const pokers = startPoke(this.#getClients(cvr.version), newCVR.version);
|
|
527
|
+
for (const patch of patches) {
|
|
528
|
+
await pokers.addPatch(patch);
|
|
529
|
+
}
|
|
530
|
+
await pokers.end(newCVR.version);
|
|
339
531
|
}
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
return startSpan(tracer, 'vs.initConnection', () => {
|
|
343
|
-
const { clientID, wsID, baseCookie, schemaVersion, tokenData, httpCookie, protocolVersion, } = ctx;
|
|
344
|
-
this.#authData = pickToken(this.#lc, this.#authData, tokenData);
|
|
345
|
-
this.#lc.debug?.(`Picked auth token: ${JSON.stringify(this.#authData?.decoded)}`);
|
|
346
|
-
this.#httpCookie = httpCookie;
|
|
347
|
-
// Handle custom query URL
|
|
348
|
-
const [, { userQueryURL }] = initConnectionMessage;
|
|
349
|
-
if (this.userQueryURL === undefined) {
|
|
350
|
-
// First client in the group - store its parameters
|
|
351
|
-
this.userQueryURL = userQueryURL;
|
|
352
|
-
}
|
|
353
|
-
else {
|
|
354
|
-
// Validate that subsequent clients have compatible parameters
|
|
355
|
-
if (this.userQueryURL !== userQueryURL) {
|
|
356
|
-
this.#lc.error?.('Client provided different query parameters than client group', {
|
|
357
|
-
clientID,
|
|
358
|
-
clientURL: userQueryURL,
|
|
359
|
-
clientGroupURL: this.userQueryURL,
|
|
360
|
-
});
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
const lc = this.#lc
|
|
364
|
-
.withContext('clientID', clientID)
|
|
365
|
-
.withContext('wsID', wsID);
|
|
366
|
-
// Setup the downstream connection.
|
|
367
|
-
const downstream = Subscription.create({
|
|
368
|
-
cleanup: (_, err) => {
|
|
369
|
-
err
|
|
370
|
-
? lc[getLogLevel(err)]?.(`client closed with error`, err)
|
|
371
|
-
: lc.info?.('client closed');
|
|
372
|
-
this.#deleteClientDueToDisconnect(clientID, newClient);
|
|
373
|
-
this.#activeClients.add(-1, {
|
|
374
|
-
[PROTOCOL_VERSION_ATTR]: protocolVersion,
|
|
375
|
-
});
|
|
376
|
-
},
|
|
377
|
-
});
|
|
378
|
-
this.#activeClients.add(1, {
|
|
379
|
-
[PROTOCOL_VERSION_ATTR]: protocolVersion,
|
|
380
|
-
});
|
|
381
|
-
if (this.#clients.size === 0) {
|
|
382
|
-
// First connection to this ViewSyncerService.
|
|
383
|
-
// initConnection must be synchronous so that the downstream
|
|
384
|
-
// subscription is returned immediately.
|
|
385
|
-
const now = Date.now();
|
|
386
|
-
this.#ttlClockBase = now;
|
|
387
|
-
}
|
|
388
|
-
const newClient = new ClientHandler(lc, this.id, clientID, wsID, this.#shard, baseCookie, schemaVersion, downstream);
|
|
389
|
-
this.#clients.get(clientID)?.close(`replaced by wsID: ${wsID}`);
|
|
390
|
-
this.#clients.set(clientID, newClient);
|
|
391
|
-
// Note: initConnection() must be synchronous so that `downstream` is
|
|
392
|
-
// immediately returned to the caller (connection.ts). This ensures
|
|
393
|
-
// that if the connection is subsequently closed, the `downstream`
|
|
394
|
-
// subscription can be properly canceled even if #runInLockForClient()
|
|
395
|
-
// has not had a chance to run.
|
|
396
|
-
void this.#runInLockForClient(ctx, initConnectionMessage, this.#handleConfigUpdate, newClient).catch(e => newClient.fail(e));
|
|
397
|
-
return downstream;
|
|
398
|
-
});
|
|
532
|
+
if (this.#pipelinesSynced) {
|
|
533
|
+
await this.#syncQueryPipelineSet(lc, this.#cvr);
|
|
399
534
|
}
|
|
400
|
-
|
|
401
|
-
|
|
535
|
+
return this.#cvr;
|
|
536
|
+
}
|
|
537
|
+
/**
|
|
538
|
+
* Runs the given `fn` to process the `msg` from within the `#lock`,
|
|
539
|
+
* optionally adding the `newClient` if supplied.
|
|
540
|
+
*/
|
|
541
|
+
#runInLockForClient(ctx, msg, fn, newClient) {
|
|
542
|
+
this.#lc.debug?.("viewSyncer.#runInLockForClient");
|
|
543
|
+
const { clientID, wsID } = ctx;
|
|
544
|
+
const [cmd, body] = msg;
|
|
545
|
+
if (newClient || !this.#clients.has(clientID)) {
|
|
546
|
+
this.#lastConnectTime = Date.now();
|
|
402
547
|
}
|
|
403
|
-
|
|
548
|
+
return startAsyncSpan(
|
|
549
|
+
tracer,
|
|
550
|
+
`vs.#runInLockForClient(${cmd})`,
|
|
551
|
+
async () => {
|
|
552
|
+
let client;
|
|
404
553
|
try {
|
|
405
|
-
|
|
554
|
+
await this.#runInLockWithCVR((lc, cvr) => {
|
|
555
|
+
lc = lc.withContext("clientID", clientID).withContext("wsID", wsID).withContext("cmd", cmd);
|
|
556
|
+
lc.debug?.("acquired lock for cvr");
|
|
557
|
+
client = this.#clients.get(clientID);
|
|
558
|
+
if (client?.wsID !== wsID) {
|
|
559
|
+
lc.debug?.("mismatched wsID", client?.wsID, wsID);
|
|
560
|
+
return;
|
|
561
|
+
}
|
|
562
|
+
if (newClient) {
|
|
563
|
+
assert(
|
|
564
|
+
newClient === client,
|
|
565
|
+
"newClient must match existing client"
|
|
566
|
+
);
|
|
567
|
+
checkClientAndCVRVersions(client.version(), cvr.version);
|
|
568
|
+
} else if (!this.#clients.has(clientID)) {
|
|
569
|
+
lc.warn?.(`Processing ${cmd} before initConnection was received`);
|
|
570
|
+
}
|
|
571
|
+
lc.debug?.(cmd, body);
|
|
572
|
+
return fn(lc, clientID, body, cvr);
|
|
573
|
+
});
|
|
574
|
+
} catch (e) {
|
|
575
|
+
const lc = this.#lc.withContext("clientID", clientID).withContext("wsID", wsID).withContext("cmd", cmd);
|
|
576
|
+
lc[getLogLevel(e)]?.(`closing connection with error`, e);
|
|
577
|
+
if (client) {
|
|
578
|
+
client.fail(e);
|
|
579
|
+
} else {
|
|
580
|
+
throw e;
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
);
|
|
585
|
+
}
|
|
586
|
+
#getClients(atVersion) {
|
|
587
|
+
const clients = [...this.#clients.values()];
|
|
588
|
+
return atVersion ? clients.filter(
|
|
589
|
+
(c) => cmpVersions(c.version() ?? EMPTY_CVR_VERSION, atVersion) === 0
|
|
590
|
+
) : clients;
|
|
591
|
+
}
|
|
592
|
+
// Must be called from within #lock.
|
|
593
|
+
#handleConfigUpdate = (lc, clientID, {
|
|
594
|
+
clientSchema,
|
|
595
|
+
deleted,
|
|
596
|
+
desiredQueriesPatch,
|
|
597
|
+
activeClients
|
|
598
|
+
}, cvr) => startAsyncSpan(tracer, "vs.#patchQueries", async () => {
|
|
599
|
+
const deletedClientIDs = [];
|
|
600
|
+
const deletedClientGroupIDs = [];
|
|
601
|
+
cvr = await this.#updateCVRConfig(lc, cvr, clientID, (updater) => {
|
|
602
|
+
const { ttlClock } = cvr;
|
|
603
|
+
const patches = [];
|
|
604
|
+
if (clientSchema) {
|
|
605
|
+
updater.setClientSchema(lc, clientSchema);
|
|
606
|
+
}
|
|
607
|
+
lc.debug?.(`applying ${desiredQueriesPatch?.length} query patches`);
|
|
608
|
+
if (desiredQueriesPatch?.length) {
|
|
609
|
+
for (const patch of desiredQueriesPatch) {
|
|
610
|
+
switch (patch.op) {
|
|
611
|
+
case "put":
|
|
612
|
+
patches.push(...updater.putDesiredQueries(clientID, [patch]));
|
|
613
|
+
break;
|
|
614
|
+
case "del":
|
|
615
|
+
patches.push(
|
|
616
|
+
...updater.markDesiredQueriesAsInactive(
|
|
617
|
+
clientID,
|
|
618
|
+
[patch.hash],
|
|
619
|
+
ttlClock
|
|
620
|
+
)
|
|
621
|
+
);
|
|
622
|
+
break;
|
|
623
|
+
case "clear":
|
|
624
|
+
patches.push(...updater.clearDesiredQueries(clientID));
|
|
625
|
+
break;
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
const clientIDsToDelete = /* @__PURE__ */ new Set();
|
|
630
|
+
if (activeClients) {
|
|
631
|
+
const allClientIDs = Object.keys(cvr.clients);
|
|
632
|
+
const activeClientsSet = new Set(activeClients);
|
|
633
|
+
for (const id of allClientIDs) {
|
|
634
|
+
if (!activeClientsSet.has(id)) {
|
|
635
|
+
clientIDsToDelete.add(id);
|
|
636
|
+
}
|
|
406
637
|
}
|
|
407
|
-
|
|
408
|
-
|
|
638
|
+
}
|
|
639
|
+
if (deleted?.clientIDs?.length) {
|
|
640
|
+
for (const cid of deleted.clientIDs) {
|
|
641
|
+
assert(cid !== clientID, "cannot delete self");
|
|
642
|
+
clientIDsToDelete.add(cid);
|
|
409
643
|
}
|
|
644
|
+
}
|
|
645
|
+
for (const cid of clientIDsToDelete) {
|
|
646
|
+
const patchesDueToClient = updater.deleteClient(cid, ttlClock);
|
|
647
|
+
patches.push(...patchesDueToClient);
|
|
648
|
+
deletedClientIDs.push(cid);
|
|
649
|
+
}
|
|
650
|
+
if (deleted?.clientGroupIDs?.length) {
|
|
651
|
+
lc.debug?.(
|
|
652
|
+
`ignoring ${deleted.clientGroupIDs.length} deprecated client group deletes`
|
|
653
|
+
);
|
|
654
|
+
}
|
|
655
|
+
return patches;
|
|
656
|
+
});
|
|
657
|
+
if (deletedClientIDs.length && deleted?.clientIDs?.length || deletedClientGroupIDs.length) {
|
|
658
|
+
const clients = this.#getClients();
|
|
659
|
+
await Promise.allSettled(
|
|
660
|
+
clients.map(
|
|
661
|
+
(client) => client.sendDeleteClients(
|
|
662
|
+
lc,
|
|
663
|
+
deletedClientIDs,
|
|
664
|
+
deletedClientGroupIDs
|
|
665
|
+
)
|
|
666
|
+
)
|
|
667
|
+
);
|
|
410
668
|
}
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
669
|
+
this.#scheduleExpireEviction(lc, cvr);
|
|
670
|
+
});
|
|
671
|
+
#scheduleExpireEviction(lc, cvr) {
|
|
672
|
+
const { ttlClock } = cvr;
|
|
673
|
+
this.#stopExpireTimer();
|
|
674
|
+
const next = nextEvictionTime(cvr);
|
|
675
|
+
if (next === void 0) {
|
|
676
|
+
lc.debug?.("no inactive queries with ttl");
|
|
677
|
+
return;
|
|
420
678
|
}
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
679
|
+
const delay = Math.max(
|
|
680
|
+
TTL_TIMER_HYSTERESIS,
|
|
681
|
+
Math.min(
|
|
682
|
+
ttlClockAsNumber(next) - ttlClockAsNumber(ttlClock) + TTL_TIMER_HYSTERESIS,
|
|
683
|
+
MAX_TTL_MS
|
|
684
|
+
)
|
|
685
|
+
);
|
|
686
|
+
lc.debug?.("Scheduling eviction timer to run in ", delay, "ms");
|
|
687
|
+
this.#expiredQueriesTimer = this.#setTimeout(() => {
|
|
688
|
+
this.#expiredQueriesTimer = 0;
|
|
689
|
+
this.#runInLockWithCVR(
|
|
690
|
+
(lc2, cvr2) => this.#removeExpiredQueries(lc2, cvr2)
|
|
691
|
+
).catch(
|
|
692
|
+
(e) => (
|
|
693
|
+
// If an error occurs (e.g. ownership change), propagate the error
|
|
694
|
+
// to the main run() loop via the #stateChanges Subscription.
|
|
695
|
+
this.#stateChanges.fail(e)
|
|
696
|
+
)
|
|
697
|
+
);
|
|
698
|
+
}, delay);
|
|
699
|
+
}
|
|
700
|
+
/**
|
|
701
|
+
* Adds and hydrates pipelines for queries whose results are already
|
|
702
|
+
* recorded in the CVR. Namely:
|
|
703
|
+
*
|
|
704
|
+
* 1. The CVR state version and database version are the same.
|
|
705
|
+
* 2. The transformation hash of the queries equal those in the CVR.
|
|
706
|
+
*
|
|
707
|
+
* Note that by definition, only "got" queries can satisfy condition (2),
|
|
708
|
+
* as desired queries do not have a transformation hash.
|
|
709
|
+
*
|
|
710
|
+
* This is an initialization step that sets up pipeline state without
|
|
711
|
+
* the expensive of loading and diffing CVR row state.
|
|
712
|
+
*
|
|
713
|
+
* This must be called from within the #lock.
|
|
714
|
+
*/
|
|
715
|
+
async #hydrateUnchangedQueries(lc, cvr) {
|
|
716
|
+
assert(this.#pipelines.initialized(), "pipelines must be initialized");
|
|
717
|
+
const dbVersion = this.#pipelines.currentVersion();
|
|
718
|
+
const cvrVersion = cvr.version;
|
|
719
|
+
if (cvrVersion.stateVersion !== dbVersion) {
|
|
720
|
+
lc.info?.(
|
|
721
|
+
`CVR (${versionToCookie(cvrVersion)}) is behind db ${dbVersion}`
|
|
722
|
+
);
|
|
723
|
+
return;
|
|
430
724
|
}
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
725
|
+
const gotQueries = Object.entries(cvr.queries).filter(
|
|
726
|
+
([_, state]) => state.transformationHash !== void 0
|
|
727
|
+
);
|
|
728
|
+
const customQueries = /* @__PURE__ */ new Map();
|
|
729
|
+
const otherQueries = [];
|
|
730
|
+
for (const [, query] of gotQueries) {
|
|
731
|
+
if (query.type !== "internal" && Object.values(query.clientState).every(
|
|
732
|
+
({ inactivatedAt }) => inactivatedAt !== void 0
|
|
733
|
+
)) {
|
|
734
|
+
continue;
|
|
735
|
+
}
|
|
736
|
+
if (query.type === "custom") {
|
|
737
|
+
customQueries.set(query.id, query);
|
|
738
|
+
} else {
|
|
739
|
+
otherQueries.push(query);
|
|
740
|
+
}
|
|
437
741
|
}
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
742
|
+
const transformedQueries = [];
|
|
743
|
+
if (customQueries.size > 0 && !this.#customQueryTransformer) {
|
|
744
|
+
lc.warn?.(
|
|
745
|
+
"Custom/named queries were requested but no `ZERO_QUERY_URL` is configured for Zero Cache."
|
|
746
|
+
);
|
|
441
747
|
}
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
this
|
|
447
|
-
|
|
448
|
-
|
|
748
|
+
if (this.#customQueryTransformer && customQueries.size > 0) {
|
|
749
|
+
const transformedCustomQueries = await this.#customQueryTransformer.transform(
|
|
750
|
+
this.#getHeaderOptions(this.#queryConfig.forwardCookies),
|
|
751
|
+
customQueries.values(),
|
|
752
|
+
this.userQueryURL
|
|
753
|
+
);
|
|
754
|
+
this.#processTransformedCustomQueries(
|
|
755
|
+
lc,
|
|
756
|
+
transformedCustomQueries,
|
|
757
|
+
(q) => transformedQueries.push(q),
|
|
758
|
+
customQueries
|
|
759
|
+
);
|
|
760
|
+
}
|
|
761
|
+
for (const q of otherQueries) {
|
|
762
|
+
const transformed = transformAndHashQuery(
|
|
763
|
+
lc,
|
|
764
|
+
q.id,
|
|
765
|
+
q.ast,
|
|
766
|
+
must(this.#pipelines.currentPermissions()).permissions ?? {
|
|
767
|
+
tables: {}
|
|
768
|
+
},
|
|
769
|
+
this.#authData?.decoded,
|
|
770
|
+
q.type === "internal"
|
|
771
|
+
);
|
|
772
|
+
if (transformed.transformationHash === q.transformationHash) {
|
|
773
|
+
transformedQueries.push(transformed);
|
|
774
|
+
}
|
|
449
775
|
}
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
776
|
+
for (const {
|
|
777
|
+
id: queryID,
|
|
778
|
+
transformationHash,
|
|
779
|
+
transformedAst
|
|
780
|
+
} of transformedQueries) {
|
|
781
|
+
const timer = new TimeSliceTimer();
|
|
782
|
+
let count = 0;
|
|
783
|
+
await startAsyncSpan(
|
|
784
|
+
tracer,
|
|
785
|
+
"vs.#hydrateUnchangedQueries.addQuery",
|
|
786
|
+
async (span) => {
|
|
787
|
+
span.setAttribute("queryHash", queryID);
|
|
788
|
+
span.setAttribute("transformationHash", transformationHash);
|
|
789
|
+
span.setAttribute("table", transformedAst.table);
|
|
790
|
+
for (const _ of this.#pipelines.addQuery(
|
|
791
|
+
transformationHash,
|
|
792
|
+
queryID,
|
|
793
|
+
transformedAst,
|
|
794
|
+
await timer.start()
|
|
795
|
+
)) {
|
|
796
|
+
if (++count % TIME_SLICE_CHECK_SIZE === 0) {
|
|
797
|
+
if (timer.elapsedLap() > TIME_SLICE_MS) {
|
|
798
|
+
await timer.yieldProcess();
|
|
799
|
+
}
|
|
463
800
|
}
|
|
464
|
-
|
|
801
|
+
}
|
|
465
802
|
}
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
803
|
+
);
|
|
804
|
+
const elapsed = timer.totalElapsed();
|
|
805
|
+
this.#hydrations.add(1);
|
|
806
|
+
this.#hydrationTime.record(elapsed / 1e3);
|
|
807
|
+
this.#addQueryMaterializationServerMetric(transformationHash, elapsed);
|
|
808
|
+
lc.debug?.(`hydrated ${count} rows for ${queryID} (${elapsed} ms)`);
|
|
470
809
|
}
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
if (newClient || !this.#clients.has(clientID)) {
|
|
480
|
-
this.#lastConnectTime = Date.now();
|
|
481
|
-
}
|
|
482
|
-
return startAsyncSpan(tracer, `vs.#runInLockForClient(${cmd})`, async () => {
|
|
483
|
-
let client;
|
|
484
|
-
try {
|
|
485
|
-
await this.#runInLockWithCVR((lc, cvr) => {
|
|
486
|
-
lc = lc
|
|
487
|
-
.withContext('clientID', clientID)
|
|
488
|
-
.withContext('wsID', wsID)
|
|
489
|
-
.withContext('cmd', cmd);
|
|
490
|
-
lc.debug?.('acquired lock for cvr');
|
|
491
|
-
client = this.#clients.get(clientID);
|
|
492
|
-
if (client?.wsID !== wsID) {
|
|
493
|
-
lc.debug?.('mismatched wsID', client?.wsID, wsID);
|
|
494
|
-
// Only respond to messages of the currently connected client.
|
|
495
|
-
// Connections may have been drained or dropped due to an error.
|
|
496
|
-
return;
|
|
497
|
-
}
|
|
498
|
-
if (newClient) {
|
|
499
|
-
assert(newClient === client, 'newClient must match existing client');
|
|
500
|
-
checkClientAndCVRVersions(client.version(), cvr.version);
|
|
501
|
-
}
|
|
502
|
-
else if (!this.#clients.has(clientID)) {
|
|
503
|
-
lc.warn?.(`Processing ${cmd} before initConnection was received`);
|
|
504
|
-
}
|
|
505
|
-
lc.debug?.(cmd, body);
|
|
506
|
-
return fn(lc, clientID, body, cvr);
|
|
507
|
-
});
|
|
508
|
-
}
|
|
509
|
-
catch (e) {
|
|
510
|
-
const lc = this.#lc
|
|
511
|
-
.withContext('clientID', clientID)
|
|
512
|
-
.withContext('wsID', wsID)
|
|
513
|
-
.withContext('cmd', cmd);
|
|
514
|
-
lc[getLogLevel(e)]?.(`closing connection with error`, e);
|
|
515
|
-
if (client) {
|
|
516
|
-
// Ideally, propagate the exception to the client's downstream subscription ...
|
|
517
|
-
client.fail(e);
|
|
518
|
-
}
|
|
519
|
-
else {
|
|
520
|
-
// unless the exception happened before the client could be looked up.
|
|
521
|
-
throw e;
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
|
-
});
|
|
810
|
+
}
|
|
811
|
+
#processTransformedCustomQueries(lc, transformedCustomQueries, cb, customQueryMap) {
|
|
812
|
+
if ("kind" in transformedCustomQueries) {
|
|
813
|
+
this.#sendQueryTransformErrorToClients(
|
|
814
|
+
customQueryMap,
|
|
815
|
+
transformedCustomQueries
|
|
816
|
+
);
|
|
817
|
+
return transformedCustomQueries.queryIDs;
|
|
525
818
|
}
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
819
|
+
const appQueryErrors = [];
|
|
820
|
+
for (const q of transformedCustomQueries) {
|
|
821
|
+
if ("error" in q) {
|
|
822
|
+
const errorMessage = `Error transforming custom query ${q.name}: ${q.error}${q.details ? ` ${JSON.stringify(q.details)}` : ""}`;
|
|
823
|
+
lc.warn?.(errorMessage, q);
|
|
824
|
+
appQueryErrors.push(q);
|
|
825
|
+
continue;
|
|
826
|
+
}
|
|
827
|
+
cb(q);
|
|
531
828
|
}
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
case 'clear':
|
|
554
|
-
patches.push(...updater.clearDesiredQueries(clientID));
|
|
555
|
-
break;
|
|
556
|
-
}
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
const clientIDsToDelete = new Set();
|
|
560
|
-
if (activeClients) {
|
|
561
|
-
// We find all the clients in this client group that are not active.
|
|
562
|
-
const allClientIDs = Object.keys(cvr.clients);
|
|
563
|
-
const activeClientsSet = new Set(activeClients);
|
|
564
|
-
for (const id of allClientIDs) {
|
|
565
|
-
if (!activeClientsSet.has(id)) {
|
|
566
|
-
clientIDsToDelete.add(id);
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
if (deleted?.clientIDs?.length) {
|
|
571
|
-
for (const cid of deleted.clientIDs) {
|
|
572
|
-
assert(cid !== clientID, 'cannot delete self');
|
|
573
|
-
clientIDsToDelete.add(cid);
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
for (const cid of clientIDsToDelete) {
|
|
577
|
-
const patchesDueToClient = updater.deleteClient(cid, ttlClock);
|
|
578
|
-
patches.push(...patchesDueToClient);
|
|
579
|
-
deletedClientIDs.push(cid);
|
|
580
|
-
}
|
|
581
|
-
if (deleted?.clientGroupIDs?.length) {
|
|
582
|
-
lc.debug?.(`ignoring ${deleted.clientGroupIDs.length} deprecated client group deletes`);
|
|
583
|
-
}
|
|
584
|
-
return patches;
|
|
585
|
-
});
|
|
586
|
-
// Send 'deleteClients' ack to the clients.
|
|
587
|
-
if ((deletedClientIDs.length && deleted?.clientIDs?.length) ||
|
|
588
|
-
deletedClientGroupIDs.length) {
|
|
589
|
-
const clients = this.#getClients();
|
|
590
|
-
await Promise.allSettled(clients.map(client => client.sendDeleteClients(lc, deletedClientIDs, deletedClientGroupIDs)));
|
|
591
|
-
}
|
|
592
|
-
this.#scheduleExpireEviction(lc, cvr);
|
|
593
|
-
});
|
|
594
|
-
#scheduleExpireEviction(lc, cvr) {
|
|
595
|
-
const { ttlClock } = cvr;
|
|
596
|
-
this.#stopExpireTimer();
|
|
597
|
-
// first see if there is any inactive query with a ttl.
|
|
598
|
-
const next = nextEvictionTime(cvr);
|
|
599
|
-
if (next === undefined) {
|
|
600
|
-
lc.debug?.('no inactive queries with ttl');
|
|
601
|
-
// no inactive queries with a ttl. Cancel existing timeout if any.
|
|
602
|
-
return;
|
|
603
|
-
}
|
|
604
|
-
// It is common for many queries to be evicted close to the same time, so
|
|
605
|
-
// we add a small delay so we can collapse multiple evictions into a
|
|
606
|
-
// single timer. However, don't add the delay if we're already at the
|
|
607
|
-
// maximum timer limit, as that's not about collapsing.
|
|
608
|
-
const delay = Math.max(TTL_TIMER_HYSTERESIS, Math.min(ttlClockAsNumber(next) -
|
|
609
|
-
ttlClockAsNumber(ttlClock) +
|
|
610
|
-
TTL_TIMER_HYSTERESIS, MAX_TTL_MS));
|
|
611
|
-
lc.debug?.('Scheduling eviction timer to run in ', delay, 'ms');
|
|
612
|
-
this.#expiredQueriesTimer = this.#setTimeout(() => {
|
|
613
|
-
this.#expiredQueriesTimer = 0;
|
|
614
|
-
this.#runInLockWithCVR((lc, cvr) => this.#removeExpiredQueries(lc, cvr)).catch(e =>
|
|
615
|
-
// If an error occurs (e.g. ownership change), propagate the error
|
|
616
|
-
// to the main run() loop via the #stateChanges Subscription.
|
|
617
|
-
this.#stateChanges.fail(e));
|
|
618
|
-
}, delay);
|
|
829
|
+
this.#sendQueryTransformErrorToClients(customQueryMap, appQueryErrors);
|
|
830
|
+
return appQueryErrors.map((q) => q.id);
|
|
831
|
+
}
|
|
832
|
+
#sendQueryTransformErrorToClients(customQueryMap, errorOrErrors) {
|
|
833
|
+
const getAffectedClientIDs = (queryIDs) => {
|
|
834
|
+
const clientIds = /* @__PURE__ */ new Set();
|
|
835
|
+
for (const queryID of queryIDs) {
|
|
836
|
+
const q = customQueryMap.get(queryID);
|
|
837
|
+
assert(
|
|
838
|
+
q,
|
|
839
|
+
`got an error for query ${queryID} that does not map back to a custom query`
|
|
840
|
+
);
|
|
841
|
+
Object.keys(q.clientState).forEach((id) => clientIds.add(id));
|
|
842
|
+
}
|
|
843
|
+
return clientIds;
|
|
844
|
+
};
|
|
845
|
+
if ("queryIDs" in errorOrErrors) {
|
|
846
|
+
for (const clientId of getAffectedClientIDs(errorOrErrors.queryIDs)) {
|
|
847
|
+
this.#clients.get(clientId)?.sendQueryTransformFailedError(errorOrErrors);
|
|
848
|
+
}
|
|
849
|
+
return;
|
|
619
850
|
}
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
851
|
+
const appErrorGroups = /* @__PURE__ */ new Map();
|
|
852
|
+
for (const err of errorOrErrors) {
|
|
853
|
+
for (const clientId of getAffectedClientIDs([err.id])) {
|
|
854
|
+
const group = appErrorGroups.get(clientId) ?? [];
|
|
855
|
+
group.push(err);
|
|
856
|
+
appErrorGroups.set(clientId, group);
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
for (const [clientId, errors] of appErrorGroups) {
|
|
860
|
+
this.#clients.get(clientId)?.sendQueryTransformApplicationErrors(errors);
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
#addQueryMaterializationServerMetric(transformationHash, elapsed) {
|
|
864
|
+
this.#inspectorDelegate.addMetric(
|
|
865
|
+
"query-materialization-server",
|
|
866
|
+
elapsed,
|
|
867
|
+
transformationHash
|
|
868
|
+
);
|
|
869
|
+
}
|
|
870
|
+
/**
|
|
871
|
+
* Adds and/or removes queries to/from the PipelineDriver to bring it
|
|
872
|
+
* in sync with the set of queries in the CVR (both got and desired).
|
|
873
|
+
* If queries are added, removed, or queried due to a new state version,
|
|
874
|
+
* a new CVR version is created and pokes sent to connected clients.
|
|
875
|
+
*
|
|
876
|
+
* This must be called from within the #lock.
|
|
877
|
+
*/
|
|
878
|
+
#syncQueryPipelineSet(lc, cvr) {
|
|
879
|
+
return startAsyncSpan(tracer, "vs.#syncQueryPipelineSet", async () => {
|
|
880
|
+
assert(
|
|
881
|
+
this.#pipelines.initialized(),
|
|
882
|
+
"pipelines must be initialized (syncQueryPipelineSet)"
|
|
883
|
+
);
|
|
884
|
+
const [hydratedQueries, byOriginalHash] = this.#pipelines.addedQueries();
|
|
885
|
+
const hashToIDs = /* @__PURE__ */ new Map();
|
|
886
|
+
if (this.#ttlClock === void 0) {
|
|
887
|
+
this.#ttlClock = cvr.ttlClock;
|
|
888
|
+
}
|
|
889
|
+
const now = Date.now();
|
|
890
|
+
const ttlClock = this.#getTTLClock(now);
|
|
891
|
+
const cvrQueryEntires = Object.entries(cvr.queries);
|
|
892
|
+
const customQueries = /* @__PURE__ */ new Map();
|
|
893
|
+
const otherQueries = [];
|
|
894
|
+
const transformedQueries = [];
|
|
895
|
+
for (const [id, query] of cvrQueryEntires) {
|
|
896
|
+
if (query.type === "custom") {
|
|
897
|
+
assert(id === query.id, "custom query id mismatch");
|
|
898
|
+
customQueries.set(id, query);
|
|
899
|
+
} else {
|
|
900
|
+
otherQueries.push({ id, query });
|
|
661
901
|
}
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
902
|
+
}
|
|
903
|
+
for (const { id, query: origQuery } of otherQueries) {
|
|
904
|
+
assert(id === origQuery.id, "query id mismatch");
|
|
905
|
+
const transformed = transformAndHashQuery(
|
|
906
|
+
lc,
|
|
907
|
+
origQuery.id,
|
|
908
|
+
origQuery.ast,
|
|
909
|
+
must(this.#pipelines.currentPermissions()).permissions ?? {
|
|
910
|
+
tables: {}
|
|
911
|
+
},
|
|
912
|
+
this.#authData?.decoded,
|
|
913
|
+
origQuery.type === "internal"
|
|
914
|
+
);
|
|
915
|
+
transformedQueries.push({
|
|
916
|
+
id,
|
|
917
|
+
origQuery,
|
|
918
|
+
transformed
|
|
919
|
+
});
|
|
920
|
+
}
|
|
921
|
+
if (customQueries.size > 0 && !this.#customQueryTransformer) {
|
|
922
|
+
lc.warn?.(
|
|
923
|
+
"Custom/named queries were requested but no `ZERO_QUERY_URL` is configured for Zero Cache."
|
|
924
|
+
);
|
|
925
|
+
}
|
|
926
|
+
let erroredQueryIDs;
|
|
927
|
+
if (this.#customQueryTransformer && customQueries.size > 0) {
|
|
928
|
+
const transformStart = performance.now();
|
|
929
|
+
let transformedCustomQueries;
|
|
930
|
+
try {
|
|
931
|
+
transformedCustomQueries = await this.#customQueryTransformer.transform(
|
|
932
|
+
this.#getHeaderOptions(true),
|
|
933
|
+
customQueries.values(),
|
|
934
|
+
this.userQueryURL
|
|
935
|
+
);
|
|
936
|
+
this.#queryTransformations.add(1, { result: "success" });
|
|
937
|
+
} catch (e) {
|
|
938
|
+
this.#queryTransformations.add(1, { result: "error" });
|
|
939
|
+
throw e;
|
|
940
|
+
} finally {
|
|
941
|
+
const transformDuration = (performance.now() - transformStart) / 1e3;
|
|
942
|
+
this.#queryTransformationTime.record(transformDuration);
|
|
667
943
|
}
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
// only processing unchanged queries here
|
|
674
|
-
transformedQueries.push(transformed);
|
|
675
|
-
}
|
|
944
|
+
if (!Array.isArray(transformedCustomQueries) && transformedCustomQueries.kind === TransformFailed) {
|
|
945
|
+
throw new ProtocolErrorWithLevel(
|
|
946
|
+
transformedCustomQueries,
|
|
947
|
+
getLogLevel(transformedCustomQueries.kind)
|
|
948
|
+
);
|
|
676
949
|
}
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
await timer.yieldProcess();
|
|
688
|
-
}
|
|
689
|
-
}
|
|
690
|
-
}
|
|
950
|
+
const successfullyTransformed = /* @__PURE__ */ new Map();
|
|
951
|
+
erroredQueryIDs = this.#processTransformedCustomQueries(
|
|
952
|
+
lc,
|
|
953
|
+
transformedCustomQueries,
|
|
954
|
+
(q) => {
|
|
955
|
+
successfullyTransformed.set(q.id, q);
|
|
956
|
+
transformedQueries.push({
|
|
957
|
+
id: q.id,
|
|
958
|
+
origQuery: must(customQueries.get(q.id)),
|
|
959
|
+
transformed: q
|
|
691
960
|
});
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
961
|
+
},
|
|
962
|
+
customQueries
|
|
963
|
+
);
|
|
964
|
+
for (const [queryID, newTransform] of successfullyTransformed) {
|
|
965
|
+
const existingTransforms = byOriginalHash.get(queryID);
|
|
966
|
+
if (existingTransforms && existingTransforms.length > 0) {
|
|
967
|
+
const oldHash = existingTransforms[0].transformationHash;
|
|
968
|
+
const newHash = newTransform.transformationHash;
|
|
969
|
+
if (oldHash !== newHash) {
|
|
970
|
+
lc.info?.(
|
|
971
|
+
`Query ${queryID} transformation changed: ${oldHash} -> ${newHash}`
|
|
972
|
+
);
|
|
973
|
+
this.#checkForThrashing(queryID);
|
|
974
|
+
this.#queryTransformationHashChanges.add(1);
|
|
975
|
+
} else {
|
|
976
|
+
this.#queryTransformationNoOps.add(1);
|
|
706
977
|
}
|
|
707
|
-
|
|
978
|
+
}
|
|
708
979
|
}
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
980
|
+
}
|
|
981
|
+
const serverQueries = transformedQueries.map(
|
|
982
|
+
({ id, origQuery, transformed }) => {
|
|
983
|
+
const ids = hashToIDs.get(transformed.transformationHash);
|
|
984
|
+
if (ids) {
|
|
985
|
+
ids.push(id);
|
|
986
|
+
} else {
|
|
987
|
+
hashToIDs.set(transformed.transformationHash, [id]);
|
|
988
|
+
}
|
|
989
|
+
return {
|
|
990
|
+
id,
|
|
991
|
+
ast: transformed.transformedAst,
|
|
992
|
+
transformationHash: transformed.transformationHash,
|
|
993
|
+
remove: expired(ttlClock, origQuery)
|
|
994
|
+
};
|
|
723
995
|
}
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
996
|
+
);
|
|
997
|
+
const addQueries = serverQueries.filter(
|
|
998
|
+
(q) => !q.remove && !hydratedQueries.has(q.transformationHash)
|
|
999
|
+
);
|
|
1000
|
+
const removeQueries = serverQueries.filter((q) => q.remove);
|
|
1001
|
+
const desiredQueries = new Set(
|
|
1002
|
+
serverQueries.filter((q) => !q.remove).map((q) => q.transformationHash)
|
|
1003
|
+
);
|
|
1004
|
+
const unhydrateQueries = [...hydratedQueries].filter(
|
|
1005
|
+
(transformationHash) => !desiredQueries.has(transformationHash)
|
|
1006
|
+
);
|
|
1007
|
+
for (const q of addQueries) {
|
|
1008
|
+
const orig = cvr.queries[q.id];
|
|
1009
|
+
lc.debug?.(
|
|
1010
|
+
"ViewSyncer adding query",
|
|
1011
|
+
q.ast,
|
|
1012
|
+
"transformed from",
|
|
1013
|
+
orig.type === "custom" ? orig.name : orig.ast
|
|
1014
|
+
);
|
|
1015
|
+
}
|
|
1016
|
+
if (erroredQueryIDs) {
|
|
1017
|
+
const successfulHashes = new Set(
|
|
1018
|
+
transformedQueries.map(
|
|
1019
|
+
({ transformed }) => transformed.transformationHash
|
|
1020
|
+
)
|
|
1021
|
+
);
|
|
1022
|
+
for (const queryID of erroredQueryIDs) {
|
|
1023
|
+
let lastKnownHash;
|
|
1024
|
+
const cvrQuery = cvr.queries[queryID];
|
|
1025
|
+
if (cvrQuery?.transformationHash) {
|
|
1026
|
+
lastKnownHash = cvrQuery.transformationHash;
|
|
1027
|
+
}
|
|
1028
|
+
const transformationHash = lastKnownHash && successfulHashes.has(lastKnownHash) ? void 0 : lastKnownHash;
|
|
1029
|
+
removeQueries.push({
|
|
1030
|
+
id: queryID,
|
|
1031
|
+
transformationHash
|
|
1032
|
+
});
|
|
729
1033
|
}
|
|
1034
|
+
}
|
|
1035
|
+
if (addQueries.length > 0 || removeQueries.length > 0 || unhydrateQueries.length > 0) {
|
|
1036
|
+
await this.#addAndRemoveQueries(
|
|
1037
|
+
lc,
|
|
1038
|
+
cvr,
|
|
1039
|
+
addQueries,
|
|
1040
|
+
removeQueries,
|
|
1041
|
+
unhydrateQueries,
|
|
1042
|
+
hashToIDs
|
|
1043
|
+
);
|
|
1044
|
+
} else {
|
|
1045
|
+
await this.#catchupClients(lc, cvr);
|
|
1046
|
+
}
|
|
1047
|
+
});
|
|
1048
|
+
}
|
|
1049
|
+
/**
|
|
1050
|
+
* Check if a query is being replaced too frequently (thrashing).
|
|
1051
|
+
* Logs a warning if the query has been replaced more than 3 times in 60 seconds.
|
|
1052
|
+
*/
|
|
1053
|
+
#checkForThrashing(queryID) {
|
|
1054
|
+
const THRASH_WINDOW_MS = 6e4;
|
|
1055
|
+
const THRASH_THRESHOLD = 3;
|
|
1056
|
+
const now = Date.now();
|
|
1057
|
+
let record = this.#queryReplacements.get(queryID);
|
|
1058
|
+
if (!record) {
|
|
1059
|
+
record = { count: 1, windowStart: now };
|
|
1060
|
+
this.#queryReplacements.set(queryID, record);
|
|
1061
|
+
return;
|
|
730
1062
|
}
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
* Adds and/or removes queries to/from the PipelineDriver to bring it
|
|
736
|
-
* in sync with the set of queries in the CVR (both got and desired).
|
|
737
|
-
* If queries are added, removed, or queried due to a new state version,
|
|
738
|
-
* a new CVR version is created and pokes sent to connected clients.
|
|
739
|
-
*
|
|
740
|
-
* This must be called from within the #lock.
|
|
741
|
-
*/
|
|
742
|
-
#syncQueryPipelineSet(lc, cvr) {
|
|
743
|
-
return startAsyncSpan(tracer, 'vs.#syncQueryPipelineSet', async () => {
|
|
744
|
-
assert(this.#pipelines.initialized(), 'pipelines must be initialized (syncQueryPipelineSet)');
|
|
745
|
-
const [hydratedQueries, byOriginalHash] = this.#pipelines.addedQueries();
|
|
746
|
-
// Convert queries to their transformed ast's and hashes
|
|
747
|
-
const hashToIDs = new Map();
|
|
748
|
-
if (this.#ttlClock === undefined) {
|
|
749
|
-
// Get it from the CVR or initialize it to now.
|
|
750
|
-
this.#ttlClock = cvr.ttlClock;
|
|
751
|
-
}
|
|
752
|
-
const now = Date.now();
|
|
753
|
-
const ttlClock = this.#getTTLClock(now);
|
|
754
|
-
// group cvr queries into:
|
|
755
|
-
// 1. custom queries
|
|
756
|
-
// 2. everything else
|
|
757
|
-
// Handle transformation appropriately
|
|
758
|
-
// Then hydrate as `serverQueries`
|
|
759
|
-
const cvrQueryEntires = Object.entries(cvr.queries);
|
|
760
|
-
const customQueries = new Map();
|
|
761
|
-
const otherQueries = [];
|
|
762
|
-
const transformedQueries = [];
|
|
763
|
-
for (const [id, query] of cvrQueryEntires) {
|
|
764
|
-
if (query.type === 'custom') {
|
|
765
|
-
// This should always match, no?
|
|
766
|
-
assert(id === query.id, 'custom query id mismatch');
|
|
767
|
-
customQueries.set(id, query);
|
|
768
|
-
}
|
|
769
|
-
else {
|
|
770
|
-
otherQueries.push({ id, query });
|
|
771
|
-
}
|
|
772
|
-
}
|
|
773
|
-
for (const { id, query: origQuery } of otherQueries) {
|
|
774
|
-
// This should always match, no?
|
|
775
|
-
assert(id === origQuery.id, 'query id mismatch');
|
|
776
|
-
const transformed = transformAndHashQuery(lc, origQuery.id, origQuery.ast, must(this.#pipelines.currentPermissions()).permissions ?? {
|
|
777
|
-
tables: {},
|
|
778
|
-
}, this.#authData?.decoded, origQuery.type === 'internal');
|
|
779
|
-
transformedQueries.push({
|
|
780
|
-
id,
|
|
781
|
-
origQuery,
|
|
782
|
-
transformed,
|
|
783
|
-
});
|
|
784
|
-
}
|
|
785
|
-
if (customQueries.size > 0 && !this.#customQueryTransformer) {
|
|
786
|
-
lc.error?.('Custom/named queries were requested but no `ZERO_GET_QUERIES_URL` is configured for Zero Cache.');
|
|
787
|
-
}
|
|
788
|
-
let erroredQueries;
|
|
789
|
-
if (this.#customQueryTransformer && customQueries.size > 0) {
|
|
790
|
-
const filteredCustomQueries = this.#filterCustomQueries(customQueries.values(), byOriginalHash, (origQuery, existing) => {
|
|
791
|
-
for (const transformed of existing) {
|
|
792
|
-
transformedQueries.push({
|
|
793
|
-
id: origQuery.id,
|
|
794
|
-
origQuery,
|
|
795
|
-
transformed: {
|
|
796
|
-
id: origQuery.id,
|
|
797
|
-
transformationHash: transformed.transformationHash,
|
|
798
|
-
transformedAst: transformed.transformedAst,
|
|
799
|
-
},
|
|
800
|
-
});
|
|
801
|
-
}
|
|
802
|
-
});
|
|
803
|
-
const transformedCustomQueries = await this.#customQueryTransformer.transform(this.#getHeaderOptions(true), filteredCustomQueries, this.userQueryURL);
|
|
804
|
-
erroredQueries = this.#processTransformedCustomQueries(lc, transformedCustomQueries, (q) => transformedQueries.push({
|
|
805
|
-
id: q.id,
|
|
806
|
-
origQuery: must(customQueries.get(q.id)),
|
|
807
|
-
transformed: q,
|
|
808
|
-
}), customQueries);
|
|
809
|
-
}
|
|
810
|
-
const serverQueries = transformedQueries.map(({ id, origQuery, transformed }) => {
|
|
811
|
-
const ids = hashToIDs.get(transformed.transformationHash);
|
|
812
|
-
if (ids) {
|
|
813
|
-
ids.push(id);
|
|
814
|
-
}
|
|
815
|
-
else {
|
|
816
|
-
hashToIDs.set(transformed.transformationHash, [id]);
|
|
817
|
-
}
|
|
818
|
-
return {
|
|
819
|
-
id,
|
|
820
|
-
ast: transformed.transformedAst,
|
|
821
|
-
transformationHash: transformed.transformationHash,
|
|
822
|
-
remove: expired(ttlClock, origQuery),
|
|
823
|
-
};
|
|
824
|
-
});
|
|
825
|
-
const addQueries = serverQueries.filter(q => !q.remove && !hydratedQueries.has(q.transformationHash));
|
|
826
|
-
const removeQueries = serverQueries.filter(q => q.remove);
|
|
827
|
-
const desiredQueries = new Set(serverQueries.filter(q => !q.remove).map(q => q.transformationHash));
|
|
828
|
-
const unhydrateQueries = [...hydratedQueries].filter(transformationHash => !desiredQueries.has(transformationHash));
|
|
829
|
-
for (const q of addQueries) {
|
|
830
|
-
const orig = cvr.queries[q.id];
|
|
831
|
-
lc.debug?.('ViewSyncer adding query', q.ast, 'transformed from', orig.type === 'custom' ? orig.name : orig.ast);
|
|
832
|
-
}
|
|
833
|
-
// These are queries we need to remove from `desired`, not `got`, because they never transformed.
|
|
834
|
-
if (erroredQueries) {
|
|
835
|
-
for (const q of erroredQueries) {
|
|
836
|
-
removeQueries.push({
|
|
837
|
-
id: q.id,
|
|
838
|
-
transformationHash: undefined,
|
|
839
|
-
});
|
|
840
|
-
}
|
|
841
|
-
}
|
|
842
|
-
if (addQueries.length > 0 ||
|
|
843
|
-
removeQueries.length > 0 ||
|
|
844
|
-
unhydrateQueries.length > 0) {
|
|
845
|
-
await this.#addAndRemoveQueries(lc, cvr, addQueries, removeQueries, unhydrateQueries, hashToIDs);
|
|
846
|
-
}
|
|
847
|
-
else {
|
|
848
|
-
await this.#catchupClients(lc, cvr);
|
|
849
|
-
}
|
|
850
|
-
});
|
|
851
|
-
}
|
|
852
|
-
// Removes queries from `customQueries` that are already
|
|
853
|
-
// transformed and in the pipelines. We do not want to re-transform
|
|
854
|
-
// a query that has already been transformed. The reason is that
|
|
855
|
-
// we do not want a query that is already running to suddenly flip
|
|
856
|
-
// to error due to re-calling transform.
|
|
857
|
-
#filterCustomQueries(customQueries, byOriginalHash, onExisting) {
|
|
858
|
-
return wrapIterable(customQueries).filter(origQuery => {
|
|
859
|
-
const existing = byOriginalHash.get(origQuery.id);
|
|
860
|
-
if (existing) {
|
|
861
|
-
onExisting?.(origQuery, existing);
|
|
862
|
-
return false;
|
|
863
|
-
}
|
|
864
|
-
return true;
|
|
865
|
-
});
|
|
866
|
-
}
|
|
867
|
-
// This must be called from within the #lock.
|
|
868
|
-
#addAndRemoveQueries(lc, cvr, addQueries, removeQueries, unhydrateQueries, hashToIDs) {
|
|
869
|
-
return startAsyncSpan(tracer, 'vs.#addAndRemoveQueries', async () => {
|
|
870
|
-
assert(addQueries.length > 0 ||
|
|
871
|
-
removeQueries.length > 0 ||
|
|
872
|
-
unhydrateQueries.length > 0, 'Must have queries to add or remove');
|
|
873
|
-
const start = performance.now();
|
|
874
|
-
const stateVersion = this.#pipelines.currentVersion();
|
|
875
|
-
lc = lc.withContext('stateVersion', stateVersion);
|
|
876
|
-
lc.info?.(`hydrating ${addQueries.length} queries`);
|
|
877
|
-
const updater = new CVRQueryDrivenUpdater(this.#cvrStore, cvr, stateVersion, this.#pipelines.replicaVersion);
|
|
878
|
-
// Note: This kicks off background PG queries for CVR data associated with the
|
|
879
|
-
// executed and removed queries.
|
|
880
|
-
const { newVersion, queryPatches } = updater.trackQueries(lc, addQueries, removeQueries);
|
|
881
|
-
const clients = this.#getClients();
|
|
882
|
-
const pokers = startPoke(clients, newVersion, this.#pipelines.currentSchemaVersions());
|
|
883
|
-
for (const patch of queryPatches) {
|
|
884
|
-
await pokers.addPatch(patch);
|
|
885
|
-
}
|
|
886
|
-
// Removing queries is easy. The pipelines are dropped, and the CVR
|
|
887
|
-
// updater handles the updates and pokes.
|
|
888
|
-
for (const q of removeQueries) {
|
|
889
|
-
if (q.transformationHash) {
|
|
890
|
-
this.#pipelines.removeQuery(q.transformationHash);
|
|
891
|
-
}
|
|
892
|
-
// Remove per-query server metrics when query is deleted
|
|
893
|
-
this.#inspectorDelegate.removeQuery(q.id);
|
|
894
|
-
}
|
|
895
|
-
for (const hash of unhydrateQueries) {
|
|
896
|
-
this.#pipelines.removeQuery(hash);
|
|
897
|
-
// Remove per-query server metrics for unhydrated queries
|
|
898
|
-
const ids = hashToIDs.get(hash);
|
|
899
|
-
if (ids) {
|
|
900
|
-
for (const id of ids) {
|
|
901
|
-
this.#inspectorDelegate.removeQuery(id);
|
|
902
|
-
}
|
|
903
|
-
}
|
|
904
|
-
}
|
|
905
|
-
let totalProcessTime = 0;
|
|
906
|
-
const timer = new TimeSliceTimer();
|
|
907
|
-
const pipelines = this.#pipelines;
|
|
908
|
-
const hydrations = this.#hydrations;
|
|
909
|
-
const hydrationTime = this.#hydrationTime;
|
|
910
|
-
// oxlint-disable-next-line @typescript-eslint/no-this-alias
|
|
911
|
-
const self = this;
|
|
912
|
-
// yield at the very beginning so that the first time slice
|
|
913
|
-
// is properly processed by the time-slice queue.
|
|
914
|
-
await yieldProcess();
|
|
915
|
-
function* generateRowChanges(slowHydrateThreshold) {
|
|
916
|
-
for (const q of addQueries) {
|
|
917
|
-
lc = lc
|
|
918
|
-
.withContext('hash', q.id)
|
|
919
|
-
.withContext('transformationHash', q.transformationHash);
|
|
920
|
-
lc.debug?.(`adding pipeline for query`, q.ast);
|
|
921
|
-
yield* pipelines.addQuery(q.transformationHash, q.id, q.ast, timer.startWithoutYielding());
|
|
922
|
-
const elapsed = timer.stop();
|
|
923
|
-
totalProcessTime += elapsed;
|
|
924
|
-
self.#addQueryMaterializationServerMetric(q.transformationHash, elapsed);
|
|
925
|
-
if (elapsed > slowHydrateThreshold) {
|
|
926
|
-
lc.warn?.('Slow query materialization', elapsed, q.ast);
|
|
927
|
-
}
|
|
928
|
-
manualSpan(tracer, 'vs.addAndConsumeQuery', elapsed, {
|
|
929
|
-
hash: q.id,
|
|
930
|
-
transformationHash: q.transformationHash,
|
|
931
|
-
});
|
|
932
|
-
}
|
|
933
|
-
hydrations.add(1);
|
|
934
|
-
hydrationTime.record(totalProcessTime / 1000);
|
|
935
|
-
}
|
|
936
|
-
// #processChanges does batched de-duping of rows. Wrap all pipelines in
|
|
937
|
-
// a single generator in order to maximize de-duping.
|
|
938
|
-
await this.#processChanges(lc, timer, generateRowChanges(this.#slowHydrateThreshold), updater, pokers, hashToIDs);
|
|
939
|
-
for (const patch of await updater.deleteUnreferencedRows(lc)) {
|
|
940
|
-
await pokers.addPatch(patch);
|
|
941
|
-
}
|
|
942
|
-
// Commit the changes and update the CVR snapshot.
|
|
943
|
-
this.#cvr = await this.#flushUpdater(lc, updater);
|
|
944
|
-
const finalVersion = this.#cvr.version;
|
|
945
|
-
// Before ending the poke, catch up clients that were behind the old CVR.
|
|
946
|
-
await this.#catchupClients(lc, cvr, finalVersion, addQueries.map(q => q.id), pokers);
|
|
947
|
-
// Signal clients to commit.
|
|
948
|
-
await pokers.end(finalVersion);
|
|
949
|
-
const wallTime = performance.now() - start;
|
|
950
|
-
lc.info?.(`finished processing queries (process: ${totalProcessTime} ms, wall: ${wallTime} ms)`);
|
|
951
|
-
});
|
|
952
|
-
}
|
|
953
|
-
/**
|
|
954
|
-
* @param cvr The CVR to which clients should be caught up to. This does
|
|
955
|
-
* not necessarily need to be the current CVR.
|
|
956
|
-
* @param current The expected current CVR version. Before performing
|
|
957
|
-
* catchup, the snapshot read will verify that the CVR has not been
|
|
958
|
-
* concurrently modified. Note that this only needs to be done for
|
|
959
|
-
* catchup because it is the only time data from the CVR DB is
|
|
960
|
-
* "exported" without being gated by a CVR flush (which provides
|
|
961
|
-
* concurrency protection in all other cases).
|
|
962
|
-
*
|
|
963
|
-
* If unspecified, the version of the `cvr` is used.
|
|
964
|
-
* @param excludeQueryHashes Exclude patches from rows associated with
|
|
965
|
-
* the specified queries.
|
|
966
|
-
* @param usePokers If specified, sends pokes on existing PokeHandlers,
|
|
967
|
-
* in which case the caller is responsible for sending the `pokeEnd`
|
|
968
|
-
* messages. If unspecified, the pokes will be started and ended
|
|
969
|
-
* using the version from the supplied `cvr`.
|
|
970
|
-
*/
|
|
971
|
-
// Must be called within #lock
|
|
972
|
-
#catchupClients(lc, cvr, current, excludeQueryHashes = [], usePokers) {
|
|
973
|
-
return startAsyncSpan(tracer, 'vs.#catchupClients', async (span) => {
|
|
974
|
-
current ??= cvr.version;
|
|
975
|
-
const clients = this.#getClients();
|
|
976
|
-
const pokers = usePokers ??
|
|
977
|
-
startPoke(clients, cvr.version, this.#pipelines.currentSchemaVersions());
|
|
978
|
-
span.setAttribute('numClients', clients.length);
|
|
979
|
-
const catchupFrom = clients
|
|
980
|
-
.map(c => c.version())
|
|
981
|
-
.reduce((a, b) => (cmpVersions(a, b) < 0 ? a : b), cvr.version);
|
|
982
|
-
// This is an AsyncGenerator which won't execute until awaited.
|
|
983
|
-
const rowPatches = this.#cvrStore.catchupRowPatches(lc, catchupFrom, cvr, current, excludeQueryHashes);
|
|
984
|
-
// This is a plain async function that kicks off immediately.
|
|
985
|
-
const configPatches = this.#cvrStore.catchupConfigPatches(lc, catchupFrom, cvr, current);
|
|
986
|
-
// await the rowPatches first so that the AsyncGenerator kicks off.
|
|
987
|
-
let rowPatchCount = 0;
|
|
988
|
-
for await (const rows of rowPatches) {
|
|
989
|
-
for (const row of rows) {
|
|
990
|
-
const { schema, table } = row;
|
|
991
|
-
const rowKey = row.rowKey;
|
|
992
|
-
const toVersion = versionFromString(row.patchVersion);
|
|
993
|
-
const id = { schema, table, rowKey };
|
|
994
|
-
let patch;
|
|
995
|
-
if (!row.refCounts) {
|
|
996
|
-
patch = { type: 'row', op: 'del', id };
|
|
997
|
-
}
|
|
998
|
-
else {
|
|
999
|
-
const row = must(this.#pipelines.getRow(table, rowKey), `Missing row ${table}:${stringify(rowKey)}`);
|
|
1000
|
-
const { contents } = contentsAndVersion(row);
|
|
1001
|
-
patch = { type: 'row', op: 'put', id, contents };
|
|
1002
|
-
}
|
|
1003
|
-
const patchToVersion = { patch, toVersion };
|
|
1004
|
-
await pokers.addPatch(patchToVersion);
|
|
1005
|
-
rowPatchCount++;
|
|
1006
|
-
}
|
|
1007
|
-
}
|
|
1008
|
-
span.setAttribute('rowPatchCount', rowPatchCount);
|
|
1009
|
-
if (rowPatchCount) {
|
|
1010
|
-
lc.debug?.(`sent ${rowPatchCount} row patches`);
|
|
1011
|
-
}
|
|
1012
|
-
// Then await the config patches which were fetched in parallel.
|
|
1013
|
-
for (const patch of await configPatches) {
|
|
1014
|
-
await pokers.addPatch(patch);
|
|
1015
|
-
}
|
|
1016
|
-
if (!usePokers) {
|
|
1017
|
-
await pokers.end(cvr.version);
|
|
1018
|
-
}
|
|
1019
|
-
});
|
|
1020
|
-
}
|
|
1021
|
-
#processChanges(lc, timer, changes, updater, pokers, hashToIDs) {
|
|
1022
|
-
return startAsyncSpan(tracer, 'vs.#processChanges', async () => {
|
|
1023
|
-
const start = performance.now();
|
|
1024
|
-
const rows = new CustomKeyMap(rowIDString);
|
|
1025
|
-
let total = 0;
|
|
1026
|
-
const processBatch = () => startAsyncSpan(tracer, 'processBatch', async () => {
|
|
1027
|
-
const wallElapsed = performance.now() - start;
|
|
1028
|
-
total += rows.size;
|
|
1029
|
-
lc.debug?.(`processing ${rows.size} (of ${total}) rows (${wallElapsed} ms)`);
|
|
1030
|
-
const patches = await updater.received(lc, rows);
|
|
1031
|
-
for (const patch of patches) {
|
|
1032
|
-
await pokers.addPatch(patch);
|
|
1033
|
-
}
|
|
1034
|
-
rows.clear();
|
|
1035
|
-
});
|
|
1036
|
-
await startAsyncSpan(tracer, 'loopingChanges', async (span) => {
|
|
1037
|
-
for (const change of changes) {
|
|
1038
|
-
const { type, queryHash: transformationHash, table, rowKey, row, } = change;
|
|
1039
|
-
const queryIDs = must(hashToIDs.get(transformationHash), 'could not find the original hash for the transformation hash');
|
|
1040
|
-
const rowID = { schema: '', table, rowKey: rowKey };
|
|
1041
|
-
let parsedRow = rows.get(rowID);
|
|
1042
|
-
if (!parsedRow) {
|
|
1043
|
-
parsedRow = { refCounts: {} };
|
|
1044
|
-
rows.set(rowID, parsedRow);
|
|
1045
|
-
}
|
|
1046
|
-
queryIDs.forEach(hash => (parsedRow.refCounts[hash] ??= 0));
|
|
1047
|
-
const updateVersion = (row) => {
|
|
1048
|
-
// IVM can output multiple versions of a row as it goes through its
|
|
1049
|
-
// intermediate stages. Always update the version and contents;
|
|
1050
|
-
// the last version will reflect the final state.
|
|
1051
|
-
const { version, contents } = contentsAndVersion(row);
|
|
1052
|
-
parsedRow.version = version;
|
|
1053
|
-
parsedRow.contents = contents;
|
|
1054
|
-
};
|
|
1055
|
-
switch (type) {
|
|
1056
|
-
case 'add':
|
|
1057
|
-
updateVersion(row);
|
|
1058
|
-
queryIDs.forEach(hash => parsedRow.refCounts[hash]++);
|
|
1059
|
-
break;
|
|
1060
|
-
case 'edit':
|
|
1061
|
-
updateVersion(row);
|
|
1062
|
-
// No update to refCounts.
|
|
1063
|
-
break;
|
|
1064
|
-
case 'remove':
|
|
1065
|
-
queryIDs.forEach(hash => parsedRow.refCounts[hash]--);
|
|
1066
|
-
break;
|
|
1067
|
-
default:
|
|
1068
|
-
unreachable(type);
|
|
1069
|
-
}
|
|
1070
|
-
if (rows.size % CURSOR_PAGE_SIZE === 0) {
|
|
1071
|
-
await processBatch();
|
|
1072
|
-
}
|
|
1073
|
-
if (rows.size % TIME_SLICE_CHECK_SIZE === 0) {
|
|
1074
|
-
if (timer.elapsedLap() > TIME_SLICE_MS) {
|
|
1075
|
-
await timer.yieldProcess();
|
|
1076
|
-
}
|
|
1077
|
-
}
|
|
1078
|
-
}
|
|
1079
|
-
if (rows.size) {
|
|
1080
|
-
await processBatch();
|
|
1081
|
-
}
|
|
1082
|
-
span.setAttribute('totalRows', total);
|
|
1083
|
-
});
|
|
1084
|
-
});
|
|
1085
|
-
}
|
|
1086
|
-
/**
|
|
1087
|
-
* Advance to the current snapshot of the replica and apply / send
|
|
1088
|
-
* changes.
|
|
1089
|
-
*
|
|
1090
|
-
* Must be called from within the #lock.
|
|
1091
|
-
*
|
|
1092
|
-
* Returns false if the advancement failed due to a schema change.
|
|
1093
|
-
*/
|
|
1094
|
-
#advancePipelines(lc, cvr) {
|
|
1095
|
-
return startAsyncSpan(tracer, 'vs.#advancePipelines', async () => {
|
|
1096
|
-
assert(this.#pipelines.initialized(), 'pipelines must be initialized (advancePipelines');
|
|
1097
|
-
const start = performance.now();
|
|
1098
|
-
const timer = new TimeSliceTimer();
|
|
1099
|
-
const { version, numChanges, changes } = this.#pipelines.advance(timer);
|
|
1100
|
-
lc = lc.withContext('newVersion', version);
|
|
1101
|
-
// Probably need a new updater type. CVRAdvancementUpdater?
|
|
1102
|
-
const updater = new CVRQueryDrivenUpdater(this.#cvrStore, cvr, version, this.#pipelines.replicaVersion);
|
|
1103
|
-
// Only poke clients that are at the cvr.version. New clients that
|
|
1104
|
-
// are behind need to first be caught up when their initConnection
|
|
1105
|
-
// message is processed (and #syncQueryPipelines is called).
|
|
1106
|
-
const pokers = startPoke(this.#getClients(cvr.version), updater.updatedVersion(), this.#pipelines.currentSchemaVersions());
|
|
1107
|
-
lc.debug?.(`applying ${numChanges} to advance to ${version}`);
|
|
1108
|
-
const hashToIDs = createHashToIDs(cvr);
|
|
1109
|
-
try {
|
|
1110
|
-
await this.#processChanges(lc, await timer.start(), changes, updater, pokers, hashToIDs);
|
|
1111
|
-
}
|
|
1112
|
-
catch (e) {
|
|
1113
|
-
if (e instanceof ResetPipelinesSignal) {
|
|
1114
|
-
await pokers.cancel();
|
|
1115
|
-
return e;
|
|
1116
|
-
}
|
|
1117
|
-
throw e;
|
|
1118
|
-
}
|
|
1119
|
-
// Commit the changes and update the CVR snapshot.
|
|
1120
|
-
this.#cvr = await this.#flushUpdater(lc, updater);
|
|
1121
|
-
const finalVersion = this.#cvr.version;
|
|
1122
|
-
// Signal clients to commit.
|
|
1123
|
-
await pokers.end(finalVersion);
|
|
1124
|
-
const elapsed = performance.now() - start;
|
|
1125
|
-
lc.info?.(`finished processing advancement of ${numChanges} changes (${elapsed} ms)`);
|
|
1126
|
-
this.#transactionAdvanceTime.record(elapsed / 1000);
|
|
1127
|
-
return 'success';
|
|
1128
|
-
});
|
|
1063
|
+
if (now - record.windowStart > THRASH_WINDOW_MS) {
|
|
1064
|
+
this.#queryReplacements.delete(queryID);
|
|
1065
|
+
this.#queryReplacements.set(queryID, { count: 1, windowStart: now });
|
|
1066
|
+
return;
|
|
1129
1067
|
}
|
|
1130
|
-
|
|
1131
|
-
|
|
1068
|
+
record.count++;
|
|
1069
|
+
if (record.count >= THRASH_THRESHOLD) {
|
|
1070
|
+
this.#lc.warn?.(
|
|
1071
|
+
`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.`
|
|
1072
|
+
);
|
|
1132
1073
|
}
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
this.#
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1074
|
+
}
|
|
1075
|
+
// This must be called from within the #lock.
|
|
1076
|
+
#addAndRemoveQueries(lc, cvr, addQueries, removeQueries, unhydrateQueries, hashToIDs) {
|
|
1077
|
+
return startAsyncSpan(tracer, "vs.#addAndRemoveQueries", async () => {
|
|
1078
|
+
assert(
|
|
1079
|
+
addQueries.length > 0 || removeQueries.length > 0 || unhydrateQueries.length > 0,
|
|
1080
|
+
"Must have queries to add or remove"
|
|
1081
|
+
);
|
|
1082
|
+
const start = performance.now();
|
|
1083
|
+
const stateVersion = this.#pipelines.currentVersion();
|
|
1084
|
+
lc = lc.withContext("stateVersion", stateVersion);
|
|
1085
|
+
lc.info?.(`hydrating ${addQueries.length} queries`);
|
|
1086
|
+
const updater = new CVRQueryDrivenUpdater(
|
|
1087
|
+
this.#cvrStore,
|
|
1088
|
+
cvr,
|
|
1089
|
+
stateVersion,
|
|
1090
|
+
this.#pipelines.replicaVersion
|
|
1091
|
+
);
|
|
1092
|
+
const { newVersion, queryPatches } = updater.trackQueries(
|
|
1093
|
+
lc,
|
|
1094
|
+
addQueries,
|
|
1095
|
+
removeQueries
|
|
1096
|
+
);
|
|
1097
|
+
const clients = this.#getClients();
|
|
1098
|
+
const pokers = startPoke(
|
|
1099
|
+
clients,
|
|
1100
|
+
newVersion,
|
|
1101
|
+
this.#pipelines.currentSchemaVersions()
|
|
1102
|
+
);
|
|
1103
|
+
for (const patch of queryPatches) {
|
|
1104
|
+
await pokers.addPatch(patch);
|
|
1105
|
+
}
|
|
1106
|
+
for (const q of removeQueries) {
|
|
1107
|
+
if (q.transformationHash) {
|
|
1108
|
+
this.#pipelines.removeQuery(q.transformationHash);
|
|
1109
|
+
}
|
|
1110
|
+
this.#inspectorDelegate.removeQuery(q.id);
|
|
1111
|
+
this.#queryReplacements.delete(q.id);
|
|
1112
|
+
}
|
|
1113
|
+
for (const hash of unhydrateQueries) {
|
|
1114
|
+
this.#pipelines.removeQuery(hash);
|
|
1115
|
+
const ids = hashToIDs.get(hash);
|
|
1116
|
+
if (ids) {
|
|
1117
|
+
for (const id of ids) {
|
|
1118
|
+
this.#inspectorDelegate.removeQuery(id);
|
|
1119
|
+
this.#queryReplacements.delete(id);
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
let totalProcessTime = 0;
|
|
1124
|
+
const timer = new TimeSliceTimer();
|
|
1125
|
+
const pipelines = this.#pipelines;
|
|
1126
|
+
const hydrations = this.#hydrations;
|
|
1127
|
+
const hydrationTime = this.#hydrationTime;
|
|
1128
|
+
const self = this;
|
|
1129
|
+
await yieldProcess();
|
|
1130
|
+
function* generateRowChanges(slowHydrateThreshold) {
|
|
1131
|
+
for (const q of addQueries) {
|
|
1132
|
+
lc = lc.withContext("hash", q.id).withContext("transformationHash", q.transformationHash);
|
|
1133
|
+
lc.debug?.(`adding pipeline for query`, q.ast);
|
|
1134
|
+
yield* pipelines.addQuery(
|
|
1135
|
+
q.transformationHash,
|
|
1136
|
+
q.id,
|
|
1137
|
+
q.ast,
|
|
1138
|
+
timer.startWithoutYielding()
|
|
1139
|
+
);
|
|
1140
|
+
const elapsed = timer.stop();
|
|
1141
|
+
totalProcessTime += elapsed;
|
|
1142
|
+
self.#addQueryMaterializationServerMetric(
|
|
1143
|
+
q.transformationHash,
|
|
1144
|
+
elapsed
|
|
1145
|
+
);
|
|
1146
|
+
if (elapsed > slowHydrateThreshold) {
|
|
1147
|
+
lc.warn?.("Slow query materialization", elapsed, q.ast);
|
|
1148
|
+
}
|
|
1149
|
+
manualSpan(tracer, "vs.addAndConsumeQuery", elapsed, {
|
|
1150
|
+
hash: q.id,
|
|
1151
|
+
transformationHash: q.transformationHash
|
|
1152
|
+
});
|
|
1153
|
+
}
|
|
1154
|
+
hydrations.add(1);
|
|
1155
|
+
hydrationTime.record(totalProcessTime / 1e3);
|
|
1156
|
+
}
|
|
1157
|
+
await this.#processChanges(
|
|
1158
|
+
lc,
|
|
1159
|
+
timer,
|
|
1160
|
+
generateRowChanges(this.#slowHydrateThreshold),
|
|
1161
|
+
updater,
|
|
1162
|
+
pokers,
|
|
1163
|
+
hashToIDs
|
|
1164
|
+
);
|
|
1165
|
+
for (const patch of await updater.deleteUnreferencedRows(lc)) {
|
|
1166
|
+
await pokers.addPatch(patch);
|
|
1167
|
+
}
|
|
1168
|
+
this.#cvr = await this.#flushUpdater(lc, updater);
|
|
1169
|
+
const finalVersion = this.#cvr.version;
|
|
1170
|
+
await this.#catchupClients(
|
|
1171
|
+
lc,
|
|
1172
|
+
cvr,
|
|
1173
|
+
finalVersion,
|
|
1174
|
+
addQueries.map((q) => q.id),
|
|
1175
|
+
pokers
|
|
1176
|
+
);
|
|
1177
|
+
await pokers.end(finalVersion);
|
|
1178
|
+
const wallTime = performance.now() - start;
|
|
1179
|
+
lc.info?.(
|
|
1180
|
+
`finished processing queries (process: ${totalProcessTime} ms, wall: ${wallTime} ms)`
|
|
1181
|
+
);
|
|
1182
|
+
});
|
|
1183
|
+
}
|
|
1184
|
+
/**
|
|
1185
|
+
* @param cvr The CVR to which clients should be caught up to. This does
|
|
1186
|
+
* not necessarily need to be the current CVR.
|
|
1187
|
+
* @param current The expected current CVR version. Before performing
|
|
1188
|
+
* catchup, the snapshot read will verify that the CVR has not been
|
|
1189
|
+
* concurrently modified. Note that this only needs to be done for
|
|
1190
|
+
* catchup because it is the only time data from the CVR DB is
|
|
1191
|
+
* "exported" without being gated by a CVR flush (which provides
|
|
1192
|
+
* concurrency protection in all other cases).
|
|
1193
|
+
*
|
|
1194
|
+
* If unspecified, the version of the `cvr` is used.
|
|
1195
|
+
* @param excludeQueryHashes Exclude patches from rows associated with
|
|
1196
|
+
* the specified queries.
|
|
1197
|
+
* @param usePokers If specified, sends pokes on existing PokeHandlers,
|
|
1198
|
+
* in which case the caller is responsible for sending the `pokeEnd`
|
|
1199
|
+
* messages. If unspecified, the pokes will be started and ended
|
|
1200
|
+
* using the version from the supplied `cvr`.
|
|
1201
|
+
*/
|
|
1202
|
+
// Must be called within #lock
|
|
1203
|
+
#catchupClients(lc, cvr, current, excludeQueryHashes = [], usePokers) {
|
|
1204
|
+
return startAsyncSpan(tracer, "vs.#catchupClients", async (span) => {
|
|
1205
|
+
current ??= cvr.version;
|
|
1206
|
+
const clients = this.#getClients();
|
|
1207
|
+
const pokers = usePokers ?? startPoke(
|
|
1208
|
+
clients,
|
|
1209
|
+
cvr.version,
|
|
1210
|
+
this.#pipelines.currentSchemaVersions()
|
|
1211
|
+
);
|
|
1212
|
+
span.setAttribute("numClients", clients.length);
|
|
1213
|
+
const catchupFrom = clients.map((c) => c.version()).reduce((a, b) => cmpVersions(a, b) < 0 ? a : b, cvr.version);
|
|
1214
|
+
const rowPatches = this.#cvrStore.catchupRowPatches(
|
|
1215
|
+
lc,
|
|
1216
|
+
catchupFrom,
|
|
1217
|
+
cvr,
|
|
1218
|
+
current,
|
|
1219
|
+
excludeQueryHashes
|
|
1220
|
+
);
|
|
1221
|
+
const configPatches = this.#cvrStore.catchupConfigPatches(
|
|
1222
|
+
lc,
|
|
1223
|
+
catchupFrom,
|
|
1224
|
+
cvr,
|
|
1225
|
+
current
|
|
1226
|
+
);
|
|
1227
|
+
let rowPatchCount = 0;
|
|
1228
|
+
for await (const rows of rowPatches) {
|
|
1229
|
+
for (const row of rows) {
|
|
1230
|
+
const { schema, table } = row;
|
|
1231
|
+
const rowKey = row.rowKey;
|
|
1232
|
+
const toVersion = versionFromString(row.patchVersion);
|
|
1233
|
+
const id = { schema, table, rowKey };
|
|
1234
|
+
let patch;
|
|
1235
|
+
if (!row.refCounts) {
|
|
1236
|
+
patch = { type: "row", op: "del", id };
|
|
1237
|
+
} else {
|
|
1238
|
+
const row2 = must(
|
|
1239
|
+
this.#pipelines.getRow(table, rowKey),
|
|
1240
|
+
`Missing row ${table}:${stringify(rowKey)}`
|
|
1241
|
+
);
|
|
1242
|
+
const { contents } = contentsAndVersion(row2);
|
|
1243
|
+
patch = { type: "row", op: "put", id, contents };
|
|
1244
|
+
}
|
|
1245
|
+
const patchToVersion = { patch, toVersion };
|
|
1246
|
+
await pokers.addPatch(patchToVersion);
|
|
1247
|
+
rowPatchCount++;
|
|
1248
|
+
}
|
|
1249
|
+
}
|
|
1250
|
+
span.setAttribute("rowPatchCount", rowPatchCount);
|
|
1251
|
+
if (rowPatchCount) {
|
|
1252
|
+
lc.debug?.(`sent ${rowPatchCount} row patches`);
|
|
1253
|
+
}
|
|
1254
|
+
for (const patch of await configPatches) {
|
|
1255
|
+
await pokers.addPatch(patch);
|
|
1256
|
+
}
|
|
1257
|
+
if (!usePokers) {
|
|
1258
|
+
await pokers.end(cvr.version);
|
|
1259
|
+
}
|
|
1260
|
+
});
|
|
1261
|
+
}
|
|
1262
|
+
#processChanges(lc, timer, changes, updater, pokers, hashToIDs) {
|
|
1263
|
+
return startAsyncSpan(tracer, "vs.#processChanges", async () => {
|
|
1264
|
+
const start = performance.now();
|
|
1265
|
+
const rows = new CustomKeyMap(rowIDString);
|
|
1266
|
+
let total = 0;
|
|
1267
|
+
const processBatch = () => startAsyncSpan(tracer, "processBatch", async () => {
|
|
1268
|
+
const wallElapsed = performance.now() - start;
|
|
1269
|
+
total += rows.size;
|
|
1270
|
+
lc.debug?.(
|
|
1271
|
+
`processing ${rows.size} (of ${total}) rows (${wallElapsed} ms)`
|
|
1272
|
+
);
|
|
1273
|
+
const patches = await updater.received(lc, rows);
|
|
1274
|
+
for (const patch of patches) {
|
|
1275
|
+
await pokers.addPatch(patch);
|
|
1276
|
+
}
|
|
1277
|
+
rows.clear();
|
|
1278
|
+
});
|
|
1279
|
+
await startAsyncSpan(tracer, "loopingChanges", async (span) => {
|
|
1280
|
+
for (const change of changes) {
|
|
1281
|
+
const {
|
|
1282
|
+
type,
|
|
1283
|
+
queryHash: transformationHash,
|
|
1284
|
+
table,
|
|
1285
|
+
rowKey,
|
|
1286
|
+
row
|
|
1287
|
+
} = change;
|
|
1288
|
+
const queryIDs = must(
|
|
1289
|
+
hashToIDs.get(transformationHash),
|
|
1290
|
+
"could not find the original hash for the transformation hash"
|
|
1291
|
+
);
|
|
1292
|
+
const rowID = { schema: "", table, rowKey };
|
|
1293
|
+
let parsedRow = rows.get(rowID);
|
|
1294
|
+
if (!parsedRow) {
|
|
1295
|
+
parsedRow = { refCounts: {} };
|
|
1296
|
+
rows.set(rowID, parsedRow);
|
|
1297
|
+
}
|
|
1298
|
+
queryIDs.forEach((hash) => parsedRow.refCounts[hash] ??= 0);
|
|
1299
|
+
const updateVersion = (row2) => {
|
|
1300
|
+
const { version: version2, contents } = contentsAndVersion(row2);
|
|
1301
|
+
parsedRow.version = version2;
|
|
1302
|
+
parsedRow.contents = contents;
|
|
1303
|
+
};
|
|
1304
|
+
switch (type) {
|
|
1305
|
+
case "add":
|
|
1306
|
+
updateVersion(row);
|
|
1307
|
+
queryIDs.forEach((hash) => parsedRow.refCounts[hash]++);
|
|
1308
|
+
break;
|
|
1309
|
+
case "edit":
|
|
1310
|
+
updateVersion(row);
|
|
1311
|
+
break;
|
|
1312
|
+
case "remove":
|
|
1313
|
+
queryIDs.forEach((hash) => parsedRow.refCounts[hash]--);
|
|
1314
|
+
break;
|
|
1315
|
+
default:
|
|
1316
|
+
unreachable(type);
|
|
1317
|
+
}
|
|
1318
|
+
if (rows.size % CURSOR_PAGE_SIZE === 0) {
|
|
1319
|
+
await processBatch();
|
|
1320
|
+
}
|
|
1321
|
+
if (rows.size % TIME_SLICE_CHECK_SIZE === 0) {
|
|
1322
|
+
if (timer.elapsedLap() > TIME_SLICE_MS) {
|
|
1323
|
+
await timer.yieldProcess();
|
|
1153
1324
|
}
|
|
1325
|
+
}
|
|
1154
1326
|
}
|
|
1327
|
+
if (rows.size) {
|
|
1328
|
+
await processBatch();
|
|
1329
|
+
}
|
|
1330
|
+
span.setAttribute("totalRows", total);
|
|
1331
|
+
});
|
|
1332
|
+
});
|
|
1333
|
+
}
|
|
1334
|
+
/**
|
|
1335
|
+
* Advance to the current snapshot of the replica and apply / send
|
|
1336
|
+
* changes.
|
|
1337
|
+
*
|
|
1338
|
+
* Must be called from within the #lock.
|
|
1339
|
+
*
|
|
1340
|
+
* Returns false if the advancement failed due to a schema change.
|
|
1341
|
+
*/
|
|
1342
|
+
#advancePipelines(lc, cvr) {
|
|
1343
|
+
return startAsyncSpan(tracer, "vs.#advancePipelines", async () => {
|
|
1344
|
+
assert(
|
|
1345
|
+
this.#pipelines.initialized(),
|
|
1346
|
+
"pipelines must be initialized (advancePipelines"
|
|
1347
|
+
);
|
|
1348
|
+
const start = performance.now();
|
|
1349
|
+
const timer = new TimeSliceTimer();
|
|
1350
|
+
const { version: version2, numChanges, changes } = this.#pipelines.advance(timer);
|
|
1351
|
+
lc = lc.withContext("newVersion", version2);
|
|
1352
|
+
const updater = new CVRQueryDrivenUpdater(
|
|
1353
|
+
this.#cvrStore,
|
|
1354
|
+
cvr,
|
|
1355
|
+
version2,
|
|
1356
|
+
this.#pipelines.replicaVersion
|
|
1357
|
+
);
|
|
1358
|
+
const pokers = startPoke(
|
|
1359
|
+
this.#getClients(cvr.version),
|
|
1360
|
+
updater.updatedVersion(),
|
|
1361
|
+
this.#pipelines.currentSchemaVersions()
|
|
1362
|
+
);
|
|
1363
|
+
lc.debug?.(`applying ${numChanges} to advance to ${version2}`);
|
|
1364
|
+
const hashToIDs = createHashToIDs(cvr);
|
|
1365
|
+
try {
|
|
1366
|
+
await this.#processChanges(
|
|
1367
|
+
lc,
|
|
1368
|
+
await timer.start(),
|
|
1369
|
+
changes,
|
|
1370
|
+
updater,
|
|
1371
|
+
pokers,
|
|
1372
|
+
hashToIDs
|
|
1373
|
+
);
|
|
1374
|
+
} catch (e) {
|
|
1375
|
+
if (e instanceof ResetPipelinesSignal) {
|
|
1376
|
+
await pokers.cancel();
|
|
1377
|
+
return e;
|
|
1378
|
+
}
|
|
1379
|
+
throw e;
|
|
1380
|
+
}
|
|
1381
|
+
this.#cvr = await this.#flushUpdater(lc, updater);
|
|
1382
|
+
const finalVersion = this.#cvr.version;
|
|
1383
|
+
await pokers.end(finalVersion);
|
|
1384
|
+
const elapsed = performance.now() - start;
|
|
1385
|
+
lc.info?.(
|
|
1386
|
+
`finished processing advancement of ${numChanges} changes (${elapsed} ms)`
|
|
1387
|
+
);
|
|
1388
|
+
this.#transactionAdvanceTime.record(elapsed / 1e3);
|
|
1389
|
+
return "success";
|
|
1390
|
+
});
|
|
1391
|
+
}
|
|
1392
|
+
inspect(context, msg) {
|
|
1393
|
+
return this.#runInLockForClient(context, msg, this.#handleInspect);
|
|
1394
|
+
}
|
|
1395
|
+
// oxlint-disable-next-line require-await
|
|
1396
|
+
#handleInspect = async (lc, clientID, body, cvr) => {
|
|
1397
|
+
const client = must(this.#clients.get(clientID));
|
|
1398
|
+
return handleInspect(
|
|
1399
|
+
lc,
|
|
1400
|
+
body,
|
|
1401
|
+
cvr,
|
|
1402
|
+
client,
|
|
1403
|
+
this.#inspectorDelegate,
|
|
1404
|
+
this.id,
|
|
1405
|
+
this.#cvrStore,
|
|
1406
|
+
this.#config,
|
|
1407
|
+
this.#getHeaderOptions(this.#queryConfig.forwardCookies ?? false),
|
|
1408
|
+
this.userQueryURL,
|
|
1409
|
+
this.#authData
|
|
1410
|
+
);
|
|
1411
|
+
};
|
|
1412
|
+
stop() {
|
|
1413
|
+
this.#lc.info?.("stopping view syncer");
|
|
1414
|
+
this.#initialized.reject("shut down before initialization completed");
|
|
1415
|
+
this.#stateChanges.cancel();
|
|
1416
|
+
return this.#stopped.promise;
|
|
1417
|
+
}
|
|
1418
|
+
#cleanup(err) {
|
|
1419
|
+
this.#stopTTLClockInterval();
|
|
1420
|
+
this.#stopExpireTimer();
|
|
1421
|
+
this.#pipelines.destroy();
|
|
1422
|
+
for (const client of this.#clients.values()) {
|
|
1423
|
+
if (err) {
|
|
1424
|
+
client.fail(err);
|
|
1425
|
+
} else {
|
|
1426
|
+
client.close(`closed clientGroupID=${this.id}`);
|
|
1427
|
+
}
|
|
1155
1428
|
}
|
|
1429
|
+
}
|
|
1430
|
+
/**
|
|
1431
|
+
* Test helper: Manually mark initialization as complete.
|
|
1432
|
+
* This should only be used in tests that don't call initConnection().
|
|
1433
|
+
*/
|
|
1434
|
+
markInitialized() {
|
|
1435
|
+
this.#initialized.resolve("initialized");
|
|
1436
|
+
}
|
|
1156
1437
|
}
|
|
1157
|
-
|
|
1158
|
-
const CURSOR_PAGE_SIZE = 10000;
|
|
1159
|
-
// Check the elapsed time every 100 rows.
|
|
1438
|
+
const CURSOR_PAGE_SIZE = 1e4;
|
|
1160
1439
|
const TIME_SLICE_CHECK_SIZE = 100;
|
|
1161
|
-
// Yield the process after churning for > 500ms.
|
|
1162
1440
|
const TIME_SLICE_MS = 500;
|
|
1163
1441
|
function createHashToIDs(cvr) {
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
hashToIDs.set(transformationHash, [id]);
|
|
1174
|
-
}
|
|
1442
|
+
const hashToIDs = /* @__PURE__ */ new Map();
|
|
1443
|
+
for (const { id, transformationHash } of Object.values(cvr.queries)) {
|
|
1444
|
+
if (!transformationHash) {
|
|
1445
|
+
continue;
|
|
1446
|
+
}
|
|
1447
|
+
if (hashToIDs.has(transformationHash)) {
|
|
1448
|
+
must(hashToIDs.get(transformationHash)).push(id);
|
|
1449
|
+
} else {
|
|
1450
|
+
hashToIDs.set(transformationHash, [id]);
|
|
1175
1451
|
}
|
|
1176
|
-
|
|
1452
|
+
}
|
|
1453
|
+
return hashToIDs;
|
|
1177
1454
|
}
|
|
1178
|
-
// A global Lock acts as a queue to run a single IVM time slice per iteration
|
|
1179
|
-
// of the node event loop, thus bounding I/O delay to the duration of a single
|
|
1180
|
-
// time slice.
|
|
1181
|
-
//
|
|
1182
|
-
// Refresher:
|
|
1183
|
-
// https://nodejs.org/en/learn/asynchronous-work/event-loop-timers-and-nexttick#phases-overview
|
|
1184
|
-
//
|
|
1185
|
-
// Note that recursive use of setImmediate() (i.e. calling setImmediate() from
|
|
1186
|
-
// within a setImmediate() callback), results in enqueuing the latter
|
|
1187
|
-
// callback in the *next* event loop iteration, as documented in:
|
|
1188
|
-
// https://nodejs.org/api/timers.html#setimmediatecallback-args
|
|
1189
|
-
//
|
|
1190
|
-
// This effectively achieves the desired one-per-event-loop-iteration behavior.
|
|
1191
1455
|
const timeSliceQueue = new Lock();
|
|
1192
1456
|
function yieldProcess() {
|
|
1193
|
-
|
|
1457
|
+
return timeSliceQueue.withLock(() => new Promise(setImmediate));
|
|
1194
1458
|
}
|
|
1195
1459
|
function contentsAndVersion(row) {
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1460
|
+
const { [ZERO_VERSION_COLUMN_NAME]: version2, ...contents } = row;
|
|
1461
|
+
if (typeof version2 !== "string" || version2.length === 0) {
|
|
1462
|
+
throw new Error(`Invalid _0_version in ${stringify(row)}`);
|
|
1463
|
+
}
|
|
1464
|
+
return { contents, version: version2 };
|
|
1201
1465
|
}
|
|
1202
|
-
const NEW_CVR_VERSION = { stateVersion:
|
|
1466
|
+
const NEW_CVR_VERSION = { stateVersion: "00" };
|
|
1203
1467
|
function checkClientAndCVRVersions(client, cvr) {
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1468
|
+
if (cmpVersions(cvr, NEW_CVR_VERSION) === 0 && cmpVersions(client, NEW_CVR_VERSION) > 0) {
|
|
1469
|
+
throw new ProtocolErrorWithLevel({
|
|
1470
|
+
kind: ClientNotFound,
|
|
1471
|
+
message: "Client not found",
|
|
1472
|
+
origin: ZeroCache
|
|
1473
|
+
});
|
|
1474
|
+
}
|
|
1475
|
+
if (cmpVersions(client, cvr) > 0) {
|
|
1476
|
+
throw new ProtocolError({
|
|
1477
|
+
kind: InvalidConnectionRequestBaseCookie,
|
|
1478
|
+
message: `CVR is at version ${versionString(cvr)}`,
|
|
1479
|
+
origin: ZeroCache
|
|
1480
|
+
});
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1483
|
+
function pickToken(lc, previousToken, newToken) {
|
|
1484
|
+
if (previousToken === void 0) {
|
|
1485
|
+
lc.debug?.(`No previous token, using new token`);
|
|
1486
|
+
return newToken;
|
|
1487
|
+
}
|
|
1488
|
+
if (newToken) {
|
|
1489
|
+
if (previousToken.decoded.sub !== newToken.decoded.sub) {
|
|
1490
|
+
throw new ProtocolError({
|
|
1491
|
+
kind: Unauthorized,
|
|
1492
|
+
message: "The user id in the new token does not match the previous token. Client groups are pinned to a single user.",
|
|
1493
|
+
origin: ZeroCache
|
|
1494
|
+
});
|
|
1211
1495
|
}
|
|
1212
|
-
if (
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
kind: ErrorKind.InvalidConnectionRequestBaseCookie,
|
|
1216
|
-
message: `CVR is at version ${versionString(cvr)}`,
|
|
1217
|
-
});
|
|
1496
|
+
if (previousToken.decoded.iat === void 0) {
|
|
1497
|
+
lc.debug?.(`No issued at time for the existing token, using new token`);
|
|
1498
|
+
return newToken;
|
|
1218
1499
|
}
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1500
|
+
if (newToken.decoded.iat === void 0) {
|
|
1501
|
+
throw new ProtocolError({
|
|
1502
|
+
kind: Unauthorized,
|
|
1503
|
+
message: "The new token does not have an issued at time but the prior token does. Tokens for a client group must either all have issued at times or all not have issued at times",
|
|
1504
|
+
origin: ZeroCache
|
|
1505
|
+
});
|
|
1224
1506
|
}
|
|
1225
|
-
if (newToken) {
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
kind: ErrorKind.Unauthorized,
|
|
1229
|
-
message: 'The user id in the new token does not match the previous token. Client groups are pinned to a single user.',
|
|
1230
|
-
});
|
|
1231
|
-
}
|
|
1232
|
-
if (previousToken.decoded.iat === undefined) {
|
|
1233
|
-
lc.debug?.(`No issued at time for the existing token, using new token`);
|
|
1234
|
-
// No issued at time for the existing token? We take the most recently received token.
|
|
1235
|
-
return newToken;
|
|
1236
|
-
}
|
|
1237
|
-
if (newToken.decoded.iat === undefined) {
|
|
1238
|
-
throw new ErrorForClient({
|
|
1239
|
-
kind: ErrorKind.Unauthorized,
|
|
1240
|
-
message: 'The new token does not have an issued at time but the prior token does. Tokens for a client group must either all have issued at times or all not have issued at times',
|
|
1241
|
-
});
|
|
1242
|
-
}
|
|
1243
|
-
// The new token is newer, so we take it.
|
|
1244
|
-
if (previousToken.decoded.iat < newToken.decoded.iat) {
|
|
1245
|
-
lc.debug?.(`New token is newer, using it`);
|
|
1246
|
-
return newToken;
|
|
1247
|
-
}
|
|
1248
|
-
// if the new token is older or the same, we keep the existing token.
|
|
1249
|
-
lc.debug?.(`New token is older or the same, using existing token`);
|
|
1250
|
-
return previousToken;
|
|
1507
|
+
if (previousToken.decoded.iat < newToken.decoded.iat) {
|
|
1508
|
+
lc.debug?.(`New token is newer, using it`);
|
|
1509
|
+
return newToken;
|
|
1251
1510
|
}
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1511
|
+
lc.debug?.(`New token is older or the same, using existing token`);
|
|
1512
|
+
return previousToken;
|
|
1513
|
+
}
|
|
1514
|
+
throw new ProtocolError({
|
|
1515
|
+
kind: Unauthorized,
|
|
1516
|
+
message: "No token provided. An unauthenticated client cannot connect to an authenticated client group.",
|
|
1517
|
+
origin: ZeroCache
|
|
1518
|
+
});
|
|
1257
1519
|
}
|
|
1258
|
-
/**
|
|
1259
|
-
* A query must be expired for all clients in order to be considered
|
|
1260
|
-
* expired.
|
|
1261
|
-
*/
|
|
1262
1520
|
function expired(ttlClock, q) {
|
|
1263
|
-
|
|
1264
|
-
|
|
1521
|
+
if (q.type === "internal") {
|
|
1522
|
+
return false;
|
|
1523
|
+
}
|
|
1524
|
+
for (const clientState of Object.values(q.clientState)) {
|
|
1525
|
+
const { ttl, inactivatedAt } = clientState;
|
|
1526
|
+
if (inactivatedAt === void 0) {
|
|
1527
|
+
return false;
|
|
1265
1528
|
}
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
return false;
|
|
1270
|
-
}
|
|
1271
|
-
const clampedTTL = clampTTL(ttl);
|
|
1272
|
-
if (ttlClockAsNumber(inactivatedAt) + clampedTTL >
|
|
1273
|
-
ttlClockAsNumber(ttlClock)) {
|
|
1274
|
-
return false;
|
|
1275
|
-
}
|
|
1529
|
+
const clampedTTL = clampTTL(ttl);
|
|
1530
|
+
if (ttlClockAsNumber(inactivatedAt) + clampedTTL > ttlClockAsNumber(ttlClock)) {
|
|
1531
|
+
return false;
|
|
1276
1532
|
}
|
|
1277
|
-
|
|
1533
|
+
}
|
|
1534
|
+
return true;
|
|
1278
1535
|
}
|
|
1279
1536
|
function hasExpiredQueries(cvr) {
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
}
|
|
1537
|
+
const { ttlClock } = cvr;
|
|
1538
|
+
for (const q of Object.values(cvr.queries)) {
|
|
1539
|
+
if (expired(ttlClock, q)) {
|
|
1540
|
+
return true;
|
|
1285
1541
|
}
|
|
1286
|
-
|
|
1542
|
+
}
|
|
1543
|
+
return false;
|
|
1287
1544
|
}
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
return this.#start === 0
|
|
1331
|
-
? this.#total
|
|
1332
|
-
: this.#total + performance.now() - this.#start;
|
|
1333
|
-
}
|
|
1545
|
+
class TimeSliceTimer {
|
|
1546
|
+
#total = 0;
|
|
1547
|
+
#start = 0;
|
|
1548
|
+
async start() {
|
|
1549
|
+
await yieldProcess();
|
|
1550
|
+
return this.startWithoutYielding();
|
|
1551
|
+
}
|
|
1552
|
+
startWithoutYielding() {
|
|
1553
|
+
this.#total = 0;
|
|
1554
|
+
this.#startLap();
|
|
1555
|
+
return this;
|
|
1556
|
+
}
|
|
1557
|
+
async yieldProcess() {
|
|
1558
|
+
this.#stopLap();
|
|
1559
|
+
await yieldProcess();
|
|
1560
|
+
this.#startLap();
|
|
1561
|
+
}
|
|
1562
|
+
#startLap() {
|
|
1563
|
+
assert(this.#start === 0, "already running");
|
|
1564
|
+
this.#start = performance.now();
|
|
1565
|
+
}
|
|
1566
|
+
elapsedLap() {
|
|
1567
|
+
assert(this.#start !== 0, "not running");
|
|
1568
|
+
return performance.now() - this.#start;
|
|
1569
|
+
}
|
|
1570
|
+
#stopLap() {
|
|
1571
|
+
assert(this.#start !== 0, "not running");
|
|
1572
|
+
this.#total += performance.now() - this.#start;
|
|
1573
|
+
this.#start = 0;
|
|
1574
|
+
}
|
|
1575
|
+
/** @returns the total elapsed time */
|
|
1576
|
+
stop() {
|
|
1577
|
+
this.#stopLap();
|
|
1578
|
+
return this.#total;
|
|
1579
|
+
}
|
|
1580
|
+
/**
|
|
1581
|
+
* @returns the elapsed time. This can be called while the Timer is running
|
|
1582
|
+
* or after it has been stopped.
|
|
1583
|
+
*/
|
|
1584
|
+
totalElapsed() {
|
|
1585
|
+
return this.#start === 0 ? this.#total : this.#total + performance.now() - this.#start;
|
|
1586
|
+
}
|
|
1334
1587
|
}
|
|
1335
|
-
|
|
1588
|
+
export {
|
|
1589
|
+
TTL_CLOCK_INTERVAL,
|
|
1590
|
+
TTL_TIMER_HYSTERESIS,
|
|
1591
|
+
TimeSliceTimer,
|
|
1592
|
+
ViewSyncerService,
|
|
1593
|
+
pickToken
|
|
1594
|
+
};
|
|
1595
|
+
//# sourceMappingURL=view-syncer.js.map
|