@rocicorp/zero 1.12.0-canary.1 → 1.12.0-canary.3
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/zero/package.js +1 -1
- package/out/zero/package.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/client-handler.d.ts +18 -0
- package/out/zero-cache/src/services/view-syncer/client-handler.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/client-handler.js +46 -20
- package/out/zero-cache/src/services/view-syncer/client-handler.js.map +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.map +1 -1
- package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts +4 -3
- package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/snapshotter.js +5 -2
- package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
- package/out/zero-client/src/client/version.js +1 -1
- package/out/zero-protocol/src/inspect-down.d.ts +81 -81
- package/out/zero-protocol/src/poke.d.ts +6 -6
- package/out/zero-protocol/src/up.d.ts +60 -60
- package/out/zql/src/ivm/cap.js +2 -4
- package/out/zql/src/ivm/cap.js.map +1 -1
- package/out/zql/src/ivm/take.js +2 -4
- package/out/zql/src/ivm/take.js.map +1 -1
- package/out/zqlite/src/database-storage.d.ts.map +1 -1
- package/out/zqlite/src/database-storage.js +38 -6
- package/out/zqlite/src/database-storage.js.map +1 -1
- package/out/zqlite/src/fetch-sql.d.ts +27 -0
- package/out/zqlite/src/fetch-sql.d.ts.map +1 -0
- package/out/zqlite/src/fetch-sql.js +112 -0
- package/out/zqlite/src/fetch-sql.js.map +1 -0
- package/out/zqlite/src/query-builder.d.ts +11 -1
- package/out/zqlite/src/query-builder.d.ts.map +1 -1
- package/out/zqlite/src/query-builder.js +22 -7
- package/out/zqlite/src/query-builder.js.map +1 -1
- package/out/zqlite/src/table-source.d.ts +9 -2
- package/out/zqlite/src/table-source.d.ts.map +1 -1
- package/out/zqlite/src/table-source.js +11 -14
- package/out/zqlite/src/table-source.js.map +1 -1
- package/package.json +1 -1
package/out/zero/package.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
var package_default = {
|
|
2
2
|
name: "@rocicorp/zero",
|
|
3
|
-
version: "1.12.0-canary.
|
|
3
|
+
version: "1.12.0-canary.3",
|
|
4
4
|
description: "Zero is a web framework for serverless web development.",
|
|
5
5
|
homepage: "https://zero.rocicorp.dev",
|
|
6
6
|
bugs: { "url": "https://bugs.rocicorp.dev" },
|
package/out/zero/package.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"package.js","names":[],"sources":["../../package.json"],"sourcesContent":["{\n \"name\": \"@rocicorp/zero\",\n \"version\": \"1.12.0-canary.
|
|
1
|
+
{"version":3,"file":"package.js","names":[],"sources":["../../package.json"],"sourcesContent":["{\n \"name\": \"@rocicorp/zero\",\n \"version\": \"1.12.0-canary.3\",\n \"description\": \"Zero is a web framework for serverless web development.\",\n \"homepage\": \"https://zero.rocicorp.dev\",\n \"bugs\": {\n \"url\": \"https://bugs.rocicorp.dev\"\n },\n \"license\": \"Apache-2.0\",\n \"author\": \"Rocicorp, Inc.\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/rocicorp/mono.git\",\n \"directory\": \"packages/zero\"\n },\n \"bin\": {\n \"analyze-query\": \"./out/zero/src/analyze-query.js\",\n \"ast-to-zql\": \"./out/zero/src/ast-to-zql.js\",\n \"transform-query\": \"./out/zero/src/transform-query.js\",\n \"zero-build-schema\": \"./out/zero/src/build-schema.js\",\n \"zero-cache\": \"./out/zero/src/cli.js\",\n \"zero-cache-dev\": \"./out/zero/src/zero-cache-dev.js\",\n \"zero-deploy-permissions\": \"./out/zero/src/deploy-permissions.js\",\n \"zero-out\": \"./out/zero/src/zero-out.js\"\n },\n \"files\": [\n \"out\",\n \"!*.tsbuildinfo\"\n ],\n \"type\": \"module\",\n \"main\": \"out/zero/src/zero.js\",\n \"module\": \"out/zero/src/zero.js\",\n \"types\": \"out/zero/src/zero.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./out/zero/src/zero.d.ts\",\n \"default\": \"./out/zero/src/zero.js\"\n },\n \"./analyze\": {\n \"types\": \"./out/zero/src/analyze.d.ts\",\n \"default\": \"./out/zero/src/analyze.js\"\n },\n \"./bindings\": {\n \"types\": \"./out/zero/src/bindings.d.ts\",\n \"default\": \"./out/zero/src/bindings.js\"\n },\n \"./change-protocol/v0\": {\n \"types\": \"./out/zero/src/change-protocol/v0.d.ts\",\n \"default\": \"./out/zero/src/change-protocol/v0.js\"\n },\n \"./expo-sqlite\": {\n \"types\": \"./out/zero/src/expo-sqlite.d.ts\",\n \"default\": \"./out/zero/src/expo-sqlite.js\"\n },\n \"./op-sqlite\": {\n \"types\": \"./out/zero/src/op-sqlite.d.ts\",\n \"default\": \"./out/zero/src/op-sqlite.js\"\n },\n \"./pg\": {\n \"types\": \"./out/zero/src/pg.d.ts\",\n \"default\": \"./out/zero/src/pg.js\"\n },\n \"./react\": {\n \"types\": \"./out/zero/src/react.d.ts\",\n \"default\": \"./out/zero/src/react.js\"\n },\n \"./react-native\": {\n \"types\": \"./out/zero/src/react-native.d.ts\",\n \"default\": \"./out/zero/src/react-native.js\"\n },\n \"./server\": {\n \"types\": \"./out/zero/src/server.d.ts\",\n \"default\": \"./out/zero/src/server.js\"\n },\n \"./server/adapters/drizzle\": {\n \"types\": \"./out/zero/src/adapters/drizzle.d.ts\",\n \"default\": \"./out/zero/src/adapters/drizzle.js\"\n },\n \"./server/adapters/kysely\": {\n \"types\": \"./out/zero/src/adapters/kysely.d.ts\",\n \"default\": \"./out/zero/src/adapters/kysely.js\"\n },\n \"./server/adapters/prisma\": {\n \"types\": \"./out/zero/src/adapters/prisma.d.ts\",\n \"default\": \"./out/zero/src/adapters/prisma.js\"\n },\n \"./server/adapters/pg\": {\n \"types\": \"./out/zero/src/adapters/pg.d.ts\",\n \"default\": \"./out/zero/src/adapters/pg.js\"\n },\n \"./server/adapters/postgresjs\": {\n \"types\": \"./out/zero/src/adapters/postgresjs.d.ts\",\n \"default\": \"./out/zero/src/adapters/postgresjs.js\"\n },\n \"./solid\": {\n \"types\": \"./out/zero/src/solid.d.ts\",\n \"default\": \"./out/zero/src/solid.js\"\n },\n \"./sqlite\": {\n \"types\": \"./out/zero/src/sqlite.d.ts\",\n \"default\": \"./out/zero/src/sqlite.js\"\n },\n \"./zqlite\": {\n \"types\": \"./out/zero/src/zqlite.d.ts\",\n \"default\": \"./out/zero/src/zqlite.js\"\n }\n },\n \"scripts\": {\n \"build\": \"node --experimental-strip-types --no-warnings tool/build.ts\",\n \"build:watch\": \"node --experimental-strip-types --no-warnings tool/build.ts --watch\",\n \"check-types\": \"tsc -p tsconfig.client.json && tsc -p tsconfig.server.json\",\n \"check-types:client:watch\": \"tsc -p tsconfig.client.json --watch\",\n \"check-types:server:watch\": \"tsc -p tsconfig.server.json --watch\",\n \"format\": \"oxfmt .\",\n \"check-format\": \"oxfmt --check .\",\n \"lint\": \"oxlint --quiet --config ../../oxlint.config.ts src/\",\n \"docs\": \"node --experimental-strip-types --no-warnings tool/generate-docs.ts\",\n \"docs:server\": \"node --watch --experimental-strip-types --no-warnings tool/generate-docs.ts --server\",\n \"fmt\": \"oxfmt .\",\n \"check-fmt\": \"oxfmt --check .\"\n },\n \"dependencies\": {\n \"@badrap/valita\": \"0.5.5\",\n \"@databases/escape-identifier\": \"^1.0.3\",\n \"@databases/sql\": \"^3.3.0\",\n \"@dotenvx/dotenvx\": \"^1.39.0\",\n \"@drdgvhbh/postgres-error-codes\": \"^0.0.6\",\n \"@fastify/cors\": \"^10.0.0\",\n \"@fastify/websocket\": \"^11.0.0\",\n \"@google-cloud/precise-date\": \"^4.0.0\",\n \"@opentelemetry/api\": \"^1.9.0\",\n \"@opentelemetry/api-logs\": \"^0.218.0\",\n \"@opentelemetry/auto-instrumentations-node\": \"^0.76.0\",\n \"@opentelemetry/exporter-metrics-otlp-http\": \"^0.218.0\",\n \"@opentelemetry/resources\": \"^2.7.1\",\n \"@opentelemetry/sdk-metrics\": \"^2.7.1\",\n \"@opentelemetry/sdk-node\": \"^0.218.0\",\n \"@opentelemetry/sdk-trace-node\": \"^2.7.1\",\n \"@opentelemetry/semantic-conventions\": \"^1.41.1\",\n \"@postgresql-typed/oids\": \"^0.2.0\",\n \"@rocicorp/lock\": \"^1.0.4\",\n \"@rocicorp/logger\": \"^6.1.0\",\n \"@rocicorp/resolver\": \"^1.0.2\",\n \"@rocicorp/zero-sqlite3\": \"^1.1.5\",\n \"@standard-schema/spec\": \"^1.0.0\",\n \"@types/basic-auth\": \"^1.1.8\",\n \"@types/ws\": \"^8.5.12\",\n \"basic-auth\": \"^2.0.1\",\n \"chalk-template\": \"^1.1.0\",\n \"chokidar\": \"^4.0.1\",\n \"cloudevents\": \"^10.0.0\",\n \"command-line-args\": \"^6.0.1\",\n \"command-line-usage\": \"^7.0.3\",\n \"compare-utf8\": \"^0.2.3\",\n \"defu\": \"^6.1.4\",\n \"eventemitter3\": \"^5.0.1\",\n \"fastify\": \"^5.0.0\",\n \"is-in-subnet\": \"^4.0.1\",\n \"jose\": \"^5.9.3\",\n \"json-custom-numbers\": \"^3.1.1\",\n \"kasi\": \"^1.1.0\",\n \"nanoid\": \"^5.1.2\",\n \"oxfmt\": \"^0.65.0\",\n \"parse-prometheus-text-format\": \"^1.1.1\",\n \"pg-format\": \"npm:pg-format-fix@^1.0.5\",\n \"postgres\": \"3.4.7\",\n \"semver\": \"^7.5.4\",\n \"url-pattern\": \"^1.0.3\",\n \"urlpattern-polyfill\": \"^10.1.0\",\n \"ws\": \"^8.18.1\"\n },\n \"devDependencies\": {\n \"@op-engineering/op-sqlite\": \">=15\",\n \"analyze-query\": \"workspace:*\",\n \"ast-to-zql\": \"workspace:*\",\n \"expo-sqlite\": \">=15\",\n \"oxc-parser\": \"^0.129.0\",\n \"replicache\": \"workspace:*\",\n \"shared\": \"workspace:*\",\n \"syncpack\": \"^14.3.0\",\n \"typedoc\": \"^0.28.17\",\n \"typescript\": \"~7.0.2\",\n \"vite\": \"^8.0.13\",\n \"vitest\": \"^5.0.0\",\n \"zero-cache\": \"workspace:*\",\n \"zero-client\": \"workspace:*\",\n \"zero-pg\": \"workspace:*\",\n \"zero-react\": \"workspace:*\",\n \"zero-server\": \"workspace:*\",\n \"zero-solid\": \"workspace:*\",\n \"zqlite\": \"workspace:*\"\n },\n \"engines\": {\n \"node\": \">=22\"\n },\n \"packageManager\": \"pnpm@11.11.0\"\n}\n"],"mappings":""}
|
|
@@ -4,6 +4,7 @@ import { type JSONObject as SafeJSONObject } from '../../../../shared/src/json.t
|
|
|
4
4
|
import type { ErroredQuery } from '../../../../zero-protocol/src/custom-queries.ts';
|
|
5
5
|
import { type TransformFailedBody } from '../../../../zero-protocol/src/error.ts';
|
|
6
6
|
import type { InspectDownBody } from '../../../../zero-protocol/src/inspect-down.ts';
|
|
7
|
+
import type { RowPatchOp } from '../../../../zero-protocol/src/row-patch.ts';
|
|
7
8
|
import type { ViewSyncerDownstream } from '../../types/downstream.ts';
|
|
8
9
|
import { type ShardID } from '../../types/shards.ts';
|
|
9
10
|
import type { Subscription } from '../../types/subscription.ts';
|
|
@@ -31,8 +32,24 @@ export interface PokeHandler {
|
|
|
31
32
|
cancel(): Promise<void>;
|
|
32
33
|
end(finalVersion: CVRVersion): Promise<void>;
|
|
33
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* A put/del row patch and its JSON serialization. Computed once per client
|
|
37
|
+
* group and shared by all of the group's clients.
|
|
38
|
+
*/
|
|
39
|
+
type SerializedRowPatch = {
|
|
40
|
+
readonly rowPatch: RowPatchOp;
|
|
41
|
+
readonly json: string;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Lazily holds the {@link SerializedRowPatch} of one patch so that it is
|
|
45
|
+
* computed at most once, by the first client that needs it.
|
|
46
|
+
*/
|
|
47
|
+
type SharedRowPatch = {
|
|
48
|
+
serialized?: SerializedRowPatch | undefined;
|
|
49
|
+
};
|
|
34
50
|
/** A {@link PokeHandler} for a single client. */
|
|
35
51
|
export interface ClientPokeHandler extends PokeHandler {
|
|
52
|
+
addPatch(patch: PatchToVersion, shared?: SharedRowPatch): Promise<void>;
|
|
36
53
|
/**
|
|
37
54
|
* Whether a patch has been sent to the client. Once one has, the poke can
|
|
38
55
|
* only be ended with a `finalVersion` that is ahead of the client's base
|
|
@@ -76,4 +93,5 @@ export declare class ClientHandler {
|
|
|
76
93
|
* result in an Error.
|
|
77
94
|
*/
|
|
78
95
|
export declare function ensureSafeJSON(row: JSONObject): SafeJSONObject;
|
|
96
|
+
export {};
|
|
79
97
|
//# sourceMappingURL=client-handler.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client-handler.d.ts","sourceRoot":"","sources":["../../../../../../zero-cache/src/services/view-syncer/client-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAEjD,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,uCAAuC,CAAC;
|
|
1
|
+
{"version":3,"file":"client-handler.d.ts","sourceRoot":"","sources":["../../../../../../zero-cache/src/services/view-syncer/client-handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { assert, unreachable } from "../../../../shared/src/asserts.js";
|
|
2
|
+
import { hasOwn } from "../../../../shared/src/has-own.js";
|
|
2
3
|
import { assertJSONValue } from "../../../../shared/src/json.js";
|
|
3
4
|
import { promiseVoid } from "../../../../shared/src/resolved-promises.js";
|
|
4
5
|
import { parse, valita_exports } from "../../../../shared/src/valita.js";
|
|
5
|
-
import { rowSchema } from "../../../../zero-protocol/src/data.js";
|
|
6
6
|
import { ProtocolError } from "../../../../zero-protocol/src/error.js";
|
|
7
7
|
import { primaryKeyValueRecordSchema } from "../../../../zero-protocol/src/primary-key.js";
|
|
8
8
|
import { mutationResultSchema } from "../../../../zero-protocol/src/mutation.js";
|
|
@@ -27,7 +27,10 @@ function startPoke(lc, clients, tentativeVersion) {
|
|
|
27
27
|
get patchesSent() {
|
|
28
28
|
return pokers.some((poker) => poker.patchesSent);
|
|
29
29
|
},
|
|
30
|
-
addPatch: (patch) =>
|
|
30
|
+
addPatch: (patch) => {
|
|
31
|
+
const shared = {};
|
|
32
|
+
return settle("addPatch", pokers.map((poker) => poker.addPatch(patch, shared)));
|
|
33
|
+
},
|
|
31
34
|
cancel: () => settle("cancel", pokers.map((poker) => poker.cancel())),
|
|
32
35
|
end: (finalVersion) => settle("end", pokers.map((poker) => poker.end(finalVersion)))
|
|
33
36
|
};
|
|
@@ -97,6 +100,8 @@ var ClientHandler = class {
|
|
|
97
100
|
};
|
|
98
101
|
let pokeStarted = false;
|
|
99
102
|
let body;
|
|
103
|
+
let rowsPatch = [];
|
|
104
|
+
let rowsJSON = [];
|
|
100
105
|
let partCount = 0;
|
|
101
106
|
let serializedRowsLength = 0;
|
|
102
107
|
const ensureBody = async () => {
|
|
@@ -108,14 +113,28 @@ var ClientHandler = class {
|
|
|
108
113
|
};
|
|
109
114
|
const flushBody = async () => {
|
|
110
115
|
if (body) {
|
|
111
|
-
|
|
112
|
-
|
|
116
|
+
let message;
|
|
117
|
+
let serialized;
|
|
118
|
+
if (rowsPatch.length === 0) {
|
|
119
|
+
message = ["pokePart", body];
|
|
120
|
+
serialized = JSON.stringify(message);
|
|
121
|
+
} else {
|
|
122
|
+
const prefix = JSON.stringify(["pokePart", body]);
|
|
123
|
+
message = ["pokePart", {
|
|
124
|
+
...body,
|
|
125
|
+
rowsPatch
|
|
126
|
+
}];
|
|
127
|
+
serialized = `${prefix.slice(0, -2)},"rowsPatch":[${rowsJSON.join(",")}]}]`;
|
|
128
|
+
rowsPatch = [];
|
|
129
|
+
rowsJSON = [];
|
|
130
|
+
}
|
|
131
|
+
await this.#push(message, serialized);
|
|
113
132
|
body = void 0;
|
|
114
133
|
partCount = 0;
|
|
115
134
|
serializedRowsLength = 0;
|
|
116
135
|
}
|
|
117
136
|
};
|
|
118
|
-
const addPatch = async (patchToVersion) => {
|
|
137
|
+
const addPatch = async (patchToVersion, shared) => {
|
|
119
138
|
const { patch, toVersion } = patchToVersion;
|
|
120
139
|
if (cmpVersions(toVersion, this.#baseVersion) <= 0) return;
|
|
121
140
|
const target = await ensureBody();
|
|
@@ -157,9 +176,10 @@ var ClientHandler = class {
|
|
|
157
176
|
});
|
|
158
177
|
}
|
|
159
178
|
} else {
|
|
160
|
-
const rowPatch =
|
|
161
|
-
|
|
162
|
-
|
|
179
|
+
const { rowPatch, json } = shared.serialized ??= serializeRowPatch(patch);
|
|
180
|
+
rowsPatch.push(rowPatch);
|
|
181
|
+
rowsJSON.push(json);
|
|
182
|
+
serializedRowsLength += json.length;
|
|
163
183
|
}
|
|
164
184
|
break;
|
|
165
185
|
default: unreachable(patch);
|
|
@@ -171,9 +191,9 @@ var ClientHandler = class {
|
|
|
171
191
|
get patchesSent() {
|
|
172
192
|
return pokeStarted;
|
|
173
193
|
},
|
|
174
|
-
addPatch: async (patchToVersion) => {
|
|
194
|
+
addPatch: async (patchToVersion, shared = {}) => {
|
|
175
195
|
try {
|
|
176
|
-
await addPatch(patchToVersion);
|
|
196
|
+
await addPatch(patchToVersion, shared);
|
|
177
197
|
if (patchToVersion.patch.type === "row") this.#pokedRows.add(1);
|
|
178
198
|
} catch (e) {
|
|
179
199
|
this.fail(e);
|
|
@@ -252,13 +272,20 @@ var mutationRowSchema = valita_exports.object({
|
|
|
252
272
|
mutationID: valita_exports.number(),
|
|
253
273
|
result: mutationResultSchema
|
|
254
274
|
});
|
|
275
|
+
function serializeRowPatch(patch) {
|
|
276
|
+
const rowPatch = makeRowPatch(patch);
|
|
277
|
+
return {
|
|
278
|
+
rowPatch,
|
|
279
|
+
json: JSON.stringify(rowPatch)
|
|
280
|
+
};
|
|
281
|
+
}
|
|
255
282
|
function makeRowPatch(patch) {
|
|
256
283
|
const { op, id: { table: tableName, rowKey: id } } = patch;
|
|
257
284
|
switch (op) {
|
|
258
285
|
case "put": return {
|
|
259
286
|
op: "put",
|
|
260
287
|
tableName,
|
|
261
|
-
value:
|
|
288
|
+
value: ensureSafeJSON(patch.contents)
|
|
262
289
|
};
|
|
263
290
|
case "del": return {
|
|
264
291
|
op,
|
|
@@ -276,17 +303,16 @@ function makeRowPatch(patch) {
|
|
|
276
303
|
* result in an Error.
|
|
277
304
|
*/
|
|
278
305
|
function ensureSafeJSON(row) {
|
|
279
|
-
|
|
306
|
+
let modified;
|
|
307
|
+
for (const k in row) {
|
|
308
|
+
if (!hasOwn(row, k)) continue;
|
|
309
|
+
const v = row[k];
|
|
280
310
|
if (typeof v === "bigint") {
|
|
281
|
-
if (v
|
|
282
|
-
|
|
311
|
+
if (v < Number.MIN_SAFE_INTEGER || v > Number.MAX_SAFE_INTEGER) throw new Error(`Value of "${k}" exceeds safe Number range (${v})`);
|
|
312
|
+
(modified ??= { ...row })[k] = Number(v);
|
|
283
313
|
} else if (typeof v === "object") assertJSONValue(v);
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
return modified.length ? {
|
|
287
|
-
...row,
|
|
288
|
-
...Object.fromEntries(modified)
|
|
289
|
-
} : row;
|
|
314
|
+
}
|
|
315
|
+
return modified ?? row;
|
|
290
316
|
}
|
|
291
317
|
//#endregion
|
|
292
318
|
export { ClientHandler, startPoke };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client-handler.js","names":["#clientGroupID","#zeroClientsTable","#zeroMutationsTable","#lc","#downstream","#pokeTime","#pokeTransactions","#pokedRows","#baseVersion","#push","#everPoked","#updateLMIDs"],"sources":["../../../../../../zero-cache/src/services/view-syncer/client-handler.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {assert, unreachable} from '../../../../shared/src/asserts.ts';\nimport type {JSONObject} from '../../../../shared/src/bigint-json.ts';\nimport {\n assertJSONValue,\n type JSONObject as SafeJSONObject,\n} from '../../../../shared/src/json.ts';\nimport {promiseVoid} from '../../../../shared/src/resolved-promises.ts';\nimport * as v from '../../../../shared/src/valita.ts';\nimport type {Writable} from '../../../../shared/src/writable.ts';\nimport type {ErroredQuery} from '../../../../zero-protocol/src/custom-queries.ts';\nimport {rowSchema} from '../../../../zero-protocol/src/data.ts';\nimport type {DeleteClientsBody} from '../../../../zero-protocol/src/delete-clients.ts';\nimport type {Downstream} from '../../../../zero-protocol/src/down.ts';\nimport {\n ProtocolError,\n type TransformFailedBody,\n} from '../../../../zero-protocol/src/error.ts';\nimport type {InspectDownBody} from '../../../../zero-protocol/src/inspect-down.ts';\nimport {mutationResultSchema} from '../../../../zero-protocol/src/mutation.ts';\nimport type {\n PokePartBody,\n PokePartMessage,\n PokeStartBody,\n} from '../../../../zero-protocol/src/poke.ts';\nimport {primaryKeyValueRecordSchema} from '../../../../zero-protocol/src/primary-key.ts';\nimport type {RowPatchOp} from '../../../../zero-protocol/src/row-patch.ts';\nimport {\n getOrCreateCounter,\n getOrCreateLatencyHistogram,\n} from '../../observability/metrics.ts';\nimport type {ViewSyncerDownstream} from '../../types/downstream.ts';\nimport {\n getLogLevel,\n wrapWithProtocolError,\n} from '../../types/error-with-level.ts';\nimport {upstreamSchema, type ShardID} from '../../types/shards.ts';\nimport type {Subscription} from '../../types/subscription.ts';\nimport {\n cmpVersions,\n cookieToVersion,\n versionToCookie,\n versionToNullableCookie,\n type CVRVersion,\n type DelQueryPatch,\n type NullableCVRVersion,\n type PutQueryPatch,\n type RowID,\n} from './schema/types.ts';\n\nexport type PutRowPatch = {\n type: 'row';\n op: 'put';\n id: RowID;\n contents: JSONObject;\n};\n\nexport type DeleteRowPatch = {\n type: 'row';\n op: 'del';\n id: RowID;\n};\n\nexport type RowPatch = PutRowPatch | DeleteRowPatch;\nexport type ConfigPatch = DelQueryPatch | PutQueryPatch;\n\nexport type Patch = ConfigPatch | RowPatch;\n\nexport type PatchToVersion = {\n patch: Patch;\n toVersion: CVRVersion;\n};\n\nexport interface PokeHandler {\n addPatch(patch: PatchToVersion): Promise<void>;\n cancel(): Promise<void>;\n end(finalVersion: CVRVersion): Promise<void>;\n}\n\n/** A {@link PokeHandler} for a single client. */\nexport interface ClientPokeHandler extends PokeHandler {\n /**\n * Whether a patch has been sent to the client. Once one has, the poke can\n * only be ended with a `finalVersion` that is ahead of the client's base\n * version.\n */\n readonly patchesSent: boolean;\n}\n\n/**\n * A {@link PokeHandler} for multiple clients, as returned by\n * {@link startPoke}.\n */\nexport interface MultiPokeHandler extends PokeHandler {\n /** Whether a patch has been sent to any of the clients. */\n readonly patchesSent: boolean;\n}\n\nconst NOOP: ClientPokeHandler = {\n patchesSent: false,\n addPatch: () => promiseVoid,\n cancel: () => promiseVoid,\n end: () => promiseVoid,\n};\n\n/** Wraps PokeHandlers for multiple clients in a single PokeHandler. */\nexport function startPoke(\n lc: LogContext,\n clients: ClientHandler[],\n tentativeVersion: CVRVersion,\n): MultiPokeHandler {\n const pokers = clients.map(c => c.startPoke(tentativeVersion));\n\n // Promise.allSettled() ensures that a failed (e.g. disconnected) client\n // does not prevent other clients from receiving the pokes. However, the\n // rate (per client group) will be limited by the slowest connection.\n //\n // The individual pokers report their own failures (by failing the\n // connection), so a rejection here is not expected. Log it rather than\n // dropping it on the floor.\n const settle = async (op: string, results: Promise<void>[]) => {\n for (const result of await Promise.allSettled(results)) {\n if (result.status === 'rejected') {\n lc.error?.(`unhandled error poking client (${op})`, result.reason);\n }\n }\n };\n\n return {\n get patchesSent() {\n return pokers.some(poker => poker.patchesSent);\n },\n addPatch: patch =>\n settle(\n 'addPatch',\n pokers.map(poker => poker.addPatch(patch)),\n ),\n cancel: () =>\n settle(\n 'cancel',\n pokers.map(poker => poker.cancel()),\n ),\n end: finalVersion =>\n settle(\n 'end',\n pokers.map(poker => poker.end(finalVersion)),\n ),\n };\n}\n\n// Soft limit on the serialized row characters accumulated in a poke part.\n// This bounds view-syncer memory and keeps legacy JSON messages reasonably\n// sized. PokeChunkEncoder separately enforces the binary frame limit in bytes.\nexport const POKE_PART_FLUSH_THRESHOLD_CHARS = 1024 * 1024;\nconst PART_COUNT_FLUSH_THRESHOLD = 100;\n\n/**\n * Handles a single `ViewSyncer` connection.\n */\nexport class ClientHandler {\n readonly #clientGroupID: string;\n readonly clientID: string;\n readonly wsID: string;\n readonly #zeroClientsTable: string;\n readonly #zeroMutationsTable: string;\n readonly #lc: LogContext;\n readonly #downstream: Subscription<ViewSyncerDownstream>;\n #baseVersion: NullableCVRVersion;\n // We will send a poke on connect even if the client is already caught up, so that it can learn its\n // got-queries state has been reconciled with the server. After that, we will only send a poke if\n // the client is behind.\n #everPoked = false;\n\n readonly #pokeTime = getOrCreateLatencyHistogram(\n 'sync',\n 'poke.time',\n 'Time elapsed for each poke transaction. Canceled / noop pokes are excluded.',\n );\n\n readonly #pokeTransactions = getOrCreateCounter(\n 'sync',\n 'poke.transactions',\n 'Count of poke transactions.',\n );\n\n readonly #pokedRows = getOrCreateCounter(\n 'sync',\n 'poke.rows',\n 'Count of poked rows.',\n );\n\n constructor(\n lc: LogContext,\n clientGroupID: string,\n clientID: string,\n wsID: string,\n shard: ShardID,\n baseCookie: string | null,\n downstream: Subscription<ViewSyncerDownstream>,\n ) {\n lc.debug?.('new client handler');\n this.#clientGroupID = clientGroupID;\n this.clientID = clientID;\n this.wsID = wsID;\n this.#zeroClientsTable = `${upstreamSchema(shard)}.clients`;\n this.#zeroMutationsTable = `${upstreamSchema(shard)}.mutations`;\n this.#lc = lc;\n this.#downstream = downstream;\n this.#baseVersion = cookieToVersion(baseCookie);\n }\n\n version(): NullableCVRVersion {\n return this.#baseVersion;\n }\n\n async #push(msg: Downstream, serialized?: string | undefined): Promise<void> {\n const {result} = this.#downstream.push({message: msg, serialized});\n await result;\n }\n\n fail(e: unknown) {\n this.#lc[getLogLevel(e)]?.(\n `view-syncer closing connection with error: ${String(e)}`,\n e,\n );\n this.#downstream.fail(wrapWithProtocolError(e));\n }\n\n close(reason: string) {\n this.#lc.debug?.(`view-syncer closing connection: ${reason}`);\n this.#downstream.cancel();\n }\n\n startPoke(tentativeVersion: CVRVersion): ClientPokeHandler {\n const pokeID = versionToCookie(tentativeVersion);\n const lc = this.#lc.withContext('pokeID', pokeID);\n\n // Force an (empty) initial poke even when already caught up; see #everPoked.\n const forceInitialPoke = !this.#everPoked;\n const cmp = cmpVersions(this.#baseVersion, tentativeVersion);\n if (cmp > 0 || (cmp === 0 && !forceInitialPoke)) {\n lc.info?.(`already caught up, not sending poke.`);\n return NOOP;\n }\n\n const baseCookie = versionToNullableCookie(this.#baseVersion);\n const cookie = versionToCookie(tentativeVersion);\n lc.debug?.(`starting poke from ${baseCookie} to ${cookie}`);\n\n const start = performance.now();\n\n const pokeStart: PokeStartBody = {pokeID, baseCookie};\n\n let pokeStarted = false;\n let body: PokePartBody | undefined;\n let partCount = 0;\n let serializedRowsLength = 0;\n\n const ensureBody = async () => {\n if (!pokeStarted) {\n await this.#push(['pokeStart', pokeStart]);\n pokeStarted = true;\n }\n return (body ??= {pokeID});\n };\n\n const flushBody = async () => {\n if (body) {\n const message = ['pokePart', body] satisfies PokePartMessage;\n await this.#push(message, JSON.stringify(message));\n body = undefined;\n partCount = 0;\n serializedRowsLength = 0;\n }\n };\n\n const addPatch = async (patchToVersion: PatchToVersion) => {\n const {patch, toVersion} = patchToVersion;\n if (cmpVersions(toVersion, this.#baseVersion) <= 0) {\n return;\n }\n const target = await ensureBody();\n\n const {type, op} = patch;\n switch (type) {\n case 'query': {\n const patches = patch.clientID\n ? ((target.desiredQueriesPatches ??= {})[patch.clientID] ??= [])\n : (target.gotQueriesPatch ??= []);\n patches.push({op, hash: patch.id});\n break;\n }\n case 'row':\n if (patch.id.table === this.#zeroClientsTable) {\n this.#updateLMIDs((target.lastMutationIDChanges ??= {}), patch);\n } else if (patch.id.table === this.#zeroMutationsTable) {\n const patches = (target.mutationsPatch ??= []);\n if (op === 'put') {\n const row = v.parse(\n ensureSafeJSON(patch.contents),\n mutationRowSchema,\n 'passthrough',\n );\n patches.push({\n op: 'put',\n mutation: {\n id: {\n clientID: row.clientID,\n id: row.mutationID,\n },\n result: row.result,\n },\n });\n } else {\n const {clientID, mutationID} = patch.id.rowKey;\n assert(\n typeof clientID === 'string',\n 'client id must be a string',\n );\n const id = Number(mutationID);\n assert(\n !Number.isNaN(id) && Number.isFinite(id) && id >= 0,\n 'mutation id must be a finite number',\n );\n patches.push({\n op: 'del',\n id: {\n clientID,\n id,\n },\n });\n }\n } else {\n const rowPatch = makeRowPatch(patch);\n (target.rowsPatch ??= []).push(rowPatch);\n serializedRowsLength += JSON.stringify(rowPatch).length;\n }\n break;\n default:\n unreachable(patch);\n }\n\n partCount++;\n if (\n serializedRowsLength >= POKE_PART_FLUSH_THRESHOLD_CHARS ||\n partCount >= PART_COUNT_FLUSH_THRESHOLD\n ) {\n await flushBody();\n }\n };\n\n // A poke that was started must always be ended. If it isn't, the\n // connection is left mid-poke and the *next* pokeStart fails the\n // DownstreamSender's in-progress check, surfacing the error far from\n // its cause. Fail the connection instead; the client reconnects and\n // resyncs from its baseVersion.\n return {\n get patchesSent() {\n return pokeStarted;\n },\n addPatch: async (patchToVersion: PatchToVersion) => {\n try {\n await addPatch(patchToVersion);\n if (patchToVersion.patch.type === 'row') {\n this.#pokedRows.add(1);\n }\n } catch (e) {\n this.fail(e);\n }\n },\n\n cancel: async () => {\n try {\n if (pokeStarted) {\n await this.#push(['pokeEnd', {pokeID, cookie: '', cancel: true}]);\n }\n } catch (e) {\n this.fail(e);\n }\n },\n\n end: async (finalVersion: CVRVersion) => {\n try {\n const cookie = versionToCookie(finalVersion);\n if (!pokeStarted) {\n if (\n cmpVersions(this.#baseVersion, finalVersion) === 0 &&\n !forceInitialPoke\n ) {\n return; // Nothing changed and nothing was sent.\n }\n await this.#push(['pokeStart', pokeStart]);\n } else if (cmpVersions(this.#baseVersion, finalVersion) >= 0) {\n // Sanity check: If the poke was started, the finalVersion\n // must be > #baseVersion.\n throw new Error(\n `Patches were sent but finalVersion ${cookie} is not ` +\n `greater than baseVersion ` +\n `${versionToNullableCookie(this.#baseVersion)}`,\n );\n }\n await flushBody();\n await this.#push(['pokeEnd', {pokeID, cookie}]);\n this.#baseVersion = finalVersion;\n this.#everPoked = true;\n\n const elapsed = performance.now() - start;\n this.#pokeTransactions.add(1);\n this.#pokeTime.recordMs(elapsed);\n } catch (e) {\n this.fail(e);\n }\n },\n };\n }\n\n async sendDeleteClients(\n lc: LogContext,\n deletedClientIDs: string[],\n deletedClientGroupIDs: string[],\n ) {\n const deleteClientsBody: Writable<DeleteClientsBody> = {};\n if (deletedClientIDs.length > 0) {\n deleteClientsBody.clientIDs = deletedClientIDs;\n }\n if (deletedClientGroupIDs.length > 0) {\n deleteClientsBody.clientGroupIDs = deletedClientGroupIDs;\n }\n lc.debug?.('sending deleteClients', deleteClientsBody);\n await this.#push(['deleteClients', deleteClientsBody]);\n }\n\n sendQueryTransformApplicationErrors(errors: ErroredQuery[]) {\n void this.#push(['transformError', errors]);\n }\n\n sendQueryTransformFailedError(error: TransformFailedBody) {\n this.fail(new ProtocolError(error));\n }\n\n sendInspectResponse(lc: LogContext, response: InspectDownBody): void {\n lc.debug?.('sending inspect response', response);\n this.#downstream.push({\n message: ['inspect', response],\n serialized: undefined,\n });\n }\n\n #updateLMIDs(lmids: Record<string, number>, patch: RowPatch) {\n if (patch.op === 'put') {\n const row = ensureSafeJSON(patch.contents);\n const {clientGroupID, clientID, lastMutationID} = v.parse(\n row,\n lmidRowSchema,\n 'passthrough',\n );\n if (clientGroupID !== this.#clientGroupID) {\n this.#lc.error?.(\n `Received clients row for wrong clientGroupID. Ignoring.`,\n clientGroupID,\n );\n } else {\n lmids[clientID] = lastMutationID;\n }\n } else {\n // The 'constrain' and 'del' ops for clients can be ignored.\n patch.op satisfies 'constrain' | 'del';\n }\n }\n}\n\n// Note: The {APP_ID}_{SHARD_ID}.clients table is set up in replicator/initial-sync.ts.\nconst lmidRowSchema = v.object({\n clientGroupID: v.string(),\n clientID: v.string(),\n lastMutationID: v.number(), // Actually returned as a bigint, but converted by ensureSafeJSON().\n});\n\nconst mutationRowSchema = v.object({\n clientGroupID: v.string(),\n clientID: v.string(),\n mutationID: v.number(),\n result: mutationResultSchema,\n});\n\nfunction makeRowPatch(patch: RowPatch): RowPatchOp {\n const {\n op,\n id: {table: tableName, rowKey: id},\n } = patch;\n\n switch (op) {\n case 'put':\n return {\n op: 'put',\n tableName,\n value: v.parse(ensureSafeJSON(patch.contents), rowSchema),\n };\n\n case 'del':\n return {\n op,\n tableName,\n id: v.parse(id, primaryKeyValueRecordSchema),\n };\n\n default:\n unreachable(op);\n }\n}\n\n/**\n * Column values of type INT8 are returned as the `bigint` from the\n * Postgres library. These are converted to `number` if they are within\n * the safe Number range, allowing the protocol to support numbers larger\n * than 32-bits. Values outside of the safe number range (e.g. > 2^53) will\n * result in an Error.\n */\nexport function ensureSafeJSON(row: JSONObject): SafeJSONObject {\n const modified = Object.entries(row)\n .filter(([k, v]) => {\n if (typeof v === 'bigint') {\n if (v >= Number.MIN_SAFE_INTEGER && v <= Number.MAX_SAFE_INTEGER) {\n return true; // send this entry onto the next map() step.\n }\n throw new Error(`Value of \"${k}\" exceeds safe Number range (${v})`);\n } else if (typeof v === 'object') {\n assertJSONValue(v);\n }\n return false;\n })\n .map(([k, v]) => [k, Number(v)]);\n\n return modified.length\n ? {...row, ...Object.fromEntries(modified)}\n : (row as SafeJSONObject);\n}\n"],"mappings":";;;;;;;;;;;;;AAkGA,IAAM,OAA0B;CAC9B,aAAa;CACb,gBAAgB;CAChB,cAAc;CACd,WAAW;AACb;;AAGA,SAAgB,UACd,IACA,SACA,kBACkB;CAClB,MAAM,SAAS,QAAQ,KAAI,MAAK,EAAE,UAAU,gBAAgB,CAAC;CAS7D,MAAM,SAAS,OAAO,IAAY,YAA6B;EAC7D,KAAK,MAAM,UAAU,MAAM,QAAQ,WAAW,OAAO,GACnD,IAAI,OAAO,WAAW,YACpB,GAAG,QAAQ,kCAAkC,GAAG,IAAI,OAAO,MAAM;CAGvE;CAEA,OAAO;EACL,IAAI,cAAc;GAChB,OAAO,OAAO,MAAK,UAAS,MAAM,WAAW;EAC/C;EACA,WAAU,UACR,OACE,YACA,OAAO,KAAI,UAAS,MAAM,SAAS,KAAK,CAAC,CAC3C;EACF,cACE,OACE,UACA,OAAO,KAAI,UAAS,MAAM,OAAO,CAAC,CACpC;EACF,MAAK,iBACH,OACE,OACA,OAAO,KAAI,UAAS,MAAM,IAAI,YAAY,CAAC,CAC7C;CACJ;AACF;AAMA,IAAM,6BAA6B;;;;AAKnC,IAAa,gBAAb,MAA2B;CACzB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAIA,aAAa;CAEb,YAAqB,4BACnB,QACA,aACA,6EACF;CAEA,oBAA6B,mBAC3B,QACA,qBACA,6BACF;CAEA,aAAsB,mBACpB,QACA,aACA,sBACF;CAEA,YACE,IACA,eACA,UACA,MACA,OACA,YACA,YACA;EACA,GAAG,QAAQ,oBAAoB;EAC/B,KAAKA,iBAAiB;EACtB,KAAK,WAAW;EAChB,KAAK,OAAO;EACZ,KAAKC,oBAAoB,GAAG,eAAe,KAAK,EAAE;EAClD,KAAKC,sBAAsB,GAAG,eAAe,KAAK,EAAE;EACpD,KAAKC,MAAM;EACX,KAAKC,cAAc;EACnB,KAAKI,eAAe,gBAAgB,UAAU;CAChD;CAEA,UAA8B;EAC5B,OAAO,KAAKA;CACd;CAEA,MAAMC,MAAM,KAAiB,YAAgD;EAC3E,MAAM,EAAC,WAAU,KAAKL,YAAY,KAAK;GAAC,SAAS;GAAK;EAAU,CAAC;EACjE,MAAM;CACR;CAEA,KAAK,GAAY;EACf,KAAKD,IAAI,YAAY,CAAC,KACpB,8CAA8C,OAAO,CAAC,KACtD,CACF;EACA,KAAKC,YAAY,KAAK,sBAAsB,CAAC,CAAC;CAChD;CAEA,MAAM,QAAgB;EACpB,KAAKD,IAAI,QAAQ,mCAAmC,QAAQ;EAC5D,KAAKC,YAAY,OAAO;CAC1B;CAEA,UAAU,kBAAiD;EACzD,MAAM,SAAS,gBAAgB,gBAAgB;EAC/C,MAAM,KAAK,KAAKD,IAAI,YAAY,UAAU,MAAM;EAGhD,MAAM,mBAAmB,CAAC,KAAKO;EAC/B,MAAM,MAAM,YAAY,KAAKF,cAAc,gBAAgB;EAC3D,IAAI,MAAM,KAAM,QAAQ,KAAK,CAAC,kBAAmB;GAC/C,GAAG,OAAO,sCAAsC;GAChD,OAAO;EACT;EAEA,MAAM,aAAa,wBAAwB,KAAKA,YAAY;EAC5D,MAAM,SAAS,gBAAgB,gBAAgB;EAC/C,GAAG,QAAQ,sBAAsB,WAAW,MAAM,QAAQ;EAE1D,MAAM,QAAQ,YAAY,IAAI;EAE9B,MAAM,YAA2B;GAAC;GAAQ;EAAU;EAEpD,IAAI,cAAc;EAClB,IAAI;EACJ,IAAI,YAAY;EAChB,IAAI,uBAAuB;EAE3B,MAAM,aAAa,YAAY;GAC7B,IAAI,CAAC,aAAa;IAChB,MAAM,KAAKC,MAAM,CAAC,aAAa,SAAS,CAAC;IACzC,cAAc;GAChB;GACA,OAAQ,SAAS,EAAC,OAAM;EAC1B;EAEA,MAAM,YAAY,YAAY;GAC5B,IAAI,MAAM;IACR,MAAM,UAAU,CAAC,YAAY,IAAI;IACjC,MAAM,KAAKA,MAAM,SAAS,KAAK,UAAU,OAAO,CAAC;IACjD,OAAO,KAAA;IACP,YAAY;IACZ,uBAAuB;GACzB;EACF;EAEA,MAAM,WAAW,OAAO,mBAAmC;GACzD,MAAM,EAAC,OAAO,cAAa;GAC3B,IAAI,YAAY,WAAW,KAAKD,YAAY,KAAK,GAC/C;GAEF,MAAM,SAAS,MAAM,WAAW;GAEhC,MAAM,EAAC,MAAM,OAAM;GACnB,QAAQ,MAAR;IACE,KAAK;KAIH,CAHgB,MAAM,WACjB,CAAC,OAAO,0BAA0B,CAAC,GAAG,MAAM,cAAc,CAAC,IAC3D,OAAO,oBAAoB,CAAC,GACzB,KAAK;MAAC;MAAI,MAAM,MAAM;KAAE,CAAC;KACjC;IAEF,KAAK;KACH,IAAI,MAAM,GAAG,UAAU,KAAKP,mBAC1B,KAAKU,aAAc,OAAO,0BAA0B,CAAC,GAAI,KAAK;UACzD,IAAI,MAAM,GAAG,UAAU,KAAKT,qBAAqB;MACtD,MAAM,UAAW,OAAO,mBAAmB,CAAC;MAC5C,IAAI,OAAO,OAAO;OAChB,MAAM,MAAM,MACV,eAAe,MAAM,QAAQ,GAC7B,mBACA,aACF;OACA,QAAQ,KAAK;QACX,IAAI;QACJ,UAAU;SACR,IAAI;UACF,UAAU,IAAI;UACd,IAAI,IAAI;SACV;SACA,QAAQ,IAAI;QACd;OACF,CAAC;MACH,OAAO;OACL,MAAM,EAAC,UAAU,eAAc,MAAM,GAAG;OACxC,OACE,OAAO,aAAa,UACpB,4BACF;OACA,MAAM,KAAK,OAAO,UAAU;OAC5B,OACE,CAAC,OAAO,MAAM,EAAE,KAAK,OAAO,SAAS,EAAE,KAAK,MAAM,GAClD,qCACF;OACA,QAAQ,KAAK;QACX,IAAI;QACJ,IAAI;SACF;SACA;QACF;OACF,CAAC;MACH;KACF,OAAO;MACL,MAAM,WAAW,aAAa,KAAK;MACnC,CAAC,OAAO,cAAc,CAAC,GAAG,KAAK,QAAQ;MACvC,wBAAwB,KAAK,UAAU,QAAQ,EAAE;KACnD;KACA;IACF,SACE,YAAY,KAAK;GACrB;GAEA;GACA,IACE,wBAAA,WACA,aAAa,4BAEb,MAAM,UAAU;EAEpB;EAOA,OAAO;GACL,IAAI,cAAc;IAChB,OAAO;GACT;GACA,UAAU,OAAO,mBAAmC;IAClD,IAAI;KACF,MAAM,SAAS,cAAc;KAC7B,IAAI,eAAe,MAAM,SAAS,OAChC,KAAKK,WAAW,IAAI,CAAC;IAEzB,SAAS,GAAG;KACV,KAAK,KAAK,CAAC;IACb;GACF;GAEA,QAAQ,YAAY;IAClB,IAAI;KACF,IAAI,aACF,MAAM,KAAKE,MAAM,CAAC,WAAW;MAAC;MAAQ,QAAQ;MAAI,QAAQ;KAAI,CAAC,CAAC;IAEpE,SAAS,GAAG;KACV,KAAK,KAAK,CAAC;IACb;GACF;GAEA,KAAK,OAAO,iBAA6B;IACvC,IAAI;KACF,MAAM,SAAS,gBAAgB,YAAY;KAC3C,IAAI,CAAC,aAAa;MAChB,IACE,YAAY,KAAKD,cAAc,YAAY,MAAM,KACjD,CAAC,kBAED;MAEF,MAAM,KAAKC,MAAM,CAAC,aAAa,SAAS,CAAC;KAC3C,OAAO,IAAI,YAAY,KAAKD,cAAc,YAAY,KAAK,GAGzD,MAAM,IAAI,MACR,sCAAsC,OAAO,mCAExC,wBAAwB,KAAKA,YAAY,GAChD;KAEF,MAAM,UAAU;KAChB,MAAM,KAAKC,MAAM,CAAC,WAAW;MAAC;MAAQ;KAAM,CAAC,CAAC;KAC9C,KAAKD,eAAe;KACpB,KAAKE,aAAa;KAElB,MAAM,UAAU,YAAY,IAAI,IAAI;KACpC,KAAKJ,kBAAkB,IAAI,CAAC;KAC5B,KAAKD,UAAU,SAAS,OAAO;IACjC,SAAS,GAAG;KACV,KAAK,KAAK,CAAC;IACb;GACF;EACF;CACF;CAEA,MAAM,kBACJ,IACA,kBACA,uBACA;EACA,MAAM,oBAAiD,CAAC;EACxD,IAAI,iBAAiB,SAAS,GAC5B,kBAAkB,YAAY;EAEhC,IAAI,sBAAsB,SAAS,GACjC,kBAAkB,iBAAiB;EAErC,GAAG,QAAQ,yBAAyB,iBAAiB;EACrD,MAAM,KAAKI,MAAM,CAAC,iBAAiB,iBAAiB,CAAC;CACvD;CAEA,oCAAoC,QAAwB;EAC1D,KAAUA,MAAM,CAAC,kBAAkB,MAAM,CAAC;CAC5C;CAEA,8BAA8B,OAA4B;EACxD,KAAK,KAAK,IAAI,cAAc,KAAK,CAAC;CACpC;CAEA,oBAAoB,IAAgB,UAAiC;EACnE,GAAG,QAAQ,4BAA4B,QAAQ;EAC/C,KAAKL,YAAY,KAAK;GACpB,SAAS,CAAC,WAAW,QAAQ;GAC7B,YAAY,KAAA;EACd,CAAC;CACH;CAEA,aAAa,OAA+B,OAAiB;EAC3D,IAAI,MAAM,OAAO,OAAO;GAEtB,MAAM,EAAC,eAAe,UAAU,mBAAkB,MADtC,eAAe,MAAM,QAE/B,GACA,eACA,aACF;GACA,IAAI,kBAAkB,KAAKJ,gBACzB,KAAKG,IAAI,QACP,2DACA,aACF;QAEA,MAAM,YAAY;EAEtB,OAEE,MAAM;CAEV;AACF;AAGA,IAAM,gBAAgB,eAAE,OAAO;CAC7B,eAAe,eAAE,OAAO;CACxB,UAAU,eAAE,OAAO;CACnB,gBAAgB,eAAE,OAAO;AAC3B,CAAC;AAED,IAAM,oBAAoB,eAAE,OAAO;CACjC,eAAe,eAAE,OAAO;CACxB,UAAU,eAAE,OAAO;CACnB,YAAY,eAAE,OAAO;CACrB,QAAQ;AACV,CAAC;AAED,SAAS,aAAa,OAA6B;CACjD,MAAM,EACJ,IACA,IAAI,EAAC,OAAO,WAAW,QAAQ,SAC7B;CAEJ,QAAQ,IAAR;EACE,KAAK,OACH,OAAO;GACL,IAAI;GACJ;GACA,OAAO,MAAQ,eAAe,MAAM,QAAQ,GAAG,SAAS;EAC1D;EAEF,KAAK,OACH,OAAO;GACL;GACA;GACA,IAAI,MAAQ,IAAI,2BAA2B;EAC7C;EAEF,SACE,YAAY,EAAE;CAClB;AACF;;;;;;;;AASA,SAAgB,eAAe,KAAiC;CAC9D,MAAM,WAAW,OAAO,QAAQ,GAAG,EAChC,QAAQ,CAAC,GAAG,OAAO;EAClB,IAAI,OAAO,MAAM,UAAU;GACzB,IAAI,KAAK,OAAO,oBAAoB,KAAK,OAAO,kBAC9C,OAAO;GAET,MAAM,IAAI,MAAM,aAAa,EAAE,+BAA+B,EAAE,EAAE;EACpE,OAAO,IAAI,OAAO,MAAM,UACtB,gBAAgB,CAAC;EAEnB,OAAO;CACT,CAAC,EACA,KAAK,CAAC,GAAG,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;CAEjC,OAAO,SAAS,SACZ;EAAC,GAAG;EAAK,GAAG,OAAO,YAAY,QAAQ;CAAC,IACvC;AACP"}
|
|
1
|
+
{"version":3,"file":"client-handler.js","names":["#clientGroupID","#zeroClientsTable","#zeroMutationsTable","#lc","#downstream","#pokeTime","#pokeTransactions","#pokedRows","#baseVersion","#push","#everPoked","#updateLMIDs"],"sources":["../../../../../../zero-cache/src/services/view-syncer/client-handler.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {assert, unreachable} from '../../../../shared/src/asserts.ts';\nimport type {JSONObject} from '../../../../shared/src/bigint-json.ts';\nimport {hasOwn} from '../../../../shared/src/has-own.ts';\nimport {\n assertJSONValue,\n type JSONObject as SafeJSONObject,\n} from '../../../../shared/src/json.ts';\nimport {promiseVoid} from '../../../../shared/src/resolved-promises.ts';\nimport * as v from '../../../../shared/src/valita.ts';\nimport type {Writable} from '../../../../shared/src/writable.ts';\nimport type {ErroredQuery} from '../../../../zero-protocol/src/custom-queries.ts';\nimport type {DeleteClientsBody} from '../../../../zero-protocol/src/delete-clients.ts';\nimport type {Downstream} from '../../../../zero-protocol/src/down.ts';\nimport {\n ProtocolError,\n type TransformFailedBody,\n} from '../../../../zero-protocol/src/error.ts';\nimport type {InspectDownBody} from '../../../../zero-protocol/src/inspect-down.ts';\nimport {mutationResultSchema} from '../../../../zero-protocol/src/mutation.ts';\nimport type {\n PokePartBody,\n PokePartMessage,\n PokeStartBody,\n} from '../../../../zero-protocol/src/poke.ts';\nimport {primaryKeyValueRecordSchema} from '../../../../zero-protocol/src/primary-key.ts';\nimport type {RowPatchOp} from '../../../../zero-protocol/src/row-patch.ts';\nimport {\n getOrCreateCounter,\n getOrCreateLatencyHistogram,\n} from '../../observability/metrics.ts';\nimport type {ViewSyncerDownstream} from '../../types/downstream.ts';\nimport {\n getLogLevel,\n wrapWithProtocolError,\n} from '../../types/error-with-level.ts';\nimport {upstreamSchema, type ShardID} from '../../types/shards.ts';\nimport type {Subscription} from '../../types/subscription.ts';\nimport {\n cmpVersions,\n cookieToVersion,\n versionToCookie,\n versionToNullableCookie,\n type CVRVersion,\n type DelQueryPatch,\n type NullableCVRVersion,\n type PutQueryPatch,\n type RowID,\n} from './schema/types.ts';\n\nexport type PutRowPatch = {\n type: 'row';\n op: 'put';\n id: RowID;\n contents: JSONObject;\n};\n\nexport type DeleteRowPatch = {\n type: 'row';\n op: 'del';\n id: RowID;\n};\n\nexport type RowPatch = PutRowPatch | DeleteRowPatch;\nexport type ConfigPatch = DelQueryPatch | PutQueryPatch;\n\nexport type Patch = ConfigPatch | RowPatch;\n\nexport type PatchToVersion = {\n patch: Patch;\n toVersion: CVRVersion;\n};\n\nexport interface PokeHandler {\n addPatch(patch: PatchToVersion): Promise<void>;\n cancel(): Promise<void>;\n end(finalVersion: CVRVersion): Promise<void>;\n}\n\n/**\n * A put/del row patch and its JSON serialization. Computed once per client\n * group and shared by all of the group's clients.\n */\ntype SerializedRowPatch = {\n readonly rowPatch: RowPatchOp;\n readonly json: string;\n};\n\n/**\n * Lazily holds the {@link SerializedRowPatch} of one patch so that it is\n * computed at most once, by the first client that needs it.\n */\ntype SharedRowPatch = {serialized?: SerializedRowPatch | undefined};\n\n/** A {@link PokeHandler} for a single client. */\nexport interface ClientPokeHandler extends PokeHandler {\n addPatch(patch: PatchToVersion, shared?: SharedRowPatch): Promise<void>;\n\n /**\n * Whether a patch has been sent to the client. Once one has, the poke can\n * only be ended with a `finalVersion` that is ahead of the client's base\n * version.\n */\n readonly patchesSent: boolean;\n}\n\n/**\n * A {@link PokeHandler} for multiple clients, as returned by\n * {@link startPoke}.\n */\nexport interface MultiPokeHandler extends PokeHandler {\n /** Whether a patch has been sent to any of the clients. */\n readonly patchesSent: boolean;\n}\n\nconst NOOP: ClientPokeHandler = {\n patchesSent: false,\n addPatch: () => promiseVoid,\n cancel: () => promiseVoid,\n end: () => promiseVoid,\n};\n\n/** Wraps PokeHandlers for multiple clients in a single PokeHandler. */\nexport function startPoke(\n lc: LogContext,\n clients: ClientHandler[],\n tentativeVersion: CVRVersion,\n): MultiPokeHandler {\n const pokers = clients.map(c => c.startPoke(tentativeVersion));\n\n // Promise.allSettled() ensures that a failed (e.g. disconnected) client\n // does not prevent other clients from receiving the pokes. However, the\n // rate (per client group) will be limited by the slowest connection.\n //\n // The individual pokers report their own failures (by failing the\n // connection), so a rejection here is not expected. Log it rather than\n // dropping it on the floor.\n const settle = async (op: string, results: Promise<void>[]) => {\n for (const result of await Promise.allSettled(results)) {\n if (result.status === 'rejected') {\n lc.error?.(`unhandled error poking client (${op})`, result.reason);\n }\n }\n };\n\n return {\n get patchesSent() {\n return pokers.some(poker => poker.patchesSent);\n },\n addPatch: patch => {\n const shared: SharedRowPatch = {};\n return settle(\n 'addPatch',\n pokers.map(poker => poker.addPatch(patch, shared)),\n );\n },\n cancel: () =>\n settle(\n 'cancel',\n pokers.map(poker => poker.cancel()),\n ),\n end: finalVersion =>\n settle(\n 'end',\n pokers.map(poker => poker.end(finalVersion)),\n ),\n };\n}\n\n// Soft limit on the serialized row characters accumulated in a poke part.\n// This bounds view-syncer memory and keeps legacy JSON messages reasonably\n// sized. PokeChunkEncoder separately enforces the binary frame limit in bytes.\nexport const POKE_PART_FLUSH_THRESHOLD_CHARS = 1024 * 1024;\nconst PART_COUNT_FLUSH_THRESHOLD = 100;\n\n/**\n * Handles a single `ViewSyncer` connection.\n */\nexport class ClientHandler {\n readonly #clientGroupID: string;\n readonly clientID: string;\n readonly wsID: string;\n readonly #zeroClientsTable: string;\n readonly #zeroMutationsTable: string;\n readonly #lc: LogContext;\n readonly #downstream: Subscription<ViewSyncerDownstream>;\n #baseVersion: NullableCVRVersion;\n // We will send a poke on connect even if the client is already caught up, so that it can learn its\n // got-queries state has been reconciled with the server. After that, we will only send a poke if\n // the client is behind.\n #everPoked = false;\n\n readonly #pokeTime = getOrCreateLatencyHistogram(\n 'sync',\n 'poke.time',\n 'Time elapsed for each poke transaction. Canceled / noop pokes are excluded.',\n );\n\n readonly #pokeTransactions = getOrCreateCounter(\n 'sync',\n 'poke.transactions',\n 'Count of poke transactions.',\n );\n\n readonly #pokedRows = getOrCreateCounter(\n 'sync',\n 'poke.rows',\n 'Count of poked rows.',\n );\n\n constructor(\n lc: LogContext,\n clientGroupID: string,\n clientID: string,\n wsID: string,\n shard: ShardID,\n baseCookie: string | null,\n downstream: Subscription<ViewSyncerDownstream>,\n ) {\n lc.debug?.('new client handler');\n this.#clientGroupID = clientGroupID;\n this.clientID = clientID;\n this.wsID = wsID;\n this.#zeroClientsTable = `${upstreamSchema(shard)}.clients`;\n this.#zeroMutationsTable = `${upstreamSchema(shard)}.mutations`;\n this.#lc = lc;\n this.#downstream = downstream;\n this.#baseVersion = cookieToVersion(baseCookie);\n }\n\n version(): NullableCVRVersion {\n return this.#baseVersion;\n }\n\n async #push(msg: Downstream, serialized?: string | undefined): Promise<void> {\n const {result} = this.#downstream.push({message: msg, serialized});\n await result;\n }\n\n fail(e: unknown) {\n this.#lc[getLogLevel(e)]?.(\n `view-syncer closing connection with error: ${String(e)}`,\n e,\n );\n this.#downstream.fail(wrapWithProtocolError(e));\n }\n\n close(reason: string) {\n this.#lc.debug?.(`view-syncer closing connection: ${reason}`);\n this.#downstream.cancel();\n }\n\n startPoke(tentativeVersion: CVRVersion): ClientPokeHandler {\n const pokeID = versionToCookie(tentativeVersion);\n const lc = this.#lc.withContext('pokeID', pokeID);\n\n // Force an (empty) initial poke even when already caught up; see #everPoked.\n const forceInitialPoke = !this.#everPoked;\n const cmp = cmpVersions(this.#baseVersion, tentativeVersion);\n if (cmp > 0 || (cmp === 0 && !forceInitialPoke)) {\n lc.info?.(`already caught up, not sending poke.`);\n return NOOP;\n }\n\n const baseCookie = versionToNullableCookie(this.#baseVersion);\n const cookie = versionToCookie(tentativeVersion);\n lc.debug?.(`starting poke from ${baseCookie} to ${cookie}`);\n\n const start = performance.now();\n\n const pokeStart: PokeStartBody = {pokeID, baseCookie};\n\n let pokeStarted = false;\n let body: PokePartBody | undefined;\n // rowsPatch is kept out of `body` until it is flushed so that the poke\n // part can be serialized by concatenating the pre-serialized rows.\n let rowsPatch: RowPatchOp[] = [];\n let rowsJSON: string[] = [];\n let partCount = 0;\n let serializedRowsLength = 0;\n\n const ensureBody = async () => {\n if (!pokeStarted) {\n await this.#push(['pokeStart', pokeStart]);\n pokeStarted = true;\n }\n return (body ??= {pokeID});\n };\n\n const flushBody = async () => {\n if (body) {\n let message: PokePartMessage;\n let serialized: string;\n if (rowsPatch.length === 0) {\n message = ['pokePart', body];\n serialized = JSON.stringify(message);\n } else {\n // Equivalent to JSON.stringify(message): rowsPatch is the last\n // property of the body.\n const prefix = JSON.stringify(['pokePart', body]);\n message = ['pokePart', {...body, rowsPatch}];\n serialized = `${prefix.slice(0, -2)},\"rowsPatch\":[${rowsJSON.join(',')}]}]`;\n rowsPatch = [];\n rowsJSON = [];\n }\n await this.#push(message, serialized);\n body = undefined;\n partCount = 0;\n serializedRowsLength = 0;\n }\n };\n\n const addPatch = async (\n patchToVersion: PatchToVersion,\n shared: SharedRowPatch,\n ) => {\n const {patch, toVersion} = patchToVersion;\n if (cmpVersions(toVersion, this.#baseVersion) <= 0) {\n return;\n }\n const target = await ensureBody();\n\n const {type, op} = patch;\n switch (type) {\n case 'query': {\n const patches = patch.clientID\n ? ((target.desiredQueriesPatches ??= {})[patch.clientID] ??= [])\n : (target.gotQueriesPatch ??= []);\n patches.push({op, hash: patch.id});\n break;\n }\n case 'row':\n if (patch.id.table === this.#zeroClientsTable) {\n this.#updateLMIDs((target.lastMutationIDChanges ??= {}), patch);\n } else if (patch.id.table === this.#zeroMutationsTable) {\n const patches = (target.mutationsPatch ??= []);\n if (op === 'put') {\n const row = v.parse(\n ensureSafeJSON(patch.contents),\n mutationRowSchema,\n 'passthrough',\n );\n patches.push({\n op: 'put',\n mutation: {\n id: {\n clientID: row.clientID,\n id: row.mutationID,\n },\n result: row.result,\n },\n });\n } else {\n const {clientID, mutationID} = patch.id.rowKey;\n assert(\n typeof clientID === 'string',\n 'client id must be a string',\n );\n const id = Number(mutationID);\n assert(\n !Number.isNaN(id) && Number.isFinite(id) && id >= 0,\n 'mutation id must be a finite number',\n );\n patches.push({\n op: 'del',\n id: {\n clientID,\n id,\n },\n });\n }\n } else {\n const {rowPatch, json} = (shared.serialized ??=\n serializeRowPatch(patch));\n rowsPatch.push(rowPatch);\n rowsJSON.push(json);\n serializedRowsLength += json.length;\n }\n break;\n default:\n unreachable(patch);\n }\n\n partCount++;\n if (\n serializedRowsLength >= POKE_PART_FLUSH_THRESHOLD_CHARS ||\n partCount >= PART_COUNT_FLUSH_THRESHOLD\n ) {\n await flushBody();\n }\n };\n\n // A poke that was started must always be ended. If it isn't, the\n // connection is left mid-poke and the *next* pokeStart fails the\n // DownstreamSender's in-progress check, surfacing the error far from\n // its cause. Fail the connection instead; the client reconnects and\n // resyncs from its baseVersion.\n return {\n get patchesSent() {\n return pokeStarted;\n },\n addPatch: async (\n patchToVersion: PatchToVersion,\n shared: SharedRowPatch = {},\n ) => {\n try {\n await addPatch(patchToVersion, shared);\n if (patchToVersion.patch.type === 'row') {\n this.#pokedRows.add(1);\n }\n } catch (e) {\n this.fail(e);\n }\n },\n\n cancel: async () => {\n try {\n if (pokeStarted) {\n await this.#push(['pokeEnd', {pokeID, cookie: '', cancel: true}]);\n }\n } catch (e) {\n this.fail(e);\n }\n },\n\n end: async (finalVersion: CVRVersion) => {\n try {\n const cookie = versionToCookie(finalVersion);\n if (!pokeStarted) {\n if (\n cmpVersions(this.#baseVersion, finalVersion) === 0 &&\n !forceInitialPoke\n ) {\n return; // Nothing changed and nothing was sent.\n }\n await this.#push(['pokeStart', pokeStart]);\n } else if (cmpVersions(this.#baseVersion, finalVersion) >= 0) {\n // Sanity check: If the poke was started, the finalVersion\n // must be > #baseVersion.\n throw new Error(\n `Patches were sent but finalVersion ${cookie} is not ` +\n `greater than baseVersion ` +\n `${versionToNullableCookie(this.#baseVersion)}`,\n );\n }\n await flushBody();\n await this.#push(['pokeEnd', {pokeID, cookie}]);\n this.#baseVersion = finalVersion;\n this.#everPoked = true;\n\n const elapsed = performance.now() - start;\n this.#pokeTransactions.add(1);\n this.#pokeTime.recordMs(elapsed);\n } catch (e) {\n this.fail(e);\n }\n },\n };\n }\n\n async sendDeleteClients(\n lc: LogContext,\n deletedClientIDs: string[],\n deletedClientGroupIDs: string[],\n ) {\n const deleteClientsBody: Writable<DeleteClientsBody> = {};\n if (deletedClientIDs.length > 0) {\n deleteClientsBody.clientIDs = deletedClientIDs;\n }\n if (deletedClientGroupIDs.length > 0) {\n deleteClientsBody.clientGroupIDs = deletedClientGroupIDs;\n }\n lc.debug?.('sending deleteClients', deleteClientsBody);\n await this.#push(['deleteClients', deleteClientsBody]);\n }\n\n sendQueryTransformApplicationErrors(errors: ErroredQuery[]) {\n void this.#push(['transformError', errors]);\n }\n\n sendQueryTransformFailedError(error: TransformFailedBody) {\n this.fail(new ProtocolError(error));\n }\n\n sendInspectResponse(lc: LogContext, response: InspectDownBody): void {\n lc.debug?.('sending inspect response', response);\n this.#downstream.push({\n message: ['inspect', response],\n serialized: undefined,\n });\n }\n\n #updateLMIDs(lmids: Record<string, number>, patch: RowPatch) {\n if (patch.op === 'put') {\n const row = ensureSafeJSON(patch.contents);\n const {clientGroupID, clientID, lastMutationID} = v.parse(\n row,\n lmidRowSchema,\n 'passthrough',\n );\n if (clientGroupID !== this.#clientGroupID) {\n this.#lc.error?.(\n `Received clients row for wrong clientGroupID. Ignoring.`,\n clientGroupID,\n );\n } else {\n lmids[clientID] = lastMutationID;\n }\n } else {\n // The 'constrain' and 'del' ops for clients can be ignored.\n patch.op satisfies 'constrain' | 'del';\n }\n }\n}\n\n// Note: The {APP_ID}_{SHARD_ID}.clients table is set up in replicator/initial-sync.ts.\nconst lmidRowSchema = v.object({\n clientGroupID: v.string(),\n clientID: v.string(),\n lastMutationID: v.number(), // Actually returned as a bigint, but converted by ensureSafeJSON().\n});\n\nconst mutationRowSchema = v.object({\n clientGroupID: v.string(),\n clientID: v.string(),\n mutationID: v.number(),\n result: mutationResultSchema,\n});\n\nfunction serializeRowPatch(patch: RowPatch): SerializedRowPatch {\n const rowPatch = makeRowPatch(patch);\n return {rowPatch, json: JSON.stringify(rowPatch)};\n}\n\nfunction makeRowPatch(patch: RowPatch): RowPatchOp {\n const {\n op,\n id: {table: tableName, rowKey: id},\n } = patch;\n\n switch (op) {\n case 'put':\n // ensureSafeJSON() converts bigints and asserts (outside of prod) that\n // the values are JSON, which is all that rowSchema checks.\n return {\n op: 'put',\n tableName,\n value: ensureSafeJSON(patch.contents),\n };\n\n case 'del':\n return {\n op,\n tableName,\n id: v.parse(id, primaryKeyValueRecordSchema),\n };\n\n default:\n unreachable(op);\n }\n}\n\n/**\n * Column values of type INT8 are returned as the `bigint` from the\n * Postgres library. These are converted to `number` if they are within\n * the safe Number range, allowing the protocol to support numbers larger\n * than 32-bits. Values outside of the safe number range (e.g. > 2^53) will\n * result in an Error.\n */\nexport function ensureSafeJSON(row: JSONObject): SafeJSONObject {\n let modified: Record<string, unknown> | undefined;\n for (const k in row) {\n if (!hasOwn(row, k)) {\n continue;\n }\n const v = row[k];\n if (typeof v === 'bigint') {\n if (v < Number.MIN_SAFE_INTEGER || v > Number.MAX_SAFE_INTEGER) {\n throw new Error(`Value of \"${k}\" exceeds safe Number range (${v})`);\n }\n (modified ??= {...row})[k] = Number(v);\n } else if (typeof v === 'object') {\n assertJSONValue(v);\n }\n }\n return (modified ?? row) as SafeJSONObject;\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pipeline-driver.d.ts","sourceRoot":"","sources":["../../../../../../zero-cache/src/services/view-syncer/pipeline-driver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAQjD,OAAO,KAAK,EAAC,GAAG,EAAE,YAAY,EAAC,MAAM,sCAAsC,CAAC;AAC5E,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,gDAAgD,CAAC;AACjF,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,uCAAuC,CAAC;AAQ/D,OAAO,EAAC,UAAU,EAAC,MAAM,wCAAwC,CAAC;AAGlE,OAAO,EAIL,KAAK,KAAK,EAIX,MAAM,qCAAqC,CAAC;AAY7C,OAAO,KAAK,EACV,WAAW,EAEZ,MAAM,iDAAiD,CAAC;AAMzD,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,4CAA4C,CAAC;
|
|
1
|
+
{"version":3,"file":"pipeline-driver.d.ts","sourceRoot":"","sources":["../../../../../../zero-cache/src/services/view-syncer/pipeline-driver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAQjD,OAAO,KAAK,EAAC,GAAG,EAAE,YAAY,EAAC,MAAM,sCAAsC,CAAC;AAC5E,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,gDAAgD,CAAC;AACjF,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,uCAAuC,CAAC;AAQ/D,OAAO,EAAC,UAAU,EAAC,MAAM,wCAAwC,CAAC;AAGlE,OAAO,EAIL,KAAK,KAAK,EAIX,MAAM,qCAAqC,CAAC;AAY7C,OAAO,KAAK,EACV,WAAW,EAEZ,MAAM,iDAAiD,CAAC;AAMzD,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,4CAA4C,CAAC;AAYnF,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,gCAAgC,CAAC;AACxC,OAAO,KAAK,EAAC,SAAS,EAAE,UAAU,EAAC,MAAM,6BAA6B,CAAC;AAEvE,OAAO,KAAK,EAAC,cAAc,EAAgB,MAAM,mBAAmB,CAAC;AAMrE,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,oCAAoC,CAAC;AAC1E,OAAO,EAAC,KAAK,MAAM,EAAC,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAC,KAAK,OAAO,EAAC,MAAM,uBAAuB,CAAC;AAMnD,OAAO,KAAK,EAAC,oBAAoB,EAAC,MAAM,6BAA6B,CAAC;AAQtE,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACtB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAa,KAAK,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAC7D,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAEjD,OAAO,KAAK,EAAkB,WAAW,EAAC,MAAM,kBAAkB,CAAC;AAGnE,KAAK,KAAK,CAAC,EAAE,SAAS,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,KAAK,CAAC,IAAI;IAC1D,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC;IAClB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC;IACrB,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;AAE3C,MAAM,MAAM,SAAS,GAAG,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;AAEjD,MAAM,MAAM,OAAO,GAAG,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;AAE7C,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;AA4BrD,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,CAAC,cAAc,EAAE,GAAG,CAAC;IAC7B,QAAQ,CAAC,WAAW,CAAC,EAAE,GAAG,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACzC,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,qCAAqC;IACrC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,qEAAqE;IACrE,QAAQ,CAAC,YAAY,EAAE,SAAS,WAAW,EAAE,CAAC;IAC9C,0EAA0E;IAC1E,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;CAC5B,CAAC;AAeF,MAAM,MAAM,uBAAuB,GAC/B,gBAAgB,GAChB,2BAA2B,CAAC;AAEhC,KAAK,kBAAkB,GACnB,eAAe,GACf,cAAc,GACd,iBAAiB,GACjB,OAAO,GACP,SAAS,CAAC;AAiCd,MAAM,MAAM,mBAAmB,GAAG;IAChC,oFAAoF;IACpF,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,8DAA8D;IAC9D,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,gDAAgD;IAChD,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,cAAc,GAAG,iBAAiB,GAAG;IAC/C,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,GAAG,QAAQ,CAAC;IAChD,0EAA0E;IAC1E,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9C,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,cAAc,EAAE,GAAG,CAAC;IAC7B,wCAAwC;IACxC,QAAQ,CAAC,WAAW,EAAE,GAAG,CAAC;IAC1B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACzC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;;OAGG;IACH,QAAQ,CAAC,YAAY,EAAE,gBAAgB,CAAC;IACxC;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC,CAAC;AAEF,4EAA4E;AAC5E,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B,CAAC;AA4EF,MAAM,MAAM,KAAK,GAAG;IAClB,UAAU,EAAE,MAAM,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,MAAM,CAAC;CAC5B,CAAC;AA2IF;;GAEG;AACH,qBAAa,cAAc;;IAoGzB,YACE,EAAE,EAAE,UAAU,EACd,SAAS,EAAE,SAAS,EACpB,WAAW,EAAE,WAAW,EACxB,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,kBAAkB,EAC3B,aAAa,EAAE,MAAM,EACrB,iBAAiB,EAAE,iBAAiB,EACpC,gBAAgB,EAAE,MAAM,MAAM,EAC9B,aAAa,CAAC,EAAE,OAAO,EACvB,MAAM,CAAC,EAAE,UAAU,EACnB,cAAc,CAAC,EAAE,oBAAoB,EACrC,UAAU,CAAC,EAAE,UAAU,GAAG,SAAS,EAqBpC;IAED;;;;;OAKG;IACH,IAAI,CAAC,YAAY,EAAE,YAAY,QAI9B;IAED;;OAEG;IACH,WAAW,IAAI,OAAO,CAErB;IAED;;;;OAIG;IACH,KAAK,CAAC,YAAY,EAAE,YAAY,QAY/B;IAiCD,mFAAmF;IACnF,IAAI,cAAc,IAAI,MAAM,CAE3B;IAED;;;;OAIG;IACH,cAAc,IAAI,MAAM,CAGvB;IAED;;OAEG;IACH,kBAAkB,IAAI,iBAAiB,GAAG,IAAI,CAiB7C;IAED;;;;;;;;;;;;;;;OAeG;IACH,kBAAkB,CAAC,uBAAuB,UAAQ,GAAG,MAAM,CAe1D;IAeD;;;OAGG;IACH,OAAO,SAUN;IAED,uEAAuE;IACvE,OAAO,IAAI,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAExC;IAED;;;;;OAKG;IACH,gBAAgB,IAAI,WAAW,CAAC,MAAM,EAAE,cAAc,CAAC,CAEtD;IAED;;;OAGG;IACH,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAU1D;IA6CD,oBAAoB,IAAI,MAAM,CAM7B;IAED;;;;OAIG;IACH,IAAI,WAAW,IAAI,MAAM,CAMxB;IAED;;;OAGG;IACH,IAAI,YAAY,IAAI,MAAM,CAMzB;IAoJD;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CACN,kBAAkB,EAAE,MAAM,EAC1B,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,GAAG,EACV,KAAK,EAAE,KAAK,EACZ,SAAS,CAAC,EAAE,MAAM,EAClB,eAAe,GAAE,uBAA0C,GAC1D,QAAQ,CAAC,SAAS,GAAG,OAAO,CAAC,CAW/B;IAsTD;;;OAGG;IACH,WAAW,CACT,OAAO,EAAE,MAAM,EACf,UAAU,GAAE,kBAAmC,QAGhD;IA2DD;;;;OAIG;IACH,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEnD;IAED;;;;OAIG;IACH,uBAAuB,IAAI,WAAW,CAAC,MAAM,CAAC,CAE7C;IAED;;OAEG;IACH,4BAA4B,IAAI,IAAI,CAEnC;IA0BD;;;;OAIG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,GAAG,GAAG,SAAS,CAIjD;IAED;;;;;;;;;;;;;;;;;;OAkBG;IACH,OAAO,CACL,KAAK,EAAE,KAAK,EACZ,SAAS,CAAC,EAAE,gBAAgB,GAC3B;QACD,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,OAAO,EAAE,QAAQ,CAAC,SAAS,GAAG,OAAO,CAAC,CAAC;QACvC,uEAAuE;QACvE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;QACpC;;;;WAIG;QACH,SAAS,EAAE,MAAM,SAAS,cAAc,EAAE,CAAC;QAC3C;;;;;WAKG;QACH,SAAS,EAAE,MAAM,SAAS,YAAY,EAAE,CAAC;KAC1C,CAsEA;CAkjCF;AA2OD;;;;;GAKG;AACH,wBAAgB,OAAO,CACrB,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,YAAY,EAC1B,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,GACtC,QAAQ,CAAC,SAAS,GAAG,OAAO,CAAC,CAK/B;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,KAAK,EACZ,UAAU,EAAE,MAAM,GACjB,YAAY,GAAG,IAAI,GAAG,SAAS,CAYjC"}
|