orez 0.4.45 → 0.4.47
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/dist/cf-do/cursor-pull.d.ts +27 -0
- package/dist/cf-do/cursor-pull.d.ts.map +1 -0
- package/dist/cf-do/cursor-pull.js +78 -0
- package/dist/cf-do/cursor-pull.js.map +1 -0
- package/dist/pg-proxy-do-backend.d.ts +1 -0
- package/dist/pg-proxy-do-backend.d.ts.map +1 -1
- package/dist/pg-proxy-do-backend.js +68 -7
- package/dist/pg-proxy-do-backend.js.map +1 -1
- package/dist/sync-server/sync-server.d.ts +77 -0
- package/dist/sync-server/sync-server.d.ts.map +1 -0
- package/dist/sync-server/sync-server.js +385 -0
- package/dist/sync-server/sync-server.js.map +1 -0
- package/dist/worker/zero-sql-write-circuit.d.ts.map +1 -1
- package/dist/worker/zero-sql-write-circuit.js +10 -2
- package/dist/worker/zero-sql-write-circuit.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
export type SyncDb = {
|
|
2
|
+
exec(sql: string, params?: unknown[]): void;
|
|
3
|
+
all(sql: string, params?: unknown[]): Record<string, unknown>[];
|
|
4
|
+
transaction<T>(fn: () => T): T;
|
|
5
|
+
};
|
|
6
|
+
export type ZeroColumnType = 'string' | 'number' | 'boolean' | 'json' | 'null';
|
|
7
|
+
export type SyncTables = Record<string, {
|
|
8
|
+
columns: Record<string, ZeroColumnType>;
|
|
9
|
+
primaryKey: string[];
|
|
10
|
+
}>;
|
|
11
|
+
export declare class SyncHttpError extends Error {
|
|
12
|
+
readonly status: number;
|
|
13
|
+
constructor(status: number, message: string);
|
|
14
|
+
}
|
|
15
|
+
export declare class MutationAppError extends Error {
|
|
16
|
+
readonly details: string;
|
|
17
|
+
constructor(details: string, message?: string);
|
|
18
|
+
}
|
|
19
|
+
export type SyncServerConfig = {
|
|
20
|
+
db: SyncDb;
|
|
21
|
+
tables: SyncTables;
|
|
22
|
+
visible?: (table: string, userID: string) => {
|
|
23
|
+
sql: string;
|
|
24
|
+
params: unknown[];
|
|
25
|
+
};
|
|
26
|
+
mutate: (tx: SyncDb, name: string, args: unknown, ctx: {
|
|
27
|
+
userID: string;
|
|
28
|
+
}) => void;
|
|
29
|
+
retainChanges?: number;
|
|
30
|
+
};
|
|
31
|
+
export declare function tablesFromZeroSchema(schema: {
|
|
32
|
+
tables: Record<string, {
|
|
33
|
+
columns: Record<string, {
|
|
34
|
+
type: string;
|
|
35
|
+
}>;
|
|
36
|
+
primaryKey: readonly string[];
|
|
37
|
+
}>;
|
|
38
|
+
}): SyncTables;
|
|
39
|
+
export declare function createSyncServer(config: SyncServerConfig): {
|
|
40
|
+
handlePull: (body: unknown, userID: string) => {
|
|
41
|
+
cookie: number;
|
|
42
|
+
unchanged: true;
|
|
43
|
+
lastMutationIDChanges?: undefined;
|
|
44
|
+
rowsPatch?: undefined;
|
|
45
|
+
} | {
|
|
46
|
+
cookie: number;
|
|
47
|
+
lastMutationIDChanges: Record<string, number>;
|
|
48
|
+
rowsPatch: unknown[];
|
|
49
|
+
unchanged?: undefined;
|
|
50
|
+
};
|
|
51
|
+
handlePush: (body: unknown, userID: string) => {
|
|
52
|
+
pushResponse: {
|
|
53
|
+
error: "unsupportedPushVersion";
|
|
54
|
+
mutationIDs: {
|
|
55
|
+
clientID: string;
|
|
56
|
+
id: number;
|
|
57
|
+
}[];
|
|
58
|
+
mutations?: undefined;
|
|
59
|
+
};
|
|
60
|
+
} | {
|
|
61
|
+
pushResponse: {
|
|
62
|
+
mutations: {
|
|
63
|
+
id: {
|
|
64
|
+
clientID: string;
|
|
65
|
+
id: number;
|
|
66
|
+
};
|
|
67
|
+
result: Record<string, unknown>;
|
|
68
|
+
}[];
|
|
69
|
+
error?: undefined;
|
|
70
|
+
mutationIDs?: undefined;
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
watermark: () => number;
|
|
74
|
+
invalidate: () => void;
|
|
75
|
+
};
|
|
76
|
+
export type SyncServer = ReturnType<typeof createSyncServer>;
|
|
77
|
+
//# sourceMappingURL=sync-server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-server.d.ts","sourceRoot":"","sources":["../../src/sync-server/sync-server.ts"],"names":[],"mappings":"AA0CA,MAAM,MAAM,MAAM,GAAG;IACnB,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,IAAI,CAAA;IAC3C,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAA;IAE/D,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAAA;CAC/B,CAAA;AAED,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,CAAA;AAE9E,MAAM,MAAM,UAAU,GAAG,MAAM,CAC7B,MAAM,EACN;IAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAAC,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE,CAClE,CAAA;AAED,qBAAa,aAAc,SAAQ,KAAK;IAEpC,QAAQ,CAAC,MAAM,EAAE,MAAM;gBAAd,MAAM,EAAE,MAAM,EACvB,OAAO,EAAE,MAAM;CAIlB;AAKD,qBAAa,gBAAiB,SAAQ,KAAK;IAEvC,QAAQ,CAAC,OAAO,EAAE,MAAM;gBAAf,OAAO,EAAE,MAAM,EACxB,OAAO,SAAU;CAIpB;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,UAAU,CAAA;IAGlB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,OAAO,EAAE,CAAA;KAAE,CAAA;IAG/E,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAA;IAGlF,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB,CAAA;AAkED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE;IAC3C,MAAM,EAAE,MAAM,CACZ,MAAM,EACN;QAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE;YAAE,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,CAC7E,CAAA;CACF,GAAG,UAAU,CAUb;AAqBD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,gBAAgB;uBA6H7B,OAAO,UAAU,MAAM;;;;;;;;;;;uBA4FvB,OAAO,UAAU,MAAM;;;;;;;;;;;;oBAiBzC;oBAAE,QAAQ,EAAE,MAAM,CAAC;oBAAC,EAAE,EAAE,MAAM,CAAA;iBAAE;wBAC5B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;;qBAnLb,MAAM;sBA0BL,IAAI;EA4O5B;AAED,MAAM,MAAM,UAAU,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAA"}
|
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
// sync-server: the sqlite-native zero sync server core (rewrite phase 2 seed,
|
|
2
|
+
// see plans/zero-server-rewrite.md + plans/zero-conformance-harness.md M2).
|
|
3
|
+
//
|
|
4
|
+
// serves the on-zero `transport: 'http-pull'` dialect to STOCK @rocicorp/zero
|
|
5
|
+
// clients: cursor-diff pulls over a trigger-fed change log (with full
|
|
6
|
+
// snapshot as the single recovery path) and v51 custom-mutator pushes with
|
|
7
|
+
// LMID bookkeeping, over any sqlite handle. no zero-cache, no CVR, no
|
|
8
|
+
// per-client resident state — durable per-client state is the clients table
|
|
9
|
+
// (lastMutationID + group→user binding) only.
|
|
10
|
+
//
|
|
11
|
+
// wire contract (pinned by ~/orez/plans/zero-http.md VERDICT +
|
|
12
|
+
// ~/orez/src/zero-http/server.test.ts, prod-proven by soot's
|
|
13
|
+
// src/zero/httpPull.server.ts):
|
|
14
|
+
// POST /pull {clientID, clientGroupID, cookie:number|null}
|
|
15
|
+
// -> {cookie, lastMutationIDChanges, rowsPatch}
|
|
16
|
+
// rowsPatch is put/del diffs when the cookie is within the retained
|
|
17
|
+
// change window, else [{op:'clear'},...puts] (fresh client, cookie
|
|
18
|
+
// below the retention floor, or per-user visibility filtering)
|
|
19
|
+
// -> {cookie, unchanged:true} when cookie === watermark
|
|
20
|
+
// -> 409 when cookie > watermark (client rebuilds via
|
|
21
|
+
// InvalidConnectionRequestBaseCookie)
|
|
22
|
+
// POST /push <v51 push body> -> {pushResponse}
|
|
23
|
+
// replayed ids ack idempotently; app errors advance the LMID and make no
|
|
24
|
+
// row change. every LMID advance appends a change-log marker so pulls
|
|
25
|
+
// never report `unchanged` past it (mutation RECOVERY settles via
|
|
26
|
+
// lastMutationIDChanges in a non-unchanged pull, so an LMID-only push —
|
|
27
|
+
// e.g. an app error — must still advance the cookie).
|
|
28
|
+
//
|
|
29
|
+
// the cookie is the change log's high watermark (rewrite phase 2, see
|
|
30
|
+
// plans/zero-server-rewrite.md). sqlite triggers installed per table feed
|
|
31
|
+
// _zsync_changes for EVERY write path — mutators and upstream/admin sql
|
|
32
|
+
// alike — a watermark-autoincrement log like orez's production
|
|
33
|
+
// `_zero_changes`, but storing touched pks only (diffs re-read live rows).
|
|
34
|
+
// retention is size-bounded: pruned changes raise the floor and clients
|
|
35
|
+
// below it get a snapshot.
|
|
36
|
+
//
|
|
37
|
+
// hosting: the caller provides the sqlite handle and the http layer. bun/node
|
|
38
|
+
// pass bun:sqlite / better-sqlite3 adapters; a DO passes ctx.storage.sql
|
|
39
|
+
// (which supports CREATE TRIGGER; probed 2026-07-09).
|
|
40
|
+
export class SyncHttpError extends Error {
|
|
41
|
+
status;
|
|
42
|
+
constructor(status, message) {
|
|
43
|
+
super(message);
|
|
44
|
+
this.status = status;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
// thrown by mutators for application-level failures: the mutation's row
|
|
48
|
+
// changes roll back, the LMID still advances, the client rolls back its
|
|
49
|
+
// optimistic state
|
|
50
|
+
export class MutationAppError extends Error {
|
|
51
|
+
details;
|
|
52
|
+
constructor(details, message = details) {
|
|
53
|
+
super(message);
|
|
54
|
+
this.details = details;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function isRecord(value) {
|
|
58
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
59
|
+
}
|
|
60
|
+
function isNonNegativeInteger(value) {
|
|
61
|
+
return typeof value === 'number' && Number.isSafeInteger(value) && value >= 0;
|
|
62
|
+
}
|
|
63
|
+
function validatePullBody(body) {
|
|
64
|
+
if (!isRecord(body) ||
|
|
65
|
+
typeof body.clientID !== 'string' ||
|
|
66
|
+
typeof body.clientGroupID !== 'string' ||
|
|
67
|
+
(body.cookie !== null && !isNonNegativeInteger(body.cookie))) {
|
|
68
|
+
throw new SyncHttpError(400, 'invalid pull body');
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function validatePushBody(body) {
|
|
72
|
+
if (!isRecord(body) ||
|
|
73
|
+
typeof body.clientGroupID !== 'string' ||
|
|
74
|
+
!Array.isArray(body.mutations) ||
|
|
75
|
+
typeof body.pushVersion !== 'number' ||
|
|
76
|
+
!Number.isFinite(body.pushVersion)) {
|
|
77
|
+
throw new SyncHttpError(400, 'invalid push body');
|
|
78
|
+
}
|
|
79
|
+
for (const [index, mutation] of body.mutations.entries()) {
|
|
80
|
+
if (!isRecord(mutation) ||
|
|
81
|
+
mutation.type !== 'custom' ||
|
|
82
|
+
!isNonNegativeInteger(mutation.id) ||
|
|
83
|
+
mutation.id === 0 ||
|
|
84
|
+
typeof mutation.clientID !== 'string' ||
|
|
85
|
+
typeof mutation.name !== 'string' ||
|
|
86
|
+
!Array.isArray(mutation.args)) {
|
|
87
|
+
throw new SyncHttpError(400, `invalid mutation at index ${index}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// derive the tables spec from a zero createSchema() result
|
|
92
|
+
export function tablesFromZeroSchema(schema) {
|
|
93
|
+
const tables = {};
|
|
94
|
+
for (const [name, table] of Object.entries(schema.tables)) {
|
|
95
|
+
const columns = {};
|
|
96
|
+
for (const [col, spec] of Object.entries(table.columns)) {
|
|
97
|
+
columns[col] = spec.type;
|
|
98
|
+
}
|
|
99
|
+
tables[name] = { columns, primaryKey: [...table.primaryKey] };
|
|
100
|
+
}
|
|
101
|
+
return tables;
|
|
102
|
+
}
|
|
103
|
+
// sqlite stores booleans as 0/1 and json as text; rowsPatch values must
|
|
104
|
+
// match the zero schema's column types (same conversion zero-cache's
|
|
105
|
+
// replication does, mirrored from soot's toZeroValue)
|
|
106
|
+
function toZeroValue(type, raw) {
|
|
107
|
+
if (raw === null || raw === undefined)
|
|
108
|
+
return null;
|
|
109
|
+
if (type === 'boolean') {
|
|
110
|
+
if (typeof raw === 'boolean')
|
|
111
|
+
return raw;
|
|
112
|
+
return raw === 1 || raw === '1' || raw === 'true' || raw === 't';
|
|
113
|
+
}
|
|
114
|
+
if (type === 'number' && typeof raw === 'string') {
|
|
115
|
+
const numeric = Number(raw);
|
|
116
|
+
if (Number.isFinite(numeric))
|
|
117
|
+
return numeric;
|
|
118
|
+
}
|
|
119
|
+
if (type === 'json' && typeof raw === 'string') {
|
|
120
|
+
return JSON.parse(raw);
|
|
121
|
+
}
|
|
122
|
+
return raw;
|
|
123
|
+
}
|
|
124
|
+
export function createSyncServer(config) {
|
|
125
|
+
const { db, tables } = config;
|
|
126
|
+
const retainChanges = config.retainChanges ?? 4096;
|
|
127
|
+
db.exec(`CREATE TABLE IF NOT EXISTS _zsync_clients (
|
|
128
|
+
clientGroupID TEXT NOT NULL,
|
|
129
|
+
clientID TEXT NOT NULL,
|
|
130
|
+
lastMutationID INTEGER NOT NULL,
|
|
131
|
+
userID TEXT,
|
|
132
|
+
PRIMARY KEY (clientGroupID, clientID)
|
|
133
|
+
)`);
|
|
134
|
+
db.exec(`CREATE TABLE IF NOT EXISTS _zsync_meta (
|
|
135
|
+
lock INTEGER PRIMARY KEY CHECK (lock = 1),
|
|
136
|
+
floor INTEGER NOT NULL
|
|
137
|
+
)`);
|
|
138
|
+
db.exec(`INSERT INTO _zsync_meta (lock, floor) VALUES (1, 0)
|
|
139
|
+
ON CONFLICT (lock) DO NOTHING`);
|
|
140
|
+
// the change log records WHICH pks were touched, never row values: sqlite's
|
|
141
|
+
// json functions format REAL at 15 significant digits (probed: 0.1+0.2 →
|
|
142
|
+
// 0.3), so row images through json_object would corrupt float columns. the
|
|
143
|
+
// diff pull re-reads live rows in its own transaction instead — exists=put,
|
|
144
|
+
// gone=del — which is also trivially consistent with pull-time state.
|
|
145
|
+
// op 'marker' rows carry no pk; they only advance the watermark (LMID-only
|
|
146
|
+
// pushes, epoch invalidation). (pk values themselves do pass through
|
|
147
|
+
// json_object: TEXT/INTEGER are exact, so don't use REAL primary keys.)
|
|
148
|
+
db.exec(`CREATE TABLE IF NOT EXISTS _zsync_changes (
|
|
149
|
+
watermark INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
150
|
+
tableName TEXT NOT NULL,
|
|
151
|
+
op TEXT NOT NULL CHECK (op IN ('row', 'marker')),
|
|
152
|
+
pk TEXT
|
|
153
|
+
)`);
|
|
154
|
+
// triggers capture EVERY write path into the change log — mutators inside
|
|
155
|
+
// handlePush and upstream/admin sql alike. installed AFTER any seed so the
|
|
156
|
+
// initial dataset stays out of the log (fresh clients snapshot anyway).
|
|
157
|
+
// updates log OLD and NEW pks so a pk-changing UPDATE dels the old row.
|
|
158
|
+
for (const [table, spec] of Object.entries(tables)) {
|
|
159
|
+
const pkObject = (ref) => `json_object(${spec.primaryKey.map((col) => `'${col}', ${ref}."${col}"`).join(', ')})`;
|
|
160
|
+
db.exec(`CREATE TRIGGER IF NOT EXISTS "_zsync_tr_${table}_i" AFTER INSERT ON "${table}" BEGIN
|
|
161
|
+
INSERT INTO _zsync_changes (tableName, op, pk)
|
|
162
|
+
VALUES ('${table}', 'row', ${pkObject('NEW')});
|
|
163
|
+
END`);
|
|
164
|
+
db.exec(`CREATE TRIGGER IF NOT EXISTS "_zsync_tr_${table}_u" AFTER UPDATE ON "${table}" BEGIN
|
|
165
|
+
INSERT INTO _zsync_changes (tableName, op, pk)
|
|
166
|
+
VALUES ('${table}', 'row', ${pkObject('OLD')});
|
|
167
|
+
INSERT INTO _zsync_changes (tableName, op, pk)
|
|
168
|
+
VALUES ('${table}', 'row', ${pkObject('NEW')});
|
|
169
|
+
END`);
|
|
170
|
+
db.exec(`CREATE TRIGGER IF NOT EXISTS "_zsync_tr_${table}_d" AFTER DELETE ON "${table}" BEGIN
|
|
171
|
+
INSERT INTO _zsync_changes (tableName, op, pk)
|
|
172
|
+
VALUES ('${table}', 'row', ${pkObject('OLD')});
|
|
173
|
+
END`);
|
|
174
|
+
}
|
|
175
|
+
// the cookie: high watermark of the change log (0 = pristine/seed-only)
|
|
176
|
+
function watermark() {
|
|
177
|
+
return Number(db.all(`SELECT COALESCE(MAX(watermark), 0) AS w FROM _zsync_changes`)[0].w);
|
|
178
|
+
}
|
|
179
|
+
function floorValue() {
|
|
180
|
+
return Number(db.all(`SELECT floor FROM _zsync_meta`)[0].floor);
|
|
181
|
+
}
|
|
182
|
+
function pruneChanges() {
|
|
183
|
+
const cutoff = watermark() - retainChanges;
|
|
184
|
+
if (cutoff > floorValue()) {
|
|
185
|
+
db.exec(`DELETE FROM _zsync_changes WHERE watermark <= ?`, [cutoff]);
|
|
186
|
+
db.exec(`UPDATE _zsync_meta SET floor = ?`, [cutoff]);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
// epoch bump: forces every client's next pull to be a full snapshot — for
|
|
190
|
+
// changes no row diff can express (visibility/membership revocation,
|
|
191
|
+
// table-set change). the marker advances the watermark so no cookie can
|
|
192
|
+
// answer `unchanged`; the floor then rises past every prior cookie. one
|
|
193
|
+
// recovery path: same snapshot the fresh-client and below-retention cases
|
|
194
|
+
// use. measured prod project snapshots are sub-MB (see
|
|
195
|
+
// plans/zero-server-rewrite.md), so a global epoch is deliberately the
|
|
196
|
+
// whole mechanism — no per-user bookkeeping.
|
|
197
|
+
function invalidate() {
|
|
198
|
+
db.transaction(() => {
|
|
199
|
+
db.exec(`INSERT INTO _zsync_changes (tableName, op, pk)
|
|
200
|
+
VALUES ('_zsync_meta', 'marker', NULL)`);
|
|
201
|
+
db.exec(`UPDATE _zsync_meta SET floor =
|
|
202
|
+
(SELECT COALESCE(MAX(watermark), 0) FROM _zsync_changes)`);
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
// guarded claim (soot's claimStatement, sqlite dialect): bind the group to
|
|
206
|
+
// this user unless another user already owns it; adopt userID-less rows
|
|
207
|
+
function claimClient(clientGroupID, clientID, userID) {
|
|
208
|
+
// plain positional ? only (repeated params passed twice): DO SqlStorage
|
|
209
|
+
// does not support ?N numbered bindings
|
|
210
|
+
db.exec(`INSERT INTO _zsync_clients (clientGroupID, clientID, lastMutationID, userID)
|
|
211
|
+
SELECT ?, ?, 0, ?
|
|
212
|
+
WHERE NOT EXISTS (
|
|
213
|
+
SELECT 1 FROM _zsync_clients
|
|
214
|
+
WHERE clientGroupID = ? AND userID IS NOT NULL AND userID <> ?
|
|
215
|
+
)
|
|
216
|
+
ON CONFLICT (clientGroupID, clientID)
|
|
217
|
+
DO UPDATE SET userID = excluded.userID WHERE userID IS NULL`, [clientGroupID, clientID, userID, clientGroupID, userID]);
|
|
218
|
+
const owners = db.all(`SELECT DISTINCT userID FROM _zsync_clients
|
|
219
|
+
WHERE clientGroupID = ? AND userID IS NOT NULL`, [clientGroupID]);
|
|
220
|
+
for (const row of owners) {
|
|
221
|
+
if (row.userID !== userID) {
|
|
222
|
+
throw new SyncHttpError(403, 'client group belongs to a different user');
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
function visibleRows(table, userID) {
|
|
227
|
+
const filter = config.visible?.(table, userID);
|
|
228
|
+
if (filter)
|
|
229
|
+
return db.all(filter.sql, filter.params);
|
|
230
|
+
return db.all(`SELECT * FROM "${table}"`);
|
|
231
|
+
}
|
|
232
|
+
function handlePull(body, userID) {
|
|
233
|
+
validatePullBody(body);
|
|
234
|
+
const { clientID, clientGroupID, cookie } = body;
|
|
235
|
+
// one synchronous sqlite transaction = one consistent view (soot needed
|
|
236
|
+
// repeatable-read gymnastics on pg; sqlite gives it for free)
|
|
237
|
+
return db.transaction(() => {
|
|
238
|
+
claimClient(clientGroupID, clientID, userID);
|
|
239
|
+
// Upstream/admin writes also feed the log, so a read-only workload must
|
|
240
|
+
// not depend on a later client push to enforce retention.
|
|
241
|
+
pruneChanges();
|
|
242
|
+
const current = watermark();
|
|
243
|
+
if (cookie !== null && cookie > current) {
|
|
244
|
+
throw new SyncHttpError(409, `future cookie ${cookie} is ahead of watermark ${current}`);
|
|
245
|
+
}
|
|
246
|
+
if (cookie === current) {
|
|
247
|
+
return { cookie: current, unchanged: true };
|
|
248
|
+
}
|
|
249
|
+
const lastMutationIDChanges = {};
|
|
250
|
+
for (const row of db.all(`SELECT clientID, lastMutationID FROM _zsync_clients WHERE clientGroupID = ?`, [clientGroupID])) {
|
|
251
|
+
lastMutationIDChanges[row.clientID] = Number(row.lastMutationID);
|
|
252
|
+
}
|
|
253
|
+
// diff pulls need uniform visibility (the project-plane assumption):
|
|
254
|
+
// a per-user visible() filter can revoke rows without any row change,
|
|
255
|
+
// which no diff can express — those configs always snapshot
|
|
256
|
+
const canDiff = cookie !== null && cookie >= floorValue() && config.visible === undefined;
|
|
257
|
+
const rowsPatch = canDiff ? diffPatch(cookie) : snapshotPatch(userID);
|
|
258
|
+
return { cookie: current, lastMutationIDChanges, rowsPatch };
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
function snapshotPatch(userID) {
|
|
262
|
+
const rowsPatch = [{ op: 'clear' }];
|
|
263
|
+
for (const [table, spec] of Object.entries(tables)) {
|
|
264
|
+
for (const row of visibleRows(table, userID)) {
|
|
265
|
+
const value = {};
|
|
266
|
+
for (const [col, type] of Object.entries(spec.columns)) {
|
|
267
|
+
value[col] = toZeroValue(type, row[col]);
|
|
268
|
+
}
|
|
269
|
+
rowsPatch.push({ op: 'put', tableName: table, value });
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
return rowsPatch;
|
|
273
|
+
}
|
|
274
|
+
// pks touched since the cookie, deduped, then resolved against LIVE table
|
|
275
|
+
// state inside the pull transaction: row exists -> put (current values),
|
|
276
|
+
// row gone -> del. no row images in the log, no op coalescing to get wrong.
|
|
277
|
+
function diffPatch(cookie) {
|
|
278
|
+
const touched = new Map();
|
|
279
|
+
for (const change of db.all(`SELECT DISTINCT tableName, pk FROM _zsync_changes
|
|
280
|
+
WHERE watermark > ? AND op = 'row'`, [cookie])) {
|
|
281
|
+
const table = change.tableName;
|
|
282
|
+
const pkText = change.pk;
|
|
283
|
+
touched.set(`${table} ${pkText}`, { table, pk: JSON.parse(pkText) });
|
|
284
|
+
}
|
|
285
|
+
const rowsPatch = [];
|
|
286
|
+
for (const { table, pk } of touched.values()) {
|
|
287
|
+
const spec = tables[table];
|
|
288
|
+
const where = spec.primaryKey.map((col) => `"${col}" = ?`).join(' AND ');
|
|
289
|
+
const params = spec.primaryKey.map((col) => pk[col]);
|
|
290
|
+
const row = db.all(`SELECT * FROM "${table}" WHERE ${where}`, params)[0];
|
|
291
|
+
if (!row) {
|
|
292
|
+
const id = {};
|
|
293
|
+
for (const col of spec.primaryKey)
|
|
294
|
+
id[col] = toZeroValue(spec.columns[col], pk[col]);
|
|
295
|
+
rowsPatch.push({ op: 'del', tableName: table, id });
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
const value = {};
|
|
299
|
+
for (const [col, type] of Object.entries(spec.columns)) {
|
|
300
|
+
value[col] = toZeroValue(type, row[col]);
|
|
301
|
+
}
|
|
302
|
+
rowsPatch.push({ op: 'put', tableName: table, value });
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
return rowsPatch;
|
|
306
|
+
}
|
|
307
|
+
function handlePush(body, userID) {
|
|
308
|
+
validatePushBody(body);
|
|
309
|
+
const { clientGroupID, mutations } = body;
|
|
310
|
+
// The pinned client still accepts this legacy pushResponse error form.
|
|
311
|
+
// It is the direct-transport equivalent of zero-cache's PushFailed /
|
|
312
|
+
// unsupportedPushVersion response and prevents any mutation processing.
|
|
313
|
+
if (body.pushVersion !== 1) {
|
|
314
|
+
return {
|
|
315
|
+
pushResponse: {
|
|
316
|
+
error: 'unsupportedPushVersion',
|
|
317
|
+
mutationIDs: mutations.map(({ clientID, id }) => ({ clientID, id })),
|
|
318
|
+
},
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
const results = [];
|
|
322
|
+
for (const mutation of mutations) {
|
|
323
|
+
// each mutation commits atomically (rows + LMID advance in one tx). an
|
|
324
|
+
// app error aborts that whole tx, then a SECOND tx advances the LMID
|
|
325
|
+
// and records the error — same net semantics as a savepoint rollback,
|
|
326
|
+
// but with NO savepoint: DO sqlite forbids raw SAVEPOINT/BEGIN (only
|
|
327
|
+
// storage.transactionSync). crash between the two txs is safe: nothing
|
|
328
|
+
// committed, replay re-executes and hits the same app error.
|
|
329
|
+
const applyMutation = (executeMutator) => db.transaction(() => {
|
|
330
|
+
claimClient(clientGroupID, mutation.clientID, userID);
|
|
331
|
+
const lmid = Number(db.all(`SELECT lastMutationID FROM _zsync_clients
|
|
332
|
+
WHERE clientGroupID = ? AND clientID = ?`, [clientGroupID, mutation.clientID])[0].lastMutationID);
|
|
333
|
+
if (mutation.id <= lmid)
|
|
334
|
+
return { status: 'replay', expectedID: lmid + 1 };
|
|
335
|
+
if (mutation.id > lmid + 1) {
|
|
336
|
+
throw new SyncHttpError(400, `mutation id ${mutation.id} skips lmid ${lmid} (out of order)`);
|
|
337
|
+
}
|
|
338
|
+
if (executeMutator) {
|
|
339
|
+
config.mutate(db, mutation.name, mutation.args[0], { userID });
|
|
340
|
+
}
|
|
341
|
+
db.exec(`UPDATE _zsync_clients SET lastMutationID = ?
|
|
342
|
+
WHERE clientGroupID = ? AND clientID = ?`, [mutation.id, clientGroupID, mutation.clientID]);
|
|
343
|
+
// watermark marker: an LMID-only mutation (app error) must still
|
|
344
|
+
// advance the cookie or group peers' pulls stay `unchanged` and
|
|
345
|
+
// mutation recovery never settles
|
|
346
|
+
db.exec(`INSERT INTO _zsync_changes (tableName, op, pk)
|
|
347
|
+
VALUES ('_zsync_clients', 'marker', NULL)`);
|
|
348
|
+
return { status: 'applied' };
|
|
349
|
+
});
|
|
350
|
+
const id = { clientID: mutation.clientID, id: mutation.id };
|
|
351
|
+
try {
|
|
352
|
+
const applied = applyMutation(true);
|
|
353
|
+
results.push({
|
|
354
|
+
id,
|
|
355
|
+
result: applied.status === 'replay'
|
|
356
|
+
? {
|
|
357
|
+
error: 'alreadyProcessed',
|
|
358
|
+
details: `Ignoring mutation from ${mutation.clientID} with ID ${mutation.id} as it was already processed. Expected: ${applied.expectedID}`,
|
|
359
|
+
}
|
|
360
|
+
: {},
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
catch (error) {
|
|
364
|
+
if (error instanceof MutationAppError) {
|
|
365
|
+
applyMutation(false);
|
|
366
|
+
results.push({
|
|
367
|
+
id,
|
|
368
|
+
result: { error: 'app', message: error.message, details: error.details },
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
else {
|
|
372
|
+
throw error;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
// size-bounded retention: pruned changes raise the floor; clients whose
|
|
377
|
+
// cookie fell below it get one snapshot on their next pull
|
|
378
|
+
if (mutations.length > 0) {
|
|
379
|
+
db.transaction(pruneChanges);
|
|
380
|
+
}
|
|
381
|
+
return { pushResponse: { mutations: results } };
|
|
382
|
+
}
|
|
383
|
+
return { handlePull, handlePush, watermark, invalidate };
|
|
384
|
+
}
|
|
385
|
+
//# sourceMappingURL=sync-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-server.js","sourceRoot":"","sources":["../../src/sync-server/sync-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zero-sql-write-circuit.d.ts","sourceRoot":"","sources":["../../src/worker/zero-sql-write-circuit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,GAAG,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAA;IAC1C,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,gBAAgB,CAAA;CAC1D;AAED,MAAM,WAAW,mBAAmB;IAClC,kEAAkE;IAClE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,uFAAuF;IACvF,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,sEAAsE;IACtE,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,mDAAmD;IACnD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,6FAA6F;IAC7F,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;
|
|
1
|
+
{"version":3,"file":"zero-sql-write-circuit.d.ts","sourceRoot":"","sources":["../../src/worker/zero-sql-write-circuit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,GAAG,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAA;IAC1C,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,gBAAgB,CAAA;CAC1D;AAED,MAAM,WAAW,mBAAmB;IAClC,kEAAkE;IAClE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,uFAAuF;IACvF,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,sEAAsE;IACtE,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,mDAAmD;IACnD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,6FAA6F;IAC7F,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAkBD;;;GAGG;AACH,wBAAgB,iCAAiC,CAC/C,GAAG,EAAE,iBAAiB,EACtB,IAAI,GAAE,mBAAwB,GAC7B,IAAI,CA+HN"}
|
|
@@ -18,7 +18,15 @@
|
|
|
18
18
|
* from their ZeroSqlDO constructor with their own table/log prefix.
|
|
19
19
|
*/
|
|
20
20
|
// any statement that can write rows (so reads never pay the meter cost).
|
|
21
|
-
const MUTATION_RE = /^\s*(?:insert|update|delete|replace|create|alter|drop|truncate|vacuum|reindex
|
|
21
|
+
const MUTATION_RE = /^\s*(?:insert|update|delete|replace|create|alter|drop|truncate|vacuum|reindex)\b/i;
|
|
22
|
+
// a WITH statement only writes when a data-modifying clause follows the CTEs;
|
|
23
|
+
// WITH ... SELECT is a read and must stay open while tripped (2026-07-10
|
|
24
|
+
// incident: gating `with` wholesale refused CTE reads during recovery). a
|
|
25
|
+
// keyword match inside a literal/identifier only over-gates, never under-gates:
|
|
26
|
+
// a real WITH write always carries insert/update/delete/replace.
|
|
27
|
+
const WITH_RE = /^\s*with\b/i;
|
|
28
|
+
const WITH_MUTATION_RE = /\b(?:insert|update|delete|replace)\b/i;
|
|
29
|
+
const isMutationStatement = (text) => MUTATION_RE.test(text) || (WITH_RE.test(text) && WITH_MUTATION_RE.test(text));
|
|
22
30
|
const INSTALLED = new WeakSet();
|
|
23
31
|
/**
|
|
24
32
|
* wrap `sql.exec` with the runaway-write circuit breaker. idempotent: a second
|
|
@@ -114,7 +122,7 @@ export function installZeroSqlWriteCircuitBreaker(sql, opts = {}) {
|
|
|
114
122
|
sql.exec = (statement, ...params) => {
|
|
115
123
|
const text = String(statement || '');
|
|
116
124
|
const isCircuitStatement = text.includes(table);
|
|
117
|
-
const isMutation =
|
|
125
|
+
const isMutation = isMutationStatement(text) && !isCircuitStatement;
|
|
118
126
|
if (isMutation)
|
|
119
127
|
assertOpen(text);
|
|
120
128
|
const cursor = rawExec(statement, ...params);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zero-sql-write-circuit.js","sourceRoot":"","sources":["../../src/worker/zero-sql-write-circuit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AA0BH,yEAAyE;AACzE,MAAM,WAAW,GACf,
|
|
1
|
+
{"version":3,"file":"zero-sql-write-circuit.js","sourceRoot":"","sources":["../../src/worker/zero-sql-write-circuit.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "orez",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.47",
|
|
4
4
|
"description": "PGlite-powered zero-sync development backend. No Docker required.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -87,7 +87,7 @@
|
|
|
87
87
|
"@electric-sql/pglite": "0.4.1",
|
|
88
88
|
"@electric-sql/pglite-tools": "^0.3.1",
|
|
89
89
|
"@pgsql/traverse": "17.2.6",
|
|
90
|
-
"bedrock-sqlite": "0.4.
|
|
90
|
+
"bedrock-sqlite": "0.4.47",
|
|
91
91
|
"citty": "^0.2.0",
|
|
92
92
|
"pg-gateway": "0.3.0-beta.4",
|
|
93
93
|
"pgsql-parser": "^17.9.11",
|