/** * Netting inside one transaction (journal spec §2.4, R8, N8; S3b, T12985). * * The sealer builds one draft op per capture; {@link netTransaction} reduces a * transaction's drafts to the ops a receiver needs. Netting is per (table, * uid) (§2.4): drafts are first chained per (table, local key `rk`), because a * re-key changes the uid but never the local key, and then chains with no K * that carry the same uid merge, so a delete of one local row and an insert * of another under the same uid (an AC relink) net to one U (T13035). * * Per chain: * * 1. **Re-keys.** Adjacent K ops collapse: K(x → NULL) followed by the fill's * K(NULL → y) is one K(x → y) (N8). A K whose old uid no sealed op ever * carried (no row meta) is **dropped**: every op of the chain then uses the * final uid, and the caller moves the row meta ({@link NetResult.renames}). * A K on a uid row meta knows is **kept** (T13035): ops sealed earlier on * the old uid are never rewritten, so the K is what links them to the new * uid. Ops before a kept K use the old uid, ops after it the new one. * 2. **Net each stretch between kept K ops** (§2.4 table): * * | sequence | result | * |---|---| * | I, then any U | I with the final image | * | U, U, … | one U: first before, last after per column; unchanged columns dropped; no op when nothing changed | * | I … D | nothing | * | D, then I | U of the non-key columns that differ, or nothing | * | D, I, D | D, before-image from the first D | * | U … D | D, before-image from the first U's before | * | I on a uid row meta knows live, not deleted earlier in the transaction (foreign REPLACE) | U against it | * * 3. **Counters (§2.6).** On a U, a column declared in * {@link SYNC_COUNTER_COLUMNS} carries `{$inc: after − before}` instead of * the absolute value; the before-image keeps the old value. * * Each op keeps its first capture's `seq` (output order) and records its last * capture's in `last`: the sealer takes the op's HLC time and local key from * the last capture (T13037). * * Apply-intent subtraction (§3.3) needs `_sync_apply_intent`, which arrives * with pull/apply (S5); {@link subtractIntents} is the seam and is a no-op * until then, so the sealer refuses apply and rebase frames. Across * transactions, the sealer drops the dead incarnation of a row that never got * a uid (I … D, T13036); the rest of cross-transaction compaction is S4, * where segment state exists. * * Pure: no database access; the caller supplies row-meta facts. * * @module store/sync/netting * @task T12985 * @epic T12323 */ import { type WireValue } from './sealer-values.js'; /** * In-place counter columns per table (§2.6, `SYNC_COUNTER_COLUMNS`): sealed * as `{$inc: delta}` on update. Empty while no counter-bearing table is in * the sync set (brain_patterns joins with T12894). */ export declare const SYNC_COUNTER_COLUMNS: Readonly>; /** A counter delta on the wire (§2.6). */ export interface IncValue { readonly $inc: number; } /** A draft op: one capture, before netting. `u`/`nu` may be NULL mid-re-key. */ export interface DraftOp { readonly t: string; /** Local key of the row (the capture's `rk`): stable across re-keys. */ readonly rk: string; /** Capture seq, for ordering. */ readonly seq: number; readonly o: 'I' | 'U' | 'D' | 'K'; /** Row uid; for K the OLD uid. NULL when not yet known. */ readonly u: string | null; /** K only: the new uid (NULL for a clear). */ readonly nu?: string | null; readonly bfp?: string; readonly obfp?: string; readonly k?: Record; readonly a?: Record; readonly b?: Record; /** * A repair U (§4.4, T12987): the before-image is unknown, so every column * of `a` is kept (none can be judged unchanged) and the op carries no `b`. */ readonly unknownBefore?: true; } /** A netted op, ready for an HLC. `last` is its last capture's seq. */ export type NettedOp = Omit & { readonly u: string | null; readonly last: number; }; /** Row-meta facts the netting needs. */ export interface MetaFacts { /** Whether a persisted segment ever carried this uid (`sent = 1`). */ sent(table: string, uid: string): boolean; /** Whether row meta knows this uid as a LIVE row (not a tombstone). */ live(table: string, uid: string): boolean; /** Whether row meta knows this uid at all: some sealed op carried it. */ known(table: string, uid: string): boolean; } /** Netting options beyond row meta. */ export interface NetOptions { /** In-place counter columns per table (§2.6). */ readonly counters?: Readonly>; /** A table's key columns: a D-then-I U never carries them (§2.4). */ readonly keyColumns?: (table: string) => readonly string[]; } /** What netting produced. */ export interface NetResult { readonly ops: NettedOp[]; /** Dropped re-keys: move row meta `from` → `to` without an op. */ readonly renames: ReadonlyArray<{ readonly t: string; readonly from: string; readonly to: string; }>; } /** Intent subtraction (§3.3): the S5 seam. No apply intents exist before pull. */ export declare function subtractIntents(ops: readonly DraftOp[]): DraftOp[]; /** * Net one transaction's drafts (§2.4). Output is ordered by each op's first * capture seq; kept K ops sit between their chain's stretches. */ export declare function netTransaction(drafts: readonly DraftOp[], facts: MetaFacts, options?: NetOptions): NetResult; //# sourceMappingURL=netting.d.ts.map