@rindle/wasm 0.5.0 → 0.6.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/dist/index.d.ts +9 -105
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -94
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/pkg/rindle.d.ts +3 -98
- package/pkg/rindle.js +3 -210
- package/pkg/rindle_bg.wasm +0 -0
- package/pkg/rindle_bg.wasm.d.ts +1 -11
- package/src/index.ts +15 -148
package/dist/index.d.ts
CHANGED
|
@@ -1,29 +1,6 @@
|
|
|
1
1
|
import { Store } from "@rindle/client";
|
|
2
|
-
import type { Ast, Backend, ChangeEvent, ColsMap,
|
|
2
|
+
import type { Ast, Backend, ChangeEvent, ColsMap, Mutation, QueryId, Schema } from "@rindle/client";
|
|
3
3
|
export * from "@rindle/client";
|
|
4
|
-
/** A serializable writable-scope descriptor: how the merge decides, per row, whether an attached
|
|
5
|
-
* room may write it (the room copy then wins, RINDLE-REALTIME-QUERY-ENABLEMENT-DESIGN.md §5.2).
|
|
6
|
-
* `"all"` = the room owns every row it holds; `"none"` = a context table the daemon stays
|
|
7
|
-
* authoritative for; `"colEq"` = writable iff `row[col] === value` (harness stand-in). The REAL
|
|
8
|
-
* shape (Slice G) is `"predicate"`: `where` is the SAME wire {@link Condition} JSON a query AST
|
|
9
|
-
* carries, restricted to what evaluates against a single row — `simple` column-vs-literal leaves
|
|
10
|
-
* under `and`/`or`; a `correlatedSubquery` (or any other non-row-local node) is rejected loudly at
|
|
11
|
-
* `addRoomSource` time. It compiles Rust-side through the engine's OWN filter lowering
|
|
12
|
-
* (`create_predicate`), so writable evaluation can never disagree with query-filter semantics.
|
|
13
|
-
* NOTE: room join-key columns (Slice H) deliberately do NOT cross this boundary — they stay
|
|
14
|
-
* TS-side. */
|
|
15
|
-
export type WritableDescriptor = {
|
|
16
|
-
kind: "all";
|
|
17
|
-
} | {
|
|
18
|
-
kind: "none";
|
|
19
|
-
} | {
|
|
20
|
-
kind: "colEq";
|
|
21
|
-
col: number;
|
|
22
|
-
value: unknown;
|
|
23
|
-
} | {
|
|
24
|
-
kind: "predicate";
|
|
25
|
-
where: Condition;
|
|
26
|
-
};
|
|
27
4
|
/** A raw staged write transaction over the wasm engine — the surface an optimistic client
|
|
28
5
|
* mutator runs against (`get` reads the live state under this txn's staged overlay, so a
|
|
29
6
|
* read-dependent mutator sees its own writes; OPTIMISTIC-WRITES-DESIGN.md §4.1). */
|
|
@@ -42,17 +19,6 @@ export interface WasmWriteTxn {
|
|
|
42
19
|
queryId: number;
|
|
43
20
|
events: unknown[];
|
|
44
21
|
}>;
|
|
45
|
-
/** Like {@link commit}, additionally returning the per-change touched-source key list in staged
|
|
46
|
-
* order (`sources`, e.g. `"daemon"` / `"room:doc:1"`) — the provenance each staged write routed
|
|
47
|
-
* through, captured pre-apply (Slice E-iii-b, design Q1). `batches` is exactly {@link commit}'s
|
|
48
|
-
* return; the source list is additive. */
|
|
49
|
-
commitTracked(): {
|
|
50
|
-
batches: Array<{
|
|
51
|
-
queryId: number;
|
|
52
|
-
events: unknown[];
|
|
53
|
-
}>;
|
|
54
|
-
sources: string[];
|
|
55
|
-
};
|
|
56
22
|
rollback(): void;
|
|
57
23
|
}
|
|
58
24
|
/** One base-table row op of a coherent server delta (the §1.3 `D`), bare cells. */
|
|
@@ -132,80 +98,18 @@ export declare class WasmBackend<S extends ColsMap> implements Backend {
|
|
|
132
98
|
* `onCommitted` runs after `tx.commit()` returns but before `dispatch` delivers to
|
|
133
99
|
* subscribers: a throw from `f` (pre-commit — engine untouched) skips it; a subscriber
|
|
134
100
|
* throw re-raised by `dispatch` happens after it. It is the only point where "the commit
|
|
135
|
-
* is applied" is knowable to a caller that must not confuse the two failure modes.
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
* per-source rebase (optimistic layer un-applied, delta folded in, the source's baseline
|
|
144
|
-
* re-forked) and starts buffering. `sourceKey` names the authority the delta confirms —
|
|
145
|
-
* `"daemon"` today (single-domain); a `room:doc:X` key once the room feed lands. Re-invoke the
|
|
146
|
-
* still-pending mutators via {@link writeWith}, then call {@link serverBatchEnd}. On error the
|
|
147
|
-
* rebase state is poisoned — discard the backend and re-hydrate. */
|
|
148
|
-
serverBatchBegin(sourceKey: string, deltas: ServerDeltaOp[]): void;
|
|
101
|
+
* is applied" is knowable to a caller that must not confuse the two failure modes. */
|
|
102
|
+
writeWith(f: (tx: WasmWriteTxn) => void, onCommitted?: () => void): void;
|
|
103
|
+
/** Open a §1.3 reconcile cycle against the coherent server delta: the engine rewinds every
|
|
104
|
+
* tracked table (optimistic layer un-applied, delta folded in, each table's baseline re-forked)
|
|
105
|
+
* and starts buffering. Re-invoke the still-pending mutators via {@link writeWith}, then call
|
|
106
|
+
* {@link serverBatchEnd}. On error the rebase state is poisoned — discard the backend and
|
|
107
|
+
* re-hydrate. */
|
|
108
|
+
serverBatchBegin(deltas: ServerDeltaOp[]): void;
|
|
149
109
|
/** Close the cycle: the whole buffered stream (rewind + re-invocations) coalesces to
|
|
150
110
|
* the minimal net per query (§3 — a confirmed-correct prediction delivers nothing)
|
|
151
111
|
* and dispatches as ONE batch per affected query on the ordinary event stream. */
|
|
152
112
|
serverBatchEnd(): void;
|
|
153
|
-
/** Attach a room source to `table`, compiling `writable` into the merge's per-row writable scope.
|
|
154
|
-
* Promotes the table Collapsed → Merged on the first room (§5.2); the room seeds empty, so no
|
|
155
|
-
* visible blip. Throws on an untracked (local-only) table or a duplicate room. */
|
|
156
|
-
addRoomSource(table: string, roomKey: string, writable: WritableDescriptor): void;
|
|
157
|
-
/** Detach a room source, emitting the compensating visible deltas on the ordinary event stream. */
|
|
158
|
-
removeRoomSource(table: string, roomKey: string): void;
|
|
159
|
-
/** Park an echoed `row` inertly on `sourceKey`'s slice of `table` (the confirm→echo hold-back
|
|
160
|
-
* window, design §7.3): keeps the row visible so the next per-source rewind of `sourceKey` does
|
|
161
|
-
* not flash-revert a confirmed-elsewhere write before its data echo lands. `sourceKey` is
|
|
162
|
-
* `"daemon"` or a `"room:doc:X"` key. */
|
|
163
|
-
holdBack(table: string, sourceKey: string, row: unknown[]): void;
|
|
164
|
-
/** Park `oldRow`'s pk as ABSENT on `sourceKey`'s slice of `table` — the §7.3 tombstone, the
|
|
165
|
-
* remove-sibling of {@link holdBack} (Slice G-ii): a confirmed cross-slice REMOVE whose delete
|
|
166
|
-
* echo has not landed on `sourceKey` must not resurrect through that source's next rewind. The
|
|
167
|
-
* overlay masks the pk (overlay-first) until the source's re-forked baseline lacks it (the
|
|
168
|
-
* delete echoed), then drops. `oldRow` is the full-width PRE-IMAGE row (same positional
|
|
169
|
-
* bare-cell marshaling as {@link holdBack}); it carries the pk and, later (Slice H), the cells
|
|
170
|
-
* writable-scope predicates evaluate on. */
|
|
171
|
-
holdBackAbsent(table: string, sourceKey: string, oldRow: unknown[]): void;
|
|
172
|
-
/** Drop one parked §7.3 hold-back at `probe`'s pk on `sourceKey`'s slice and reconcile the
|
|
173
|
-
* pk's visible winner — the §301 FENCE-driven drop (`301-ECHO-FENCE-DESIGN.md` §2.2), fired
|
|
174
|
-
* by the optimistic backend's pin registry once `sourceKey`'s stream has provably delivered
|
|
175
|
-
* through the pinned write's commit. Unlike the park-time seams (whose install is a no-op by
|
|
176
|
-
* construction) a drop is exactly the moment a masked authoritative row becomes visible, so
|
|
177
|
-
* the engine's compensating deltas are DELIVERED here: dispatched on the ordinary event
|
|
178
|
-
* stream (or folded into an open server-batch cycle's one delivery). No-op when nothing is
|
|
179
|
-
* parked at the pk — the rewind's state-match fallback may have raced it. */
|
|
180
|
-
dropHeldBack(table: string, sourceKey: string, probe: unknown[]): void;
|
|
181
|
-
/** The parked hold-back at `probe`'s pk on `sourceKey`'s slice, or `undefined` (§301
|
|
182
|
-
* introspection): `absent` names the tombstone variant; `baseline` is the source's CURRENT
|
|
183
|
-
* confirmed-baseline row at the pk (`undefined` when the baseline lacks it) — the pin
|
|
184
|
-
* registry's lazy-prune probe and the §2.5 stuck-pin tripwire input. Non-throwing on an
|
|
185
|
-
* unknown source (a removed room), so pruning after a whole-source removal just works. */
|
|
186
|
-
heldBackState(table: string, sourceKey: string, probe: unknown[]): {
|
|
187
|
-
absent: boolean;
|
|
188
|
-
baseline: unknown[] | undefined;
|
|
189
|
-
} | undefined;
|
|
190
|
-
/** Freeze a physical source — the D4 downgrade-ghost stub (wins-if-present in the merge). */
|
|
191
|
-
freezeSource(table: string, sourceKey: string): void;
|
|
192
|
-
/** The source currently serving `row`'s pk on `table` — `"daemon"`, a room key, or `undefined`
|
|
193
|
-
* when no source holds the pk (Slice H-i routing probe #1, design §3.2 #3). `row` is a
|
|
194
|
-
* full-width positional row (the pk derives from it — same marshaling as {@link holdBack});
|
|
195
|
-
* an unknown table throws loudly. Reads the LIVE visible state, overlay-first (§7.3): an open
|
|
196
|
-
* write txn's staged-but-uncommitted rows are NOT consulted (they have not routed yet), which
|
|
197
|
-
* is exactly the pre-commit view the §3 routing proof decides on — a present read is proven
|
|
198
|
-
* room-covered iff this reports the occupied room. */
|
|
199
|
-
provenanceOf(table: string, row: unknown[]): string | undefined;
|
|
200
|
-
/** Evaluate the REGISTERED writable scope of `table`'s room source `roomKey` against a
|
|
201
|
-
* caller-supplied full-width row (Slice H-i routing probe #2, design §3.1): a prediction-run
|
|
202
|
-
* write is proven room-covered iff this is `true` on the written row. Runs the SAME compiled
|
|
203
|
-
* predicate the merge's winner tiering uses (the {@link WritableDescriptor} registered at
|
|
204
|
-
* {@link addRoomSource}), so routing can never disagree with the engine; `all` ⇒ always true,
|
|
205
|
-
* `none` ⇒ always false, and a frozen source still answers (the predicate is static). Throws
|
|
206
|
-
* loudly on an unknown table, a room key not attached to the table, a wrong-width row, or
|
|
207
|
-
* `"daemon"` (which has no writable scope). */
|
|
208
|
-
writableMatches(table: string, roomKey: string, row: unknown[]): boolean;
|
|
209
113
|
}
|
|
210
114
|
/** Convenience: init the wasm + return a ready local {@link Store}. */
|
|
211
115
|
export declare function createWasmStore<S extends ColsMap>(schema: Schema<S>): Promise<Store<S>>;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA,OAAO,EAAmB,KAAK,EAAa,MAAM,gBAAgB,CAAC;AACnE,OAAO,KAAK,EACV,GAAG,EACH,OAAO,EACP,WAAW,EACX,OAAO,EACP,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -191,28 +191,21 @@ export class WasmBackend {
|
|
|
191
191
|
* `onCommitted` runs after `tx.commit()` returns but before `dispatch` delivers to
|
|
192
192
|
* subscribers: a throw from `f` (pre-commit — engine untouched) skips it; a subscriber
|
|
193
193
|
* throw re-raised by `dispatch` happens after it. It is the only point where "the commit
|
|
194
|
-
* is applied" is knowable to a caller that must not confuse the two failure modes.
|
|
195
|
-
*
|
|
196
|
-
* Returns the per-change **touched-source key list** in staged-write order (`"daemon"` /
|
|
197
|
-
* `"room:doc:X"`, Slice E-iii-b design Q1) — additive; every current caller (`mutate`,
|
|
198
|
-
* `writeLocal`, `@rindle/optimistic`) ignores it. The per-source reconcile (Slice E-iii-c) zips
|
|
199
|
-
* it with the mutation's write-set for the per-pk hold-back source. */
|
|
194
|
+
* is applied" is knowable to a caller that must not confuse the two failure modes. */
|
|
200
195
|
writeWith(f, onCommitted) {
|
|
201
196
|
const tx = this.db.write();
|
|
202
197
|
f(tx);
|
|
203
|
-
const
|
|
198
|
+
const batches = tx.commit();
|
|
204
199
|
onCommitted?.();
|
|
205
200
|
this.dispatch(batches);
|
|
206
|
-
return sources;
|
|
207
201
|
}
|
|
208
|
-
/** Open a §1.3 reconcile cycle against the coherent server delta: the engine rewinds
|
|
209
|
-
*
|
|
210
|
-
*
|
|
211
|
-
*
|
|
212
|
-
*
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
this.db.serverBatchBegin(sourceKey, deltas);
|
|
202
|
+
/** Open a §1.3 reconcile cycle against the coherent server delta: the engine rewinds every
|
|
203
|
+
* tracked table (optimistic layer un-applied, delta folded in, each table's baseline re-forked)
|
|
204
|
+
* and starts buffering. Re-invoke the still-pending mutators via {@link writeWith}, then call
|
|
205
|
+
* {@link serverBatchEnd}. On error the rebase state is poisoned — discard the backend and
|
|
206
|
+
* re-hydrate. */
|
|
207
|
+
serverBatchBegin(deltas) {
|
|
208
|
+
this.db.serverBatchBegin(deltas);
|
|
216
209
|
}
|
|
217
210
|
/** Close the cycle: the whole buffered stream (rewind + re-invocations) coalesces to
|
|
218
211
|
* the minimal net per query (§3 — a confirmed-correct prediction delivers nothing)
|
|
@@ -220,84 +213,6 @@ export class WasmBackend {
|
|
|
220
213
|
serverBatchEnd() {
|
|
221
214
|
this.dispatch(this.db.serverBatchEnd());
|
|
222
215
|
}
|
|
223
|
-
// --- multi-source seams (Slice E-iii-b harness → Slice G-ii ABI) ------------------
|
|
224
|
-
//
|
|
225
|
-
// Thin pass-throughs to the engine's `Merge` (RINDLE-REALTIME-QUERY-ENABLEMENT-DESIGN.md §5).
|
|
226
|
-
// `addRoomSource`'s {@link WritableDescriptor} now carries the real row-local `predicate` arm
|
|
227
|
-
// (a wire-Condition `where`, compiled Rust-side through the engine's own filter lowering)
|
|
228
|
-
// alongside the narrow `all`/`none`/`colEq` harness shapes. Single-domain behavior is untouched
|
|
229
|
-
// unless `addRoomSource` is called (a table stays Collapsed = today's daemon-only path).
|
|
230
|
-
/** Attach a room source to `table`, compiling `writable` into the merge's per-row writable scope.
|
|
231
|
-
* Promotes the table Collapsed → Merged on the first room (§5.2); the room seeds empty, so no
|
|
232
|
-
* visible blip. Throws on an untracked (local-only) table or a duplicate room. */
|
|
233
|
-
addRoomSource(table, roomKey, writable) {
|
|
234
|
-
this.db.addRoomSource(table, roomKey, writable);
|
|
235
|
-
}
|
|
236
|
-
/** Detach a room source, emitting the compensating visible deltas on the ordinary event stream. */
|
|
237
|
-
removeRoomSource(table, roomKey) {
|
|
238
|
-
this.db.removeRoomSource(table, roomKey);
|
|
239
|
-
}
|
|
240
|
-
/** Park an echoed `row` inertly on `sourceKey`'s slice of `table` (the confirm→echo hold-back
|
|
241
|
-
* window, design §7.3): keeps the row visible so the next per-source rewind of `sourceKey` does
|
|
242
|
-
* not flash-revert a confirmed-elsewhere write before its data echo lands. `sourceKey` is
|
|
243
|
-
* `"daemon"` or a `"room:doc:X"` key. */
|
|
244
|
-
holdBack(table, sourceKey, row) {
|
|
245
|
-
this.db.holdBack(table, sourceKey, row);
|
|
246
|
-
}
|
|
247
|
-
/** Park `oldRow`'s pk as ABSENT on `sourceKey`'s slice of `table` — the §7.3 tombstone, the
|
|
248
|
-
* remove-sibling of {@link holdBack} (Slice G-ii): a confirmed cross-slice REMOVE whose delete
|
|
249
|
-
* echo has not landed on `sourceKey` must not resurrect through that source's next rewind. The
|
|
250
|
-
* overlay masks the pk (overlay-first) until the source's re-forked baseline lacks it (the
|
|
251
|
-
* delete echoed), then drops. `oldRow` is the full-width PRE-IMAGE row (same positional
|
|
252
|
-
* bare-cell marshaling as {@link holdBack}); it carries the pk and, later (Slice H), the cells
|
|
253
|
-
* writable-scope predicates evaluate on. */
|
|
254
|
-
holdBackAbsent(table, sourceKey, oldRow) {
|
|
255
|
-
this.db.holdBackAbsent(table, sourceKey, oldRow);
|
|
256
|
-
}
|
|
257
|
-
/** Drop one parked §7.3 hold-back at `probe`'s pk on `sourceKey`'s slice and reconcile the
|
|
258
|
-
* pk's visible winner — the §301 FENCE-driven drop (`301-ECHO-FENCE-DESIGN.md` §2.2), fired
|
|
259
|
-
* by the optimistic backend's pin registry once `sourceKey`'s stream has provably delivered
|
|
260
|
-
* through the pinned write's commit. Unlike the park-time seams (whose install is a no-op by
|
|
261
|
-
* construction) a drop is exactly the moment a masked authoritative row becomes visible, so
|
|
262
|
-
* the engine's compensating deltas are DELIVERED here: dispatched on the ordinary event
|
|
263
|
-
* stream (or folded into an open server-batch cycle's one delivery). No-op when nothing is
|
|
264
|
-
* parked at the pk — the rewind's state-match fallback may have raced it. */
|
|
265
|
-
dropHeldBack(table, sourceKey, probe) {
|
|
266
|
-
this.dispatch(this.db.dropHeldBack(table, sourceKey, probe));
|
|
267
|
-
}
|
|
268
|
-
/** The parked hold-back at `probe`'s pk on `sourceKey`'s slice, or `undefined` (§301
|
|
269
|
-
* introspection): `absent` names the tombstone variant; `baseline` is the source's CURRENT
|
|
270
|
-
* confirmed-baseline row at the pk (`undefined` when the baseline lacks it) — the pin
|
|
271
|
-
* registry's lazy-prune probe and the §2.5 stuck-pin tripwire input. Non-throwing on an
|
|
272
|
-
* unknown source (a removed room), so pruning after a whole-source removal just works. */
|
|
273
|
-
heldBackState(table, sourceKey, probe) {
|
|
274
|
-
return this.db.heldBackState(table, sourceKey, probe);
|
|
275
|
-
}
|
|
276
|
-
/** Freeze a physical source — the D4 downgrade-ghost stub (wins-if-present in the merge). */
|
|
277
|
-
freezeSource(table, sourceKey) {
|
|
278
|
-
this.db.freezeSource(table, sourceKey);
|
|
279
|
-
}
|
|
280
|
-
/** The source currently serving `row`'s pk on `table` — `"daemon"`, a room key, or `undefined`
|
|
281
|
-
* when no source holds the pk (Slice H-i routing probe #1, design §3.2 #3). `row` is a
|
|
282
|
-
* full-width positional row (the pk derives from it — same marshaling as {@link holdBack});
|
|
283
|
-
* an unknown table throws loudly. Reads the LIVE visible state, overlay-first (§7.3): an open
|
|
284
|
-
* write txn's staged-but-uncommitted rows are NOT consulted (they have not routed yet), which
|
|
285
|
-
* is exactly the pre-commit view the §3 routing proof decides on — a present read is proven
|
|
286
|
-
* room-covered iff this reports the occupied room. */
|
|
287
|
-
provenanceOf(table, row) {
|
|
288
|
-
return this.db.provenanceOf(table, row);
|
|
289
|
-
}
|
|
290
|
-
/** Evaluate the REGISTERED writable scope of `table`'s room source `roomKey` against a
|
|
291
|
-
* caller-supplied full-width row (Slice H-i routing probe #2, design §3.1): a prediction-run
|
|
292
|
-
* write is proven room-covered iff this is `true` on the written row. Runs the SAME compiled
|
|
293
|
-
* predicate the merge's winner tiering uses (the {@link WritableDescriptor} registered at
|
|
294
|
-
* {@link addRoomSource}), so routing can never disagree with the engine; `all` ⇒ always true,
|
|
295
|
-
* `none` ⇒ always false, and a frozen source still answers (the predicate is static). Throws
|
|
296
|
-
* loudly on an unknown table, a room key not attached to the table, a wrong-width row, or
|
|
297
|
-
* `"daemon"` (which has no writable scope). */
|
|
298
|
-
writableMatches(table, roomKey, row) {
|
|
299
|
-
return this.db.writableMatches(table, roomKey, row);
|
|
300
|
-
}
|
|
301
216
|
}
|
|
302
217
|
/** Convenience: init the wasm + return a ready local {@link Store}. */
|
|
303
218
|
export async function createWasmStore(schema) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,yFAAyF;AACzF,kGAAkG;AAClG,6CAA6C;AAC7C,EAAE;AACF,yFAAyF;AACzF,yFAAyF;AACzF,yFAAyF;AAEzF,OAAO,IAAI,EAAE,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rindle/wasm",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.3",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"README.md"
|
|
30
30
|
],
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@rindle/client": "0.
|
|
32
|
+
"@rindle/client": "0.6.3"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@types/node": "^22.10.0",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"build": "tsc -p tsconfig.build.json",
|
|
40
40
|
"build:wasm": "./build.sh",
|
|
41
41
|
"typecheck": "tsc --noEmit",
|
|
42
|
-
"test": "node test/bundle-size.mjs && node --conditions=@rindle/source test/e2e.mjs && node --conditions=@rindle/source test/one-start.e2e.mjs && node --conditions=@rindle/source test/repro-high.e2e.mjs && node --conditions=@rindle/source test/partial-write.e2e.mjs
|
|
42
|
+
"test": "node test/bundle-size.mjs && node --conditions=@rindle/source test/e2e.mjs && node --conditions=@rindle/source test/one-start.e2e.mjs && node --conditions=@rindle/source test/repro-high.e2e.mjs && node --conditions=@rindle/source test/partial-write.e2e.mjs",
|
|
43
43
|
"test:browser": "node test/browser-smoke.mjs"
|
|
44
44
|
}
|
|
45
45
|
}
|
package/pkg/rindle.d.ts
CHANGED
|
@@ -7,69 +7,13 @@
|
|
|
7
7
|
export class Db {
|
|
8
8
|
free(): void;
|
|
9
9
|
[Symbol.dispose](): void;
|
|
10
|
-
/**
|
|
11
|
-
* Attach a room source to `table`, compiling `writable` into the merge's per-row
|
|
12
|
-
* [`WritableScope`] ([`parse_writable_scope`]): `{ kind: "all" }` = the room may write every row
|
|
13
|
-
* (room wins); `{ kind: "none" }` = a context table (daemon stays authoritative);
|
|
14
|
-
* `{ kind: "colEq", col, value }` = writable iff `row[col] == value` (harness stand-in);
|
|
15
|
-
* `{ kind: "predicate", where }` = the row-local wire-`Condition` predicate (Slice G-ii),
|
|
16
|
-
* lowered by the engine's own [`create_predicate`] against `table`'s schema.
|
|
17
|
-
*/
|
|
18
|
-
addRoomSource(table: string, room_key: string, writable: any): void;
|
|
19
10
|
/**
|
|
20
11
|
* Tear down a registered query: drop its sink + reclaim its pipeline (disconnect from
|
|
21
12
|
* the shared sources, free its slots — [`Graph::destroy_pipeline`]). Other queries
|
|
22
13
|
* and the shared sources are untouched. A no-op for an unknown id.
|
|
23
14
|
*/
|
|
24
15
|
destroyQuery(query_id: number): void;
|
|
25
|
-
/**
|
|
26
|
-
* Drop one parked hold-back at `probe`'s pk ([`Db::drop_held_back`] — the §301 fence-driven
|
|
27
|
-
* drop) and **deliver** the compensating deltas: returns the same
|
|
28
|
-
* `[{ queryId, events: FlatChange[] }]` shape as `WriteTxn.commit` (empty inside an open
|
|
29
|
-
* server-batch cycle, where the events join the cycle's one delivery instead) — unlike the
|
|
30
|
-
* park-time seams, whose install reconcile is a no-op by construction, a fence drop is
|
|
31
|
-
* exactly the moment a masked authoritative row becomes visible, so it must reach the
|
|
32
|
-
* views. `probe` is a full-width positional row (the pk derives from it — the same
|
|
33
|
-
* marshalling as [`holdBack`](Self::hold_back_js)).
|
|
34
|
-
*/
|
|
35
|
-
dropHeldBack(table: string, source_key: string, probe: any): any;
|
|
36
|
-
/**
|
|
37
|
-
* Freeze a physical source — the D4 downgrade-ghost stub ([`Db::freeze_source`]).
|
|
38
|
-
*/
|
|
39
|
-
freezeSource(table: string, source_key: string): void;
|
|
40
|
-
/**
|
|
41
|
-
* The parked hold-back at `probe`'s pk on `source_key`'s slice, as
|
|
42
|
-
* `{ absent: boolean, baseline: row | undefined } | undefined`
|
|
43
|
-
* ([`Db::held_back_state`], §301): `undefined` when nothing is parked — including an
|
|
44
|
-
* unknown source (non-throwing, so the client registry prunes lazily after a state-match
|
|
45
|
-
* drop or a room removal); `baseline` is the source's current confirmed-baseline row at
|
|
46
|
-
* the pk (the §2.5 stuck-pin tripwire input). An unknown TABLE still throws (the row
|
|
47
|
-
* cannot even be marshalled).
|
|
48
|
-
*/
|
|
49
|
-
heldBackState(table: string, source_key: string, probe: any): any;
|
|
50
|
-
/**
|
|
51
|
-
* Park an echoed `row` inertly on `source_key`'s slice of `table` ([`Db::hold_back`]).
|
|
52
|
-
*/
|
|
53
|
-
holdBack(table: string, source_key: string, row: any): void;
|
|
54
|
-
/**
|
|
55
|
-
* Park `old_row`'s pk as **absent** on `source_key`'s slice of `table`
|
|
56
|
-
* ([`Db::hold_back_absent`]) — the §7.3 tombstone for a confirmed cross-slice REMOVE.
|
|
57
|
-
* `old_row` is the full pre-image row, marshalled exactly like [`holdBack`](Self::hold_back_js)'s
|
|
58
|
-
* `row` (a full-width positional array of bare cells).
|
|
59
|
-
*/
|
|
60
|
-
holdBackAbsent(table: string, source_key: string, old_row: any): void;
|
|
61
16
|
constructor();
|
|
62
|
-
/**
|
|
63
|
-
* The winning source currently serving `row`'s pk on `table`, as its wasm-boundary key
|
|
64
|
-
* string (`"daemon"` / the room key, [`source_key_to_string`]), or `undefined` when no
|
|
65
|
-
* source holds the pk ([`Db::provenance`], §3.2 #3 — Slice H-i routing probe #1). `row` is
|
|
66
|
-
* a full-width positional row (the pk derives from it — the same marshalling as
|
|
67
|
-
* [`holdBack`](Self::hold_back_js)); an unknown table throws loudly. Reads the LIVE visible
|
|
68
|
-
* state, **overlay-first** (§7.3): an open [`WriteTxn`]'s staged-but-uncommitted writes are
|
|
69
|
-
* not consulted (they have not routed yet), which is exactly the pre-commit view the §3
|
|
70
|
-
* routing proof decides on.
|
|
71
|
-
*/
|
|
72
|
-
provenanceOf(table: string, row: any): any;
|
|
73
17
|
/**
|
|
74
18
|
* Register a live query from a Zero-wire AST under the caller's opaque `query_id`.
|
|
75
19
|
* Lowers it into the shared graph, sinks it in a change-sink, and hydrates. Returns
|
|
@@ -94,10 +38,6 @@ export class Db {
|
|
|
94
38
|
* (`createSchema`, N1) has a loud backstop instead of a silent one.
|
|
95
39
|
*/
|
|
96
40
|
registerTable(table: string, schema: any, local: boolean): void;
|
|
97
|
-
/**
|
|
98
|
-
* Detach a room source, emitting the compensating visible deltas ([`Db::remove_room_source`]).
|
|
99
|
-
*/
|
|
100
|
-
removeRoomSource(table: string, room_key: string): void;
|
|
101
41
|
/**
|
|
102
42
|
* Open a §1.3 reconcile cycle against the coherent server delta `deltas` —
|
|
103
43
|
* an array of base-table row ops `{ table, type: "add"|"remove"|"edit", row,
|
|
@@ -109,15 +49,11 @@ export class Db {
|
|
|
109
49
|
* events buffer into the cycle), then calls
|
|
110
50
|
* [`server_batch_end`](Db::server_batch_end) for the one coalesced delivery.
|
|
111
51
|
*
|
|
112
|
-
* `source_key` names the authority these `deltas` confirm — `"daemon"` at the wasm boundary
|
|
113
|
-
* today (single-domain); a `room:doc:X` string once the room feed lands (Slice E-iii/G). It
|
|
114
|
-
* selects which physical source [`Merge::rewind`] folds the delta into.
|
|
115
|
-
*
|
|
116
52
|
* Errors if a cycle is already open, on an unknown table, or on a push failure
|
|
117
|
-
* — after which the
|
|
53
|
+
* — after which the optimistic state is poisoned (a partial rewind may have
|
|
118
54
|
* applied): the only safe recovery is to discard this `Db` and re-hydrate.
|
|
119
55
|
*/
|
|
120
|
-
serverBatchBegin(
|
|
56
|
+
serverBatchBegin(deltas: any): void;
|
|
121
57
|
/**
|
|
122
58
|
* Close the open cycle: deliver the whole buffered event stream (rewind +
|
|
123
59
|
* re-invocations) per query, **in order**, as `[{ queryId, events: FlatChange[] }]`
|
|
@@ -145,17 +81,6 @@ export class Db {
|
|
|
145
81
|
* holds).
|
|
146
82
|
*/
|
|
147
83
|
unregisterTable(table: string): void;
|
|
148
|
-
/**
|
|
149
|
-
* Evaluate the REGISTERED writable scope of `table`'s room source `room_key` against a
|
|
150
|
-
* caller-supplied full-width `row` ([`Db::writable_matches`] — Slice H-i routing probe #2):
|
|
151
|
-
* the §3 proof's write-set rule, run through the SAME compiled predicate the merge's winner
|
|
152
|
-
* tiering uses (the G-ii descriptor `addRoomSource` registered), so routing can never
|
|
153
|
-
* disagree with the engine. `{kind:"all"}` ⇒ always `true`; `{kind:"none"}` ⇒ always
|
|
154
|
-
* `false`; a frozen source still answers (the predicate is static). Loud errors: unknown
|
|
155
|
-
* table, a room key not attached to the table, a wrong-width row, and `"daemon"` (reserved
|
|
156
|
-
* by [`parse_source_key`]; the daemon has no writable scope).
|
|
157
|
-
*/
|
|
158
|
-
writableMatches(table: string, room_key: string, row: any): boolean;
|
|
159
84
|
/**
|
|
160
85
|
* Open a write transaction. Stage row ops with [`WriteTxn::add`]/`remove`/`edit`,
|
|
161
86
|
* then [`WriteTxn::commit`] to apply them as one batch and get the per-query flat
|
|
@@ -241,16 +166,6 @@ export class WriteTxn {
|
|
|
241
166
|
* `serverBatchEnd`.
|
|
242
167
|
*/
|
|
243
168
|
commit(): any;
|
|
244
|
-
/**
|
|
245
|
-
* Like [`commit`](WriteTxn::commit), but ALSO returns the per-change **touched-source key list**
|
|
246
|
-
* in staged order as `{ batches, sources: string[] }` (Slice E-iii-b, design Q1). Each `sources`
|
|
247
|
-
* entry is the [`SourceKey`] the corresponding staged change routed through — the pk's provenance
|
|
248
|
-
* captured **pre-apply** (a `remove` erases the row, so provenance is unrecoverable afterward),
|
|
249
|
-
* `"daemon"` for a new/unknown pk or any Collapsed table. The order aligns 1:1 with the staged
|
|
250
|
-
* writes, so the optimistic layer can zip it with a mutation's write-set (per-pk hold-back
|
|
251
|
-
* source, Slice E-iii-c). `batches` is exactly what [`commit`](WriteTxn::commit) returns.
|
|
252
|
-
*/
|
|
253
|
-
commitTracked(): any;
|
|
254
169
|
/**
|
|
255
170
|
* Stage an edit of `old` → `new_row` in `table` (both width-checked).
|
|
256
171
|
*
|
|
@@ -321,22 +236,13 @@ export interface InitOutput {
|
|
|
321
236
|
readonly __wbg_db_free: (a: number, b: number) => void;
|
|
322
237
|
readonly __wbg_rindleview_free: (a: number, b: number) => void;
|
|
323
238
|
readonly __wbg_writetxn_free: (a: number, b: number) => void;
|
|
324
|
-
readonly db_addRoomSource: (a: number, b: number, c: number, d: number, e: number, f: any) => [number, number];
|
|
325
239
|
readonly db_destroyQuery: (a: number, b: number) => void;
|
|
326
|
-
readonly db_dropHeldBack: (a: number, b: number, c: number, d: number, e: number, f: any) => [number, number, number];
|
|
327
|
-
readonly db_freezeSource: (a: number, b: number, c: number, d: number, e: number) => [number, number];
|
|
328
|
-
readonly db_heldBackState: (a: number, b: number, c: number, d: number, e: number, f: any) => [number, number, number];
|
|
329
|
-
readonly db_holdBack: (a: number, b: number, c: number, d: number, e: number, f: any) => [number, number];
|
|
330
|
-
readonly db_holdBackAbsent: (a: number, b: number, c: number, d: number, e: number, f: any) => [number, number];
|
|
331
240
|
readonly db_new: () => number;
|
|
332
|
-
readonly db_provenanceOf: (a: number, b: number, c: number, d: any) => [number, number, number];
|
|
333
241
|
readonly db_query: (a: number, b: number, c: any) => [number, number, number];
|
|
334
242
|
readonly db_registerTable: (a: number, b: number, c: number, d: any, e: number) => [number, number];
|
|
335
|
-
readonly
|
|
336
|
-
readonly db_serverBatchBegin: (a: number, b: number, c: number, d: any) => [number, number];
|
|
243
|
+
readonly db_serverBatchBegin: (a: number, b: any) => [number, number];
|
|
337
244
|
readonly db_serverBatchEnd: (a: number) => [number, number, number];
|
|
338
245
|
readonly db_unregisterTable: (a: number, b: number, c: number) => [number, number];
|
|
339
|
-
readonly db_writableMatches: (a: number, b: number, c: number, d: number, e: number, f: any) => [number, number, number];
|
|
340
246
|
readonly db_write: (a: number) => number;
|
|
341
247
|
readonly rindleview_build: (a: any, b: any, c: any) => [number, number, number];
|
|
342
248
|
readonly rindleview_data: (a: number) => any;
|
|
@@ -347,7 +253,6 @@ export interface InitOutput {
|
|
|
347
253
|
readonly rindleview_subscribe: (a: number, b: any) => number;
|
|
348
254
|
readonly writetxn_add: (a: number, b: number, c: number, d: any) => [number, number];
|
|
349
255
|
readonly writetxn_commit: (a: number) => [number, number, number];
|
|
350
|
-
readonly writetxn_commitTracked: (a: number) => [number, number, number];
|
|
351
256
|
readonly writetxn_edit: (a: number, b: number, c: number, d: any, e: any) => [number, number];
|
|
352
257
|
readonly writetxn_get: (a: number, b: number, c: number, d: any) => [number, number, number];
|
|
353
258
|
readonly writetxn_query: (a: number, b: any) => [number, number, number];
|
package/pkg/rindle.js
CHANGED
|
@@ -14,27 +14,6 @@ export class Db {
|
|
|
14
14
|
const ptr = this.__destroy_into_raw();
|
|
15
15
|
wasm.__wbg_db_free(ptr, 0);
|
|
16
16
|
}
|
|
17
|
-
/**
|
|
18
|
-
* Attach a room source to `table`, compiling `writable` into the merge's per-row
|
|
19
|
-
* [`WritableScope`] ([`parse_writable_scope`]): `{ kind: "all" }` = the room may write every row
|
|
20
|
-
* (room wins); `{ kind: "none" }` = a context table (daemon stays authoritative);
|
|
21
|
-
* `{ kind: "colEq", col, value }` = writable iff `row[col] == value` (harness stand-in);
|
|
22
|
-
* `{ kind: "predicate", where }` = the row-local wire-`Condition` predicate (Slice G-ii),
|
|
23
|
-
* lowered by the engine's own [`create_predicate`] against `table`'s schema.
|
|
24
|
-
* @param {string} table
|
|
25
|
-
* @param {string} room_key
|
|
26
|
-
* @param {any} writable
|
|
27
|
-
*/
|
|
28
|
-
addRoomSource(table, room_key, writable) {
|
|
29
|
-
const ptr0 = passStringToWasm0(table, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
30
|
-
const len0 = WASM_VECTOR_LEN;
|
|
31
|
-
const ptr1 = passStringToWasm0(room_key, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
32
|
-
const len1 = WASM_VECTOR_LEN;
|
|
33
|
-
const ret = wasm.db_addRoomSource(this.__wbg_ptr, ptr0, len0, ptr1, len1, writable);
|
|
34
|
-
if (ret[1]) {
|
|
35
|
-
throw takeFromExternrefTable0(ret[0]);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
17
|
/**
|
|
39
18
|
* Tear down a registered query: drop its sink + reclaim its pipeline (disconnect from
|
|
40
19
|
* the shared sources, free its slots — [`Graph::destroy_pipeline`]). Other queries
|
|
@@ -44,133 +23,12 @@ export class Db {
|
|
|
44
23
|
destroyQuery(query_id) {
|
|
45
24
|
wasm.db_destroyQuery(this.__wbg_ptr, query_id);
|
|
46
25
|
}
|
|
47
|
-
/**
|
|
48
|
-
* Drop one parked hold-back at `probe`'s pk ([`Db::drop_held_back`] — the §301 fence-driven
|
|
49
|
-
* drop) and **deliver** the compensating deltas: returns the same
|
|
50
|
-
* `[{ queryId, events: FlatChange[] }]` shape as `WriteTxn.commit` (empty inside an open
|
|
51
|
-
* server-batch cycle, where the events join the cycle's one delivery instead) — unlike the
|
|
52
|
-
* park-time seams, whose install reconcile is a no-op by construction, a fence drop is
|
|
53
|
-
* exactly the moment a masked authoritative row becomes visible, so it must reach the
|
|
54
|
-
* views. `probe` is a full-width positional row (the pk derives from it — the same
|
|
55
|
-
* marshalling as [`holdBack`](Self::hold_back_js)).
|
|
56
|
-
* @param {string} table
|
|
57
|
-
* @param {string} source_key
|
|
58
|
-
* @param {any} probe
|
|
59
|
-
* @returns {any}
|
|
60
|
-
*/
|
|
61
|
-
dropHeldBack(table, source_key, probe) {
|
|
62
|
-
const ptr0 = passStringToWasm0(table, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
63
|
-
const len0 = WASM_VECTOR_LEN;
|
|
64
|
-
const ptr1 = passStringToWasm0(source_key, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
65
|
-
const len1 = WASM_VECTOR_LEN;
|
|
66
|
-
const ret = wasm.db_dropHeldBack(this.__wbg_ptr, ptr0, len0, ptr1, len1, probe);
|
|
67
|
-
if (ret[2]) {
|
|
68
|
-
throw takeFromExternrefTable0(ret[1]);
|
|
69
|
-
}
|
|
70
|
-
return takeFromExternrefTable0(ret[0]);
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Freeze a physical source — the D4 downgrade-ghost stub ([`Db::freeze_source`]).
|
|
74
|
-
* @param {string} table
|
|
75
|
-
* @param {string} source_key
|
|
76
|
-
*/
|
|
77
|
-
freezeSource(table, source_key) {
|
|
78
|
-
const ptr0 = passStringToWasm0(table, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
79
|
-
const len0 = WASM_VECTOR_LEN;
|
|
80
|
-
const ptr1 = passStringToWasm0(source_key, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
81
|
-
const len1 = WASM_VECTOR_LEN;
|
|
82
|
-
const ret = wasm.db_freezeSource(this.__wbg_ptr, ptr0, len0, ptr1, len1);
|
|
83
|
-
if (ret[1]) {
|
|
84
|
-
throw takeFromExternrefTable0(ret[0]);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* The parked hold-back at `probe`'s pk on `source_key`'s slice, as
|
|
89
|
-
* `{ absent: boolean, baseline: row | undefined } | undefined`
|
|
90
|
-
* ([`Db::held_back_state`], §301): `undefined` when nothing is parked — including an
|
|
91
|
-
* unknown source (non-throwing, so the client registry prunes lazily after a state-match
|
|
92
|
-
* drop or a room removal); `baseline` is the source's current confirmed-baseline row at
|
|
93
|
-
* the pk (the §2.5 stuck-pin tripwire input). An unknown TABLE still throws (the row
|
|
94
|
-
* cannot even be marshalled).
|
|
95
|
-
* @param {string} table
|
|
96
|
-
* @param {string} source_key
|
|
97
|
-
* @param {any} probe
|
|
98
|
-
* @returns {any}
|
|
99
|
-
*/
|
|
100
|
-
heldBackState(table, source_key, probe) {
|
|
101
|
-
const ptr0 = passStringToWasm0(table, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
102
|
-
const len0 = WASM_VECTOR_LEN;
|
|
103
|
-
const ptr1 = passStringToWasm0(source_key, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
104
|
-
const len1 = WASM_VECTOR_LEN;
|
|
105
|
-
const ret = wasm.db_heldBackState(this.__wbg_ptr, ptr0, len0, ptr1, len1, probe);
|
|
106
|
-
if (ret[2]) {
|
|
107
|
-
throw takeFromExternrefTable0(ret[1]);
|
|
108
|
-
}
|
|
109
|
-
return takeFromExternrefTable0(ret[0]);
|
|
110
|
-
}
|
|
111
|
-
/**
|
|
112
|
-
* Park an echoed `row` inertly on `source_key`'s slice of `table` ([`Db::hold_back`]).
|
|
113
|
-
* @param {string} table
|
|
114
|
-
* @param {string} source_key
|
|
115
|
-
* @param {any} row
|
|
116
|
-
*/
|
|
117
|
-
holdBack(table, source_key, row) {
|
|
118
|
-
const ptr0 = passStringToWasm0(table, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
119
|
-
const len0 = WASM_VECTOR_LEN;
|
|
120
|
-
const ptr1 = passStringToWasm0(source_key, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
121
|
-
const len1 = WASM_VECTOR_LEN;
|
|
122
|
-
const ret = wasm.db_holdBack(this.__wbg_ptr, ptr0, len0, ptr1, len1, row);
|
|
123
|
-
if (ret[1]) {
|
|
124
|
-
throw takeFromExternrefTable0(ret[0]);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
/**
|
|
128
|
-
* Park `old_row`'s pk as **absent** on `source_key`'s slice of `table`
|
|
129
|
-
* ([`Db::hold_back_absent`]) — the §7.3 tombstone for a confirmed cross-slice REMOVE.
|
|
130
|
-
* `old_row` is the full pre-image row, marshalled exactly like [`holdBack`](Self::hold_back_js)'s
|
|
131
|
-
* `row` (a full-width positional array of bare cells).
|
|
132
|
-
* @param {string} table
|
|
133
|
-
* @param {string} source_key
|
|
134
|
-
* @param {any} old_row
|
|
135
|
-
*/
|
|
136
|
-
holdBackAbsent(table, source_key, old_row) {
|
|
137
|
-
const ptr0 = passStringToWasm0(table, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
138
|
-
const len0 = WASM_VECTOR_LEN;
|
|
139
|
-
const ptr1 = passStringToWasm0(source_key, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
140
|
-
const len1 = WASM_VECTOR_LEN;
|
|
141
|
-
const ret = wasm.db_holdBackAbsent(this.__wbg_ptr, ptr0, len0, ptr1, len1, old_row);
|
|
142
|
-
if (ret[1]) {
|
|
143
|
-
throw takeFromExternrefTable0(ret[0]);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
26
|
constructor() {
|
|
147
27
|
const ret = wasm.db_new();
|
|
148
28
|
this.__wbg_ptr = ret;
|
|
149
29
|
DbFinalization.register(this, this.__wbg_ptr, this);
|
|
150
30
|
return this;
|
|
151
31
|
}
|
|
152
|
-
/**
|
|
153
|
-
* The winning source currently serving `row`'s pk on `table`, as its wasm-boundary key
|
|
154
|
-
* string (`"daemon"` / the room key, [`source_key_to_string`]), or `undefined` when no
|
|
155
|
-
* source holds the pk ([`Db::provenance`], §3.2 #3 — Slice H-i routing probe #1). `row` is
|
|
156
|
-
* a full-width positional row (the pk derives from it — the same marshalling as
|
|
157
|
-
* [`holdBack`](Self::hold_back_js)); an unknown table throws loudly. Reads the LIVE visible
|
|
158
|
-
* state, **overlay-first** (§7.3): an open [`WriteTxn`]'s staged-but-uncommitted writes are
|
|
159
|
-
* not consulted (they have not routed yet), which is exactly the pre-commit view the §3
|
|
160
|
-
* routing proof decides on.
|
|
161
|
-
* @param {string} table
|
|
162
|
-
* @param {any} row
|
|
163
|
-
* @returns {any}
|
|
164
|
-
*/
|
|
165
|
-
provenanceOf(table, row) {
|
|
166
|
-
const ptr0 = passStringToWasm0(table, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
167
|
-
const len0 = WASM_VECTOR_LEN;
|
|
168
|
-
const ret = wasm.db_provenanceOf(this.__wbg_ptr, ptr0, len0, row);
|
|
169
|
-
if (ret[2]) {
|
|
170
|
-
throw takeFromExternrefTable0(ret[1]);
|
|
171
|
-
}
|
|
172
|
-
return takeFromExternrefTable0(ret[0]);
|
|
173
|
-
}
|
|
174
32
|
/**
|
|
175
33
|
* Register a live query from a Zero-wire AST under the caller's opaque `query_id`.
|
|
176
34
|
* Lowers it into the shared graph, sinks it in a change-sink, and hydrates. Returns
|
|
@@ -214,21 +72,6 @@ export class Db {
|
|
|
214
72
|
throw takeFromExternrefTable0(ret[0]);
|
|
215
73
|
}
|
|
216
74
|
}
|
|
217
|
-
/**
|
|
218
|
-
* Detach a room source, emitting the compensating visible deltas ([`Db::remove_room_source`]).
|
|
219
|
-
* @param {string} table
|
|
220
|
-
* @param {string} room_key
|
|
221
|
-
*/
|
|
222
|
-
removeRoomSource(table, room_key) {
|
|
223
|
-
const ptr0 = passStringToWasm0(table, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
224
|
-
const len0 = WASM_VECTOR_LEN;
|
|
225
|
-
const ptr1 = passStringToWasm0(room_key, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
226
|
-
const len1 = WASM_VECTOR_LEN;
|
|
227
|
-
const ret = wasm.db_removeRoomSource(this.__wbg_ptr, ptr0, len0, ptr1, len1);
|
|
228
|
-
if (ret[1]) {
|
|
229
|
-
throw takeFromExternrefTable0(ret[0]);
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
75
|
/**
|
|
233
76
|
* Open a §1.3 reconcile cycle against the coherent server delta `deltas` —
|
|
234
77
|
* an array of base-table row ops `{ table, type: "add"|"remove"|"edit", row,
|
|
@@ -240,20 +83,13 @@ export class Db {
|
|
|
240
83
|
* events buffer into the cycle), then calls
|
|
241
84
|
* [`server_batch_end`](Db::server_batch_end) for the one coalesced delivery.
|
|
242
85
|
*
|
|
243
|
-
* `source_key` names the authority these `deltas` confirm — `"daemon"` at the wasm boundary
|
|
244
|
-
* today (single-domain); a `room:doc:X` string once the room feed lands (Slice E-iii/G). It
|
|
245
|
-
* selects which physical source [`Merge::rewind`] folds the delta into.
|
|
246
|
-
*
|
|
247
86
|
* Errors if a cycle is already open, on an unknown table, or on a push failure
|
|
248
|
-
* — after which the
|
|
87
|
+
* — after which the optimistic state is poisoned (a partial rewind may have
|
|
249
88
|
* applied): the only safe recovery is to discard this `Db` and re-hydrate.
|
|
250
|
-
* @param {string} source_key
|
|
251
89
|
* @param {any} deltas
|
|
252
90
|
*/
|
|
253
|
-
serverBatchBegin(
|
|
254
|
-
const
|
|
255
|
-
const len0 = WASM_VECTOR_LEN;
|
|
256
|
-
const ret = wasm.db_serverBatchBegin(this.__wbg_ptr, ptr0, len0, deltas);
|
|
91
|
+
serverBatchBegin(deltas) {
|
|
92
|
+
const ret = wasm.db_serverBatchBegin(this.__wbg_ptr, deltas);
|
|
257
93
|
if (ret[1]) {
|
|
258
94
|
throw takeFromExternrefTable0(ret[0]);
|
|
259
95
|
}
|
|
@@ -300,31 +136,6 @@ export class Db {
|
|
|
300
136
|
throw takeFromExternrefTable0(ret[0]);
|
|
301
137
|
}
|
|
302
138
|
}
|
|
303
|
-
/**
|
|
304
|
-
* Evaluate the REGISTERED writable scope of `table`'s room source `room_key` against a
|
|
305
|
-
* caller-supplied full-width `row` ([`Db::writable_matches`] — Slice H-i routing probe #2):
|
|
306
|
-
* the §3 proof's write-set rule, run through the SAME compiled predicate the merge's winner
|
|
307
|
-
* tiering uses (the G-ii descriptor `addRoomSource` registered), so routing can never
|
|
308
|
-
* disagree with the engine. `{kind:"all"}` ⇒ always `true`; `{kind:"none"}` ⇒ always
|
|
309
|
-
* `false`; a frozen source still answers (the predicate is static). Loud errors: unknown
|
|
310
|
-
* table, a room key not attached to the table, a wrong-width row, and `"daemon"` (reserved
|
|
311
|
-
* by [`parse_source_key`]; the daemon has no writable scope).
|
|
312
|
-
* @param {string} table
|
|
313
|
-
* @param {string} room_key
|
|
314
|
-
* @param {any} row
|
|
315
|
-
* @returns {boolean}
|
|
316
|
-
*/
|
|
317
|
-
writableMatches(table, room_key, row) {
|
|
318
|
-
const ptr0 = passStringToWasm0(table, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
319
|
-
const len0 = WASM_VECTOR_LEN;
|
|
320
|
-
const ptr1 = passStringToWasm0(room_key, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
321
|
-
const len1 = WASM_VECTOR_LEN;
|
|
322
|
-
const ret = wasm.db_writableMatches(this.__wbg_ptr, ptr0, len0, ptr1, len1, row);
|
|
323
|
-
if (ret[2]) {
|
|
324
|
-
throw takeFromExternrefTable0(ret[1]);
|
|
325
|
-
}
|
|
326
|
-
return ret[0] !== 0;
|
|
327
|
-
}
|
|
328
139
|
/**
|
|
329
140
|
* Open a write transaction. Stage row ops with [`WriteTxn::add`]/`remove`/`edit`,
|
|
330
141
|
* then [`WriteTxn::commit`] to apply them as one batch and get the per-query flat
|
|
@@ -498,24 +309,6 @@ export class WriteTxn {
|
|
|
498
309
|
}
|
|
499
310
|
return takeFromExternrefTable0(ret[0]);
|
|
500
311
|
}
|
|
501
|
-
/**
|
|
502
|
-
* Like [`commit`](WriteTxn::commit), but ALSO returns the per-change **touched-source key list**
|
|
503
|
-
* in staged order as `{ batches, sources: string[] }` (Slice E-iii-b, design Q1). Each `sources`
|
|
504
|
-
* entry is the [`SourceKey`] the corresponding staged change routed through — the pk's provenance
|
|
505
|
-
* captured **pre-apply** (a `remove` erases the row, so provenance is unrecoverable afterward),
|
|
506
|
-
* `"daemon"` for a new/unknown pk or any Collapsed table. The order aligns 1:1 with the staged
|
|
507
|
-
* writes, so the optimistic layer can zip it with a mutation's write-set (per-pk hold-back
|
|
508
|
-
* source, Slice E-iii-c). `batches` is exactly what [`commit`](WriteTxn::commit) returns.
|
|
509
|
-
* @returns {any}
|
|
510
|
-
*/
|
|
511
|
-
commitTracked() {
|
|
512
|
-
const ptr = this.__destroy_into_raw();
|
|
513
|
-
const ret = wasm.writetxn_commitTracked(ptr);
|
|
514
|
-
if (ret[2]) {
|
|
515
|
-
throw takeFromExternrefTable0(ret[1]);
|
|
516
|
-
}
|
|
517
|
-
return takeFromExternrefTable0(ret[0]);
|
|
518
|
-
}
|
|
519
312
|
/**
|
|
520
313
|
* Stage an edit of `old` → `new_row` in `table` (both width-checked).
|
|
521
314
|
*
|
package/pkg/rindle_bg.wasm
CHANGED
|
Binary file
|
package/pkg/rindle_bg.wasm.d.ts
CHANGED
|
@@ -5,22 +5,13 @@ export const __rindle_wasm_start: () => void;
|
|
|
5
5
|
export const __wbg_db_free: (a: number, b: number) => void;
|
|
6
6
|
export const __wbg_rindleview_free: (a: number, b: number) => void;
|
|
7
7
|
export const __wbg_writetxn_free: (a: number, b: number) => void;
|
|
8
|
-
export const db_addRoomSource: (a: number, b: number, c: number, d: number, e: number, f: any) => [number, number];
|
|
9
8
|
export const db_destroyQuery: (a: number, b: number) => void;
|
|
10
|
-
export const db_dropHeldBack: (a: number, b: number, c: number, d: number, e: number, f: any) => [number, number, number];
|
|
11
|
-
export const db_freezeSource: (a: number, b: number, c: number, d: number, e: number) => [number, number];
|
|
12
|
-
export const db_heldBackState: (a: number, b: number, c: number, d: number, e: number, f: any) => [number, number, number];
|
|
13
|
-
export const db_holdBack: (a: number, b: number, c: number, d: number, e: number, f: any) => [number, number];
|
|
14
|
-
export const db_holdBackAbsent: (a: number, b: number, c: number, d: number, e: number, f: any) => [number, number];
|
|
15
9
|
export const db_new: () => number;
|
|
16
|
-
export const db_provenanceOf: (a: number, b: number, c: number, d: any) => [number, number, number];
|
|
17
10
|
export const db_query: (a: number, b: number, c: any) => [number, number, number];
|
|
18
11
|
export const db_registerTable: (a: number, b: number, c: number, d: any, e: number) => [number, number];
|
|
19
|
-
export const
|
|
20
|
-
export const db_serverBatchBegin: (a: number, b: number, c: number, d: any) => [number, number];
|
|
12
|
+
export const db_serverBatchBegin: (a: number, b: any) => [number, number];
|
|
21
13
|
export const db_serverBatchEnd: (a: number) => [number, number, number];
|
|
22
14
|
export const db_unregisterTable: (a: number, b: number, c: number) => [number, number];
|
|
23
|
-
export const db_writableMatches: (a: number, b: number, c: number, d: number, e: number, f: any) => [number, number, number];
|
|
24
15
|
export const db_write: (a: number) => number;
|
|
25
16
|
export const rindleview_build: (a: any, b: any, c: any) => [number, number, number];
|
|
26
17
|
export const rindleview_data: (a: number) => any;
|
|
@@ -31,7 +22,6 @@ export const rindleview_setResultType: (a: number, b: number, c: number) => void
|
|
|
31
22
|
export const rindleview_subscribe: (a: number, b: any) => number;
|
|
32
23
|
export const writetxn_add: (a: number, b: number, c: number, d: any) => [number, number];
|
|
33
24
|
export const writetxn_commit: (a: number) => [number, number, number];
|
|
34
|
-
export const writetxn_commitTracked: (a: number) => [number, number, number];
|
|
35
25
|
export const writetxn_edit: (a: number, b: number, c: number, d: any, e: any) => [number, number];
|
|
36
26
|
export const writetxn_get: (a: number, b: number, c: number, d: any) => [number, number, number];
|
|
37
27
|
export const writetxn_query: (a: number, b: any) => [number, number, number];
|
package/src/index.ts
CHANGED
|
@@ -13,7 +13,6 @@ import type {
|
|
|
13
13
|
Backend,
|
|
14
14
|
ChangeEvent,
|
|
15
15
|
ColsMap,
|
|
16
|
-
Condition,
|
|
17
16
|
Mutation,
|
|
18
17
|
QueryId,
|
|
19
18
|
Schema,
|
|
@@ -21,47 +20,19 @@ import type {
|
|
|
21
20
|
|
|
22
21
|
export * from "@rindle/client";
|
|
23
22
|
|
|
24
|
-
/** A serializable writable-scope descriptor: how the merge decides, per row, whether an attached
|
|
25
|
-
* room may write it (the room copy then wins, RINDLE-REALTIME-QUERY-ENABLEMENT-DESIGN.md §5.2).
|
|
26
|
-
* `"all"` = the room owns every row it holds; `"none"` = a context table the daemon stays
|
|
27
|
-
* authoritative for; `"colEq"` = writable iff `row[col] === value` (harness stand-in). The REAL
|
|
28
|
-
* shape (Slice G) is `"predicate"`: `where` is the SAME wire {@link Condition} JSON a query AST
|
|
29
|
-
* carries, restricted to what evaluates against a single row — `simple` column-vs-literal leaves
|
|
30
|
-
* under `and`/`or`; a `correlatedSubquery` (or any other non-row-local node) is rejected loudly at
|
|
31
|
-
* `addRoomSource` time. It compiles Rust-side through the engine's OWN filter lowering
|
|
32
|
-
* (`create_predicate`), so writable evaluation can never disagree with query-filter semantics.
|
|
33
|
-
* NOTE: room join-key columns (Slice H) deliberately do NOT cross this boundary — they stay
|
|
34
|
-
* TS-side. */
|
|
35
|
-
export type WritableDescriptor =
|
|
36
|
-
| { kind: "all" }
|
|
37
|
-
| { kind: "none" }
|
|
38
|
-
| { kind: "colEq"; col: number; value: unknown }
|
|
39
|
-
| { kind: "predicate"; where: Condition };
|
|
40
|
-
|
|
41
23
|
// The wasm Db surface this backend uses (kept local so it doesn't depend on the generated .d.ts).
|
|
24
|
+
// One source per table (302-ROOM-STORE-SEPARATION-DESIGN.md): the engine holds ordinary tables
|
|
25
|
+
// only — a room-backed table is just another registered table whose deltas happen to arrive on a
|
|
26
|
+
// room channel. The multi-source merge surface that briefly lived here was removed with
|
|
27
|
+
// `rust/src/merge.rs`.
|
|
42
28
|
interface WasmDb {
|
|
43
29
|
registerTable(table: string, spec: { columns: string[]; primaryKey: number[] }, local: boolean): void;
|
|
44
30
|
unregisterTable(table: string): void;
|
|
45
31
|
query(queryId: number, ast: Ast): { comparatorVersion: number; schema: unknown; snapshot: unknown[] };
|
|
46
32
|
destroyQuery(queryId: number): void;
|
|
47
33
|
write(): WasmWriteTxn;
|
|
48
|
-
serverBatchBegin(
|
|
34
|
+
serverBatchBegin(deltas: ServerDeltaOp[]): void;
|
|
49
35
|
serverBatchEnd(): Array<{ queryId: number; events: unknown[] }>;
|
|
50
|
-
// Multi-source seams (Slice E-iii-b harness → Slice G-ii ABI — see WritableDescriptor).
|
|
51
|
-
addRoomSource(table: string, roomKey: string, writable: WritableDescriptor): void;
|
|
52
|
-
removeRoomSource(table: string, roomKey: string): void;
|
|
53
|
-
holdBack(table: string, sourceKey: string, row: unknown[]): void;
|
|
54
|
-
holdBackAbsent(table: string, sourceKey: string, oldRow: unknown[]): void;
|
|
55
|
-
dropHeldBack(table: string, sourceKey: string, probe: unknown[]): unknown;
|
|
56
|
-
heldBackState(
|
|
57
|
-
table: string,
|
|
58
|
-
sourceKey: string,
|
|
59
|
-
probe: unknown[],
|
|
60
|
-
): { absent: boolean; baseline: unknown[] | undefined } | undefined;
|
|
61
|
-
freezeSource(table: string, sourceKey: string): void;
|
|
62
|
-
// Slice H-i routing probes (design §3.1/§3.2 — see the WasmBackend mirrors below).
|
|
63
|
-
provenanceOf(table: string, row: unknown[]): string | undefined;
|
|
64
|
-
writableMatches(table: string, roomKey: string, row: unknown[]): boolean;
|
|
65
36
|
}
|
|
66
37
|
|
|
67
38
|
/** A raw staged write transaction over the wasm engine — the surface an optimistic client
|
|
@@ -79,11 +50,6 @@ export interface WasmWriteTxn {
|
|
|
79
50
|
* shape to a `view.data` row), in the query's order. */
|
|
80
51
|
query(ast: Ast): unknown[];
|
|
81
52
|
commit(): Array<{ queryId: number; events: unknown[] }>;
|
|
82
|
-
/** Like {@link commit}, additionally returning the per-change touched-source key list in staged
|
|
83
|
-
* order (`sources`, e.g. `"daemon"` / `"room:doc:1"`) — the provenance each staged write routed
|
|
84
|
-
* through, captured pre-apply (Slice E-iii-b, design Q1). `batches` is exactly {@link commit}'s
|
|
85
|
-
* return; the source list is additive. */
|
|
86
|
-
commitTracked(): { batches: Array<{ queryId: number; events: unknown[] }>; sources: string[] };
|
|
87
53
|
rollback(): void;
|
|
88
54
|
}
|
|
89
55
|
|
|
@@ -280,29 +246,22 @@ export class WasmBackend<S extends ColsMap> implements Backend {
|
|
|
280
246
|
* `onCommitted` runs after `tx.commit()` returns but before `dispatch` delivers to
|
|
281
247
|
* subscribers: a throw from `f` (pre-commit — engine untouched) skips it; a subscriber
|
|
282
248
|
* throw re-raised by `dispatch` happens after it. It is the only point where "the commit
|
|
283
|
-
* is applied" is knowable to a caller that must not confuse the two failure modes.
|
|
284
|
-
|
|
285
|
-
* Returns the per-change **touched-source key list** in staged-write order (`"daemon"` /
|
|
286
|
-
* `"room:doc:X"`, Slice E-iii-b design Q1) — additive; every current caller (`mutate`,
|
|
287
|
-
* `writeLocal`, `@rindle/optimistic`) ignores it. The per-source reconcile (Slice E-iii-c) zips
|
|
288
|
-
* it with the mutation's write-set for the per-pk hold-back source. */
|
|
289
|
-
writeWith(f: (tx: WasmWriteTxn) => void, onCommitted?: () => void): string[] {
|
|
249
|
+
* is applied" is knowable to a caller that must not confuse the two failure modes. */
|
|
250
|
+
writeWith(f: (tx: WasmWriteTxn) => void, onCommitted?: () => void): void {
|
|
290
251
|
const tx = this.db.write();
|
|
291
252
|
f(tx);
|
|
292
|
-
const
|
|
253
|
+
const batches = tx.commit() as BatchSet;
|
|
293
254
|
onCommitted?.();
|
|
294
255
|
this.dispatch(batches);
|
|
295
|
-
return sources;
|
|
296
256
|
}
|
|
297
257
|
|
|
298
|
-
/** Open a §1.3 reconcile cycle against the coherent server delta: the engine rewinds
|
|
299
|
-
*
|
|
300
|
-
*
|
|
301
|
-
*
|
|
302
|
-
*
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
this.db.serverBatchBegin(sourceKey, deltas);
|
|
258
|
+
/** Open a §1.3 reconcile cycle against the coherent server delta: the engine rewinds every
|
|
259
|
+
* tracked table (optimistic layer un-applied, delta folded in, each table's baseline re-forked)
|
|
260
|
+
* and starts buffering. Re-invoke the still-pending mutators via {@link writeWith}, then call
|
|
261
|
+
* {@link serverBatchEnd}. On error the rebase state is poisoned — discard the backend and
|
|
262
|
+
* re-hydrate. */
|
|
263
|
+
serverBatchBegin(deltas: ServerDeltaOp[]): void {
|
|
264
|
+
this.db.serverBatchBegin(deltas);
|
|
306
265
|
}
|
|
307
266
|
|
|
308
267
|
/** Close the cycle: the whole buffered stream (rewind + re-invocations) coalesces to
|
|
@@ -311,98 +270,6 @@ export class WasmBackend<S extends ColsMap> implements Backend {
|
|
|
311
270
|
serverBatchEnd(): void {
|
|
312
271
|
this.dispatch(this.db.serverBatchEnd() as BatchSet);
|
|
313
272
|
}
|
|
314
|
-
|
|
315
|
-
// --- multi-source seams (Slice E-iii-b harness → Slice G-ii ABI) ------------------
|
|
316
|
-
//
|
|
317
|
-
// Thin pass-throughs to the engine's `Merge` (RINDLE-REALTIME-QUERY-ENABLEMENT-DESIGN.md §5).
|
|
318
|
-
// `addRoomSource`'s {@link WritableDescriptor} now carries the real row-local `predicate` arm
|
|
319
|
-
// (a wire-Condition `where`, compiled Rust-side through the engine's own filter lowering)
|
|
320
|
-
// alongside the narrow `all`/`none`/`colEq` harness shapes. Single-domain behavior is untouched
|
|
321
|
-
// unless `addRoomSource` is called (a table stays Collapsed = today's daemon-only path).
|
|
322
|
-
|
|
323
|
-
/** Attach a room source to `table`, compiling `writable` into the merge's per-row writable scope.
|
|
324
|
-
* Promotes the table Collapsed → Merged on the first room (§5.2); the room seeds empty, so no
|
|
325
|
-
* visible blip. Throws on an untracked (local-only) table or a duplicate room. */
|
|
326
|
-
addRoomSource(table: string, roomKey: string, writable: WritableDescriptor): void {
|
|
327
|
-
this.db.addRoomSource(table, roomKey, writable);
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
/** Detach a room source, emitting the compensating visible deltas on the ordinary event stream. */
|
|
331
|
-
removeRoomSource(table: string, roomKey: string): void {
|
|
332
|
-
this.db.removeRoomSource(table, roomKey);
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
/** Park an echoed `row` inertly on `sourceKey`'s slice of `table` (the confirm→echo hold-back
|
|
336
|
-
* window, design §7.3): keeps the row visible so the next per-source rewind of `sourceKey` does
|
|
337
|
-
* not flash-revert a confirmed-elsewhere write before its data echo lands. `sourceKey` is
|
|
338
|
-
* `"daemon"` or a `"room:doc:X"` key. */
|
|
339
|
-
holdBack(table: string, sourceKey: string, row: unknown[]): void {
|
|
340
|
-
this.db.holdBack(table, sourceKey, row);
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
/** Park `oldRow`'s pk as ABSENT on `sourceKey`'s slice of `table` — the §7.3 tombstone, the
|
|
344
|
-
* remove-sibling of {@link holdBack} (Slice G-ii): a confirmed cross-slice REMOVE whose delete
|
|
345
|
-
* echo has not landed on `sourceKey` must not resurrect through that source's next rewind. The
|
|
346
|
-
* overlay masks the pk (overlay-first) until the source's re-forked baseline lacks it (the
|
|
347
|
-
* delete echoed), then drops. `oldRow` is the full-width PRE-IMAGE row (same positional
|
|
348
|
-
* bare-cell marshaling as {@link holdBack}); it carries the pk and, later (Slice H), the cells
|
|
349
|
-
* writable-scope predicates evaluate on. */
|
|
350
|
-
holdBackAbsent(table: string, sourceKey: string, oldRow: unknown[]): void {
|
|
351
|
-
this.db.holdBackAbsent(table, sourceKey, oldRow);
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
/** Drop one parked §7.3 hold-back at `probe`'s pk on `sourceKey`'s slice and reconcile the
|
|
355
|
-
* pk's visible winner — the §301 FENCE-driven drop (`301-ECHO-FENCE-DESIGN.md` §2.2), fired
|
|
356
|
-
* by the optimistic backend's pin registry once `sourceKey`'s stream has provably delivered
|
|
357
|
-
* through the pinned write's commit. Unlike the park-time seams (whose install is a no-op by
|
|
358
|
-
* construction) a drop is exactly the moment a masked authoritative row becomes visible, so
|
|
359
|
-
* the engine's compensating deltas are DELIVERED here: dispatched on the ordinary event
|
|
360
|
-
* stream (or folded into an open server-batch cycle's one delivery). No-op when nothing is
|
|
361
|
-
* parked at the pk — the rewind's state-match fallback may have raced it. */
|
|
362
|
-
dropHeldBack(table: string, sourceKey: string, probe: unknown[]): void {
|
|
363
|
-
this.dispatch(this.db.dropHeldBack(table, sourceKey, probe) as BatchSet);
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
/** The parked hold-back at `probe`'s pk on `sourceKey`'s slice, or `undefined` (§301
|
|
367
|
-
* introspection): `absent` names the tombstone variant; `baseline` is the source's CURRENT
|
|
368
|
-
* confirmed-baseline row at the pk (`undefined` when the baseline lacks it) — the pin
|
|
369
|
-
* registry's lazy-prune probe and the §2.5 stuck-pin tripwire input. Non-throwing on an
|
|
370
|
-
* unknown source (a removed room), so pruning after a whole-source removal just works. */
|
|
371
|
-
heldBackState(
|
|
372
|
-
table: string,
|
|
373
|
-
sourceKey: string,
|
|
374
|
-
probe: unknown[],
|
|
375
|
-
): { absent: boolean; baseline: unknown[] | undefined } | undefined {
|
|
376
|
-
return this.db.heldBackState(table, sourceKey, probe);
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
/** Freeze a physical source — the D4 downgrade-ghost stub (wins-if-present in the merge). */
|
|
380
|
-
freezeSource(table: string, sourceKey: string): void {
|
|
381
|
-
this.db.freezeSource(table, sourceKey);
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
/** The source currently serving `row`'s pk on `table` — `"daemon"`, a room key, or `undefined`
|
|
385
|
-
* when no source holds the pk (Slice H-i routing probe #1, design §3.2 #3). `row` is a
|
|
386
|
-
* full-width positional row (the pk derives from it — same marshaling as {@link holdBack});
|
|
387
|
-
* an unknown table throws loudly. Reads the LIVE visible state, overlay-first (§7.3): an open
|
|
388
|
-
* write txn's staged-but-uncommitted rows are NOT consulted (they have not routed yet), which
|
|
389
|
-
* is exactly the pre-commit view the §3 routing proof decides on — a present read is proven
|
|
390
|
-
* room-covered iff this reports the occupied room. */
|
|
391
|
-
provenanceOf(table: string, row: unknown[]): string | undefined {
|
|
392
|
-
return this.db.provenanceOf(table, row);
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
/** Evaluate the REGISTERED writable scope of `table`'s room source `roomKey` against a
|
|
396
|
-
* caller-supplied full-width row (Slice H-i routing probe #2, design §3.1): a prediction-run
|
|
397
|
-
* write is proven room-covered iff this is `true` on the written row. Runs the SAME compiled
|
|
398
|
-
* predicate the merge's winner tiering uses (the {@link WritableDescriptor} registered at
|
|
399
|
-
* {@link addRoomSource}), so routing can never disagree with the engine; `all` ⇒ always true,
|
|
400
|
-
* `none` ⇒ always false, and a frozen source still answers (the predicate is static). Throws
|
|
401
|
-
* loudly on an unknown table, a room key not attached to the table, a wrong-width row, or
|
|
402
|
-
* `"daemon"` (which has no writable scope). */
|
|
403
|
-
writableMatches(table: string, roomKey: string, row: unknown[]): boolean {
|
|
404
|
-
return this.db.writableMatches(table, roomKey, row);
|
|
405
|
-
}
|
|
406
273
|
}
|
|
407
274
|
|
|
408
275
|
/** Convenience: init the wasm + return a ready local {@link Store}. */
|