@rocicorp/zero 1.12.0-canary.12 → 1.12.0-canary.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/out/replicache/src/btree/diff.d.ts.map +1 -1
- package/out/replicache/src/btree/diff.js +1 -2
- package/out/replicache/src/btree/diff.js.map +1 -1
- package/out/replicache/src/btree/read.d.ts +31 -1
- package/out/replicache/src/btree/read.d.ts.map +1 -1
- package/out/replicache/src/btree/read.js +74 -19
- package/out/replicache/src/btree/read.js.map +1 -1
- package/out/replicache/src/btree/splice.d.ts.map +1 -1
- package/out/replicache/src/btree/splice.js +2 -1
- package/out/replicache/src/btree/splice.js.map +1 -1
- package/out/replicache/src/btree/write.d.ts.map +1 -1
- package/out/replicache/src/btree/write.js +2 -1
- package/out/replicache/src/btree/write.js.map +1 -1
- package/out/replicache/src/persist/collect-idb-databases.d.ts +1 -0
- package/out/replicache/src/persist/collect-idb-databases.d.ts.map +1 -1
- package/out/replicache/src/persist/collect-idb-databases.js +13 -5
- package/out/replicache/src/persist/collect-idb-databases.js.map +1 -1
- package/out/replicache/src/scan-iterator.js +1 -1
- package/out/replicache/src/sync/request-id.js +2 -2
- package/out/replicache/src/sync/request-id.js.map +1 -1
- package/out/shared/src/bigint-json.d.ts.map +1 -1
- package/out/shared/src/bigint-json.js +1 -0
- package/out/shared/src/bigint-json.js.map +1 -1
- package/out/shared/src/btree-set.d.ts +21 -0
- package/out/shared/src/btree-set.d.ts.map +1 -1
- package/out/shared/src/btree-set.js +54 -0
- package/out/shared/src/btree-set.js.map +1 -1
- package/out/shared/src/headers.js +20 -0
- package/out/shared/src/headers.js.map +1 -0
- package/out/shared/src/natural-runs.d.ts +191 -0
- package/out/shared/src/natural-runs.d.ts.map +1 -0
- package/out/shared/src/natural-runs.js +337 -0
- package/out/shared/src/natural-runs.js.map +1 -0
- package/out/shared/src/random-uint64.d.ts.map +1 -1
- package/out/shared/src/random-uint64.js +2 -2
- package/out/shared/src/random-uint64.js.map +1 -1
- package/out/shared/src/random-values.d.ts +19 -1
- package/out/shared/src/random-values.d.ts.map +1 -1
- package/out/shared/src/random-values.js +38 -4
- package/out/shared/src/random-values.js.map +1 -1
- package/out/shared/src/tuple-map.d.ts +22 -0
- package/out/shared/src/tuple-map.d.ts.map +1 -0
- package/out/shared/src/tuple-map.js +48 -0
- package/out/shared/src/tuple-map.js.map +1 -0
- package/out/zero/package.js +1 -1
- package/out/zero/package.js.map +1 -1
- package/out/zero-cache/src/auth/auth.d.ts.map +1 -1
- package/out/zero-cache/src/auth/auth.js +5 -0
- package/out/zero-cache/src/auth/auth.js.map +1 -1
- package/out/zero-cache/src/config/zero-config.d.ts +21 -0
- package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
- package/out/zero-cache/src/config/zero-config.js +47 -9
- package/out/zero-cache/src/config/zero-config.js.map +1 -1
- package/out/zero-cache/src/custom-queries/transform-query.js +2 -2
- package/out/zero-cache/src/custom-queries/transform-query.js.map +1 -1
- package/out/zero-cache/src/db/pg-to-lite.d.ts.map +1 -1
- package/out/zero-cache/src/db/pg-to-lite.js +3 -2
- package/out/zero-cache/src/db/pg-to-lite.js.map +1 -1
- package/out/zero-cache/src/db/pg-type-parser.js +55 -2
- package/out/zero-cache/src/db/pg-type-parser.js.map +1 -1
- package/out/zero-cache/src/server/change-streamer.js +5 -2
- package/out/zero-cache/src/server/change-streamer.js.map +1 -1
- package/out/zero-cache/src/server/inspector-delegate.js +6 -29
- package/out/zero-cache/src/server/inspector-delegate.js.map +1 -1
- package/out/zero-cache/src/server/main.js +5 -0
- package/out/zero-cache/src/server/main.js.map +1 -1
- package/out/zero-cache/src/server/replicator.js +3 -2
- package/out/zero-cache/src/server/replicator.js.map +1 -1
- package/out/zero-cache/src/server/syncer.js +5 -4
- package/out/zero-cache/src/server/syncer.js.map +1 -1
- package/out/zero-cache/src/server/worker-dispatcher.d.ts.map +1 -1
- package/out/zero-cache/src/server/worker-dispatcher.js +2 -1
- package/out/zero-cache/src/server/worker-dispatcher.js.map +1 -1
- package/out/zero-cache/src/services/admin-auth.d.ts +22 -0
- package/out/zero-cache/src/services/admin-auth.d.ts.map +1 -0
- package/out/zero-cache/src/services/admin-auth.js +42 -0
- package/out/zero-cache/src/services/admin-auth.js.map +1 -0
- package/out/zero-cache/src/services/auth-attempt-counter.d.ts +33 -0
- package/out/zero-cache/src/services/auth-attempt-counter.d.ts.map +1 -0
- package/out/zero-cache/src/services/auth-attempt-counter.js +61 -0
- package/out/zero-cache/src/services/auth-attempt-counter.js.map +1 -0
- package/out/zero-cache/src/services/change-source/pg/backfill-stream.js +1 -1
- package/out/zero-cache/src/services/change-source/pg/change-source.js +110 -13
- package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/ddl.d.ts +13 -7
- package/out/zero-cache/src/services/change-source/pg/schema/ddl.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/ddl.js +38 -5
- 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 +10 -1
- package/out/zero-cache/src/services/change-source/pg/schema/init.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts +4 -0
- package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/shard.js +10 -3
- package/out/zero-cache/src/services/change-source/pg/schema/shard.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +23 -2
- 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.js +2 -2
- 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.js +10 -3
- package/out/zero-cache/src/services/change-streamer/change-streamer.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/subscriber.js.map +1 -1
- package/out/zero-cache/src/services/heapz.d.ts.map +1 -1
- package/out/zero-cache/src/services/heapz.js +4 -5
- package/out/zero-cache/src/services/heapz.js.map +1 -1
- package/out/zero-cache/src/services/mutagen/error.d.ts +5 -0
- package/out/zero-cache/src/services/mutagen/error.d.ts.map +1 -1
- package/out/zero-cache/src/services/mutagen/error.js +7 -1
- package/out/zero-cache/src/services/mutagen/error.js.map +1 -1
- package/out/zero-cache/src/services/mutagen/mutagen.js +1 -1
- package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -1
- package/out/zero-cache/src/services/mutagen/pusher.js +1 -1
- package/out/zero-cache/src/services/mutagen/pusher.js.map +1 -1
- package/out/zero-cache/src/services/plannerz.d.ts.map +1 -1
- package/out/zero-cache/src/services/plannerz.js +3 -7
- package/out/zero-cache/src/services/plannerz.js.map +1 -1
- package/out/zero-cache/src/services/profz.d.ts.map +1 -1
- package/out/zero-cache/src/services/profz.js +4 -13
- package/out/zero-cache/src/services/profz.js.map +1 -1
- package/out/zero-cache/src/services/replicator/change-processor.js +29 -2
- package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
- package/out/zero-cache/src/services/replicator/incremental-sync.js +3 -3
- package/out/zero-cache/src/services/replicator/incremental-sync.js.map +1 -1
- package/out/zero-cache/src/services/statz.d.ts.map +1 -1
- package/out/zero-cache/src/services/statz.js +2 -7
- package/out/zero-cache/src/services/statz.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/client-handler.js +22 -1
- package/out/zero-cache/src/services/view-syncer/client-handler.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/connection-context-manager.js +40 -2
- package/out/zero-cache/src/services/view-syncer/connection-context-manager.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr-store.js +54 -17
- package/out/zero-cache/src/services/view-syncer/cvr-store.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr.js +11 -0
- package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/inspect-auth-limiter.js +107 -0
- package/out/zero-cache/src/services/view-syncer/inspect-auth-limiter.js.map +1 -0
- package/out/zero-cache/src/services/view-syncer/inspect-handler.js +11 -6
- package/out/zero-cache/src/services/view-syncer/inspect-handler.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +2 -1
- 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.js +16 -14
- 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.js +4 -1
- package/out/zero-cache/src/services/view-syncer/schema/cvr.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/schema/init.js +3 -0
- package/out/zero-cache/src/services/view-syncer/schema/init.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.js +89 -51
- package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
- package/out/zero-cache/src/types/client-group-log-id.d.ts +9 -0
- package/out/zero-cache/src/types/client-group-log-id.d.ts.map +1 -0
- package/out/zero-cache/src/types/client-group-log-id.js +16 -0
- package/out/zero-cache/src/types/client-group-log-id.js.map +1 -0
- package/out/zero-cache/src/types/lite.d.ts.map +1 -1
- package/out/zero-cache/src/types/lite.js +1 -0
- package/out/zero-cache/src/types/lite.js.map +1 -1
- package/out/zero-cache/src/types/pg.d.ts +13 -2
- package/out/zero-cache/src/types/pg.d.ts.map +1 -1
- package/out/zero-cache/src/types/pg.js +2 -2
- package/out/zero-cache/src/types/pg.js.map +1 -1
- package/out/zero-cache/src/types/poke-chunk.d.ts +25 -4
- package/out/zero-cache/src/types/poke-chunk.d.ts.map +1 -1
- package/out/zero-cache/src/types/poke-chunk.js +46 -5
- package/out/zero-cache/src/types/poke-chunk.js.map +1 -1
- package/out/zero-cache/src/workers/connection.d.ts.map +1 -1
- package/out/zero-cache/src/workers/connection.js +10 -3
- package/out/zero-cache/src/workers/connection.js.map +1 -1
- package/out/zero-cache/src/workers/rehome.d.ts +10 -0
- package/out/zero-cache/src/workers/rehome.d.ts.map +1 -1
- package/out/zero-cache/src/workers/rehome.js +4 -2
- package/out/zero-cache/src/workers/rehome.js.map +1 -1
- package/out/zero-cache/src/workers/syncer-ws-message-handler.js +3 -2
- package/out/zero-cache/src/workers/syncer-ws-message-handler.js.map +1 -1
- package/out/zero-cache/src/workers/syncer.js +15 -15
- package/out/zero-cache/src/workers/syncer.js.map +1 -1
- package/out/zero-client/src/client/inspector/inspector.d.ts +4 -0
- package/out/zero-client/src/client/inspector/inspector.d.ts.map +1 -1
- package/out/zero-client/src/client/inspector/inspector.js +4 -0
- package/out/zero-client/src/client/inspector/inspector.js.map +1 -1
- package/out/zero-client/src/client/inspector/lazy-inspector.d.ts +10 -2
- package/out/zero-client/src/client/inspector/lazy-inspector.d.ts.map +1 -1
- package/out/zero-client/src/client/inspector/lazy-inspector.js +38 -31
- package/out/zero-client/src/client/inspector/lazy-inspector.js.map +1 -1
- package/out/zero-client/src/client/inspector/query.d.ts +2 -2
- package/out/zero-client/src/client/inspector/query.d.ts.map +1 -1
- package/out/zero-client/src/client/inspector/query.js +4 -4
- package/out/zero-client/src/client/inspector/query.js.map +1 -1
- package/out/zero-client/src/client/ivm-branch.d.ts +3 -0
- package/out/zero-client/src/client/ivm-branch.d.ts.map +1 -1
- package/out/zero-client/src/client/ivm-branch.js +10 -5
- package/out/zero-client/src/client/ivm-branch.js.map +1 -1
- package/out/zero-client/src/client/reconnect-backoff.d.ts +31 -0
- package/out/zero-client/src/client/reconnect-backoff.d.ts.map +1 -0
- package/out/zero-client/src/client/reconnect-backoff.js +44 -0
- package/out/zero-client/src/client/reconnect-backoff.js.map +1 -0
- package/out/zero-client/src/client/version.js +1 -1
- package/out/zero-client/src/client/zero.d.ts.map +1 -1
- package/out/zero-client/src/client/zero.js +7 -0
- package/out/zero-client/src/client/zero.js.map +1 -1
- package/out/zero-client/src/util/nanoid.js +2 -2
- package/out/zero-client/src/util/nanoid.js.map +1 -1
- package/out/zero-protocol/src/up.d.ts +42 -42
- package/out/zero-server/src/process-mutations.d.ts +10 -0
- package/out/zero-server/src/process-mutations.d.ts.map +1 -1
- package/out/zero-server/src/process-mutations.js +39 -6
- package/out/zero-server/src/process-mutations.js.map +1 -1
- package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
- package/out/zql/src/ivm/memory-source.js +89 -6
- package/out/zql/src/ivm/memory-source.js.map +1 -1
- package/out/zql/src/planner/planner-connection.d.ts.map +1 -1
- package/out/zql/src/planner/planner-connection.js +37 -3
- package/out/zql/src/planner/planner-connection.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../../../../../zero-client/src/client/inspector/query.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,gCAAgC,CAAC;AAEtE,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,uDAAuD,CAAC;AAE9F,OAAO,EACL,KAAK,eAAe,EAErB,MAAM,+CAA+C,CAAC;AACvD,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,6CAA6C,CAAC;AACrF,OAAO,EAAC,KAAK,GAAG,EAAe,MAAM,kCAAkC,CAAC;AACxE,OAAO,EACL,KAAK,yBAAyB,EAC9B,KAAK,
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../../../../../zero-client/src/client/inspector/query.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,gCAAgC,CAAC;AAEtE,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,uDAAuD,CAAC;AAE9F,OAAO,EACL,KAAK,eAAe,EAErB,MAAM,+CAA+C,CAAC;AACvD,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,6CAA6C,CAAC;AACrF,OAAO,EAAC,KAAK,GAAG,EAAe,MAAM,kCAAkC,CAAC;AACxE,OAAO,EACL,KAAK,yBAAyB,EAC9B,KAAK,OAAO,EAGb,MAAM,qBAAqB,CAAC;AAE7B,qBAAa,KAAK;;IAGhB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC,iBAAiB,CAAC,GAAG,IAAI,CAAC;IACvD,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAClB,QAAQ,CAAC,aAAa,EAAE,IAAI,GAAG,IAAI,CAAC;IACpC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAGlC,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAErC,QAAQ,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IACxC,QAAQ,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IACxC,QAAQ,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IACxC,QAAQ,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAExC,YAAY,GAAG,EAAE,eAAe,EAAE,QAAQ,EAAE,yBAAyB,EAsDpE;IAIK,OAAO,CAAC,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAkBxE;CACF"}
|
|
@@ -5,7 +5,7 @@ import { astToZQL } from "../../../../ast-to-zql/src/ast-to-zql.js";
|
|
|
5
5
|
import { mergeMetrics, rpc } from "./lazy-inspector.js";
|
|
6
6
|
//#region ../zero-client/src/client/inspector/query.ts
|
|
7
7
|
var Query = class {
|
|
8
|
-
#
|
|
8
|
+
#delegate;
|
|
9
9
|
name;
|
|
10
10
|
args;
|
|
11
11
|
got;
|
|
@@ -26,8 +26,8 @@ var Query = class {
|
|
|
26
26
|
updateClientP95;
|
|
27
27
|
updateServerP50;
|
|
28
28
|
updateServerP95;
|
|
29
|
-
constructor(row, delegate
|
|
30
|
-
this.#
|
|
29
|
+
constructor(row, delegate) {
|
|
30
|
+
this.#delegate = delegate;
|
|
31
31
|
const { ast, queryID, inactivatedAt } = row;
|
|
32
32
|
this.clientID = row.clientID;
|
|
33
33
|
this.id = queryID;
|
|
@@ -64,7 +64,7 @@ var Query = class {
|
|
|
64
64
|
name: this.name,
|
|
65
65
|
args: this.args
|
|
66
66
|
} : { value: must(this.#serverAST, "AST is required for unnamed queries") };
|
|
67
|
-
return rpc(
|
|
67
|
+
return rpc(this.#delegate, {
|
|
68
68
|
op: "analyze-query",
|
|
69
69
|
...details,
|
|
70
70
|
options
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.js","names":[],"sources":["../../../../../../zero-client/src/client/inspector/query.ts"],"sourcesContent":["import {astToZQL} from '../../../../ast-to-zql/src/ast-to-zql.ts';\nimport type {ReadonlyJSONValue} from '../../../../shared/src/json.ts';\nimport {must} from '../../../../shared/src/must.ts';\nimport type {AnalyzeQueryResult} from '../../../../zero-protocol/src/analyze-query-result.ts';\nimport type {AST} from '../../../../zero-protocol/src/ast.ts';\nimport {\n type InspectQueryRow,\n inspectAnalyzeQueryDownSchema,\n} from '../../../../zero-protocol/src/inspect-down.ts';\nimport type {AnalyzeQueryOptions} from '../../../../zero-protocol/src/inspect-up.ts';\nimport {type TTL, normalizeTTL} from '../../../../zql/src/query/ttl.ts';\nimport {\n type ExtendedInspectorDelegate,\n type
|
|
1
|
+
{"version":3,"file":"query.js","names":[],"sources":["../../../../../../zero-client/src/client/inspector/query.ts"],"sourcesContent":["import {astToZQL} from '../../../../ast-to-zql/src/ast-to-zql.ts';\nimport type {ReadonlyJSONValue} from '../../../../shared/src/json.ts';\nimport {must} from '../../../../shared/src/must.ts';\nimport type {AnalyzeQueryResult} from '../../../../zero-protocol/src/analyze-query-result.ts';\nimport type {AST} from '../../../../zero-protocol/src/ast.ts';\nimport {\n type InspectQueryRow,\n inspectAnalyzeQueryDownSchema,\n} from '../../../../zero-protocol/src/inspect-down.ts';\nimport type {AnalyzeQueryOptions} from '../../../../zero-protocol/src/inspect-up.ts';\nimport {type TTL, normalizeTTL} from '../../../../zql/src/query/ttl.ts';\nimport {\n type ExtendedInspectorDelegate,\n type Metrics,\n mergeMetrics,\n rpc,\n} from './lazy-inspector.ts';\n\nexport class Query {\n readonly #delegate: ExtendedInspectorDelegate;\n\n readonly name: string | null;\n readonly args: ReadonlyArray<ReadonlyJSONValue> | null;\n readonly got: boolean;\n readonly ttl: TTL;\n readonly inactivatedAt: Date | null;\n readonly rowCount: number;\n readonly deleted: boolean;\n readonly id: string;\n readonly clientID: string;\n readonly metrics: Metrics | null;\n readonly clientZQL: string | null;\n readonly serverZQL: string | null;\n readonly #serverAST: AST | null;\n\n readonly hydrateClient: number | null;\n readonly hydrateServer: number | null;\n readonly hydrateTotal: number | null;\n\n readonly updateClientP50: number | null;\n readonly updateClientP95: number | null;\n readonly updateServerP50: number | null;\n readonly updateServerP95: number | null;\n\n constructor(row: InspectQueryRow, delegate: ExtendedInspectorDelegate) {\n this.#delegate = delegate;\n\n const {ast, queryID, inactivatedAt} = row;\n // Use own properties to make this more useful in dev tools. For example, in\n // Chrome dev tools, if you do console.table(queries) you'll see the\n // properties in the table, if these were getters you would not see them in the table.\n this.clientID = row.clientID;\n this.id = queryID;\n this.inactivatedAt =\n inactivatedAt === null ? null : new Date(inactivatedAt);\n this.ttl = normalizeTTL(row.ttl);\n this.name = row.name;\n this.args = row.args;\n this.got = row.got;\n this.rowCount = row.rowCount;\n this.deleted = row.deleted;\n this.#serverAST = ast;\n this.serverZQL = ast ? ast.table + astToZQL(ast) : null;\n const clientAST = delegate.getAST(queryID);\n this.clientZQL = clientAST ? clientAST.table + astToZQL(clientAST) : null;\n\n // Merge client and server metrics\n const clientMetrics = delegate.getQueryMetrics(queryID);\n const serverMetrics = row.metrics;\n\n const merged = mergeMetrics(clientMetrics, serverMetrics);\n this.metrics = merged;\n\n const percentile = (\n name: keyof typeof merged,\n percentile: number,\n ): number | null => {\n if (!merged?.[name]) {\n return null;\n }\n const n = merged[name].quantile(percentile);\n return Number.isNaN(n) ? null : n;\n };\n\n // Hydration times are plain numbers (performance.now()-based durations), so\n // read them directly instead of going through the TDigest percentile path.\n this.hydrateClient =\n clientMetrics?.['query-materialization-client'] ?? null;\n this.hydrateServer = serverMetrics?.['query-hydration-server-ms'] ?? null;\n this.hydrateTotal =\n clientMetrics?.['query-materialization-end-to-end'] ?? null;\n\n // Extract update metrics (P50 and P95) - handle NaN by defaulting to 0\n this.updateClientP50 = percentile('query-update-client', 0.5);\n this.updateClientP95 = percentile('query-update-client', 0.95);\n\n this.updateServerP50 = percentile('query-update-server', 0.5);\n this.updateServerP95 = percentile('query-update-server', 0.95);\n }\n\n // Async so that a missing AST rejects instead of throwing synchronously.\n // oxlint-disable-next-line require-await\n async analyze(options?: AnalyzeQueryOptions): Promise<AnalyzeQueryResult> {\n const details =\n this.name && this.args\n ? {\n name: this.name,\n args: this.args,\n }\n : {value: must(this.#serverAST, 'AST is required for unnamed queries')};\n\n return rpc(\n this.#delegate,\n {\n op: 'analyze-query',\n ...details,\n options,\n },\n inspectAnalyzeQueryDownSchema,\n );\n }\n}\n"],"mappings":";;;;;;AAkBA,IAAa,QAAb,MAAmB;CACjB;CAEA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAEA;CACA;CACA;CAEA;CACA;CACA;CACA;CAEA,YAAY,KAAsB,UAAqC;EACrE,KAAK,YAAY;EAEjB,MAAM,EAAC,KAAK,SAAS,kBAAiB;EAItC,KAAK,WAAW,IAAI;EACpB,KAAK,KAAK;EACV,KAAK,gBACH,kBAAkB,OAAO,OAAO,IAAI,KAAK,aAAa;EACxD,KAAK,MAAM,aAAa,IAAI,GAAG;EAC/B,KAAK,OAAO,IAAI;EAChB,KAAK,OAAO,IAAI;EAChB,KAAK,MAAM,IAAI;EACf,KAAK,WAAW,IAAI;EACpB,KAAK,UAAU,IAAI;EACnB,KAAK,aAAa;EAClB,KAAK,YAAY,MAAM,IAAI,QAAQ,SAAS,GAAG,IAAI;EACnD,MAAM,YAAY,SAAS,OAAO,OAAO;EACzC,KAAK,YAAY,YAAY,UAAU,QAAQ,SAAS,SAAS,IAAI;EAGrE,MAAM,gBAAgB,SAAS,gBAAgB,OAAO;EACtD,MAAM,gBAAgB,IAAI;EAE1B,MAAM,SAAS,aAAa,eAAe,aAAa;EACxD,KAAK,UAAU;EAEf,MAAM,cACJ,MACA,eACkB;GAClB,IAAI,CAAC,SAAS,OACZ,OAAO;GAET,MAAM,IAAI,OAAO,KAAK,CAAC,SAAS,UAAU;GAC1C,OAAO,OAAO,MAAM,CAAC,IAAI,OAAO;EAClC;EAIA,KAAK,gBACH,gBAAgB,mCAAmC;EACrD,KAAK,gBAAgB,gBAAgB,gCAAgC;EACrE,KAAK,eACH,gBAAgB,uCAAuC;EAGzD,KAAK,kBAAkB,WAAW,uBAAuB,EAAG;EAC5D,KAAK,kBAAkB,WAAW,uBAAuB,GAAI;EAE7D,KAAK,kBAAkB,WAAW,uBAAuB,EAAG;EAC5D,KAAK,kBAAkB,WAAW,uBAAuB,GAAI;CAC/D;CAIA,MAAM,QAAQ,SAA4D;EACxE,MAAM,UACJ,KAAK,QAAQ,KAAK,OACd;GACE,MAAM,KAAK;GACX,MAAM,KAAK;EACb,IACA,EAAC,OAAO,KAAK,KAAK,YAAY,qCAAqC,EAAC;EAE1E,OAAO,IACL,KAAK,WACL;GACE,IAAI;GACJ,GAAG;GACH;EACF,GACA,6BACF;CACF;AACF"}
|
|
@@ -105,6 +105,9 @@ export declare function initFromStore(branch: IVMSourceBranch, hash: Hash, store
|
|
|
105
105
|
/**
|
|
106
106
|
* An `add` diff for each row at `hash` that the IVM sources hold: the table
|
|
107
107
|
* rows under `e/` and the aggregate rows under `a/`, in key order.
|
|
108
|
+
*
|
|
109
|
+
* Nothing can render until this returns, and it reads both ranges to their
|
|
110
|
+
* end, so it visits the tree rather than scanning it. See `BTreeRead.visit`.
|
|
108
111
|
*/
|
|
109
112
|
export declare function readRowDiffs(store: Store, hash: Hash): Promise<InternalDiffOperation[]>;
|
|
110
113
|
//# sourceMappingURL=ivm-branch.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ivm-branch.d.ts","sourceRoot":"","sources":["../../../../../zero-client/src/client/ivm-branch.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"ivm-branch.d.ts","sourceRoot":"","sources":["../../../../../zero-client/src/client/ivm-branch.ts"],"names":[],"mappings":"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"}
|
|
@@ -161,19 +161,24 @@ var IVMSourceBranch = class IVMSourceBranch {
|
|
|
161
161
|
/**
|
|
162
162
|
* An `add` diff for each row at `hash` that the IVM sources hold: the table
|
|
163
163
|
* rows under `e/` and the aggregate rows under `a/`, in key order.
|
|
164
|
+
*
|
|
165
|
+
* Nothing can render until this returns, and it reads both ranges to their
|
|
166
|
+
* end, so it visits the tree rather than scanning it. See `BTreeRead.visit`.
|
|
164
167
|
*/
|
|
165
168
|
async function readRowDiffs(store, hash) {
|
|
166
169
|
const diffs = [];
|
|
167
170
|
await withRead(store, async (dagRead) => {
|
|
168
|
-
const
|
|
169
|
-
for (const prefix of ROW_KEY_PREFIXES)
|
|
170
|
-
|
|
171
|
+
const { map } = await readFromHash(hash, dagRead, 7);
|
|
172
|
+
for (const prefix of ROW_KEY_PREFIXES) await map.visit(prefix, true, (entry) => {
|
|
173
|
+
const key = entry[0];
|
|
174
|
+
if (!key.startsWith(prefix)) return false;
|
|
171
175
|
diffs.push({
|
|
172
176
|
op: "add",
|
|
173
|
-
key
|
|
177
|
+
key,
|
|
174
178
|
newValue: entry[1]
|
|
175
179
|
});
|
|
176
|
-
|
|
180
|
+
return true;
|
|
181
|
+
});
|
|
177
182
|
});
|
|
178
183
|
return diffs;
|
|
179
184
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ivm-branch.js","names":[],"sources":["../../../../../zero-client/src/client/ivm-branch.ts"],"sourcesContent":["import type {\n InternalDiff,\n InternalDiffOperation,\n NoIndexDiff,\n} from '../../../replicache/src/btree/node.ts';\nimport type {LazyStore} from '../../../replicache/src/dag/lazy-store.ts';\nimport {type Read, type Store} from '../../../replicache/src/dag/store.ts';\nimport {readFromHash} from '../../../replicache/src/db/read.ts';\nimport * as FormatVersion from '../../../replicache/src/format-version-enum.ts';\nimport type {Hash} from '../../../replicache/src/hash.ts';\nimport type {ZeroReadOptions} from '../../../replicache/src/replicache-options.ts';\nimport {diffBinarySearch} from '../../../replicache/src/subscriptions.ts';\nimport type {DiffsMap} from '../../../replicache/src/sync/diff.ts';\nimport {diff} from '../../../replicache/src/sync/diff.ts';\nimport {using, withRead} from '../../../replicache/src/with-transactions.ts';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport {wrapIterable} from '../../../shared/src/iterables.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport {assignProperty} from '../../../shared/src/objects.ts';\nimport type {\n AggregateFunction,\n CompoundKey,\n} from '../../../zero-protocol/src/ast.ts';\nimport type {Row} from '../../../zero-protocol/src/data.ts';\nimport type {PrimaryKey} from '../../../zero-protocol/src/primary-key.ts';\nimport type {TableSchema} from '../../../zero-schema/src/table-schema.ts';\nimport {\n valueTypeOf,\n type SchemaValue,\n} from '../../../zero-types/src/schema-value.ts';\nimport {\n isAggregateTableName,\n isTopLevelAggregateTableName,\n type AggregateOptimisticDelta,\n} from '../../../zql/src/builder/builder.ts';\nimport {\n AGGREGATE_KEY_COLUMN,\n AGGREGATE_PAYLOAD_COLUMNS,\n AGGREGATE_VALUE_COLUMN,\n} from '../../../zql/src/ivm/aggregate.ts';\nimport {MemorySource} from '../../../zql/src/ivm/memory-source.ts';\nimport {consume} from '../../../zql/src/ivm/stream.ts';\nimport {\n aggregateRowKeyColumns,\n ROW_KEY_PREFIXES,\n ROW_VERSION_COLUMN,\n sourceNameFromKey,\n} from './keys.ts';\n\nimport {\n makeSourceChangeEdit,\n makeSourceChangeRemove,\n} from '../../../zql/src/ivm/source.ts';\n/**\n * Replicache needs to rebase mutations onto different\n * commits of it's b-tree. These mutations can have reads\n * in them and those reads must be run against the IVM sources.\n *\n * To ensure the reads get the correct state, the IVM\n * sources need to reflect the state of the commit\n * being rebased onto. `IVMSourceBranch` allows us to:\n * 1. fork the IVM sources\n * 2. patch them up to match the desired head\n * 3. run the reads against the forked sources\n *\n * (2) is expected to be a cheap operation as there should only\n * ever be a few outstanding diffs to apply given Zero is meant\n * to be run in a connected state.\n */\n/**\n * Metadata for optimistically updating a synced aggregate when a child row is\n * locally mutated. Registered when a relationship-aggregate query materializes.\n */\nexport type OptimisticAggregate = {\n /** The synthetic aggregate table, e.g. `aggregate:<queryID>:<alias>`. */\n readonly aggTableName: string;\n /** The correlation columns of a child row, as the client names them. */\n readonly childField: readonly string[];\n /**\n * The same columns as the synced aggregate rows name them (server names), in\n * the same order. An aggregate row's key is built from these.\n */\n readonly keyField: readonly string[];\n /** The aggregate function (`count`/`sum`/`avg` are optimistically deltaed). */\n readonly fn: AggregateFunction;\n /** The aggregated field, for `sum`/`avg` (`undefined` for `count`). */\n readonly field: string | undefined;\n /** A JSON path into `field` (see `Aggregate.path`). */\n readonly path: readonly (string | number)[] | undefined;\n /**\n * The aggregate's `where`, compiled to a per-row predicate. A child row\n * contributes only when it returns true; `undefined` means no filter (every\n * child contributes). Only set when the whole `where` is per-row evaluable —\n * a correlated subquery in the `where` makes the aggregate\n * server-authoritative (it is never registered for optimism at all).\n */\n readonly predicate: ((row: Row) => boolean) | undefined;\n /** The rows are a grouped query's groups (see `AggregateOptimisticDelta`). */\n readonly grouped: boolean;\n};\n\nexport class IVMSourceBranch {\n readonly #sources: Map<string, MemorySource | undefined>;\n readonly #tables: Record<string, TableSchema>;\n // Registry for optimistic aggregate deltas: child table name -> (synthetic\n // aggregate table name -> metadata). Lets an optimistic child mutation find\n // the aggregate rows it should bump. Shared by reference across forks (it is\n // query metadata, independent of branch row state).\n readonly #aggregateOptimism: Map<string, Map<string, OptimisticAggregate>>;\n // Only the main branch registers optimistic aggregates: see\n // getOrCreateAggregateSource.\n readonly #isFork: boolean;\n #advanceError: unknown;\n hash: Hash | undefined;\n\n constructor(\n tables: Record<string, TableSchema>,\n hash?: Hash,\n sources: Map<string, MemorySource | undefined> = new Map(),\n aggregateOptimism: Map<\n string,\n Map<string, OptimisticAggregate>\n > = new Map(),\n isFork = false,\n ) {\n this.#tables = tables;\n this.#sources = sources;\n this.#aggregateOptimism = aggregateOptimism;\n this.#isFork = isFork;\n this.hash = hash;\n }\n\n getSource(name: string): MemorySource | undefined {\n this.#throwIfInvalid();\n\n if (this.#sources.has(name)) {\n return this.#sources.get(name);\n }\n\n const schema = this.#tables[name];\n let source: MemorySource | undefined;\n if (schema) {\n source = new MemorySource(name, schema.columns, schema.primaryKey);\n } else if (isTopLevelAggregateTableName(name)) {\n // Synthetic source for a synced top-level aggregate (e.g. `count()`). It\n // is not in the static schema; its shape is fixed (the singleton key\n // column + the result value), so it can be provisioned from the name\n // alone — including at reload time, before the query re-materializes. The\n // server streams the precomputed value here; the underlying rows are never\n // synced. The payload is typed as `inferAggregateSchema` types it: the\n // value is null over no rows, and `sum`/`avg` add their components.\n const columns: Record<string, SchemaValue> = {\n [AGGREGATE_KEY_COLUMN]: {type: 'number'},\n };\n for (const col of AGGREGATE_PAYLOAD_COLUMNS) {\n columns[col] = {type: 'number', optional: true};\n }\n source = new MemorySource(name, columns, [AGGREGATE_KEY_COLUMN]);\n } else {\n source = undefined;\n }\n this.#sources.set(name, source);\n return source;\n }\n\n /**\n * Get-or-create the synthetic source for a *relationship* aggregate\n * (`aggregate:<queryID>:<alias>`), whose shape (the correlation-key columns +\n * value) cannot be derived from the name. The query builder supplies the\n * schema when a query materializes; {@link applyDiffs} supplies an inferred\n * one when persisted rows are replayed before the query re-materializes (e.g.\n * on reload). Idempotent — the first caller wins.\n */\n getOrCreateAggregateSource(\n name: string,\n columns: Record<string, SchemaValue>,\n primaryKey: PrimaryKey,\n optimistic?: AggregateOptimisticDelta,\n ): MemorySource {\n // A fork (a mutator's `tx.run`, or a rebase) shares the main branch's\n // registry, but only the main branch releases registrations, when the\n // server empties a source a view of it holds. A query materialized on a\n // fork is never synced, so its registration would never be released, and\n // a synced one is registered by the main branch already.\n if (optimistic && !this.#isFork) {\n let byTable = this.#aggregateOptimism.get(optimistic.table);\n if (!byTable) {\n byTable = new Map();\n this.#aggregateOptimism.set(optimistic.table, byTable);\n }\n // Keyed by aggregate table name so re-registering the same query is a\n // no-op (idempotent).\n byTable.set(name, {\n aggTableName: name,\n childField: optimistic.childField,\n keyField: optimistic.keyField,\n fn: optimistic.fn,\n field: optimistic.field,\n path: optimistic.path,\n predicate: optimistic.predicate,\n grouped: optimistic.grouped ?? false,\n });\n }\n const existing = this.#sources.get(name);\n if (existing) {\n return existing;\n }\n const source = new MemorySource(name, columns, primaryKey);\n this.#sources.set(name, source);\n return source;\n }\n\n /**\n * The server names of `columns` of `table`, in the same order. A column with\n * no server name of its own, or of a table not in the schema, keeps its name.\n */\n serverColumnNames(table: string, columns: CompoundKey): CompoundKey {\n const tableColumns = this.#tables[table]?.columns;\n return columns.map(\n c => tableColumns?.[c]?.serverName ?? c,\n ) as unknown as CompoundKey;\n }\n\n /**\n * The optimistic-aggregate registrations whose child rows live in `table`.\n * An optimistic insert/delete of such a child row bumps these aggregates.\n */\n getOptimisticAggregates(table: string): Iterable<OptimisticAggregate> {\n return this.#aggregateOptimism.get(table)?.values() ?? [];\n }\n\n clear() {\n this.#sources.clear();\n }\n\n /**\n * Drops the synthetic aggregate sources that are empty and that no view\n * reads, with their optimistic registrations. The server deletes an\n * aggregate's rows when its query is removed, so this is how the query's\n * client state goes away. A later materialization recreates both.\n *\n * Every advance checks every aggregate source, not just the ones it emptied:\n * the server can empty a source while a view still reads it, and a source\n * can be destroyed without ever getting a row.\n *\n * Only the main branch does this: a fork's sources have no views, and the\n * registrations are shared with the main branch.\n */\n #releaseAggregateSources() {\n for (const [name, source] of this.#sources) {\n if (\n source &&\n isAggregateTableName(name) &&\n source.data.size === 0 &&\n !source.connected\n ) {\n this.#sources.delete(name);\n for (const byTable of this.#aggregateOptimism.values()) {\n byTable.delete(name);\n }\n }\n }\n }\n\n #throwIfInvalid() {\n if (this.#advanceError) {\n throw this.#advanceError;\n }\n }\n\n /**\n * Mutates the current branch, advancing it to the new head\n * by applying the given diffs.\n */\n advance(expectedHead: Hash | undefined, newHead: Hash, diffs: NoIndexDiff) {\n this.#throwIfInvalid();\n\n assert(\n this.hash === expectedHead,\n () =>\n `Expected head must match the main head. Got: ${this.hash}, expected: ${expectedHead}`,\n );\n\n try {\n applyDiffs(diffs, this);\n this.#releaseAggregateSources();\n this.hash = newHead;\n } catch (e) {\n this.#advanceError = e;\n this.clear();\n throw e;\n }\n }\n\n /**\n * Fork the branch and patch it up to match the desired head.\n */\n async forkToHead(\n store: LazyStore,\n desiredHead: Hash,\n readOptions?: ZeroReadOptions,\n ): Promise<IVMSourceBranch> {\n this.#throwIfInvalid();\n\n const fork = this.fork();\n\n if (fork.hash === desiredHead) {\n return fork;\n }\n\n await patchBranch(desiredHead, store, fork, readOptions);\n fork.hash = desiredHead;\n return fork;\n }\n\n /**\n * Creates a new IVMSourceBranch that is a copy of the current one.\n * This is a cheap operation since the b-trees are shared until a write is performed\n * and then only the modified nodes are copied.\n *\n * IVM branches are forked when we need to rebase mutations.\n * The mutations modify the fork rather than original branch.\n */\n fork() {\n this.#throwIfInvalid();\n\n return new IVMSourceBranch(\n this.#tables,\n this.hash,\n new Map(\n wrapIterable(this.#sources.entries()).map(([name, source]) => [\n name,\n source?.fork(),\n ]),\n ),\n // Share the optimistic-aggregate registry by reference: it is query\n // metadata, the same for the fork as for the main branch.\n this.#aggregateOptimism,\n true,\n );\n }\n}\n\nexport async function initFromStore(\n branch: IVMSourceBranch,\n hash: Hash,\n store: Store,\n) {\n branch.advance(undefined, hash, await readRowDiffs(store, hash));\n}\n\n/**\n * An `add` diff for each row at `hash` that the IVM sources hold: the table\n * rows under `e/` and the aggregate rows under `a/`, in key order.\n */\nexport async function readRowDiffs(\n store: Store,\n hash: Hash,\n): Promise<InternalDiffOperation[]> {\n const diffs: InternalDiffOperation[] = [];\n await withRead(store, async dagRead => {\n const read = await readFromHash(hash, dagRead, FormatVersion.Latest);\n for (const prefix of ROW_KEY_PREFIXES) {\n for await (const entry of read.map.scan(prefix, true)) {\n if (!entry[0].startsWith(prefix)) {\n break;\n }\n diffs.push({\n op: 'add',\n key: entry[0],\n newValue: entry[1],\n });\n }\n }\n });\n return diffs;\n}\n\nasync function patchBranch(\n desiredHead: Hash,\n store: LazyStore,\n fork: IVMSourceBranch,\n readOptions: ZeroReadOptions | undefined,\n) {\n const diffs = await computeDiffs(\n must(fork.hash),\n desiredHead,\n store,\n readOptions,\n );\n if (!diffs) {\n return;\n }\n applyDiffs(diffs, fork);\n}\n\nasync function computeDiffs(\n startHash: Hash,\n endHash: Hash,\n store: LazyStore,\n readOptions: ZeroReadOptions | undefined,\n): Promise<InternalDiff | undefined> {\n const readFn = (dagRead: Read) =>\n diff(\n startHash,\n endHash,\n dagRead,\n {\n shouldComputeDiffs: () => true,\n shouldComputeDiffsForIndex(_name) {\n return false;\n },\n },\n FormatVersion.Latest,\n );\n\n let diffs: DiffsMap;\n if (readOptions?.openLazySourceRead) {\n diffs = await using(store.read(readOptions.openLazySourceRead), readFn);\n } else if (readOptions?.openLazyRead) {\n diffs = await readFn(readOptions.openLazyRead);\n } else {\n diffs = await withRead(store, readFn);\n }\n\n return diffs.get('');\n}\n\nfunction applyDiffs(diffs: NoIndexDiff, branch: IVMSourceBranch) {\n for (const prefix of ROW_KEY_PREFIXES) {\n applyRowDiffs(diffs, prefix, branch);\n }\n}\n\n/** Applies the diffs of the rows under `prefix`, `e/` or `a/`. */\nfunction applyRowDiffs(\n diffs: NoIndexDiff,\n prefix: string,\n branch: IVMSourceBranch,\n) {\n for (\n let i = diffBinarySearch(diffs, prefix, diff => diff.key);\n i < diffs.length;\n i++\n ) {\n const diff = diffs[i];\n const {key} = diff;\n if (!key.startsWith(prefix)) {\n break;\n }\n const name = sourceNameFromKey(key);\n let source = branch.getSource(name);\n if (!source && isAggregateTableName(name)) {\n // A relationship aggregate source isn't derivable from the name, so it\n // may not exist yet when persisted rows are replayed before the query\n // re-materializes (reload). Provision it from the row's own shape; the\n // builder will reuse this same source when the query materializes.\n const row = (diff.op === 'del' ? diff.oldValue : diff.newValue) as Row;\n source = branch.getOrCreateAggregateSource(\n name,\n ...inferAggregateSchema(name, row),\n );\n }\n source = must(source);\n switch (diff.op) {\n case 'del':\n consume(source.push(makeSourceChangeRemove(diff.oldValue as Row)));\n break;\n case 'add': {\n // The source's own prefix: the key up to the slash after its name.\n const sourcePrefix = key.slice(0, key.indexOf('/', prefix.length) + 1);\n const rows = takeAddsForSource(diffs, i, sourcePrefix);\n i += rows.length - 1;\n source.pushAdds(rows);\n break;\n }\n case 'change':\n consume(\n source.push(\n makeSourceChangeEdit(diff.newValue as Row, diff.oldValue as Row),\n ),\n );\n break;\n }\n }\n}\n\n/**\n * Returns the rows of the run of `add` diffs under `prefix` (a source's key\n * prefix, e.g. `e/issue/`) that starts at `start`. Diffs are ordered by key so\n * a table's rows are contiguous.\n */\nfunction takeAddsForSource(\n diffs: NoIndexDiff,\n start: number,\n prefix: string,\n): Row[] {\n const rows: Row[] = [];\n for (let i = start; i < diffs.length; i++) {\n const diff = diffs[i];\n if (diff.op !== 'add' || !diff.key.startsWith(prefix)) {\n break;\n }\n rows.push(diff.newValue as Row);\n }\n return rows;\n}\n\n/**\n * Infers a synthetic aggregate source's schema from one of its rows: the key\n * columns are every column except the payload and the row-version, with types\n * read off the actual values. Used only on the reload path, where a\n * relationship aggregate's rows are replayed before its query (which would\n * otherwise supply the exact schema) materializes.\n */\nfunction inferAggregateSchema(\n name: string,\n row: Row,\n): [columns: Record<string, SchemaValue>, primaryKey: PrimaryKey] {\n const columns: Record<string, SchemaValue> = {};\n for (const k of Object.keys(row)) {\n if (k === ROW_VERSION_COLUMN) {\n continue;\n }\n if (AGGREGATE_PAYLOAD_COLUMNS.has(k)) {\n // The result (and, for sum/avg, its components) — numeric payload, never part of the key.\n assignProperty(columns, k, {type: 'number', optional: true});\n } else {\n assignProperty(columns, k, {type: valueTypeOf(row[k])});\n }\n }\n const keyColumns = aggregateRowKeyColumns(name, row);\n // The result column is always present even if absent from this particular row.\n if (!(AGGREGATE_VALUE_COLUMN in columns)) {\n columns[AGGREGATE_VALUE_COLUMN] = {type: 'number', optional: true};\n }\n return [columns, keyColumns as unknown as PrimaryKey];\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ivm-branch.js","names":[],"sources":["../../../../../zero-client/src/client/ivm-branch.ts"],"sourcesContent":["import type {\n InternalDiff,\n InternalDiffOperation,\n NoIndexDiff,\n} from '../../../replicache/src/btree/node.ts';\nimport type {LazyStore} from '../../../replicache/src/dag/lazy-store.ts';\nimport {type Read, type Store} from '../../../replicache/src/dag/store.ts';\nimport {readFromHash} from '../../../replicache/src/db/read.ts';\nimport * as FormatVersion from '../../../replicache/src/format-version-enum.ts';\nimport type {Hash} from '../../../replicache/src/hash.ts';\nimport type {ZeroReadOptions} from '../../../replicache/src/replicache-options.ts';\nimport {diffBinarySearch} from '../../../replicache/src/subscriptions.ts';\nimport type {DiffsMap} from '../../../replicache/src/sync/diff.ts';\nimport {diff} from '../../../replicache/src/sync/diff.ts';\nimport {using, withRead} from '../../../replicache/src/with-transactions.ts';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport {wrapIterable} from '../../../shared/src/iterables.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport {assignProperty} from '../../../shared/src/objects.ts';\nimport type {\n AggregateFunction,\n CompoundKey,\n} from '../../../zero-protocol/src/ast.ts';\nimport type {Row} from '../../../zero-protocol/src/data.ts';\nimport type {PrimaryKey} from '../../../zero-protocol/src/primary-key.ts';\nimport type {TableSchema} from '../../../zero-schema/src/table-schema.ts';\nimport {\n valueTypeOf,\n type SchemaValue,\n} from '../../../zero-types/src/schema-value.ts';\nimport {\n isAggregateTableName,\n isTopLevelAggregateTableName,\n type AggregateOptimisticDelta,\n} from '../../../zql/src/builder/builder.ts';\nimport {\n AGGREGATE_KEY_COLUMN,\n AGGREGATE_PAYLOAD_COLUMNS,\n AGGREGATE_VALUE_COLUMN,\n} from '../../../zql/src/ivm/aggregate.ts';\nimport {MemorySource} from '../../../zql/src/ivm/memory-source.ts';\nimport {consume} from '../../../zql/src/ivm/stream.ts';\nimport {\n aggregateRowKeyColumns,\n ROW_KEY_PREFIXES,\n ROW_VERSION_COLUMN,\n sourceNameFromKey,\n} from './keys.ts';\n\nimport {\n makeSourceChangeEdit,\n makeSourceChangeRemove,\n} from '../../../zql/src/ivm/source.ts';\n/**\n * Replicache needs to rebase mutations onto different\n * commits of it's b-tree. These mutations can have reads\n * in them and those reads must be run against the IVM sources.\n *\n * To ensure the reads get the correct state, the IVM\n * sources need to reflect the state of the commit\n * being rebased onto. `IVMSourceBranch` allows us to:\n * 1. fork the IVM sources\n * 2. patch them up to match the desired head\n * 3. run the reads against the forked sources\n *\n * (2) is expected to be a cheap operation as there should only\n * ever be a few outstanding diffs to apply given Zero is meant\n * to be run in a connected state.\n */\n/**\n * Metadata for optimistically updating a synced aggregate when a child row is\n * locally mutated. Registered when a relationship-aggregate query materializes.\n */\nexport type OptimisticAggregate = {\n /** The synthetic aggregate table, e.g. `aggregate:<queryID>:<alias>`. */\n readonly aggTableName: string;\n /** The correlation columns of a child row, as the client names them. */\n readonly childField: readonly string[];\n /**\n * The same columns as the synced aggregate rows name them (server names), in\n * the same order. An aggregate row's key is built from these.\n */\n readonly keyField: readonly string[];\n /** The aggregate function (`count`/`sum`/`avg` are optimistically deltaed). */\n readonly fn: AggregateFunction;\n /** The aggregated field, for `sum`/`avg` (`undefined` for `count`). */\n readonly field: string | undefined;\n /** A JSON path into `field` (see `Aggregate.path`). */\n readonly path: readonly (string | number)[] | undefined;\n /**\n * The aggregate's `where`, compiled to a per-row predicate. A child row\n * contributes only when it returns true; `undefined` means no filter (every\n * child contributes). Only set when the whole `where` is per-row evaluable —\n * a correlated subquery in the `where` makes the aggregate\n * server-authoritative (it is never registered for optimism at all).\n */\n readonly predicate: ((row: Row) => boolean) | undefined;\n /** The rows are a grouped query's groups (see `AggregateOptimisticDelta`). */\n readonly grouped: boolean;\n};\n\nexport class IVMSourceBranch {\n readonly #sources: Map<string, MemorySource | undefined>;\n readonly #tables: Record<string, TableSchema>;\n // Registry for optimistic aggregate deltas: child table name -> (synthetic\n // aggregate table name -> metadata). Lets an optimistic child mutation find\n // the aggregate rows it should bump. Shared by reference across forks (it is\n // query metadata, independent of branch row state).\n readonly #aggregateOptimism: Map<string, Map<string, OptimisticAggregate>>;\n // Only the main branch registers optimistic aggregates: see\n // getOrCreateAggregateSource.\n readonly #isFork: boolean;\n #advanceError: unknown;\n hash: Hash | undefined;\n\n constructor(\n tables: Record<string, TableSchema>,\n hash?: Hash,\n sources: Map<string, MemorySource | undefined> = new Map(),\n aggregateOptimism: Map<\n string,\n Map<string, OptimisticAggregate>\n > = new Map(),\n isFork = false,\n ) {\n this.#tables = tables;\n this.#sources = sources;\n this.#aggregateOptimism = aggregateOptimism;\n this.#isFork = isFork;\n this.hash = hash;\n }\n\n getSource(name: string): MemorySource | undefined {\n this.#throwIfInvalid();\n\n if (this.#sources.has(name)) {\n return this.#sources.get(name);\n }\n\n const schema = this.#tables[name];\n let source: MemorySource | undefined;\n if (schema) {\n source = new MemorySource(name, schema.columns, schema.primaryKey);\n } else if (isTopLevelAggregateTableName(name)) {\n // Synthetic source for a synced top-level aggregate (e.g. `count()`). It\n // is not in the static schema; its shape is fixed (the singleton key\n // column + the result value), so it can be provisioned from the name\n // alone — including at reload time, before the query re-materializes. The\n // server streams the precomputed value here; the underlying rows are never\n // synced. The payload is typed as `inferAggregateSchema` types it: the\n // value is null over no rows, and `sum`/`avg` add their components.\n const columns: Record<string, SchemaValue> = {\n [AGGREGATE_KEY_COLUMN]: {type: 'number'},\n };\n for (const col of AGGREGATE_PAYLOAD_COLUMNS) {\n columns[col] = {type: 'number', optional: true};\n }\n source = new MemorySource(name, columns, [AGGREGATE_KEY_COLUMN]);\n } else {\n source = undefined;\n }\n this.#sources.set(name, source);\n return source;\n }\n\n /**\n * Get-or-create the synthetic source for a *relationship* aggregate\n * (`aggregate:<queryID>:<alias>`), whose shape (the correlation-key columns +\n * value) cannot be derived from the name. The query builder supplies the\n * schema when a query materializes; {@link applyDiffs} supplies an inferred\n * one when persisted rows are replayed before the query re-materializes (e.g.\n * on reload). Idempotent — the first caller wins.\n */\n getOrCreateAggregateSource(\n name: string,\n columns: Record<string, SchemaValue>,\n primaryKey: PrimaryKey,\n optimistic?: AggregateOptimisticDelta,\n ): MemorySource {\n // A fork (a mutator's `tx.run`, or a rebase) shares the main branch's\n // registry, but only the main branch releases registrations, when the\n // server empties a source a view of it holds. A query materialized on a\n // fork is never synced, so its registration would never be released, and\n // a synced one is registered by the main branch already.\n if (optimistic && !this.#isFork) {\n let byTable = this.#aggregateOptimism.get(optimistic.table);\n if (!byTable) {\n byTable = new Map();\n this.#aggregateOptimism.set(optimistic.table, byTable);\n }\n // Keyed by aggregate table name so re-registering the same query is a\n // no-op (idempotent).\n byTable.set(name, {\n aggTableName: name,\n childField: optimistic.childField,\n keyField: optimistic.keyField,\n fn: optimistic.fn,\n field: optimistic.field,\n path: optimistic.path,\n predicate: optimistic.predicate,\n grouped: optimistic.grouped ?? false,\n });\n }\n const existing = this.#sources.get(name);\n if (existing) {\n return existing;\n }\n const source = new MemorySource(name, columns, primaryKey);\n this.#sources.set(name, source);\n return source;\n }\n\n /**\n * The server names of `columns` of `table`, in the same order. A column with\n * no server name of its own, or of a table not in the schema, keeps its name.\n */\n serverColumnNames(table: string, columns: CompoundKey): CompoundKey {\n const tableColumns = this.#tables[table]?.columns;\n return columns.map(\n c => tableColumns?.[c]?.serverName ?? c,\n ) as unknown as CompoundKey;\n }\n\n /**\n * The optimistic-aggregate registrations whose child rows live in `table`.\n * An optimistic insert/delete of such a child row bumps these aggregates.\n */\n getOptimisticAggregates(table: string): Iterable<OptimisticAggregate> {\n return this.#aggregateOptimism.get(table)?.values() ?? [];\n }\n\n clear() {\n this.#sources.clear();\n }\n\n /**\n * Drops the synthetic aggregate sources that are empty and that no view\n * reads, with their optimistic registrations. The server deletes an\n * aggregate's rows when its query is removed, so this is how the query's\n * client state goes away. A later materialization recreates both.\n *\n * Every advance checks every aggregate source, not just the ones it emptied:\n * the server can empty a source while a view still reads it, and a source\n * can be destroyed without ever getting a row.\n *\n * Only the main branch does this: a fork's sources have no views, and the\n * registrations are shared with the main branch.\n */\n #releaseAggregateSources() {\n for (const [name, source] of this.#sources) {\n if (\n source &&\n isAggregateTableName(name) &&\n source.data.size === 0 &&\n !source.connected\n ) {\n this.#sources.delete(name);\n for (const byTable of this.#aggregateOptimism.values()) {\n byTable.delete(name);\n }\n }\n }\n }\n\n #throwIfInvalid() {\n if (this.#advanceError) {\n throw this.#advanceError;\n }\n }\n\n /**\n * Mutates the current branch, advancing it to the new head\n * by applying the given diffs.\n */\n advance(expectedHead: Hash | undefined, newHead: Hash, diffs: NoIndexDiff) {\n this.#throwIfInvalid();\n\n assert(\n this.hash === expectedHead,\n () =>\n `Expected head must match the main head. Got: ${this.hash}, expected: ${expectedHead}`,\n );\n\n try {\n applyDiffs(diffs, this);\n this.#releaseAggregateSources();\n this.hash = newHead;\n } catch (e) {\n this.#advanceError = e;\n this.clear();\n throw e;\n }\n }\n\n /**\n * Fork the branch and patch it up to match the desired head.\n */\n async forkToHead(\n store: LazyStore,\n desiredHead: Hash,\n readOptions?: ZeroReadOptions,\n ): Promise<IVMSourceBranch> {\n this.#throwIfInvalid();\n\n const fork = this.fork();\n\n if (fork.hash === desiredHead) {\n return fork;\n }\n\n await patchBranch(desiredHead, store, fork, readOptions);\n fork.hash = desiredHead;\n return fork;\n }\n\n /**\n * Creates a new IVMSourceBranch that is a copy of the current one.\n * This is a cheap operation since the b-trees are shared until a write is performed\n * and then only the modified nodes are copied.\n *\n * IVM branches are forked when we need to rebase mutations.\n * The mutations modify the fork rather than original branch.\n */\n fork() {\n this.#throwIfInvalid();\n\n return new IVMSourceBranch(\n this.#tables,\n this.hash,\n new Map(\n wrapIterable(this.#sources.entries()).map(([name, source]) => [\n name,\n source?.fork(),\n ]),\n ),\n // Share the optimistic-aggregate registry by reference: it is query\n // metadata, the same for the fork as for the main branch.\n this.#aggregateOptimism,\n true,\n );\n }\n}\n\nexport async function initFromStore(\n branch: IVMSourceBranch,\n hash: Hash,\n store: Store,\n) {\n branch.advance(undefined, hash, await readRowDiffs(store, hash));\n}\n\n/**\n * An `add` diff for each row at `hash` that the IVM sources hold: the table\n * rows under `e/` and the aggregate rows under `a/`, in key order.\n *\n * Nothing can render until this returns, and it reads both ranges to their\n * end, so it visits the tree rather than scanning it. See `BTreeRead.visit`.\n */\nexport async function readRowDiffs(\n store: Store,\n hash: Hash,\n): Promise<InternalDiffOperation[]> {\n const diffs: InternalDiffOperation[] = [];\n await withRead(store, async dagRead => {\n const {map} = await readFromHash(hash, dagRead, FormatVersion.Latest);\n for (const prefix of ROW_KEY_PREFIXES) {\n // Indexed and not destructured: this runs once per row, and\n // destructuring the entry measured about 15ns slower per row on Hermes.\n await map.visit(prefix, true, entry => {\n const key = entry[0];\n if (!key.startsWith(prefix)) {\n return false;\n }\n diffs.push({op: 'add', key, newValue: entry[1]});\n return true;\n });\n }\n });\n return diffs;\n}\n\nasync function patchBranch(\n desiredHead: Hash,\n store: LazyStore,\n fork: IVMSourceBranch,\n readOptions: ZeroReadOptions | undefined,\n) {\n const diffs = await computeDiffs(\n must(fork.hash),\n desiredHead,\n store,\n readOptions,\n );\n if (!diffs) {\n return;\n }\n applyDiffs(diffs, fork);\n}\n\nasync function computeDiffs(\n startHash: Hash,\n endHash: Hash,\n store: LazyStore,\n readOptions: ZeroReadOptions | undefined,\n): Promise<InternalDiff | undefined> {\n const readFn = (dagRead: Read) =>\n diff(\n startHash,\n endHash,\n dagRead,\n {\n shouldComputeDiffs: () => true,\n shouldComputeDiffsForIndex(_name) {\n return false;\n },\n },\n FormatVersion.Latest,\n );\n\n let diffs: DiffsMap;\n if (readOptions?.openLazySourceRead) {\n diffs = await using(store.read(readOptions.openLazySourceRead), readFn);\n } else if (readOptions?.openLazyRead) {\n diffs = await readFn(readOptions.openLazyRead);\n } else {\n diffs = await withRead(store, readFn);\n }\n\n return diffs.get('');\n}\n\nfunction applyDiffs(diffs: NoIndexDiff, branch: IVMSourceBranch) {\n for (const prefix of ROW_KEY_PREFIXES) {\n applyRowDiffs(diffs, prefix, branch);\n }\n}\n\n/** Applies the diffs of the rows under `prefix`, `e/` or `a/`. */\nfunction applyRowDiffs(\n diffs: NoIndexDiff,\n prefix: string,\n branch: IVMSourceBranch,\n) {\n for (\n let i = diffBinarySearch(diffs, prefix, diff => diff.key);\n i < diffs.length;\n i++\n ) {\n const diff = diffs[i];\n const {key} = diff;\n if (!key.startsWith(prefix)) {\n break;\n }\n const name = sourceNameFromKey(key);\n let source = branch.getSource(name);\n if (!source && isAggregateTableName(name)) {\n // A relationship aggregate source isn't derivable from the name, so it\n // may not exist yet when persisted rows are replayed before the query\n // re-materializes (reload). Provision it from the row's own shape; the\n // builder will reuse this same source when the query materializes.\n const row = (diff.op === 'del' ? diff.oldValue : diff.newValue) as Row;\n source = branch.getOrCreateAggregateSource(\n name,\n ...inferAggregateSchema(name, row),\n );\n }\n source = must(source);\n switch (diff.op) {\n case 'del':\n consume(source.push(makeSourceChangeRemove(diff.oldValue as Row)));\n break;\n case 'add': {\n // The source's own prefix: the key up to the slash after its name.\n const sourcePrefix = key.slice(0, key.indexOf('/', prefix.length) + 1);\n const rows = takeAddsForSource(diffs, i, sourcePrefix);\n i += rows.length - 1;\n source.pushAdds(rows);\n break;\n }\n case 'change':\n consume(\n source.push(\n makeSourceChangeEdit(diff.newValue as Row, diff.oldValue as Row),\n ),\n );\n break;\n }\n }\n}\n\n/**\n * Returns the rows of the run of `add` diffs under `prefix` (a source's key\n * prefix, e.g. `e/issue/`) that starts at `start`. Diffs are ordered by key so\n * a table's rows are contiguous.\n */\nfunction takeAddsForSource(\n diffs: NoIndexDiff,\n start: number,\n prefix: string,\n): Row[] {\n const rows: Row[] = [];\n for (let i = start; i < diffs.length; i++) {\n const diff = diffs[i];\n if (diff.op !== 'add' || !diff.key.startsWith(prefix)) {\n break;\n }\n rows.push(diff.newValue as Row);\n }\n return rows;\n}\n\n/**\n * Infers a synthetic aggregate source's schema from one of its rows: the key\n * columns are every column except the payload and the row-version, with types\n * read off the actual values. Used only on the reload path, where a\n * relationship aggregate's rows are replayed before its query (which would\n * otherwise supply the exact schema) materializes.\n */\nfunction inferAggregateSchema(\n name: string,\n row: Row,\n): [columns: Record<string, SchemaValue>, primaryKey: PrimaryKey] {\n const columns: Record<string, SchemaValue> = {};\n for (const k of Object.keys(row)) {\n if (k === ROW_VERSION_COLUMN) {\n continue;\n }\n if (AGGREGATE_PAYLOAD_COLUMNS.has(k)) {\n // The result (and, for sum/avg, its components) — numeric payload, never part of the key.\n assignProperty(columns, k, {type: 'number', optional: true});\n } else {\n assignProperty(columns, k, {type: valueTypeOf(row[k])});\n }\n }\n const keyColumns = aggregateRowKeyColumns(name, row);\n // The result column is always present even if absent from this particular row.\n if (!(AGGREGATE_VALUE_COLUMN in columns)) {\n columns[AGGREGATE_VALUE_COLUMN] = {type: 'number', optional: true};\n }\n return [columns, keyColumns as unknown as PrimaryKey];\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The longest wait before the first retry after a failed connection attempt.
|
|
3
|
+
* Each further consecutive failure doubles it, up to the run loop interval.
|
|
4
|
+
*/
|
|
5
|
+
export declare const FAST_RECONNECT_INITIAL_MS = 500;
|
|
6
|
+
/**
|
|
7
|
+
* How long a connection must stay up before a later failure starts the
|
|
8
|
+
* schedule from the beginning again. Without this, a server that accepts
|
|
9
|
+
* connections and then fails each one would keep clients on the fast end of
|
|
10
|
+
* the schedule.
|
|
11
|
+
*/
|
|
12
|
+
export declare const STABLE_CONNECTION_MS = 5000;
|
|
13
|
+
/**
|
|
14
|
+
* Whether `ex` is a failure of the transport rather than a reply from the
|
|
15
|
+
* server: the socket closed or never answered. These carry no backoff
|
|
16
|
+
* instructions, and the usual cause (a server that has just gone away, or a
|
|
17
|
+
* load balancer that has not yet stopped routing to it) clears within a few
|
|
18
|
+
* seconds, so they are retried on the fast schedule. Errors sent by the server
|
|
19
|
+
* keep their own backoff rules.
|
|
20
|
+
*/
|
|
21
|
+
export declare function isTransportFailure(ex: unknown): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* The wait before retrying after `failedAttempts` consecutive transport
|
|
24
|
+
* failures (1 for the first). The ceiling starts at
|
|
25
|
+
* {@link FAST_RECONNECT_INITIAL_MS} and doubles with each failure, and the
|
|
26
|
+
* wait is chosen between half the ceiling and the ceiling, so that clients
|
|
27
|
+
* that lost the same server don't all retry at once. Once the ceiling reaches
|
|
28
|
+
* `maxMs`, the wait is exactly `maxMs`.
|
|
29
|
+
*/
|
|
30
|
+
export declare function reconnectBackoffMs(failedAttempts: number, maxMs: number, random?: () => number): number;
|
|
31
|
+
//# sourceMappingURL=reconnect-backoff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconnect-backoff.d.ts","sourceRoot":"","sources":["../../../../../zero-client/src/client/reconnect-backoff.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAE7C;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,OAAQ,CAAC;AAE1C;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,OAAO,GAAG,OAAO,CAavD;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,cAAc,EAAE,MAAM,EACtB,KAAK,EAAE,MAAM,EACb,MAAM,GAAE,MAAM,MAAoB,GACjC,MAAM,CAMR"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { AbruptClose, CleanClose, ConnectTimeout, PingTimeout } from "./client-error-kind-enum.js";
|
|
2
|
+
import { isClientError } from "./error.js";
|
|
3
|
+
/**
|
|
4
|
+
* How long a connection must stay up before a later failure starts the
|
|
5
|
+
* schedule from the beginning again. Without this, a server that accepts
|
|
6
|
+
* connections and then fails each one would keep clients on the fast end of
|
|
7
|
+
* the schedule.
|
|
8
|
+
*/
|
|
9
|
+
var STABLE_CONNECTION_MS = 5e3;
|
|
10
|
+
/**
|
|
11
|
+
* Whether `ex` is a failure of the transport rather than a reply from the
|
|
12
|
+
* server: the socket closed or never answered. These carry no backoff
|
|
13
|
+
* instructions, and the usual cause (a server that has just gone away, or a
|
|
14
|
+
* load balancer that has not yet stopped routing to it) clears within a few
|
|
15
|
+
* seconds, so they are retried on the fast schedule. Errors sent by the server
|
|
16
|
+
* keep their own backoff rules.
|
|
17
|
+
*/
|
|
18
|
+
function isTransportFailure(ex) {
|
|
19
|
+
if (!isClientError(ex)) return false;
|
|
20
|
+
switch (ex.kind) {
|
|
21
|
+
case AbruptClose:
|
|
22
|
+
case CleanClose:
|
|
23
|
+
case ConnectTimeout:
|
|
24
|
+
case PingTimeout: return true;
|
|
25
|
+
default: return false;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* The wait before retrying after `failedAttempts` consecutive transport
|
|
30
|
+
* failures (1 for the first). The ceiling starts at
|
|
31
|
+
* {@link FAST_RECONNECT_INITIAL_MS} and doubles with each failure, and the
|
|
32
|
+
* wait is chosen between half the ceiling and the ceiling, so that clients
|
|
33
|
+
* that lost the same server don't all retry at once. Once the ceiling reaches
|
|
34
|
+
* `maxMs`, the wait is exactly `maxMs`.
|
|
35
|
+
*/
|
|
36
|
+
function reconnectBackoffMs(failedAttempts, maxMs, random = Math.random) {
|
|
37
|
+
const ceiling = 500 * 2 ** (failedAttempts - 1);
|
|
38
|
+
if (ceiling >= maxMs) return maxMs;
|
|
39
|
+
return Math.round(ceiling / 2 + random() * ceiling / 2);
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
export { STABLE_CONNECTION_MS, isTransportFailure, reconnectBackoffMs };
|
|
43
|
+
|
|
44
|
+
//# sourceMappingURL=reconnect-backoff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconnect-backoff.js","names":["ClientErrorKind.AbruptClose","ClientErrorKind.CleanClose","ClientErrorKind.ConnectTimeout","ClientErrorKind.PingTimeout"],"sources":["../../../../../zero-client/src/client/reconnect-backoff.ts"],"sourcesContent":["import {ClientErrorKind} from './client-error-kind.ts';\nimport {isClientError} from './error.ts';\n\n/**\n * The longest wait before the first retry after a failed connection attempt.\n * Each further consecutive failure doubles it, up to the run loop interval.\n */\nexport const FAST_RECONNECT_INITIAL_MS = 500;\n\n/**\n * How long a connection must stay up before a later failure starts the\n * schedule from the beginning again. Without this, a server that accepts\n * connections and then fails each one would keep clients on the fast end of\n * the schedule.\n */\nexport const STABLE_CONNECTION_MS = 5_000;\n\n/**\n * Whether `ex` is a failure of the transport rather than a reply from the\n * server: the socket closed or never answered. These carry no backoff\n * instructions, and the usual cause (a server that has just gone away, or a\n * load balancer that has not yet stopped routing to it) clears within a few\n * seconds, so they are retried on the fast schedule. Errors sent by the server\n * keep their own backoff rules.\n */\nexport function isTransportFailure(ex: unknown): boolean {\n if (!isClientError(ex)) {\n return false;\n }\n switch (ex.kind) {\n case ClientErrorKind.AbruptClose:\n case ClientErrorKind.CleanClose:\n case ClientErrorKind.ConnectTimeout:\n case ClientErrorKind.PingTimeout:\n return true;\n default:\n return false;\n }\n}\n\n/**\n * The wait before retrying after `failedAttempts` consecutive transport\n * failures (1 for the first). The ceiling starts at\n * {@link FAST_RECONNECT_INITIAL_MS} and doubles with each failure, and the\n * wait is chosen between half the ceiling and the ceiling, so that clients\n * that lost the same server don't all retry at once. Once the ceiling reaches\n * `maxMs`, the wait is exactly `maxMs`.\n */\nexport function reconnectBackoffMs(\n failedAttempts: number,\n maxMs: number,\n random: () => number = Math.random,\n): number {\n const ceiling = FAST_RECONNECT_INITIAL_MS * 2 ** (failedAttempts - 1);\n if (ceiling >= maxMs) {\n return maxMs;\n }\n return Math.round(ceiling / 2 + (random() * ceiling) / 2);\n}\n"],"mappings":";;;;;;;;AAeA,IAAa,uBAAuB;;;;;;;;;AAUpC,SAAgB,mBAAmB,IAAsB;CACvD,IAAI,CAAC,cAAc,EAAE,GACnB,OAAO;CAET,QAAQ,GAAG,MAAX;EACE,KAAKA;EACL,KAAKC;EACL,KAAKC;EACL,KAAKC,aACH,OAAO;EACT,SACE,OAAO;CACX;AACF;;;;;;;;;AAUA,SAAgB,mBACd,gBACA,OACA,SAAuB,KAAK,QACpB;CACR,MAAM,UAAA,MAAsC,MAAM,iBAAiB;CACnE,IAAI,WAAW,OACb,OAAO;CAET,OAAO,KAAK,MAAM,UAAU,IAAK,OAAO,IAAI,UAAW,CAAC;AAC1D"}
|
|
@@ -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;AAEzE,OAAO,EACL,cAAc,EAEf,MAAM,iCAAiC,CAAC;AACzC,OAAO,KAAK,EAAC,KAAK,IAAI,OAAO,EAAC,MAAM,qCAAqC,CAAC;AAK1E,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;AAInE,OAAO,EAAC,KAAK,QAAQ,EAAW,MAAM,iCAAiC,CAAC;AAGxE,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;AAajE,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;
|
|
1
|
+
{"version":3,"file":"zero.d.ts","sourceRoot":"","sources":["../../../../../zero-client/src/client/zero.ts"],"names":[],"mappings":"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"}
|
|
@@ -55,6 +55,7 @@ import { makeReplicacheMutators } from "./make-replicache-mutators.js";
|
|
|
55
55
|
import { DID_NOT_CONNECT_VALUE, MetricManager, REPORT_INTERVAL_MS, getLastConnectErrorValue, shouldReportConnectError } from "./metrics.js";
|
|
56
56
|
import { MutationTracker } from "./mutation-tracker.js";
|
|
57
57
|
import { MutatorProxy } from "./mutator-proxy.js";
|
|
58
|
+
import { isTransportFailure, reconnectBackoffMs } from "./reconnect-backoff.js";
|
|
58
59
|
import { reloadScheduled, reloadWithReason, reportReloadReason, resetBackoff } from "./reload-error-handler.js";
|
|
59
60
|
import { getServer } from "./server-option.js";
|
|
60
61
|
import { PokeHandler } from "./zero-poke-handler.js";
|
|
@@ -191,6 +192,7 @@ var Zero = class Zero {
|
|
|
191
192
|
#connectedCount = 0;
|
|
192
193
|
#messageCount = 0;
|
|
193
194
|
#connectedAt = 0;
|
|
195
|
+
#transportFailures = 0;
|
|
194
196
|
#connectErrorCount = 0;
|
|
195
197
|
#abortPingTimeout = () => {};
|
|
196
198
|
#forceEnableRefresh = false;
|
|
@@ -1041,6 +1043,7 @@ var Zero = class Zero {
|
|
|
1041
1043
|
case Error$1: break;
|
|
1042
1044
|
default: unreachable(connectionStatus);
|
|
1043
1045
|
}
|
|
1046
|
+
if (this.#connectedAt !== 0 && Date.now() - this.#connectedAt >= 5e3) this.#transportFailures = 0;
|
|
1044
1047
|
this.#socketResolver = resolver();
|
|
1045
1048
|
this.#messageCount = 0;
|
|
1046
1049
|
this.#connectStart = void 0;
|
|
@@ -1340,6 +1343,10 @@ var Zero = class Zero {
|
|
|
1340
1343
|
let sleepMs = void 0;
|
|
1341
1344
|
switch (transition.status) {
|
|
1342
1345
|
case NO_STATUS_TRANSITION: {
|
|
1346
|
+
if (isTransportFailure(transition.reason)) {
|
|
1347
|
+
this.#transportFailures++;
|
|
1348
|
+
backoffMs = reconnectBackoffMs(this.#transportFailures, RUN_LOOP_INTERVAL_MS);
|
|
1349
|
+
}
|
|
1343
1350
|
const backoffParams = getBackoffParams(transition.reason);
|
|
1344
1351
|
if (backoffParams) {
|
|
1345
1352
|
if (backoffParams.minBackoffMs !== void 0) backoffMs = Math.max(backoffMs, backoffParams.minBackoffMs);
|