@rocicorp/zero 1.10.0-canary.21 → 1.10.0-canary.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/out/analyze-query/src/analyze-cli.js +2 -2
- package/out/analyze-query/src/analyze-cli.js.map +1 -1
- package/out/replicache/src/dag/gc.d.ts.map +1 -1
- package/out/replicache/src/dag/gc.js +2 -1
- package/out/replicache/src/dag/gc.js.map +1 -1
- package/out/replicache/src/dag/invalid-ref-count-error.d.ts +12 -0
- package/out/replicache/src/dag/invalid-ref-count-error.d.ts.map +1 -0
- package/out/replicache/src/dag/invalid-ref-count-error.js +19 -0
- package/out/replicache/src/dag/invalid-ref-count-error.js.map +1 -0
- package/out/replicache/src/dag/store-impl.d.ts +12 -2
- package/out/replicache/src/dag/store-impl.d.ts.map +1 -1
- package/out/replicache/src/dag/store-impl.js +22 -8
- package/out/replicache/src/dag/store-impl.js.map +1 -1
- package/out/replicache/src/kv/expo-sqlite/store.d.ts.map +1 -1
- package/out/replicache/src/kv/expo-sqlite/store.js +1 -1
- package/out/replicache/src/kv/expo-sqlite/store.js.map +1 -1
- package/out/replicache/src/kv/idb-store-with-mem-fallback.d.ts +15 -5
- package/out/replicache/src/kv/idb-store-with-mem-fallback.d.ts.map +1 -1
- package/out/replicache/src/kv/idb-store-with-mem-fallback.js +25 -25
- package/out/replicache/src/kv/idb-store-with-mem-fallback.js.map +1 -1
- package/out/replicache/src/kv/idb-store.d.ts +9 -0
- package/out/replicache/src/kv/idb-store.d.ts.map +1 -1
- package/out/replicache/src/kv/idb-store.js +14 -2
- package/out/replicache/src/kv/idb-store.js.map +1 -1
- package/out/replicache/src/kv/mem-store.d.ts +1 -0
- package/out/replicache/src/kv/mem-store.d.ts.map +1 -1
- package/out/replicache/src/kv/mem-store.js +3 -0
- package/out/replicache/src/kv/mem-store.js.map +1 -1
- package/out/replicache/src/kv/op-sqlite/store.d.ts.map +1 -1
- package/out/replicache/src/kv/op-sqlite/store.js +1 -1
- package/out/replicache/src/kv/op-sqlite/store.js.map +1 -1
- package/out/replicache/src/kv/sqlite-store.d.ts +2 -1
- package/out/replicache/src/kv/sqlite-store.d.ts.map +1 -1
- package/out/replicache/src/kv/sqlite-store.js +6 -1
- package/out/replicache/src/kv/sqlite-store.js.map +1 -1
- package/out/replicache/src/kv/store.d.ts +6 -0
- package/out/replicache/src/kv/store.d.ts.map +1 -1
- package/out/replicache/src/persist/collect-idb-databases.d.ts +10 -5
- package/out/replicache/src/persist/collect-idb-databases.d.ts.map +1 -1
- package/out/replicache/src/persist/collect-idb-databases.js +16 -9
- package/out/replicache/src/persist/collect-idb-databases.js.map +1 -1
- package/out/replicache/src/replicache-impl.d.ts +14 -3
- package/out/replicache/src/replicache-impl.d.ts.map +1 -1
- package/out/replicache/src/replicache-impl.js +104 -9
- package/out/replicache/src/replicache-impl.js.map +1 -1
- package/out/shared/src/arrays.js +1 -15
- package/out/shared/src/arrays.js.map +1 -1
- package/out/shared/src/hash.d.ts +1 -0
- package/out/shared/src/hash.d.ts.map +1 -1
- package/out/shared/src/hash.js +10 -28
- package/out/shared/src/hash.js.map +1 -1
- package/out/shared/src/iterables.d.ts +2 -0
- package/out/shared/src/iterables.d.ts.map +1 -1
- package/out/shared/src/iterables.js +18 -1
- package/out/shared/src/iterables.js.map +1 -1
- package/out/shared/src/json.d.ts.map +1 -1
- package/out/shared/src/json.js +2 -2
- package/out/shared/src/json.js.map +1 -1
- package/out/shared/src/ring-buffer.d.ts +8 -0
- package/out/shared/src/ring-buffer.d.ts.map +1 -1
- package/out/shared/src/ring-buffer.js +22 -1
- package/out/shared/src/ring-buffer.js.map +1 -1
- package/out/shared/src/xxhash32.d.ts +36 -0
- package/out/shared/src/xxhash32.d.ts.map +1 -0
- package/out/shared/src/xxhash32.js +51 -0
- package/out/shared/src/xxhash32.js.map +1 -0
- package/out/z2s/src/compiler.js +1 -1
- package/out/zero/package.js +1 -1
- package/out/zero/package.js.map +1 -1
- package/out/zero-cache/src/auth/read-authorizer.js +1 -1
- package/out/zero-cache/src/custom-queries/transform-query.js +1 -1
- package/out/zero-cache/src/server/inspector-delegate.js +3 -2
- package/out/zero-cache/src/server/inspector-delegate.js.map +1 -1
- package/out/zero-cache/src/services/change-source/custom/change-source.js +2 -2
- package/out/zero-cache/src/services/change-source/custom/change-source.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +3 -3
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
- package/out/zero-cache/src/services/mutagen/pusher.js +1 -1
- package/out/zero-cache/src/services/run-ast.js +1 -1
- 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 +6 -10
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/query-covering.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/query-covering.js.map +1 -1
- package/out/zero-cache/src/workers/connection.js +3 -3
- package/out/zero-cache/src/workers/connection.js.map +1 -1
- package/out/zero-client/src/client/connection-manager.d.ts +20 -0
- package/out/zero-client/src/client/connection-manager.d.ts.map +1 -1
- package/out/zero-client/src/client/connection-manager.js +32 -14
- package/out/zero-client/src/client/connection-manager.js.map +1 -1
- package/out/zero-client/src/client/connection-status-enum.d.ts +2 -0
- package/out/zero-client/src/client/connection-status-enum.d.ts.map +1 -1
- package/out/zero-client/src/client/connection-status-enum.js +3 -1
- package/out/zero-client/src/client/connection-status-enum.js.map +1 -1
- package/out/zero-client/src/client/connection.d.ts +6 -0
- package/out/zero-client/src/client/connection.d.ts.map +1 -1
- package/out/zero-client/src/client/connection.js +2 -1
- package/out/zero-client/src/client/connection.js.map +1 -1
- package/out/zero-client/src/client/context.d.ts +8 -11
- package/out/zero-client/src/client/context.d.ts.map +1 -1
- package/out/zero-client/src/client/context.js +11 -15
- package/out/zero-client/src/client/context.js.map +1 -1
- package/out/zero-client/src/client/custom.js +2 -2
- package/out/zero-client/src/client/custom.js.map +1 -1
- package/out/zero-client/src/client/error.js +1 -1
- package/out/zero-client/src/client/mutator-proxy.d.ts.map +1 -1
- package/out/zero-client/src/client/mutator-proxy.js +2 -1
- package/out/zero-client/src/client/mutator-proxy.js.map +1 -1
- package/out/zero-client/src/client/options.d.ts +3 -0
- package/out/zero-client/src/client/options.d.ts.map +1 -1
- package/out/zero-client/src/client/options.js.map +1 -1
- package/out/zero-client/src/client/query-manager.d.ts +2 -0
- package/out/zero-client/src/client/query-manager.d.ts.map +1 -1
- package/out/zero-client/src/client/query-manager.js +48 -9
- package/out/zero-client/src/client/query-manager.js.map +1 -1
- package/out/zero-client/src/client/version.js +1 -1
- package/out/zero-client/src/client/zero.d.ts +18 -3
- package/out/zero-client/src/client/zero.d.ts.map +1 -1
- package/out/zero-client/src/client/zero.js +59 -12
- package/out/zero-client/src/client/zero.js.map +1 -1
- package/out/zero-client/src/types/query-result.d.ts +2 -0
- package/out/zero-client/src/types/query-result.d.ts.map +1 -1
- package/out/zero-protocol/src/ast.d.ts +64 -1
- package/out/zero-protocol/src/ast.d.ts.map +1 -1
- package/out/zero-protocol/src/ast.js +223 -51
- package/out/zero-protocol/src/ast.js.map +1 -1
- package/out/zero-protocol/src/query-hash-visitor.d.ts +81 -0
- package/out/zero-protocol/src/query-hash-visitor.d.ts.map +1 -0
- package/out/zero-protocol/src/query-hash-visitor.js +324 -0
- package/out/zero-protocol/src/query-hash-visitor.js.map +1 -0
- package/out/zero-protocol/src/query-hash.d.ts +7 -2
- package/out/zero-protocol/src/query-hash.d.ts.map +1 -1
- package/out/zero-protocol/src/query-hash.js +12 -9
- package/out/zero-protocol/src/query-hash.js.map +1 -1
- package/out/zero-react/src/use-query.d.ts +5 -4
- package/out/zero-react/src/use-query.d.ts.map +1 -1
- package/out/zero-react/src/use-query.js +86 -9
- package/out/zero-react/src/use-query.js.map +1 -1
- package/out/zero-solid/src/solid-view.d.ts +10 -0
- package/out/zero-solid/src/solid-view.d.ts.map +1 -1
- package/out/zero-solid/src/solid-view.js +27 -0
- package/out/zero-solid/src/solid-view.js.map +1 -1
- package/out/zero-solid/src/use-query.js +5 -3
- package/out/zero-solid/src/use-query.js.map +1 -1
- package/out/zql/src/ivm/array-view.d.ts +10 -0
- package/out/zql/src/ivm/array-view.d.ts.map +1 -1
- package/out/zql/src/ivm/array-view.js +20 -8
- package/out/zql/src/ivm/array-view.js.map +1 -1
- package/out/zql/src/ivm/cap.d.ts.map +1 -1
- package/out/zql/src/ivm/cap.js +5 -3
- package/out/zql/src/ivm/cap.js.map +1 -1
- package/out/zql/src/ivm/deferred-input.d.ts.map +1 -1
- package/out/zql/src/ivm/deferred-input.js +3 -2
- package/out/zql/src/ivm/deferred-input.js.map +1 -1
- package/out/zql/src/ivm/exists.d.ts +1 -1
- package/out/zql/src/ivm/exists.d.ts.map +1 -1
- package/out/zql/src/ivm/exists.js +1 -1
- package/out/zql/src/ivm/exists.js.map +1 -1
- package/out/zql/src/ivm/fan-in.d.ts +2 -2
- package/out/zql/src/ivm/fan-in.d.ts.map +1 -1
- package/out/zql/src/ivm/fan-in.js +6 -5
- package/out/zql/src/ivm/fan-in.js.map +1 -1
- package/out/zql/src/ivm/fan-out.d.ts +2 -2
- package/out/zql/src/ivm/fan-out.d.ts.map +1 -1
- package/out/zql/src/ivm/fan-out.js.map +1 -1
- package/out/zql/src/ivm/filter-operators.d.ts +4 -4
- package/out/zql/src/ivm/filter-operators.d.ts.map +1 -1
- package/out/zql/src/ivm/filter-operators.js +10 -8
- package/out/zql/src/ivm/filter-operators.js.map +1 -1
- package/out/zql/src/ivm/filter.d.ts +2 -2
- package/out/zql/src/ivm/filter.d.ts.map +1 -1
- package/out/zql/src/ivm/filter.js +7 -4
- package/out/zql/src/ivm/filter.js.map +1 -1
- package/out/zql/src/ivm/flipped-join.js +2 -2
- package/out/zql/src/ivm/flipped-join.js.map +1 -1
- package/out/zql/src/ivm/maybe-split-and-push-edit-change.d.ts +1 -1
- package/out/zql/src/ivm/maybe-split-and-push-edit-change.d.ts.map +1 -1
- package/out/zql/src/ivm/maybe-split-and-push-edit-change.js +6 -4
- package/out/zql/src/ivm/maybe-split-and-push-edit-change.js.map +1 -1
- package/out/zql/src/ivm/memory-source.d.ts +2 -2
- package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
- package/out/zql/src/ivm/memory-source.js +9 -9
- package/out/zql/src/ivm/memory-source.js.map +1 -1
- package/out/zql/src/ivm/take.d.ts.map +1 -1
- package/out/zql/src/ivm/take.js +3 -4
- package/out/zql/src/ivm/take.js.map +1 -1
- package/out/zql/src/ivm/union-fan-in.d.ts.map +1 -1
- package/out/zql/src/ivm/union-fan-in.js +9 -7
- package/out/zql/src/ivm/union-fan-in.js.map +1 -1
- package/out/zql/src/ivm/view-apply-change.d.ts.map +1 -1
- package/out/zql/src/ivm/view-apply-change.js +3 -3
- package/out/zql/src/ivm/view-apply-change.js.map +1 -1
- package/out/zql/src/mutate/mutator-registry.d.ts.map +1 -1
- package/out/zql/src/mutate/mutator-registry.js +2 -2
- package/out/zql/src/mutate/mutator-registry.js.map +1 -1
- package/out/zql/src/query/query-delegate-base.d.ts +2 -0
- package/out/zql/src/query/query-delegate-base.d.ts.map +1 -1
- package/out/zql/src/query/query-delegate-base.js +58 -31
- package/out/zql/src/query/query-delegate-base.js.map +1 -1
- package/out/zql/src/query/query-delegate.d.ts +11 -1
- package/out/zql/src/query/query-delegate.d.ts.map +1 -1
- package/out/zql/src/query/query-impl.d.ts +25 -14
- package/out/zql/src/query/query-impl.d.ts.map +1 -1
- package/out/zql/src/query/query-impl.js +414 -94
- package/out/zql/src/query/query-impl.js.map +1 -1
- package/out/zql/src/query/query-internals.d.ts +21 -11
- package/out/zql/src/query/query-internals.d.ts.map +1 -1
- package/out/zql/src/query/query-internals.js.map +1 -1
- package/out/zql/src/query/query-transitions.d.ts +171 -0
- package/out/zql/src/query/query-transitions.d.ts.map +1 -0
- package/out/zql/src/query/query-transitions.js +207 -0
- package/out/zql/src/query/query-transitions.js.map +1 -0
- package/out/zql/src/query/query.d.ts +7 -1
- package/out/zql/src/query/query.d.ts.map +1 -1
- package/out/zql/src/query/runnable-query-impl.d.ts +3 -2
- package/out/zql/src/query/runnable-query-impl.d.ts.map +1 -1
- package/out/zql/src/query/runnable-query-impl.js +23 -2
- package/out/zql/src/query/runnable-query-impl.js.map +1 -1
- package/out/zql/src/query/typed-view.d.ts +1 -1
- package/out/zql/src/query/typed-view.d.ts.map +1 -1
- package/out/zqlite/src/table-source.d.ts.map +1 -1
- package/out/zqlite/src/table-source.js +7 -5
- package/out/zqlite/src/table-source.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-manager.js","names":["#clientID","#clientToServer","#serverToClient","#send","#onFatalError","#queries","#recentQueriesMaxSize","#recentQueries","#gotQueries","#mutationTracker","#pendingQueryChanges","#queryChangeThrottleMs","#lc","#metrics","#queryMetrics","#slowMaterializeThreshold","#pendingRemovals","#gotQueriesAuthoritative","#fireGotCallbacks","#queryEvictedCallback","#closedError","#add","#queueQueryChange","#updateEntry","#remove","#scheduleBatch","#batchTimer"],"sources":["../../../../../zero-client/src/client/query-manager.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport type {ReplicacheImpl} from '../../../replicache/src/replicache-impl.ts';\nimport type {ClientID} from '../../../replicache/src/sync/ids.ts';\nimport {assert, unreachable} from '../../../shared/src/asserts.ts';\nimport type {ReadonlyJSONValue} from '../../../shared/src/json.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport {difference} from '../../../shared/src/set-utils.ts';\nimport {TDigest} from '../../../shared/src/tdigest.ts';\nimport {\n mapAST,\n normalizeAST,\n type AST,\n} from '../../../zero-protocol/src/ast.ts';\nimport type {ChangeDesiredQueriesMessage} from '../../../zero-protocol/src/change-desired-queries.ts';\nimport type {ErroredQuery} from '../../../zero-protocol/src/custom-queries.ts';\nimport {ErrorKind} from '../../../zero-protocol/src/error-kind.ts';\nimport {ErrorOrigin} from '../../../zero-protocol/src/error-origin.ts';\nimport {ErrorReason} from '../../../zero-protocol/src/error-reason.ts';\nimport {ProtocolError} from '../../../zero-protocol/src/error.ts';\nimport type {UpQueriesPatchOp} from '../../../zero-protocol/src/queries-patch.ts';\nimport {\n hashOfAST,\n hashOfNameAndArgs,\n} from '../../../zero-protocol/src/query-hash.ts';\nimport {\n clientToServer,\n serverToClient,\n type NameMapper,\n} from '../../../zero-schema/src/name-mapper.ts';\nimport type {TableSchema} from '../../../zero-schema/src/table-schema.ts';\nimport type {ClientMetricMap} from '../../../zql/src/query/metrics-delegate.ts';\nimport type {CustomQueryID} from '../../../zql/src/query/named.ts';\nimport type {GotCallback} from '../../../zql/src/query/query-delegate.ts';\nimport {clampTTL, compareTTL, type TTL} from '../../../zql/src/query/ttl.ts';\nimport type {ClientErrorKind} from './client-error-kind.ts';\nimport type {ClientError} from './error.ts';\nimport {type ZeroError} from './error.ts';\nimport type {InspectorDelegate} from './inspector/inspector.ts';\nimport type {QueryClientMetrics} from './inspector/lazy-inspector.ts';\nimport {desiredQueriesPrefixForClient, GOT_QUERIES_KEY_PREFIX} from './keys.ts';\nimport type {MutationTracker} from './mutation-tracker.ts';\nimport type {ReadTransaction} from './replicache-types.ts';\n\ntype QueryHash = string;\n\ntype Entry = {\n // We keep track of the AST so we can use it in the inspector.\n normalized: AST;\n name: string | undefined;\n args: readonly ReadonlyJSONValue[] | undefined;\n count: number;\n gotCallbacks: GotCallback[];\n ttl: TTL;\n};\n\ntype ClientMetric = {\n [K in keyof ClientMetricMap]: TDigest;\n};\n\ntype PerQueryClientMetric = {\n 'query-materialization-client': number | undefined;\n 'query-materialization-end-to-end': number | undefined;\n 'query-update-client': TDigest;\n};\n\n/**\n * Tracks what queries the client is currently subscribed to on the server.\n * Sends `changeDesiredQueries` message to server when this changes.\n * Deduplicates requests so that we only listen to a given unique query once.\n */\nexport class QueryManager implements InspectorDelegate {\n readonly #clientID: ClientID;\n readonly #clientToServer: NameMapper;\n readonly #serverToClient: NameMapper;\n readonly #send: (change: ChangeDesiredQueriesMessage) => void;\n readonly #onFatalError: (error: ZeroError) => void;\n readonly #queries: Map<QueryHash, Entry> = new Map();\n readonly #recentQueriesMaxSize: number;\n readonly #recentQueries: Set<string> = new Set();\n readonly #gotQueries: Set<string> = new Set();\n // Whether `#gotQueries` can be trusted. The persisted set loaded from\n // IndexedDB may be stale (a query 'got' in a previous session can be evicted\n // server-side); see `markGotQueriesAuthoritative`.\n #gotQueriesAuthoritative = false;\n readonly #mutationTracker: MutationTracker;\n readonly #pendingQueryChanges: UpQueriesPatchOp[] = [];\n readonly #queryChangeThrottleMs: number;\n #pendingRemovals: Array<() => void> = [];\n #batchTimer: ReturnType<typeof setTimeout> | undefined;\n readonly #lc: LogContext;\n readonly #metrics: ClientMetric = newMetrics();\n readonly #queryMetrics: Map<string, PerQueryClientMetric> = new Map();\n readonly #slowMaterializeThreshold: number;\n #closedError: ZeroError | undefined;\n #queryEvictedCallback:\n | ((hash: string, ast: AST, metrics: QueryClientMetrics) => void)\n | undefined;\n\n constructor(\n lc: LogContext,\n mutationTracker: MutationTracker,\n clientID: ClientID,\n tables: Record<string, TableSchema>,\n send: (change: ChangeDesiredQueriesMessage) => void,\n experimentalWatch: ReplicacheImpl['experimentalWatch'],\n recentQueriesMaxSize: number,\n queryChangeThrottleMs: number,\n slowMaterializeThreshold: number,\n onFatalError: (error: ZeroError) => void,\n ) {\n this.#lc = lc.withContext('QueryManager');\n this.#clientID = clientID;\n this.#clientToServer = clientToServer(tables);\n this.#serverToClient = serverToClient(tables);\n this.#recentQueriesMaxSize = recentQueriesMaxSize;\n this.#send = send;\n this.#mutationTracker = mutationTracker;\n this.#queryChangeThrottleMs = queryChangeThrottleMs;\n this.#slowMaterializeThreshold = slowMaterializeThreshold;\n this.#onFatalError = onFatalError;\n this.#mutationTracker.onAllMutationsApplied(() => {\n if (this.#pendingRemovals.length === 0) {\n return;\n }\n const pendingRemovals = this.#pendingRemovals;\n this.#pendingRemovals = [];\n for (const removal of pendingRemovals) {\n removal();\n }\n });\n\n experimentalWatch(\n diff => {\n for (const diffOp of diff) {\n const queryHash = diffOp.key.substring(GOT_QUERIES_KEY_PREFIX.length);\n switch (diffOp.op) {\n case 'add':\n this.#gotQueries.add(queryHash);\n if (this.#gotQueriesAuthoritative) {\n this.#fireGotCallbacks(queryHash, true);\n }\n break;\n case 'del':\n this.#gotQueries.delete(queryHash);\n this.#fireGotCallbacks(queryHash, false);\n break;\n }\n }\n },\n {\n prefix: GOT_QUERIES_KEY_PREFIX,\n initialValuesInFirstDiff: true,\n },\n );\n }\n\n getAST(queryID: string): AST | undefined {\n const ast = this.#queries.get(queryID)?.normalized;\n return ast && mapAST(ast, this.#serverToClient);\n }\n\n setQueryEvictedCallback(\n cb: (hash: string, ast: AST, metrics: QueryClientMetrics) => void,\n ): void {\n this.#queryEvictedCallback = cb;\n }\n\n mapClientASTToServer(ast: AST): AST {\n return mapAST(ast, this.#clientToServer);\n }\n\n #fireGotCallbacks(queryHash: string, got: boolean) {\n const gotCallbacks = this.#queries.get(queryHash)?.gotCallbacks ?? [];\n for (const gotCallback of gotCallbacks) {\n gotCallback(got);\n }\n }\n\n /**\n * Trust `#gotQueries`. Called once the first poke after a (re)connect has\n * been applied. Because `gotQueriesPatch` is a diff, the server won't re-send\n * `put`s for queries it thinks the client already has, so we re-derive and\n * fire `got` for every subscribed query already in the set. Only fires\n * `true`, so this never reverts a query from 'complete'. Idempotent.\n */\n markGotQueriesAuthoritative(): void {\n if (this.#gotQueriesAuthoritative) {\n return;\n }\n this.#gotQueriesAuthoritative = true;\n for (const queryHash of this.#queries.keys()) {\n if (this.#gotQueries.has(queryHash)) {\n this.#fireGotCallbacks(queryHash, true);\n }\n }\n }\n\n /** Called on disconnect. The next connect must re-confirm `#gotQueries`. */\n clearGotQueriesAuthoritative(): void {\n this.#gotQueriesAuthoritative = false;\n }\n\n /**\n * Get the queries that need to be registered with the server.\n *\n * An optional `lastPatch` can be provided. This is the last patch that was\n * sent to the server and may not yet have been acked. If `lastPatch` is provided,\n * this method will return a patch that does not include any events sent in `lastPatch`.\n *\n * This diffing of last patch and current patch is needed since we send\n * a set of queries to the server when we first connect inside of the `sec-protocol` as\n * the `initConnectionMessage`.\n *\n * While we're waiting for the `connected` response to come back from the server,\n * the client may have registered more queries. We need to diff the `initConnectionMessage`\n * queries with the current set of queries to understand what those were.\n */\n async getQueriesPatch(\n tx: ReadTransaction,\n lastPatch?: Map<string, UpQueriesPatchOp>,\n ): Promise<Map<string, UpQueriesPatchOp>> {\n const existingQueryHashes = new Set<string>();\n const prefix = desiredQueriesPrefixForClient(this.#clientID);\n for await (const key of tx.scan({prefix}).keys()) {\n existingQueryHashes.add(key.substring(prefix.length, key.length));\n }\n const patch: Map<string, UpQueriesPatchOp> = new Map();\n for (const hash of existingQueryHashes) {\n if (!this.#queries.has(hash)) {\n patch.set(hash, {op: 'del', hash});\n }\n }\n\n for (const [hash, {normalized, ttl, name, args}] of this.#queries) {\n if (!existingQueryHashes.has(hash)) {\n patch.set(hash, {\n op: 'put',\n hash,\n ast: name === undefined ? normalized : undefined,\n name,\n args,\n // We get TTL out of the DagStore so it is possible that the TTL was written\n // with a too high TTL.\n ttl: clampTTL(ttl), // no lc here since no need to log here\n });\n }\n }\n\n if (lastPatch) {\n // if there are any `puts` in `lastPatch` that are not in `patch` then we need to\n // send a `del` event in `patch`.\n for (const [hash, {op}] of lastPatch) {\n if (op === 'put' && !patch.has(hash)) {\n patch.set(hash, {op: 'del', hash});\n }\n }\n // Remove everything from `patch` that was already sent in `lastPatch`.\n for (const [hash, {op}] of patch) {\n const lastPatchOp = lastPatch.get(hash);\n if (lastPatchOp && lastPatchOp.op === op) {\n patch.delete(hash);\n }\n }\n }\n\n return patch;\n }\n\n handleTransformErrors(errors: ErroredQuery[]) {\n for (const error of errors) {\n const queryId = error.id;\n const entry = this.#queries.get(queryId);\n\n // if we don't have the query registered, continue\n if (!entry) {\n continue;\n }\n\n if (error.error === 'app' || error.error === 'parse') {\n entry.gotCallbacks.forEach(callback => callback(false, error));\n }\n // this code path is not possible technically since errors were never implemented in the legacy query transform error\n // but is included for backwards compatibility and we have a test case for it\n else {\n this.#onFatalError(\n new ProtocolError({\n kind: ErrorKind.TransformFailed,\n origin: ErrorOrigin.ZeroCache,\n reason: ErrorReason.Internal,\n message: `Unknown error transforming queries: ${JSON.stringify(error)}`,\n queryIDs: [],\n }),\n );\n // unreachable(error); TODO(0xcadams): this should eventually be unreachable\n }\n }\n }\n\n handleClosed(\n reason: ClientError<{kind: ClientErrorKind.ClientClosed; message: string}>,\n ) {\n if (this.#closedError) {\n return;\n }\n this.#closedError = reason;\n for (const [queryId, entry] of this.#queries) {\n const erroredQuery: ErroredQuery = {\n error: 'app',\n id: queryId,\n name: entry.name ?? 'legacy',\n message: reason.message,\n details: {kind: reason.kind},\n };\n for (const gotCallback of entry.gotCallbacks) {\n gotCallback(false, erroredQuery);\n }\n }\n }\n\n addCustom(\n ast: AST,\n {name, args}: CustomQueryID,\n ttl: TTL,\n gotCallback?: GotCallback,\n ): () => void {\n const normalized = normalizeAST(ast);\n const queryId = hashOfNameAndArgs(name, args);\n return this.#add(queryId, normalized, name, args, ttl, gotCallback);\n }\n\n addLegacy(ast: AST, ttl: TTL, gotCallback?: GotCallback): () => void {\n const normalized = normalizeAST(ast);\n const astHash = hashOfAST(normalized);\n return this.#add(\n astHash,\n normalized,\n undefined, // name is undefined for legacy queries\n undefined, // args are undefined for legacy queries\n ttl,\n gotCallback,\n );\n }\n\n #add(\n queryId: string,\n normalized: AST,\n name: string | undefined,\n args: readonly ReadonlyJSONValue[] | undefined,\n ttl: TTL,\n gotCallback?: GotCallback,\n ) {\n assert(\n (name === undefined) === (args === undefined),\n 'If name is defined, args must be defined',\n );\n ttl = clampTTL(ttl, this.#lc);\n let entry = this.#queries.get(queryId);\n this.#recentQueries.delete(queryId);\n if (!entry) {\n normalized = mapAST(normalized, this.#clientToServer);\n\n entry = {\n normalized,\n name,\n args,\n count: 1,\n gotCallbacks: gotCallback ? [gotCallback] : [],\n ttl,\n };\n this.#queries.set(queryId, entry);\n this.#queueQueryChange({\n op: 'put',\n hash: queryId,\n ast: name === undefined ? normalized : undefined,\n name,\n args,\n ttl,\n });\n } else {\n ++entry.count;\n this.#updateEntry(entry, queryId, ttl);\n\n if (gotCallback) {\n entry.gotCallbacks.push(gotCallback);\n }\n }\n\n if (gotCallback) {\n gotCallback(\n this.#gotQueriesAuthoritative && this.#gotQueries.has(queryId),\n );\n }\n\n let removed = false;\n const cleanupCb = () => {\n if (removed) {\n return;\n }\n removed = true;\n\n // We cannot remove queries while mutations are pending\n // as that could take data out of scope that is needed in a rebase\n if (this.#mutationTracker.size > 0) {\n this.#pendingRemovals.push(() =>\n this.#remove(entry, queryId, gotCallback),\n );\n return;\n }\n\n this.#remove(entry, queryId, gotCallback);\n };\n return cleanupCb;\n }\n\n updateCustom({name, args}: CustomQueryID, ttl: TTL) {\n const queryID = hashOfNameAndArgs(name, args);\n const entry = must(this.#queries.get(queryID));\n this.#updateEntry(entry, queryID, ttl);\n }\n\n updateLegacy(ast: AST, ttl: TTL) {\n const normalized = normalizeAST(ast);\n const queryID = hashOfAST(normalized);\n const entry = must(this.#queries.get(queryID));\n this.#updateEntry(entry, queryID, ttl);\n }\n\n #updateEntry(entry: Entry, queryID: string, ttl: TTL): void {\n // If the query already exists and the new ttl is larger than the old one\n // we send a changeDesiredQueries message to the server to update the ttl.\n ttl = clampTTL(ttl, this.#lc);\n if (compareTTL(ttl, entry.ttl) > 0) {\n entry.ttl = ttl;\n this.#queueQueryChange({\n op: 'put',\n hash: queryID,\n ast: entry.name === undefined ? entry.normalized : undefined,\n name: entry.name,\n args: entry.args,\n ttl,\n });\n }\n }\n\n #queueQueryChange(op: UpQueriesPatchOp) {\n this.#pendingQueryChanges.push(op);\n this.#scheduleBatch();\n }\n\n #scheduleBatch() {\n if (this.#batchTimer === undefined) {\n this.#batchTimer = setTimeout(\n () => this.flushBatch(),\n this.#queryChangeThrottleMs,\n );\n }\n }\n\n flushBatch() {\n if (this.#batchTimer !== undefined) {\n clearTimeout(this.#batchTimer);\n this.#batchTimer = undefined;\n }\n if (this.#pendingQueryChanges.length > 0) {\n this.#send([\n 'changeDesiredQueries',\n {\n desiredQueriesPatch: [...this.#pendingQueryChanges],\n },\n ]);\n this.#pendingQueryChanges.length = 0;\n }\n }\n\n #remove(entry: Entry, astHash: string, gotCallback: GotCallback | undefined) {\n if (gotCallback) {\n const index = entry.gotCallbacks.indexOf(gotCallback);\n entry.gotCallbacks.splice(index, 1);\n }\n --entry.count;\n if (entry.count === 0) {\n this.#recentQueries.add(astHash);\n if (this.#recentQueries.size > this.#recentQueriesMaxSize) {\n const lruQueryID = this.#recentQueries.values().next().value;\n assert(lruQueryID, 'Expected LRU query ID to exist');\n const evictedAST = this.getAST(lruQueryID);\n const evictedMetrics =\n this.#queryMetrics.get(lruQueryID) ?? newPerQueryMetrics();\n this.#queries.delete(lruQueryID);\n this.#recentQueries.delete(lruQueryID);\n this.#queryMetrics.delete(lruQueryID);\n this.#queueQueryChange({op: 'del', hash: lruQueryID});\n assert(evictedAST, 'Expected evicted AST to exist');\n this.#queryEvictedCallback?.(lruQueryID, evictedAST, evictedMetrics);\n }\n }\n }\n\n /**\n * Gets the aggregated metrics for all queries managed by this QueryManager.\n */\n get metrics(): ClientMetric {\n return this.#metrics;\n }\n\n addMetric<K extends keyof ClientMetricMap>(\n metric: K,\n value: number,\n ...args: ClientMetricMap[K]\n ): void {\n // Only query metrics are tracked at this point.\n // If this check fails then we need to add a runtime check.\n metric satisfies `query-${string}`;\n\n // We track all materializations of queries as well as per\n // query materializations.\n this.#metrics[metric].add(value);\n\n const queryID = args[0];\n\n // Handle slow query logging for end-to-end materialization\n if (metric === 'query-materialization-end-to-end') {\n const ast = args[1];\n\n if (\n this.#slowMaterializeThreshold !== undefined &&\n value > this.#slowMaterializeThreshold\n ) {\n this.#lc.warn?.(\n 'Slow query materialization (including server/network)',\n queryID,\n ast,\n value,\n );\n } else {\n this.#lc.debug?.(\n 'Materialized query (including server/network)',\n queryID,\n ast,\n value,\n );\n }\n }\n\n // The query manager manages metrics that are per query.\n let existing = this.#queryMetrics.get(queryID);\n if (!existing) {\n existing = newPerQueryMetrics();\n this.#queryMetrics.set(queryID, existing);\n }\n switch (metric) {\n case 'query-update-client':\n existing['query-update-client'].add(value);\n break;\n case 'query-materialization-client':\n case 'query-materialization-end-to-end':\n // Recorded once per query (last value wins).\n existing[\n metric as\n | 'query-materialization-client'\n | 'query-materialization-end-to-end'\n ] = value;\n break;\n default:\n unreachable(metric);\n }\n }\n\n getQueryMetrics(queryID: string): PerQueryClientMetric | undefined {\n return this.#queryMetrics.get(queryID);\n }\n\n /**\n * For testing only: returns all query hashes currently registered.\n */\n getAllNonGotQueryHashes(): Iterable<string> {\n return difference(this.#queries, this.#gotQueries);\n }\n}\n\nfunction newMetrics(): ClientMetric {\n return {\n 'query-materialization-client': new TDigest(),\n 'query-materialization-end-to-end': new TDigest(),\n 'query-update-client': new TDigest(),\n };\n}\n\nfunction newPerQueryMetrics(): PerQueryClientMetric {\n return {\n 'query-materialization-client': undefined,\n 'query-materialization-end-to-end': undefined,\n 'query-update-client': new TDigest(),\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"query-manager.js","names":["#clientID","#clientToServer","#serverToClient","#send","#onFatalError","#queries","#recentQueriesMaxSize","#recentQueries","#gotQueries","#cachedQueries","#mutationTracker","#pendingQueryChanges","#queryChangeThrottleMs","#lc","#metrics","#queryMetrics","#slowMaterializeThreshold","#pendingRemovals","#awaitingPersistedGotDiff","#fireGotCallbacks","#gotQueriesAuthoritative","#queryEvictedCallback","#closedError","#add","#queueQueryChange","#updateEntry","#remove","#scheduleBatch","#batchTimer"],"sources":["../../../../../zero-client/src/client/query-manager.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport type {ReplicacheImpl} from '../../../replicache/src/replicache-impl.ts';\nimport type {ClientID} from '../../../replicache/src/sync/ids.ts';\nimport {assert, unreachable} from '../../../shared/src/asserts.ts';\nimport type {ReadonlyJSONValue} from '../../../shared/src/json.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport {difference} from '../../../shared/src/set-utils.ts';\nimport {TDigest} from '../../../shared/src/tdigest.ts';\nimport {\n mapAST,\n normalizeAST,\n type AST,\n} from '../../../zero-protocol/src/ast.ts';\nimport type {ChangeDesiredQueriesMessage} from '../../../zero-protocol/src/change-desired-queries.ts';\nimport type {ErroredQuery} from '../../../zero-protocol/src/custom-queries.ts';\nimport {ErrorKind} from '../../../zero-protocol/src/error-kind.ts';\nimport {ErrorOrigin} from '../../../zero-protocol/src/error-origin.ts';\nimport {ErrorReason} from '../../../zero-protocol/src/error-reason.ts';\nimport {ProtocolError} from '../../../zero-protocol/src/error.ts';\nimport type {UpQueriesPatchOp} from '../../../zero-protocol/src/queries-patch.ts';\nimport {\n hashOfAST,\n hashOfNameAndArgs,\n} from '../../../zero-protocol/src/query-hash.ts';\nimport {\n clientToServer,\n serverToClient,\n type NameMapper,\n} from '../../../zero-schema/src/name-mapper.ts';\nimport type {TableSchema} from '../../../zero-schema/src/table-schema.ts';\nimport type {ClientMetricMap} from '../../../zql/src/query/metrics-delegate.ts';\nimport type {CustomQueryID} from '../../../zql/src/query/named.ts';\nimport type {GotCallback} from '../../../zql/src/query/query-delegate.ts';\nimport {clampTTL, compareTTL, type TTL} from '../../../zql/src/query/ttl.ts';\nimport type {ClientErrorKind} from './client-error-kind.ts';\nimport type {ClientError} from './error.ts';\nimport {type ZeroError} from './error.ts';\nimport type {InspectorDelegate} from './inspector/inspector.ts';\nimport type {QueryClientMetrics} from './inspector/lazy-inspector.ts';\nimport {desiredQueriesPrefixForClient, GOT_QUERIES_KEY_PREFIX} from './keys.ts';\nimport type {MutationTracker} from './mutation-tracker.ts';\nimport type {ReadTransaction} from './replicache-types.ts';\n\ntype QueryHash = string;\n\ntype Entry = {\n // We keep track of the AST so we can use it in the inspector.\n normalized: AST;\n name: string | undefined;\n args: readonly ReadonlyJSONValue[] | undefined;\n count: number;\n gotCallbacks: GotCallback[];\n ttl: TTL;\n};\n\n// A thrown value, boxed so that `throw undefined` is still distinguishable\n// from \"nothing thrown\".\ntype ThrownBy = {readonly error: unknown};\n\ntype ClientMetric = {\n [K in keyof ClientMetricMap]: TDigest;\n};\n\ntype PerQueryClientMetric = {\n 'query-materialization-client': number | undefined;\n 'query-materialization-end-to-end': number | undefined;\n 'query-update-client': TDigest;\n};\n\n/**\n * Tracks what queries the client is currently subscribed to on the server.\n * Sends `changeDesiredQueries` message to server when this changes.\n * Deduplicates requests so that we only listen to a given unique query once.\n */\nexport class QueryManager implements InspectorDelegate {\n readonly #clientID: ClientID;\n readonly #clientToServer: NameMapper;\n readonly #serverToClient: NameMapper;\n readonly #send: (change: ChangeDesiredQueriesMessage) => void;\n readonly #onFatalError: (error: ZeroError) => void;\n readonly #queries: Map<QueryHash, Entry> = new Map();\n readonly #recentQueriesMaxSize: number;\n readonly #recentQueries: Set<string> = new Set();\n readonly #gotQueries: Set<string> = new Set();\n // Whether `#gotQueries` can be trusted. The persisted set loaded from\n // IndexedDB may be stale (a query 'got' in a previous session can be evicted\n // server-side); see `markGotQueriesAuthoritative`.\n #gotQueriesAuthoritative = false;\n // The got keys whose result the store holds from a previous connection: the\n // set persisted by a previous session, and on disconnect everything the\n // connection just torn down had confirmed. Until the got set is\n // authoritative, a registration reports these as 'cached'. Keys added by a\n // live diff are not in it; see the watch below.\n readonly #cachedQueries: Set<string> = new Set();\n // Whether the got-queries watch has yet to deliver its first diff, the\n // persisted set. Cleared before that diff is processed, so a throwing\n // callback cannot leave it set.\n #awaitingPersistedGotDiff = true;\n readonly #mutationTracker: MutationTracker;\n readonly #pendingQueryChanges: UpQueriesPatchOp[] = [];\n readonly #queryChangeThrottleMs: number;\n #pendingRemovals: Array<() => void> = [];\n #batchTimer: ReturnType<typeof setTimeout> | undefined;\n readonly #lc: LogContext;\n readonly #metrics: ClientMetric = newMetrics();\n readonly #queryMetrics: Map<string, PerQueryClientMetric> = new Map();\n readonly #slowMaterializeThreshold: number;\n #closedError: ZeroError | undefined;\n #queryEvictedCallback:\n | ((hash: string, ast: AST, metrics: QueryClientMetrics) => void)\n | undefined;\n\n constructor(\n lc: LogContext,\n mutationTracker: MutationTracker,\n clientID: ClientID,\n tables: Record<string, TableSchema>,\n send: (change: ChangeDesiredQueriesMessage) => void,\n experimentalWatch: ReplicacheImpl['experimentalWatch'],\n recentQueriesMaxSize: number,\n queryChangeThrottleMs: number,\n slowMaterializeThreshold: number,\n onFatalError: (error: ZeroError) => void,\n ) {\n this.#lc = lc.withContext('QueryManager');\n this.#clientID = clientID;\n this.#clientToServer = clientToServer(tables);\n this.#serverToClient = serverToClient(tables);\n this.#recentQueriesMaxSize = recentQueriesMaxSize;\n this.#send = send;\n this.#mutationTracker = mutationTracker;\n this.#queryChangeThrottleMs = queryChangeThrottleMs;\n this.#slowMaterializeThreshold = slowMaterializeThreshold;\n this.#onFatalError = onFatalError;\n this.#mutationTracker.onAllMutationsApplied(() => {\n if (this.#pendingRemovals.length === 0) {\n return;\n }\n const pendingRemovals = this.#pendingRemovals;\n this.#pendingRemovals = [];\n for (const removal of pendingRemovals) {\n removal();\n }\n });\n\n // The first diff is the got set persisted by a previous session, the only\n // state the watch may report as 'cached'. Every later diff is live: this\n // tab's own poke, whose keys are confirmations on this connection and are\n // reported as got once the poke has been applied (see\n // `markGotQueriesAuthoritative`), or another tab's state arriving via\n // replicache refresh. A live diff can therefore only revoke a cached\n // claim (a deleted key), never grant one.\n experimentalWatch(\n diff => {\n const persisted = this.#awaitingPersistedGotDiff;\n this.#awaitingPersistedGotDiff = false;\n // A throwing callback must not leave the rest of the diff unapplied,\n // or later keys would never enter the got set. The first error is\n // rethrown once the sets are consistent.\n let thrown: ThrownBy | undefined;\n const fire = (queryHash: string, got: boolean | 'cached') => {\n const e = this.#fireGotCallbacks(queryHash, got);\n thrown ??= e;\n };\n for (const diffOp of diff) {\n const queryHash = diffOp.key.substring(GOT_QUERIES_KEY_PREFIX.length);\n switch (diffOp.op) {\n case 'add':\n this.#gotQueries.add(queryHash);\n if (this.#gotQueriesAuthoritative) {\n fire(queryHash, true);\n } else if (persisted) {\n this.#cachedQueries.add(queryHash);\n fire(queryHash, 'cached');\n }\n break;\n case 'del':\n this.#gotQueries.delete(queryHash);\n this.#cachedQueries.delete(queryHash);\n fire(queryHash, false);\n break;\n }\n }\n if (thrown) {\n throw thrown.error;\n }\n },\n {\n prefix: GOT_QUERIES_KEY_PREFIX,\n initialValuesInFirstDiff: true,\n },\n );\n }\n\n getAST(queryID: string): AST | undefined {\n const ast = this.#queries.get(queryID)?.normalized;\n return ast && mapAST(ast, this.#serverToClient);\n }\n\n setQueryEvictedCallback(\n cb: (hash: string, ast: AST, metrics: QueryClientMetrics) => void,\n ): void {\n this.#queryEvictedCallback = cb;\n }\n\n mapClientASTToServer(ast: AST): AST {\n return mapAST(ast, this.#clientToServer);\n }\n\n /**\n * Notifies every subscriber of the query. A throwing subscriber does not\n * keep the others from being notified; the first error is returned so the\n * caller can rethrow it once its own bookkeeping is consistent.\n */\n #fireGotCallbacks(\n queryHash: string,\n got: boolean | 'cached',\n ): ThrownBy | undefined {\n const entry = this.#queries.get(queryHash);\n if (!entry) {\n return undefined;\n }\n let thrown: ThrownBy | undefined;\n // A subscriber may unregister during dispatch (a run() waiter destroys its\n // view on the notification it was waiting for), so iterate a snapshot.\n for (const gotCallback of [...entry.gotCallbacks]) {\n try {\n gotCallback(got);\n } catch (error) {\n thrown ??= {error};\n }\n }\n return thrown;\n }\n\n /**\n * Trust `#gotQueries`. Called once the first poke after a (re)connect has\n * been applied. Because `gotQueriesPatch` is a diff, the server won't re-send\n * `put`s for queries it thinks the client already has, so we re-derive and\n * fire `got` for every subscribed query already in the set. Only fires\n * `true`, so this never reverts a query from 'complete'. Idempotent.\n */\n markGotQueriesAuthoritative(): void {\n if (this.#gotQueriesAuthoritative) {\n return;\n }\n this.#gotQueriesAuthoritative = true;\n // Whatever the previous connection held, this one has now confirmed or\n // deleted. Should the watch's first diff have been skipped (a failed\n // initial run), the next diff is live too.\n this.#cachedQueries.clear();\n this.#awaitingPersistedGotDiff = false;\n let thrown: ThrownBy | undefined;\n for (const queryHash of this.#queries.keys()) {\n if (this.#gotQueries.has(queryHash)) {\n const e = this.#fireGotCallbacks(queryHash, true);\n thrown ??= e;\n }\n }\n if (thrown) {\n throw thrown.error;\n }\n }\n\n /** Called on disconnect. The next connect must re-confirm `#gotQueries`. */\n clearGotQueriesAuthoritative(): void {\n if (!this.#gotQueriesAuthoritative) {\n // The connection never confirmed the got set, so the persisted\n // classification still stands. Keys a live diff added in the meantime\n // were not confirmed by this connection and stay unclaimed.\n return;\n }\n this.#gotQueriesAuthoritative = false;\n // Everything got at this point was confirmed by the connection just torn\n // down, which for a new registration is the cached claim.\n for (const queryHash of this.#gotQueries) {\n this.#cachedQueries.add(queryHash);\n }\n }\n\n /**\n * Get the queries that need to be registered with the server.\n *\n * An optional `lastPatch` can be provided. This is the last patch that was\n * sent to the server and may not yet have been acked. If `lastPatch` is provided,\n * this method will return a patch that does not include any events sent in `lastPatch`.\n *\n * This diffing of last patch and current patch is needed since we send\n * a set of queries to the server when we first connect inside of the `sec-protocol` as\n * the `initConnectionMessage`.\n *\n * While we're waiting for the `connected` response to come back from the server,\n * the client may have registered more queries. We need to diff the `initConnectionMessage`\n * queries with the current set of queries to understand what those were.\n */\n async getQueriesPatch(\n tx: ReadTransaction,\n lastPatch?: Map<string, UpQueriesPatchOp>,\n ): Promise<Map<string, UpQueriesPatchOp>> {\n const existingQueryHashes = new Set<string>();\n const prefix = desiredQueriesPrefixForClient(this.#clientID);\n for await (const key of tx.scan({prefix}).keys()) {\n existingQueryHashes.add(key.substring(prefix.length, key.length));\n }\n const patch: Map<string, UpQueriesPatchOp> = new Map();\n for (const hash of existingQueryHashes) {\n if (!this.#queries.has(hash)) {\n patch.set(hash, {op: 'del', hash});\n }\n }\n\n for (const [hash, {normalized, ttl, name, args}] of this.#queries) {\n if (!existingQueryHashes.has(hash)) {\n patch.set(hash, {\n op: 'put',\n hash,\n ast: name === undefined ? normalized : undefined,\n name,\n args,\n // We get TTL out of the DagStore so it is possible that the TTL was written\n // with a too high TTL.\n ttl: clampTTL(ttl), // no lc here since no need to log here\n });\n }\n }\n\n if (lastPatch) {\n // if there are any `puts` in `lastPatch` that are not in `patch` then we need to\n // send a `del` event in `patch`.\n for (const [hash, {op}] of lastPatch) {\n if (op === 'put' && !patch.has(hash)) {\n patch.set(hash, {op: 'del', hash});\n }\n }\n // Remove everything from `patch` that was already sent in `lastPatch`.\n for (const [hash, {op}] of patch) {\n const lastPatchOp = lastPatch.get(hash);\n if (lastPatchOp && lastPatchOp.op === op) {\n patch.delete(hash);\n }\n }\n }\n\n return patch;\n }\n\n handleTransformErrors(errors: ErroredQuery[]) {\n for (const error of errors) {\n const queryId = error.id;\n const entry = this.#queries.get(queryId);\n\n // if we don't have the query registered, continue\n if (!entry) {\n continue;\n }\n\n if (error.error === 'app' || error.error === 'parse') {\n entry.gotCallbacks.forEach(callback => callback(false, error));\n }\n // this code path is not possible technically since errors were never implemented in the legacy query transform error\n // but is included for backwards compatibility and we have a test case for it\n else {\n this.#onFatalError(\n new ProtocolError({\n kind: ErrorKind.TransformFailed,\n origin: ErrorOrigin.ZeroCache,\n reason: ErrorReason.Internal,\n message: `Unknown error transforming queries: ${JSON.stringify(error)}`,\n queryIDs: [],\n }),\n );\n // unreachable(error); TODO(0xcadams): this should eventually be unreachable\n }\n }\n }\n\n handleClosed(\n reason: ClientError<{kind: ClientErrorKind.ClientClosed; message: string}>,\n ) {\n if (this.#closedError) {\n return;\n }\n this.#closedError = reason;\n for (const [queryId, entry] of this.#queries) {\n const erroredQuery: ErroredQuery = {\n error: 'app',\n id: queryId,\n name: entry.name ?? 'legacy',\n message: reason.message,\n details: {kind: reason.kind},\n };\n for (const gotCallback of entry.gotCallbacks) {\n gotCallback(false, erroredQuery);\n }\n }\n }\n\n addCustom(\n ast: AST,\n {name, args}: CustomQueryID,\n ttl: TTL,\n gotCallback?: GotCallback,\n ): () => void {\n const normalized = normalizeAST(ast);\n const queryId = hashOfNameAndArgs(name, args);\n return this.#add(queryId, normalized, name, args, ttl, gotCallback);\n }\n\n /** @deprecated */\n addLegacy(ast: AST, ttl: TTL, gotCallback?: GotCallback): () => void {\n const normalized = normalizeAST(ast);\n const astHash = hashOfAST(normalized);\n return this.#add(\n astHash,\n normalized,\n undefined, // name is undefined for legacy queries\n undefined, // args are undefined for legacy queries\n ttl,\n gotCallback,\n );\n }\n\n #add(\n queryId: string,\n normalized: AST,\n name: string | undefined,\n args: readonly ReadonlyJSONValue[] | undefined,\n ttl: TTL,\n gotCallback?: GotCallback,\n ) {\n assert(\n (name === undefined) === (args === undefined),\n 'If name is defined, args must be defined',\n );\n ttl = clampTTL(ttl, this.#lc);\n let entry = this.#queries.get(queryId);\n this.#recentQueries.delete(queryId);\n if (!entry) {\n normalized = mapAST(normalized, this.#clientToServer);\n\n entry = {\n normalized,\n name,\n args,\n count: 1,\n gotCallbacks: gotCallback ? [gotCallback] : [],\n ttl,\n };\n this.#queries.set(queryId, entry);\n this.#queueQueryChange({\n op: 'put',\n hash: queryId,\n ast: name === undefined ? normalized : undefined,\n name,\n args,\n ttl,\n });\n } else {\n ++entry.count;\n this.#updateEntry(entry, queryId, ttl);\n\n if (gotCallback) {\n entry.gotCallbacks.push(gotCallback);\n }\n }\n\n if (gotCallback) {\n gotCallback(\n this.#gotQueriesAuthoritative\n ? this.#gotQueries.has(queryId)\n : this.#cachedQueries.has(queryId) && 'cached',\n );\n }\n\n let removed = false;\n const cleanupCb = () => {\n if (removed) {\n return;\n }\n removed = true;\n\n // We cannot remove queries while mutations are pending\n // as that could take data out of scope that is needed in a rebase\n if (this.#mutationTracker.size > 0) {\n this.#pendingRemovals.push(() =>\n this.#remove(entry, queryId, gotCallback),\n );\n return;\n }\n\n this.#remove(entry, queryId, gotCallback);\n };\n return cleanupCb;\n }\n\n updateCustom({name, args}: CustomQueryID, ttl: TTL) {\n const queryID = hashOfNameAndArgs(name, args);\n const entry = must(this.#queries.get(queryID));\n this.#updateEntry(entry, queryID, ttl);\n }\n\n /** @deprecated */\n updateLegacy(ast: AST, ttl: TTL) {\n const normalized = normalizeAST(ast);\n const queryID = hashOfAST(normalized);\n const entry = must(this.#queries.get(queryID));\n this.#updateEntry(entry, queryID, ttl);\n }\n\n #updateEntry(entry: Entry, queryID: string, ttl: TTL): void {\n // If the query already exists and the new ttl is larger than the old one\n // we send a changeDesiredQueries message to the server to update the ttl.\n ttl = clampTTL(ttl, this.#lc);\n if (compareTTL(ttl, entry.ttl) > 0) {\n entry.ttl = ttl;\n this.#queueQueryChange({\n op: 'put',\n hash: queryID,\n ast: entry.name === undefined ? entry.normalized : undefined,\n name: entry.name,\n args: entry.args,\n ttl,\n });\n }\n }\n\n #queueQueryChange(op: UpQueriesPatchOp) {\n this.#pendingQueryChanges.push(op);\n this.#scheduleBatch();\n }\n\n #scheduleBatch() {\n if (this.#batchTimer === undefined) {\n this.#batchTimer = setTimeout(\n () => this.flushBatch(),\n this.#queryChangeThrottleMs,\n );\n }\n }\n\n flushBatch() {\n if (this.#batchTimer !== undefined) {\n clearTimeout(this.#batchTimer);\n this.#batchTimer = undefined;\n }\n if (this.#pendingQueryChanges.length > 0) {\n this.#send([\n 'changeDesiredQueries',\n {\n desiredQueriesPatch: [...this.#pendingQueryChanges],\n },\n ]);\n this.#pendingQueryChanges.length = 0;\n }\n }\n\n #remove(entry: Entry, astHash: string, gotCallback: GotCallback | undefined) {\n if (gotCallback) {\n const index = entry.gotCallbacks.indexOf(gotCallback);\n entry.gotCallbacks.splice(index, 1);\n }\n --entry.count;\n if (entry.count === 0) {\n this.#recentQueries.add(astHash);\n if (this.#recentQueries.size > this.#recentQueriesMaxSize) {\n const lruQueryID = this.#recentQueries.values().next().value;\n assert(lruQueryID, 'Expected LRU query ID to exist');\n const evictedAST = this.getAST(lruQueryID);\n const evictedMetrics =\n this.#queryMetrics.get(lruQueryID) ?? newPerQueryMetrics();\n this.#queries.delete(lruQueryID);\n this.#recentQueries.delete(lruQueryID);\n this.#queryMetrics.delete(lruQueryID);\n this.#queueQueryChange({op: 'del', hash: lruQueryID});\n assert(evictedAST, 'Expected evicted AST to exist');\n this.#queryEvictedCallback?.(lruQueryID, evictedAST, evictedMetrics);\n }\n }\n }\n\n /**\n * Gets the aggregated metrics for all queries managed by this QueryManager.\n */\n get metrics(): ClientMetric {\n return this.#metrics;\n }\n\n addMetric<K extends keyof ClientMetricMap>(\n metric: K,\n value: number,\n ...args: ClientMetricMap[K]\n ): void {\n // Only query metrics are tracked at this point.\n // If this check fails then we need to add a runtime check.\n metric satisfies `query-${string}`;\n\n // We track all materializations of queries as well as per\n // query materializations.\n this.#metrics[metric].add(value);\n\n const queryID = args[0];\n\n // Handle slow query logging for end-to-end materialization\n if (metric === 'query-materialization-end-to-end') {\n const ast = args[1];\n\n if (\n this.#slowMaterializeThreshold !== undefined &&\n value > this.#slowMaterializeThreshold\n ) {\n this.#lc.warn?.(\n 'Slow query materialization (including server/network)',\n queryID,\n ast,\n value,\n );\n } else {\n this.#lc.debug?.(\n 'Materialized query (including server/network)',\n queryID,\n ast,\n value,\n );\n }\n }\n\n // The query manager manages metrics that are per query.\n let existing = this.#queryMetrics.get(queryID);\n if (!existing) {\n existing = newPerQueryMetrics();\n this.#queryMetrics.set(queryID, existing);\n }\n switch (metric) {\n case 'query-update-client':\n existing['query-update-client'].add(value);\n break;\n case 'query-materialization-client':\n case 'query-materialization-end-to-end':\n // Recorded once per query (last value wins).\n existing[\n metric as\n | 'query-materialization-client'\n | 'query-materialization-end-to-end'\n ] = value;\n break;\n default:\n unreachable(metric);\n }\n }\n\n getQueryMetrics(queryID: string): PerQueryClientMetric | undefined {\n return this.#queryMetrics.get(queryID);\n }\n\n /**\n * For testing only: returns all query hashes currently registered.\n */\n getAllNonGotQueryHashes(): Iterable<string> {\n return difference(this.#queries, this.#gotQueries);\n }\n}\n\nfunction newMetrics(): ClientMetric {\n return {\n 'query-materialization-client': new TDigest(),\n 'query-materialization-end-to-end': new TDigest(),\n 'query-update-client': new TDigest(),\n };\n}\n\nfunction newPerQueryMetrics(): PerQueryClientMetric {\n return {\n 'query-materialization-client': undefined,\n 'query-materialization-end-to-end': undefined,\n 'query-update-client': new TDigest(),\n };\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { LogContext } from '@rocicorp/logger';
|
|
2
2
|
import { type Resolver } from '@rocicorp/resolver';
|
|
3
3
|
import { ReplicacheImpl } from '../../../replicache/src/impl.ts';
|
|
4
|
+
import type { Store as KVStore } from '../../../replicache/src/kv/store.ts';
|
|
4
5
|
import type { Puller } from '../../../replicache/src/puller.ts';
|
|
5
6
|
import type { Pusher } from '../../../replicache/src/pusher.ts';
|
|
6
7
|
import type { ClientGroupID, ClientID } from '../../../replicache/src/sync/ids.ts';
|
|
@@ -107,8 +108,11 @@ export declare class Zero<const S extends BaseDefaultSchema = DefaultSchema, MD
|
|
|
107
108
|
* This function is useful when you want to populate the cache ahead of time,
|
|
108
109
|
* for example after login, to avoid a flash of loading screen on the next page.
|
|
109
110
|
*
|
|
110
|
-
* Returns an object with
|
|
111
|
-
* - `complete`: a Promise that resolves when the
|
|
111
|
+
* Returns an object with three properties:
|
|
112
|
+
* - `complete`: a Promise that resolves when the server has confirmed the
|
|
113
|
+
* data on this connection
|
|
114
|
+
* - `cached`: a Promise that resolves as soon as the store holds a
|
|
115
|
+
* server-confirmed result, from this connection or a previous one
|
|
112
116
|
* - `cleanup`: a function that can be called to cancel the preload
|
|
113
117
|
*
|
|
114
118
|
* @example
|
|
@@ -121,12 +125,15 @@ export declare class Zero<const S extends BaseDefaultSchema = DefaultSchema, MD
|
|
|
121
125
|
preload<TTable extends keyof S['tables'] & string, TInput extends ReadonlyJSONValue | undefined, TOutput extends ReadonlyJSONValue | undefined, TReturn>(query: QueryOrQueryRequest<TTable, TInput, TOutput, S, TReturn, C>, options?: PreloadOptions): {
|
|
122
126
|
cleanup: () => void;
|
|
123
127
|
complete: Promise<void>;
|
|
128
|
+
cached: Promise<void>;
|
|
124
129
|
};
|
|
125
130
|
/**
|
|
126
131
|
* Executes a query once and returns the results.
|
|
127
132
|
*
|
|
128
133
|
* By default, runs immediately with whatever data is available locally.
|
|
129
|
-
* Use `{type: 'complete'}` to wait for fresh results from the server
|
|
134
|
+
* Use `{type: 'complete'}` to wait for fresh results from the server, or
|
|
135
|
+
* `{type: 'cached'}` to accept a result the server confirmed on a previous
|
|
136
|
+
* connection when the store holds one.
|
|
130
137
|
*
|
|
131
138
|
* @param query - The query to execute
|
|
132
139
|
* @param runOptions - Options controlling query execution
|
|
@@ -178,6 +185,14 @@ export declare class Zero<const S extends BaseDefaultSchema = DefaultSchema, MD
|
|
|
178
185
|
* instance of Zero is stored.
|
|
179
186
|
*/
|
|
180
187
|
get idbName(): string;
|
|
188
|
+
/**
|
|
189
|
+
* The KV store backing this instance of Zero. Its `kind` is the storage
|
|
190
|
+
* currently in use: `'idb'`, `'mem'`, `'op-sqlite'`, `'expo-sqlite'`, or
|
|
191
|
+
* whatever a custom store reports. An IndexedDB store that fails to open
|
|
192
|
+
* falls back to memory, so `kind` can change from `'idb'` to `'mem'` after
|
|
193
|
+
* the first read or write.
|
|
194
|
+
*/
|
|
195
|
+
get kvStore(): KVStore;
|
|
181
196
|
/**
|
|
182
197
|
* The schema version of the data understood by this application.
|
|
183
198
|
* See [[ZeroOptions.schemaVersion]].
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zero.d.ts","sourceRoot":"","sources":["../../../../../zero-client/src/client/zero.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAA8B,MAAM,kBAAkB,CAAC;AACzE,OAAO,EAAC,KAAK,QAAQ,EAAW,MAAM,oBAAoB,CAAC;AAG3D,OAAO,EACL,cAAc,EAEf,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"zero.d.ts","sourceRoot":"","sources":["../../../../../zero-client/src/client/zero.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAA8B,MAAM,kBAAkB,CAAC;AACzE,OAAO,EAAC,KAAK,QAAQ,EAAW,MAAM,oBAAoB,CAAC;AAG3D,OAAO,EACL,cAAc,EAEf,MAAM,iCAAiC,CAAC;AACzC,OAAO,KAAK,EAAC,KAAK,IAAI,OAAO,EAAC,MAAM,qCAAqC,CAAC;AAG1E,OAAO,KAAK,EAAC,MAAM,EAAe,MAAM,mCAAmC,CAAC;AAC5E,OAAO,KAAK,EAAC,MAAM,EAAe,MAAM,mCAAmC,CAAC;AAE5E,OAAO,KAAK,EACV,aAAa,EACb,QAAQ,EACT,MAAM,qCAAqC,CAAC;AAG7C,OAAO,KAAK,EACV,WAAW,EAEZ,MAAM,kCAAkC,CAAC;AAU1C,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,6BAA6B,CAAC;AAMnE,OAAO,EAAC,YAAY,EAAC,MAAM,qCAAqC,CAAC;AAIjE,OAAO,EAAC,KAAK,YAAY,EAAC,MAAM,6CAA6C,CAAC;AAG9E,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,8CAA8C,CAAC;AA+BpF,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,6CAA6C,CAAC;AAElF,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,uCAAuC,CAAC;AAO3E,OAAO,KAAK,EACV,kBAAkB,EAClB,iBAAiB,EACjB,cAAc,EACd,aAAa,EACd,MAAM,0CAA0C,CAAC;AAClD,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,mCAAmC,CAAC;AAC9D,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,8BAA8B,CAAC;AAK9D,OAAO,KAAK,EAEV,aAAa,EACd,MAAM,oCAAoC,CAAC;AAO5C,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,0CAA0C,CAAC;AAC5E,OAAO,EACL,KAAK,mBAAmB,EAEzB,MAAM,0CAA0C,CAAC;AAClD,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,UAAU,EAChB,MAAM,iCAAiC,CAAC;AACzC,OAAO,KAAK,EAAC,sBAAsB,EAAC,MAAM,wCAAwC,CAAC;AACnF,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,sCAAsC,CAAC;AAGpE,OAAO,EAAC,oBAAoB,EAAC,MAAM,6BAA6B,CAAC;AAEjE,OAAO,EACL,iBAAiB,EAGlB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAC,KAAK,UAAU,EAAiB,MAAM,iBAAiB,CAAC;AAEhE,OAAO,EACL,KAAK,YAAY,EAIlB,MAAM,WAAW,CAAC;AACnB,OAAO,KAAK,EAAC,iBAAiB,EAAE,aAAa,EAAC,MAAM,aAAa,CAAC;AAClE,OAAO,EAAC,oBAAoB,EAAC,MAAM,6BAA6B,CAAC;AAYjE,OAAO,EACL,KAAK,UAAU,EACf,KAAK,QAAQ,EAGd,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAC,SAAS,EAAC,MAAM,0BAA0B,CAAC;AAEnD,OAAO,EAAC,KAAK,UAAU,EAAmB,MAAM,kBAAkB,CAAC;AACnE,OAAO,KAAK,EAAC,sBAAsB,EAAC,MAAM,2BAA2B,CAAC;AAatE,OAAO,KAAK,EAAqB,WAAW,EAAC,MAAM,cAAc,CAAC;AAClE,OAAO,EAAC,YAAY,EAAC,MAAM,oBAAoB,CAAC;AAgBhD,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AAEhD,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,CAAC,CAAC,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;IACnC,UAAU,EAAE,UAAU,CAAC;IACvB,YAAY,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;IACvC,cAAc,EAAE,MAAM,QAAQ,CAAC,SAAS,CAAC,CAAC;IAC1C,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;IAC3C,aAAa,EAAE,MAAM,aAAa,CAAC;IACnC,YAAY,EAAE,MAAM,YAAY,CAAC;IACjC,aAAa,EAAE,MAAM,OAAO,CAAC;CAC9B,CAAC;AAEF,eAAO,MAAM,sBAAsB,eAAW,CAAC;AAC/C,eAAO,MAAM,sBAAsB,eAAW,CAAC;AAoD/C,eAAO,MAAM,oBAAoB,OAAQ,CAAC;AAE1C;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,OAAQ,CAAC;AAE7C;;;GAGG;AACH,eAAO,MAAM,eAAe,OAAQ,CAAC;AAErC,eAAO,MAAM,kCAAkC,QAAgB,CAAC;AAEhE;;;GAGG;AACH,eAAO,MAAM,6BAA6B,QAAa,CAAC;AAExD;;;GAGG;AACH,eAAO,MAAM,kBAAkB,QAAS,CAAC;AAYzC,eAAO,MAAM,0BAA0B,kBAAkB,CAAC;AAyC1D,MAAM,WAAW,qBAAqB;IACpC,cAAc,IAAI,MAAM,CAAC;CAC1B;AAID,wBAAgB,mCAAmC,CACjD,CAAC,EAAE,MAAM,GACR,cAAc,CAAC,WAAW,CAAC,CAG7B;AAMD,MAAM,MAAM,UAAU,CACpB,CAAC,SAAS,MAAM,EAChB,EAAE,SAAS,iBAAiB,GAAG,SAAS,EACxC,CAAC,IACC,sBAAsB,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,GAGlC,CAAC,CAAC,EAAE,EAAE,aAAa,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,KAAK,aAAa,CAAC,CAAC;AAEzD,qBAAa,IAAI,CACf,KAAK,CAAC,CAAC,SAAS,iBAAiB,GAAG,aAAa,EACjD,EAAE,SAAS,iBAAiB,GAAG,SAAS,GAAG,SAAS,EACpD,CAAC,SAAS,kBAAkB,GAAG,cAAc;;IAE7C,QAAQ,CAAC,OAAO,SAAW;IAI3B,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAsF5B;;;;;;;;OAQG;IACH,aAAa,EAAE,MAAM,CAAC;IAuCtB;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,sBAAsB,CAAC,CAAC,CAAC,CAAC;IAU1C;;OAEG;gBAES,OAAO,EAAE,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;IAse1C;;;;;;;;;;;;;;;;;;;OAmBG;IACH,OAAO,CACL,MAAM,SAAS,MAAM,CAAC,CAAC,QAAQ,CAAC,GAAG,MAAM,EACzC,MAAM,SAAS,iBAAiB,GAAG,SAAS,EAC5C,OAAO,SAAS,iBAAiB,GAAG,SAAS,EAC7C,OAAO,EAEP,KAAK,EAAE,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,EAClE,OAAO,CAAC,EAAE,cAAc;;;;;IAQ1B;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,GAAG,CACD,MAAM,SAAS,MAAM,CAAC,CAAC,QAAQ,CAAC,GAAG,MAAM,EACzC,MAAM,SAAS,iBAAiB,GAAG,SAAS,EAC5C,OAAO,SAAS,iBAAiB,GAAG,SAAS,EAC7C,OAAO,EAEP,KAAK,EAAE,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,EAClE,UAAU,CAAC,EAAE,UAAU,GACtB,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IAOlC,IAAI,OAAO,IAAI,CAAC,CAEf;IAED;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,WAAW,CACT,MAAM,SAAS,MAAM,CAAC,CAAC,QAAQ,CAAC,GAAG,MAAM,EACzC,MAAM,SAAS,iBAAiB,GAAG,SAAS,EAC5C,OAAO,SAAS,iBAAiB,GAAG,SAAS,EAC7C,OAAO,EAEP,KAAK,EAAE,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,EAClE,OAAO,CAAC,EAAE,kBAAkB,GAC3B,SAAS,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IACpC,WAAW,CACT,CAAC,EACD,MAAM,SAAS,MAAM,CAAC,CAAC,QAAQ,CAAC,GAAG,MAAM,EACzC,MAAM,SAAS,iBAAiB,GAAG,SAAS,EAC5C,OAAO,SAAS,iBAAiB,GAAG,SAAS,EAC7C,OAAO,EAEP,KAAK,EAAE,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,EAClE,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,EAC3C,OAAO,CAAC,EAAE,kBAAkB,GAC3B,CAAC;IAyBJ;;OAEG;IACH,IAAI,MAAM,IAAI,UAAU,GAAG,IAAI,CAE9B;IAED;;;OAGG;IACH,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED;;;;;;OAMG;IACH,IAAI,OAAO,IAAI,OAAO,CAErB;IAED;;;OAGG;IACH,IAAI,aAAa,IAAI,MAAM,CAE1B;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH,IAAI,MAAM,IAAI,CAAC,CAEd;IAED;;;OAGG;IACH,IAAI,QAAQ,IAAI,QAAQ,CAEvB;IAED,IAAI,aAAa,IAAI,OAAO,CAAC,aAAa,CAAC,CAE1C;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACH,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;IAEtC;;;;;;;;;;;;;;;;;;OAkBG;IACH,QAAQ,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;IAEtC;;;;;;;;;;;;;;;OAeG;IACH,IAAI,UAAU,IAAI,UAAU,CAE3B;IAED;;;;;OAKG;IACH,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED;;;;;OAKG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAg2C5B;;;;;OAKG;IACH,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED;;;;;;;;;OASG;IACH,QAAQ,GAAI,UAAU,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC,CACpB;IAsG1C;;;OAGG;IACH,IAAI,SAAS,IAAI,SAAS,CAiBzB;IAEK,MAAM,IAAI,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,EAAE,OAAO,EAAE,CAAA;KAAC,CAAC;CA0DhE;AAED,qBAAa,aAAc,SAAQ,YAAY,CAAC,OAAO,CAAC;;IAGtD,SAAS,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI;IAQhC,IAAI,MAAM,IAAI,OAAO,CAEpB;CACF;AAED,wBAAsB,YAAY,CAChC,GAAG,EAAE,cAAc,EACnB,YAAY,EAAE,YAAY,EAC1B,oBAAoB,EAAE,oBAAoB,EAC1C,YAAY,EAAE,QAAQ,EACtB,UAAU,EAAE,eAAe,EAC3B,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,OAAO,EAClB,EAAE,EAAE,UAAU,EACd,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,EACnD,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,EACpD,uBAAuB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,EAC3D,oBAAoB,EAAE,IAAI,CAAC,oBAAoB,EAAE,eAAe,CAAC,EACjE,eAAe,SAAW,EAC1B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAChC,OAAO,CACR;IACE,SAAS;IACT,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,GAAG,SAAS;IACzC,iBAAiB,GAAG,SAAS;CAC9B,CACF,CAuEA;AAED,wBAAsB,mBAAmB,CACvC,YAAY,EAAE,UAAU,GAAG,QAAQ,EACnC,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,UAAU,EAAE,MAAM,GAAG,IAAI,EACzB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC,EAAE,WAAW,CAAC,EAC1C,SAAS,EAAE,OAAO,EAClB,uBAAuB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,EAC3D,EAAE,EAAE,UAAU,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,gBA+B3D"}
|
|
@@ -4,7 +4,6 @@ import { AbortError } from "../../../shared/src/abort-error.js";
|
|
|
4
4
|
import { sleep, sleepWithAbort } from "../../../shared/src/sleep.js";
|
|
5
5
|
import { parse } from "../../../shared/src/valita.js";
|
|
6
6
|
import "../../../replicache/src/deleted-clients.js";
|
|
7
|
-
import { localNavigator } from "../../../shared/src/navigator.js";
|
|
8
7
|
import { getKVStoreProvider } from "../../../replicache/src/get-kv-store-provider.js";
|
|
9
8
|
import { IDBDatabasesStore } from "../../../replicache/src/persist/idb-databases-store.js";
|
|
10
9
|
import { dropDatabase } from "../../../replicache/src/persist/collect-idb-databases.js";
|
|
@@ -20,10 +19,11 @@ import { isMutatorRegistry, iterateMutators } from "../../../zql/src/mutate/muta
|
|
|
20
19
|
import { createRunnableBuilder } from "../../../zql/src/query/create-builder.js";
|
|
21
20
|
import "../../../zql/src/query/query.js";
|
|
22
21
|
import { addContextToQuery } from "../../../zql/src/query/query-registry.js";
|
|
23
|
-
import { Closed, Connected, Connecting, Disconnected, Error as Error$1, NeedsAuth } from "./connection-status-enum.js";
|
|
22
|
+
import { Closed, Connected, Connecting, Disconnected, Error as Error$1, Initializing, NeedsAuth } from "./connection-status-enum.js";
|
|
24
23
|
import { getDocumentVisibilityWatcher } from "../../../shared/src/document-visible.js";
|
|
25
24
|
import { ReplicacheImpl } from "../../../replicache/src/replicache-impl.js";
|
|
26
25
|
import "../../../replicache/src/impl.js";
|
|
26
|
+
import { localNavigator } from "../../../shared/src/navigator.js";
|
|
27
27
|
import { promiseRace } from "../../../shared/src/promise-race.js";
|
|
28
28
|
import { emptyFunction } from "../../../shared/src/sentinels.js";
|
|
29
29
|
import { Subscribable } from "../../../shared/src/subscribable.js";
|
|
@@ -38,7 +38,7 @@ import { isClientMetric } from "../../../zql/src/query/metrics-delegate.js";
|
|
|
38
38
|
import { nanoid } from "../util/nanoid.js";
|
|
39
39
|
import { ActiveClientsManager } from "./active-clients-manager.js";
|
|
40
40
|
import { AbruptClose, CleanClose, ClientClosed, ConnectTimeout, Hidden, Internal, InvalidMessage as InvalidMessage$1, NoSocketOrigin, PingTimeout, PullTimeout, UnexpectedBaseCookie } from "./client-error-kind-enum.js";
|
|
41
|
-
import { ClientError, NO_STATUS_TRANSITION, getBackoffParams, getErrorConnectionTransition,
|
|
41
|
+
import { ClientError, NO_STATUS_TRANSITION, getBackoffParams, getErrorConnectionTransition, isClientError, isServerError, isZeroError } from "./error.js";
|
|
42
42
|
import { ConnectionManager, throwIfConnectionError } from "./connection-manager.js";
|
|
43
43
|
import { ConnectionImpl } from "./connection.js";
|
|
44
44
|
import { IVMSourceBranch } from "./ivm-branch.js";
|
|
@@ -122,7 +122,7 @@ var serverAheadReloadReason = `Server reported that client is ahead of server. T
|
|
|
122
122
|
function onClientStateNotFoundServerReason(serverErrMsg) {
|
|
123
123
|
return `Server could not find state needed to synchronize this client. ${serverErrMsg}`;
|
|
124
124
|
}
|
|
125
|
-
var ON_CLIENT_STATE_NOT_FOUND_REASON_CLIENT = "The local persistent state needed to synchronize this client has been garbage collected.";
|
|
125
|
+
var ON_CLIENT_STATE_NOT_FOUND_REASON_CLIENT = "The local persistent state needed to synchronize this client has been garbage collected or was found to be corrupt.";
|
|
126
126
|
var CLOSE_CODE_NORMAL = 1e3;
|
|
127
127
|
var Zero = class Zero {
|
|
128
128
|
version = version;
|
|
@@ -307,7 +307,6 @@ var Zero = class Zero {
|
|
|
307
307
|
}, (ast, customQueryID, ttl, gotCallback) => this.#queryManager.addCustom(ast, customQueryID, ttl, gotCallback), (ast, ttl) => {
|
|
308
308
|
if (enableLegacyQueries) this.#queryManager.updateLegacy(ast, ttl);
|
|
309
309
|
}, (customQueryID, ttl) => this.#queryManager.updateCustom(customQueryID, ttl), () => this.#queryManager.flushBatch(), batchViewUpdates, this.#addMetric, assertValidRunOptions);
|
|
310
|
-
this.#zeroContext.deferPipelines();
|
|
311
310
|
this.query = createRunnableBuilder(this.#zeroContext, schema);
|
|
312
311
|
const rep = new ReplicacheImpl(replicacheOptions, {
|
|
313
312
|
enableClientGroupForking: false,
|
|
@@ -378,15 +377,16 @@ var Zero = class Zero {
|
|
|
378
377
|
});
|
|
379
378
|
this.#metrics.tags.push(`version:${this.version}`);
|
|
380
379
|
this.#pokeHandler = new PokeHandler(async (poke) => {
|
|
380
|
+
const socket = this.#socket;
|
|
381
381
|
await this.#rep.poke(poke);
|
|
382
|
-
this.#queryManager.markGotQueriesAuthoritative();
|
|
382
|
+
if (socket !== void 0 && this.#socket === socket) this.#queryManager.markGotQueriesAuthoritative();
|
|
383
383
|
}, (e) => this.#onPokeError(e), rep.clientID, schema, this.#lc, this.#mutationTracker);
|
|
384
384
|
this.#visibilityWatcher = getDocumentVisibilityWatcher(getBrowserGlobal("document"), hiddenTabDisconnectDelay, this.#closeAbortController.signal);
|
|
385
385
|
this.#runLoop();
|
|
386
386
|
this.#expose();
|
|
387
387
|
}
|
|
388
388
|
#enableRefresh() {
|
|
389
|
-
return this.#forceEnableRefresh || !this.#connectionManager.is("connected") && !this.#connectionManager.is("connecting");
|
|
389
|
+
return this.#forceEnableRefresh || !this.#connectionManager.is("connected") && !this.#connectionManager.is("connecting") && !this.#connectionManager.is("initializing");
|
|
390
390
|
}
|
|
391
391
|
#expose() {
|
|
392
392
|
const g = globalThis;
|
|
@@ -437,8 +437,11 @@ var Zero = class Zero {
|
|
|
437
437
|
* This function is useful when you want to populate the cache ahead of time,
|
|
438
438
|
* for example after login, to avoid a flash of loading screen on the next page.
|
|
439
439
|
*
|
|
440
|
-
* Returns an object with
|
|
441
|
-
* - `complete`: a Promise that resolves when the
|
|
440
|
+
* Returns an object with three properties:
|
|
441
|
+
* - `complete`: a Promise that resolves when the server has confirmed the
|
|
442
|
+
* data on this connection
|
|
443
|
+
* - `cached`: a Promise that resolves as soon as the store holds a
|
|
444
|
+
* server-confirmed result, from this connection or a previous one
|
|
442
445
|
* - `cleanup`: a function that can be called to cancel the preload
|
|
443
446
|
*
|
|
444
447
|
* @example
|
|
@@ -455,7 +458,9 @@ var Zero = class Zero {
|
|
|
455
458
|
* Executes a query once and returns the results.
|
|
456
459
|
*
|
|
457
460
|
* By default, runs immediately with whatever data is available locally.
|
|
458
|
-
* Use `{type: 'complete'}` to wait for fresh results from the server
|
|
461
|
+
* Use `{type: 'complete'}` to wait for fresh results from the server, or
|
|
462
|
+
* `{type: 'cached'}` to accept a result the server confirmed on a previous
|
|
463
|
+
* connection when the store holds one.
|
|
459
464
|
*
|
|
460
465
|
* @param query - The query to execute
|
|
461
466
|
* @param runOptions - Options controlling query execution
|
|
@@ -500,6 +505,16 @@ var Zero = class Zero {
|
|
|
500
505
|
return this.#rep.idbName;
|
|
501
506
|
}
|
|
502
507
|
/**
|
|
508
|
+
* The KV store backing this instance of Zero. Its `kind` is the storage
|
|
509
|
+
* currently in use: `'idb'`, `'mem'`, `'op-sqlite'`, `'expo-sqlite'`, or
|
|
510
|
+
* whatever a custom store reports. An IndexedDB store that fails to open
|
|
511
|
+
* falls back to memory, so `kind` can change from `'idb'` to `'mem'` after
|
|
512
|
+
* the first read or write.
|
|
513
|
+
*/
|
|
514
|
+
get kvStore() {
|
|
515
|
+
return this.#rep.kvStore;
|
|
516
|
+
}
|
|
517
|
+
/**
|
|
503
518
|
* The schema version of the data understood by this application.
|
|
504
519
|
* See [[ZeroOptions.schemaVersion]].
|
|
505
520
|
*/
|
|
@@ -1011,6 +1026,7 @@ var Zero = class Zero {
|
|
|
1011
1026
|
case Closed:
|
|
1012
1027
|
lc.debug?.("disconnect() called while closed");
|
|
1013
1028
|
return;
|
|
1029
|
+
case Initializing:
|
|
1014
1030
|
case Disconnected:
|
|
1015
1031
|
case Connecting:
|
|
1016
1032
|
case NeedsAuth:
|
|
@@ -1154,6 +1170,26 @@ var Zero = class Zero {
|
|
|
1154
1170
|
};
|
|
1155
1171
|
const { auth } = this.#options;
|
|
1156
1172
|
this.#setAuth(auth);
|
|
1173
|
+
const { signal: closeSignal } = this.#closeAbortController;
|
|
1174
|
+
const closed = resolver();
|
|
1175
|
+
const onClose = () => closed.resolve();
|
|
1176
|
+
closeSignal.addEventListener("abort", onClose, { once: true });
|
|
1177
|
+
try {
|
|
1178
|
+
if ((await promiseRace({
|
|
1179
|
+
initialized: Promise.all([
|
|
1180
|
+
this.#rep.cookie,
|
|
1181
|
+
this.clientGroupID,
|
|
1182
|
+
this.#activeClientsManager
|
|
1183
|
+
]),
|
|
1184
|
+
closed: closed.promise
|
|
1185
|
+
})).key === "closed") {
|
|
1186
|
+
this.#lc.debug?.("Closed while initializing, not connecting");
|
|
1187
|
+
return;
|
|
1188
|
+
}
|
|
1189
|
+
} catch {} finally {
|
|
1190
|
+
closeSignal.removeEventListener("abort", onClose);
|
|
1191
|
+
}
|
|
1192
|
+
this.#connectionManager.initialized();
|
|
1157
1193
|
let backoffMs;
|
|
1158
1194
|
let additionalConnectParams;
|
|
1159
1195
|
while (this.#connectionManager.shouldContinueRunLoop()) {
|
|
@@ -1267,12 +1303,24 @@ var Zero = class Zero {
|
|
|
1267
1303
|
})).key === "connectRequest") this.#connectionManager.resumeFromConnectRequest();
|
|
1268
1304
|
break;
|
|
1269
1305
|
case Closed: break;
|
|
1306
|
+
case Initializing: unreachable();
|
|
1270
1307
|
default: unreachable(currentState);
|
|
1271
1308
|
}
|
|
1272
1309
|
} catch (ex) {
|
|
1273
1310
|
const isClientClosedError = isClientError(ex) && ex.kind === "ClientClosed";
|
|
1311
|
+
const transition = getErrorConnectionTransition(ex);
|
|
1274
1312
|
if (!this.#connectionManager.is("connected") && !isClientClosedError) {
|
|
1275
|
-
|
|
1313
|
+
let level;
|
|
1314
|
+
switch (transition.status) {
|
|
1315
|
+
case Error$1:
|
|
1316
|
+
level = "error";
|
|
1317
|
+
break;
|
|
1318
|
+
case Disconnected:
|
|
1319
|
+
case Closed:
|
|
1320
|
+
level = "info";
|
|
1321
|
+
break;
|
|
1322
|
+
default: level = "warn";
|
|
1323
|
+
}
|
|
1276
1324
|
const kind = isServerError(ex) ? ex.kind : "Unknown Error";
|
|
1277
1325
|
lc[level]?.("Failed to connect", ex, ...getErrorCauses(ex), kind, {
|
|
1278
1326
|
lmid: this.#lastMutationIDReceived,
|
|
@@ -1280,7 +1328,6 @@ var Zero = class Zero {
|
|
|
1280
1328
|
});
|
|
1281
1329
|
}
|
|
1282
1330
|
lc.debug?.("Got an exception in the run loop", "state:", this.#connectionManager.state, "exception:", ex);
|
|
1283
|
-
const transition = getErrorConnectionTransition(ex);
|
|
1284
1331
|
let sleepMs = void 0;
|
|
1285
1332
|
switch (transition.status) {
|
|
1286
1333
|
case NO_STATUS_TRANSITION: {
|