@quereus/sync 3.3.0 → 4.0.0
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/README.md +17 -7
- package/dist/src/clock/hlc.d.ts +43 -3
- package/dist/src/clock/hlc.d.ts.map +1 -1
- package/dist/src/clock/hlc.js +60 -10
- package/dist/src/clock/hlc.js.map +1 -1
- package/dist/src/create-sync-module.d.ts +46 -9
- package/dist/src/create-sync-module.d.ts.map +1 -1
- package/dist/src/create-sync-module.js +11 -8
- package/dist/src/create-sync-module.js.map +1 -1
- package/dist/src/index.d.ts +10 -8
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +8 -5
- package/dist/src/index.js.map +1 -1
- package/dist/src/metadata/basis-lifecycle.d.ts +180 -0
- package/dist/src/metadata/basis-lifecycle.d.ts.map +1 -0
- package/dist/src/metadata/basis-lifecycle.js +211 -0
- package/dist/src/metadata/basis-lifecycle.js.map +1 -0
- package/dist/src/metadata/change-log.d.ts +1 -1
- package/dist/src/metadata/change-log.d.ts.map +1 -1
- package/dist/src/metadata/change-log.js +6 -6
- package/dist/src/metadata/change-log.js.map +1 -1
- package/dist/src/metadata/column-version.d.ts +14 -5
- package/dist/src/metadata/column-version.d.ts.map +1 -1
- package/dist/src/metadata/column-version.js +22 -12
- package/dist/src/metadata/column-version.js.map +1 -1
- package/dist/src/metadata/index.d.ts +2 -0
- package/dist/src/metadata/index.d.ts.map +1 -1
- package/dist/src/metadata/index.js +2 -0
- package/dist/src/metadata/index.js.map +1 -1
- package/dist/src/metadata/keys.d.ts +52 -2
- package/dist/src/metadata/keys.d.ts.map +1 -1
- package/dist/src/metadata/keys.js +99 -14
- package/dist/src/metadata/keys.js.map +1 -1
- package/dist/src/metadata/peer-state.d.ts +1 -1
- package/dist/src/metadata/peer-state.js +5 -5
- package/dist/src/metadata/quarantine.d.ts +90 -0
- package/dist/src/metadata/quarantine.d.ts.map +1 -0
- package/dist/src/metadata/quarantine.js +167 -0
- package/dist/src/metadata/quarantine.js.map +1 -0
- package/dist/src/metadata/schema-migration.d.ts +1 -1
- package/dist/src/metadata/schema-migration.js +7 -7
- package/dist/src/metadata/schema-version.d.ts +1 -1
- package/dist/src/metadata/schema-version.js +7 -7
- package/dist/src/metadata/tombstones.d.ts +26 -9
- package/dist/src/metadata/tombstones.d.ts.map +1 -1
- package/dist/src/metadata/tombstones.js +42 -19
- package/dist/src/metadata/tombstones.js.map +1 -1
- package/dist/src/sql/basis-lifecycle-tvf.d.ts +34 -0
- package/dist/src/sql/basis-lifecycle-tvf.d.ts.map +1 -0
- package/dist/src/sql/basis-lifecycle-tvf.js +101 -0
- package/dist/src/sql/basis-lifecycle-tvf.js.map +1 -0
- package/dist/src/sync/admission.d.ts +81 -0
- package/dist/src/sync/admission.d.ts.map +1 -0
- package/dist/src/sync/admission.js +94 -0
- package/dist/src/sync/admission.js.map +1 -0
- package/dist/src/sync/change-applicator.d.ts +65 -2
- package/dist/src/sync/change-applicator.d.ts.map +1 -1
- package/dist/src/sync/change-applicator.js +493 -68
- package/dist/src/sync/change-applicator.js.map +1 -1
- package/dist/src/sync/change-grouping.d.ts +43 -0
- package/dist/src/sync/change-grouping.d.ts.map +1 -0
- package/dist/src/sync/change-grouping.js +103 -0
- package/dist/src/sync/change-grouping.js.map +1 -0
- package/dist/src/sync/events.d.ts +159 -1
- package/dist/src/sync/events.d.ts.map +1 -1
- package/dist/src/sync/events.js +50 -0
- package/dist/src/sync/events.js.map +1 -1
- package/dist/src/sync/manager.d.ts +87 -0
- package/dist/src/sync/manager.d.ts.map +1 -1
- package/dist/src/sync/protocol.d.ts +174 -11
- package/dist/src/sync/protocol.d.ts.map +1 -1
- package/dist/src/sync/protocol.js +4 -1
- package/dist/src/sync/protocol.js.map +1 -1
- package/dist/src/sync/snapshot-stream.d.ts.map +1 -1
- package/dist/src/sync/snapshot-stream.js +89 -19
- package/dist/src/sync/snapshot-stream.js.map +1 -1
- package/dist/src/sync/snapshot.d.ts.map +1 -1
- package/dist/src/sync/snapshot.js +63 -44
- package/dist/src/sync/snapshot.js.map +1 -1
- package/dist/src/sync/store-adapter.d.ts +117 -15
- package/dist/src/sync/store-adapter.d.ts.map +1 -1
- package/dist/src/sync/store-adapter.js +247 -91
- package/dist/src/sync/store-adapter.js.map +1 -1
- package/dist/src/sync/sync-context.d.ts +44 -1
- package/dist/src/sync/sync-context.d.ts.map +1 -1
- package/dist/src/sync/sync-context.js +26 -0
- package/dist/src/sync/sync-context.js.map +1 -1
- package/dist/src/sync/sync-manager-impl.d.ts +247 -13
- package/dist/src/sync/sync-manager-impl.d.ts.map +1 -1
- package/dist/src/sync/sync-manager-impl.js +788 -193
- package/dist/src/sync/sync-manager-impl.js.map +1 -1
- package/package.json +6 -6
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Basis-table lifecycle store — durable per-basis-table classification + the
|
|
3
|
+
* mapped-since / unmapped-since bookkeeping that drives legacy-table retirement
|
|
4
|
+
* (`docs/migration.md` § 2 Converge).
|
|
5
|
+
*
|
|
6
|
+
* Each shared (basis) table is classified into one of four states relative to
|
|
7
|
+
* the app's current lens deployments and the basis schema's own derivations:
|
|
8
|
+
*
|
|
9
|
+
* - `directly-mapped` — some deployed lens backs a logical column with it.
|
|
10
|
+
* - `derivation-source-only` — referenced *solely* as a maintained table's
|
|
11
|
+
* source (the "this table is now legacy" signal).
|
|
12
|
+
* - `unreferenced` — in the basis, but neither mapped nor a
|
|
13
|
+
* derivation source.
|
|
14
|
+
* - `detached` — no longer in the basis schema; physical storage
|
|
15
|
+
* may linger (an eviction candidate).
|
|
16
|
+
*
|
|
17
|
+
* The classification is recomputed on every lens deploy
|
|
18
|
+
* ({@link import('../sync/sync-manager-impl.js').SyncManagerImpl.recordLensDeployment}).
|
|
19
|
+
* Records are KV-durable so the classification — and its timestamps — survive a
|
|
20
|
+
* restart with no prior deploy in the session.
|
|
21
|
+
*
|
|
22
|
+
* The record is a flat JSON-safe object (strings / numbers / booleans /
|
|
23
|
+
* `string[]`), so serialization is a plain `JSON.stringify`; no custom
|
|
24
|
+
* SqlValue / HLC encoding is needed (unlike `quarantine.ts` / `column-version.ts`).
|
|
25
|
+
*/
|
|
26
|
+
import type { SqlValue } from '@quereus/quereus';
|
|
27
|
+
import type { KVStore, WriteBatch } from '@quereus/store';
|
|
28
|
+
import type { SyncConfig } from '../sync/protocol.js';
|
|
29
|
+
/** The aggregate lifecycle state of one basis table. */
|
|
30
|
+
export type BasisLifecycleState = 'directly-mapped' | 'derivation-source-only' | 'unreferenced' | 'detached';
|
|
31
|
+
/**
|
|
32
|
+
* Per-table eviction override (the `quereus.sync.evict` reserved tag, captured
|
|
33
|
+
* into the lifecycle record at observation time). `never` opts the table out of
|
|
34
|
+
* auto-eviction; `immediate` evicts on the first sweep after detach (zero
|
|
35
|
+
* horizon); a number is a custom horizon in milliseconds. Absent ⇒ fall back to
|
|
36
|
+
* the global {@link SyncConfig.basisEviction} mode.
|
|
37
|
+
*/
|
|
38
|
+
export type EvictPolicy = 'never' | 'immediate' | number;
|
|
39
|
+
/**
|
|
40
|
+
* The persisted lifecycle record for one basis table.
|
|
41
|
+
*
|
|
42
|
+
* `mappedBy` stores each deployed logical schema's contribution separately and
|
|
43
|
+
* the aggregate `state` ORs them, so a basis table mapped by logical schema `A`
|
|
44
|
+
* but not `B` stays `directly-mapped` until the *last* mapper drops it — without
|
|
45
|
+
* the recorder having to enumerate every deployed logical schema (no public
|
|
46
|
+
* enumerator exists; see the recorder's per-schema-contribution note).
|
|
47
|
+
*/
|
|
48
|
+
export interface BasisTableLifecycleRecord {
|
|
49
|
+
/** Basis schema name (original case where known, else the lowercased key part). */
|
|
50
|
+
schema: string;
|
|
51
|
+
/** Basis table name (original case where known, else the lowercased key part). */
|
|
52
|
+
table: string;
|
|
53
|
+
/** Aggregate state across all deployed logical schemas + the basis derivations. */
|
|
54
|
+
state: BasisLifecycleState;
|
|
55
|
+
/** Logical schema names (lowercased) whose latest deploy directly maps this table. */
|
|
56
|
+
mappedBy: string[];
|
|
57
|
+
/** True iff some maintained table in the current basis lists it in `sourceTables`. */
|
|
58
|
+
derivationSource: boolean;
|
|
59
|
+
/** True iff the table is present in the basis schema as of the last deploy. */
|
|
60
|
+
inBasis: boolean;
|
|
61
|
+
/** Wall-clock ms when the aggregate state last entered `directly-mapped`. */
|
|
62
|
+
mappedSince?: number;
|
|
63
|
+
/** Wall-clock ms when it last left `directly-mapped` (the retirement hint timestamp). */
|
|
64
|
+
unmappedSince?: number;
|
|
65
|
+
/** Wall-clock ms when the state last entered `detached` (cleared on re-attach). */
|
|
66
|
+
detachedAt?: number;
|
|
67
|
+
/**
|
|
68
|
+
* The dynamic network signal: the wall-time (ms) of the latest *inbound remote*
|
|
69
|
+
* write observed while this table was NOT directly mapped locally — presumed to
|
|
70
|
+
* originate at a peer that still maps it directly (a conservative over-estimate;
|
|
71
|
+
* see `docs/migration.md` § 2 Converge). Bumped by the change applicator; resets
|
|
72
|
+
* the eviction quiet clock. Absent until the first such write.
|
|
73
|
+
*/
|
|
74
|
+
lastDirectlyMappedWriteAt?: number;
|
|
75
|
+
/**
|
|
76
|
+
* Per-table eviction override, captured from the `quereus.sync.evict` reserved
|
|
77
|
+
* tag at observation time (the tag is gone once the table detaches, so it is
|
|
78
|
+
* snapshotted while in-basis and carried through detach). Absent ⇒ the global
|
|
79
|
+
* {@link SyncConfig.basisEviction} mode governs.
|
|
80
|
+
*/
|
|
81
|
+
evictPolicy?: EvictPolicy;
|
|
82
|
+
/**
|
|
83
|
+
* Secondary-index names captured while the table was in-basis, so the eviction
|
|
84
|
+
* sweep can reclaim the index stores by name after detach (the table schema —
|
|
85
|
+
* and its index list — is gone once detached). Carried through detach; absent
|
|
86
|
+
* for an index-less table.
|
|
87
|
+
*/
|
|
88
|
+
indexNames?: string[];
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Aggregate one basis table's state from its three orthogonal facts.
|
|
92
|
+
* `directly-mapped` wins over `derivation-source-only`, which wins over plain
|
|
93
|
+
* basis membership; a table no longer in the basis is `detached`.
|
|
94
|
+
*/
|
|
95
|
+
export declare function classifyBasisLifecycle(mappedBy: ReadonlyArray<string>, derivationSource: boolean, inBasis: boolean): BasisLifecycleState;
|
|
96
|
+
/**
|
|
97
|
+
* Split a lowercased `schema.table` relation key into its parts (first dot is the
|
|
98
|
+
* separator — schema names carry no dots). Used as the display-name fallback for
|
|
99
|
+
* a key that no current basis enumeration provides original case for (a stored
|
|
100
|
+
* detached record, or a derivation source that resolved to no basis member).
|
|
101
|
+
*/
|
|
102
|
+
export declare function splitRelKey(key: string): {
|
|
103
|
+
schema: string;
|
|
104
|
+
table: string;
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* True iff the recomputed record differs from the prior in any persisted field —
|
|
108
|
+
* the gate that keeps an idempotent re-apply (identical deploy) from rewriting
|
|
109
|
+
* every record. Compares the comparable fields explicitly rather than by
|
|
110
|
+
* stringify so field-presence/order quirks never produce a false diff. Reserved
|
|
111
|
+
* eviction-policy fields are carried through unchanged, so they only differ when
|
|
112
|
+
* `basis-eviction-policy` actually mutated them.
|
|
113
|
+
*/
|
|
114
|
+
export declare function basisLifecycleRecordChanged(a: BasisTableLifecycleRecord, b: BasisTableLifecycleRecord): boolean;
|
|
115
|
+
/**
|
|
116
|
+
* Parse a `quereus.sync.evict` reserved-tag value into an {@link EvictPolicy}, or
|
|
117
|
+
* `undefined` when absent / malformed (a malformed tag falls back to the global
|
|
118
|
+
* mode rather than failing the deploy — the engine's reserved-tag validator
|
|
119
|
+
* surfaces the shape error separately). Accepts `'never'` / `'immediate'`
|
|
120
|
+
* (case-insensitive) and a non-negative number (numeric value or numeric string).
|
|
121
|
+
*/
|
|
122
|
+
export declare function parseEvictPolicyTag(value: SqlValue): EvictPolicy | undefined;
|
|
123
|
+
/**
|
|
124
|
+
* Resolve a record's effective eviction horizon (ms) by composing its per-table
|
|
125
|
+
* {@link EvictPolicy} override with the global {@link SyncConfig.basisEviction}
|
|
126
|
+
* mode. Returns `null` for "never evict", `0` for "evict immediately once
|
|
127
|
+
* detached", or a positive horizon in milliseconds. The per-table override always
|
|
128
|
+
* wins over the global mode.
|
|
129
|
+
*/
|
|
130
|
+
export declare function effectiveEvictHorizonMs(record: Pick<BasisTableLifecycleRecord, 'evictPolicy'>, config: Pick<SyncConfig, 'basisEviction' | 'retentionHorizonMs'>): number | null;
|
|
131
|
+
/**
|
|
132
|
+
* The wall-time (ms) the table's "quiet" clock starts from: the later of when the
|
|
133
|
+
* local peer stopped directly mapping it (`unmappedSince`, falling back to
|
|
134
|
+
* `detachedAt` for a table never directly mapped) and the last observed inbound
|
|
135
|
+
* remote write (`lastDirectlyMappedWriteAt`). See `docs/migration.md` § 4 Contract.
|
|
136
|
+
*/
|
|
137
|
+
export declare function quietSince(record: BasisTableLifecycleRecord): number;
|
|
138
|
+
/**
|
|
139
|
+
* Whether a record is eligible for storage reclamation at `now`. Default eviction
|
|
140
|
+
* targets `detached` tables ONLY — an in-basis `unreferenced` table is a signal,
|
|
141
|
+
* never auto-dropped (dropping it would diverge from the basis the app still
|
|
142
|
+
* declares, and a re-map would resurrect it). `'never'` opts out entirely;
|
|
143
|
+
* `'immediate'` still requires `detached`.
|
|
144
|
+
*/
|
|
145
|
+
export declare function isEvictable(record: BasisTableLifecycleRecord, now: number, config: Pick<SyncConfig, 'basisEviction' | 'retentionHorizonMs'>): boolean;
|
|
146
|
+
/** Serialize a lifecycle record to bytes (flat JSON — see file header). */
|
|
147
|
+
export declare function serializeBasisLifecycleRecord(record: BasisTableLifecycleRecord): Uint8Array;
|
|
148
|
+
/** Deserialize a lifecycle record from bytes. */
|
|
149
|
+
export declare function deserializeBasisLifecycleRecord(buffer: Uint8Array): BasisTableLifecycleRecord;
|
|
150
|
+
/**
|
|
151
|
+
* KV-backed store for basis-table lifecycle records. Owns read / write / iterate;
|
|
152
|
+
* the transition detection + timestamp stamping live in the recorder, which
|
|
153
|
+
* stages writes into a single batch per deploy.
|
|
154
|
+
*/
|
|
155
|
+
export declare class BasisLifecycleStore {
|
|
156
|
+
private readonly kv;
|
|
157
|
+
constructor(kv: KVStore);
|
|
158
|
+
/** Read one record by basis `schema.table`, or undefined when none is stored. */
|
|
159
|
+
get(schemaName: string, tableName: string): Promise<BasisTableLifecycleRecord | undefined>;
|
|
160
|
+
/**
|
|
161
|
+
* Stage a record write into a caller-owned batch (keyed by `schema.table`
|
|
162
|
+
* lowercased, so re-recording overwrites its own entry). The recorder folds
|
|
163
|
+
* all of a deploy's changed records into one batch.
|
|
164
|
+
*/
|
|
165
|
+
put(batch: WriteBatch, record: BasisTableLifecycleRecord): void;
|
|
166
|
+
/**
|
|
167
|
+
* Delete one record by basis `schema.table` (the eviction sweep clears the
|
|
168
|
+
* record once a detached table's storage is reclaimed; a later re-create starts
|
|
169
|
+
* fresh). Idempotent — deleting an absent key is a no-op.
|
|
170
|
+
*/
|
|
171
|
+
delete(schemaName: string, tableName: string): Promise<void>;
|
|
172
|
+
/**
|
|
173
|
+
* Read every stored record, keyed by lowercased `schema.table` — the recorder's
|
|
174
|
+
* starting point for transition detection (it OR-folds the new deploy over these).
|
|
175
|
+
*/
|
|
176
|
+
getAll(): Promise<Map<string, BasisTableLifecycleRecord>>;
|
|
177
|
+
/** List every stored record (introspection — bounded by the basis table count). */
|
|
178
|
+
list(): Promise<BasisTableLifecycleRecord[]>;
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=basis-lifecycle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"basis-lifecycle.d.ts","sourceRoot":"","sources":["../../../src/metadata/basis-lifecycle.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Basis-table lifecycle store — durable per-basis-table classification + the
|
|
3
|
+
* mapped-since / unmapped-since bookkeeping that drives legacy-table retirement
|
|
4
|
+
* (`docs/migration.md` § 2 Converge).
|
|
5
|
+
*
|
|
6
|
+
* Each shared (basis) table is classified into one of four states relative to
|
|
7
|
+
* the app's current lens deployments and the basis schema's own derivations:
|
|
8
|
+
*
|
|
9
|
+
* - `directly-mapped` — some deployed lens backs a logical column with it.
|
|
10
|
+
* - `derivation-source-only` — referenced *solely* as a maintained table's
|
|
11
|
+
* source (the "this table is now legacy" signal).
|
|
12
|
+
* - `unreferenced` — in the basis, but neither mapped nor a
|
|
13
|
+
* derivation source.
|
|
14
|
+
* - `detached` — no longer in the basis schema; physical storage
|
|
15
|
+
* may linger (an eviction candidate).
|
|
16
|
+
*
|
|
17
|
+
* The classification is recomputed on every lens deploy
|
|
18
|
+
* ({@link import('../sync/sync-manager-impl.js').SyncManagerImpl.recordLensDeployment}).
|
|
19
|
+
* Records are KV-durable so the classification — and its timestamps — survive a
|
|
20
|
+
* restart with no prior deploy in the session.
|
|
21
|
+
*
|
|
22
|
+
* The record is a flat JSON-safe object (strings / numbers / booleans /
|
|
23
|
+
* `string[]`), so serialization is a plain `JSON.stringify`; no custom
|
|
24
|
+
* SqlValue / HLC encoding is needed (unlike `quarantine.ts` / `column-version.ts`).
|
|
25
|
+
*/
|
|
26
|
+
import { buildBasisLifecycleKey, buildAllBasisLifecycleScanBounds } from './keys.js';
|
|
27
|
+
/**
|
|
28
|
+
* Aggregate one basis table's state from its three orthogonal facts.
|
|
29
|
+
* `directly-mapped` wins over `derivation-source-only`, which wins over plain
|
|
30
|
+
* basis membership; a table no longer in the basis is `detached`.
|
|
31
|
+
*/
|
|
32
|
+
export function classifyBasisLifecycle(mappedBy, derivationSource, inBasis) {
|
|
33
|
+
if (mappedBy.length > 0)
|
|
34
|
+
return 'directly-mapped';
|
|
35
|
+
if (derivationSource)
|
|
36
|
+
return 'derivation-source-only';
|
|
37
|
+
if (inBasis)
|
|
38
|
+
return 'unreferenced';
|
|
39
|
+
return 'detached';
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Split a lowercased `schema.table` relation key into its parts (first dot is the
|
|
43
|
+
* separator — schema names carry no dots). Used as the display-name fallback for
|
|
44
|
+
* a key that no current basis enumeration provides original case for (a stored
|
|
45
|
+
* detached record, or a derivation source that resolved to no basis member).
|
|
46
|
+
*/
|
|
47
|
+
export function splitRelKey(key) {
|
|
48
|
+
const dot = key.indexOf('.');
|
|
49
|
+
if (dot === -1)
|
|
50
|
+
return { schema: '', table: key };
|
|
51
|
+
return { schema: key.slice(0, dot), table: key.slice(dot + 1) };
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* True iff the recomputed record differs from the prior in any persisted field —
|
|
55
|
+
* the gate that keeps an idempotent re-apply (identical deploy) from rewriting
|
|
56
|
+
* every record. Compares the comparable fields explicitly rather than by
|
|
57
|
+
* stringify so field-presence/order quirks never produce a false diff. Reserved
|
|
58
|
+
* eviction-policy fields are carried through unchanged, so they only differ when
|
|
59
|
+
* `basis-eviction-policy` actually mutated them.
|
|
60
|
+
*/
|
|
61
|
+
export function basisLifecycleRecordChanged(a, b) {
|
|
62
|
+
return a.state !== b.state
|
|
63
|
+
|| a.derivationSource !== b.derivationSource
|
|
64
|
+
|| a.inBasis !== b.inBasis
|
|
65
|
+
|| a.mappedSince !== b.mappedSince
|
|
66
|
+
|| a.unmappedSince !== b.unmappedSince
|
|
67
|
+
|| a.detachedAt !== b.detachedAt
|
|
68
|
+
|| a.lastDirectlyMappedWriteAt !== b.lastDirectlyMappedWriteAt
|
|
69
|
+
|| a.evictPolicy !== b.evictPolicy
|
|
70
|
+
|| a.mappedBy.length !== b.mappedBy.length
|
|
71
|
+
|| a.mappedBy.some((v, i) => v !== b.mappedBy[i])
|
|
72
|
+
|| (a.indexNames ?? []).length !== (b.indexNames ?? []).length
|
|
73
|
+
|| (a.indexNames ?? []).some((v, i) => v !== (b.indexNames ?? [])[i]);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Parse a `quereus.sync.evict` reserved-tag value into an {@link EvictPolicy}, or
|
|
77
|
+
* `undefined` when absent / malformed (a malformed tag falls back to the global
|
|
78
|
+
* mode rather than failing the deploy — the engine's reserved-tag validator
|
|
79
|
+
* surfaces the shape error separately). Accepts `'never'` / `'immediate'`
|
|
80
|
+
* (case-insensitive) and a non-negative number (numeric value or numeric string).
|
|
81
|
+
*/
|
|
82
|
+
export function parseEvictPolicyTag(value) {
|
|
83
|
+
if (value === null || value === undefined)
|
|
84
|
+
return undefined;
|
|
85
|
+
if (typeof value === 'number')
|
|
86
|
+
return Number.isFinite(value) && value >= 0 ? value : undefined;
|
|
87
|
+
if (typeof value === 'bigint')
|
|
88
|
+
return value >= 0n ? Number(value) : undefined;
|
|
89
|
+
if (typeof value === 'string') {
|
|
90
|
+
const v = value.trim().toLowerCase();
|
|
91
|
+
if (v === 'never')
|
|
92
|
+
return 'never';
|
|
93
|
+
if (v === 'immediate')
|
|
94
|
+
return 'immediate';
|
|
95
|
+
if (v.length === 0)
|
|
96
|
+
return undefined;
|
|
97
|
+
const n = Number(v);
|
|
98
|
+
return Number.isFinite(n) && n >= 0 ? n : undefined;
|
|
99
|
+
}
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Resolve a record's effective eviction horizon (ms) by composing its per-table
|
|
104
|
+
* {@link EvictPolicy} override with the global {@link SyncConfig.basisEviction}
|
|
105
|
+
* mode. Returns `null` for "never evict", `0` for "evict immediately once
|
|
106
|
+
* detached", or a positive horizon in milliseconds. The per-table override always
|
|
107
|
+
* wins over the global mode.
|
|
108
|
+
*/
|
|
109
|
+
export function effectiveEvictHorizonMs(record, config) {
|
|
110
|
+
const p = record.evictPolicy;
|
|
111
|
+
if (p === 'never')
|
|
112
|
+
return null;
|
|
113
|
+
if (p === 'immediate')
|
|
114
|
+
return 0;
|
|
115
|
+
if (typeof p === 'number')
|
|
116
|
+
return p;
|
|
117
|
+
// No per-table override — fall back to the global mode.
|
|
118
|
+
const eviction = config.basisEviction ?? { mode: 'horizon' };
|
|
119
|
+
switch (eviction.mode) {
|
|
120
|
+
case 'never': return null;
|
|
121
|
+
case 'immediate': return 0;
|
|
122
|
+
case 'horizon':
|
|
123
|
+
default: return eviction.horizonMs ?? config.retentionHorizonMs;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* The wall-time (ms) the table's "quiet" clock starts from: the later of when the
|
|
128
|
+
* local peer stopped directly mapping it (`unmappedSince`, falling back to
|
|
129
|
+
* `detachedAt` for a table never directly mapped) and the last observed inbound
|
|
130
|
+
* remote write (`lastDirectlyMappedWriteAt`). See `docs/migration.md` § 4 Contract.
|
|
131
|
+
*/
|
|
132
|
+
export function quietSince(record) {
|
|
133
|
+
const base = record.unmappedSince ?? record.detachedAt ?? 0;
|
|
134
|
+
return Math.max(base, record.lastDirectlyMappedWriteAt ?? 0);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Whether a record is eligible for storage reclamation at `now`. Default eviction
|
|
138
|
+
* targets `detached` tables ONLY — an in-basis `unreferenced` table is a signal,
|
|
139
|
+
* never auto-dropped (dropping it would diverge from the basis the app still
|
|
140
|
+
* declares, and a re-map would resurrect it). `'never'` opts out entirely;
|
|
141
|
+
* `'immediate'` still requires `detached`.
|
|
142
|
+
*/
|
|
143
|
+
export function isEvictable(record, now, config) {
|
|
144
|
+
if (record.state !== 'detached')
|
|
145
|
+
return false;
|
|
146
|
+
const horizon = effectiveEvictHorizonMs(record, config);
|
|
147
|
+
if (horizon === null)
|
|
148
|
+
return false; // 'never'
|
|
149
|
+
return now - quietSince(record) >= horizon;
|
|
150
|
+
}
|
|
151
|
+
/** Serialize a lifecycle record to bytes (flat JSON — see file header). */
|
|
152
|
+
export function serializeBasisLifecycleRecord(record) {
|
|
153
|
+
return new TextEncoder().encode(JSON.stringify(record));
|
|
154
|
+
}
|
|
155
|
+
/** Deserialize a lifecycle record from bytes. */
|
|
156
|
+
export function deserializeBasisLifecycleRecord(buffer) {
|
|
157
|
+
return JSON.parse(new TextDecoder().decode(buffer));
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* KV-backed store for basis-table lifecycle records. Owns read / write / iterate;
|
|
161
|
+
* the transition detection + timestamp stamping live in the recorder, which
|
|
162
|
+
* stages writes into a single batch per deploy.
|
|
163
|
+
*/
|
|
164
|
+
export class BasisLifecycleStore {
|
|
165
|
+
kv;
|
|
166
|
+
constructor(kv) {
|
|
167
|
+
this.kv = kv;
|
|
168
|
+
}
|
|
169
|
+
/** Read one record by basis `schema.table`, or undefined when none is stored. */
|
|
170
|
+
async get(schemaName, tableName) {
|
|
171
|
+
const value = await this.kv.get(buildBasisLifecycleKey(schemaName, tableName));
|
|
172
|
+
return value ? deserializeBasisLifecycleRecord(value) : undefined;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Stage a record write into a caller-owned batch (keyed by `schema.table`
|
|
176
|
+
* lowercased, so re-recording overwrites its own entry). The recorder folds
|
|
177
|
+
* all of a deploy's changed records into one batch.
|
|
178
|
+
*/
|
|
179
|
+
put(batch, record) {
|
|
180
|
+
batch.put(buildBasisLifecycleKey(record.schema, record.table), serializeBasisLifecycleRecord(record));
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Delete one record by basis `schema.table` (the eviction sweep clears the
|
|
184
|
+
* record once a detached table's storage is reclaimed; a later re-create starts
|
|
185
|
+
* fresh). Idempotent — deleting an absent key is a no-op.
|
|
186
|
+
*/
|
|
187
|
+
async delete(schemaName, tableName) {
|
|
188
|
+
await this.kv.delete(buildBasisLifecycleKey(schemaName, tableName));
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Read every stored record, keyed by lowercased `schema.table` — the recorder's
|
|
192
|
+
* starting point for transition detection (it OR-folds the new deploy over these).
|
|
193
|
+
*/
|
|
194
|
+
async getAll() {
|
|
195
|
+
const result = new Map();
|
|
196
|
+
for await (const entry of this.kv.iterate(buildAllBasisLifecycleScanBounds())) {
|
|
197
|
+
const record = deserializeBasisLifecycleRecord(entry.value);
|
|
198
|
+
result.set(`${record.schema}.${record.table}`.toLowerCase(), record);
|
|
199
|
+
}
|
|
200
|
+
return result;
|
|
201
|
+
}
|
|
202
|
+
/** List every stored record (introspection — bounded by the basis table count). */
|
|
203
|
+
async list() {
|
|
204
|
+
const records = [];
|
|
205
|
+
for await (const entry of this.kv.iterate(buildAllBasisLifecycleScanBounds())) {
|
|
206
|
+
records.push(deserializeBasisLifecycleRecord(entry.value));
|
|
207
|
+
}
|
|
208
|
+
return records;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
//# sourceMappingURL=basis-lifecycle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"basis-lifecycle.js","sourceRoot":"","sources":["../../../src/metadata/basis-lifecycle.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import type { KVStore, WriteBatch } from '@quereus/store';
|
|
8
8
|
import type { SqlValue } from '@quereus/quereus';
|
|
9
|
-
import type
|
|
9
|
+
import { type HLC } from '../clock/hlc.js';
|
|
10
10
|
import { type ChangeLogEntryType } from './keys.js';
|
|
11
11
|
/**
|
|
12
12
|
* Change log entry stored in KV.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"change-log.d.ts","sourceRoot":"","sources":["../../../src/metadata/change-log.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"change-log.d.ts","sourceRoot":"","sources":["../../../src/metadata/change-log.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,KAAK,GAAG,EAAc,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAKL,KAAK,kBAAkB,EACxB,MAAM,WAAW,CAAC;AAEnB;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAClB,QAAQ,CAAC,SAAS,EAAE,kBAAkB,CAAC;IACvC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,EAAE,QAAQ,EAAE,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,qBAAa,cAAc;IACb,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,OAAO;IAExC;;OAEG;IACG,kBAAkB,CACtB,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,EAAE,EAAE,QAAQ,EAAE,EACd,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC;IAMhB;;OAEG;IACH,uBAAuB,CACrB,KAAK,EAAE,UAAU,EACjB,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,EAAE,EAAE,QAAQ,EAAE,EACd,MAAM,EAAE,MAAM,GACb,IAAI;IAKP;;OAEG;IACG,cAAc,CAClB,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,EAAE,EAAE,QAAQ,EAAE,GACb,OAAO,CAAC,IAAI,CAAC;IAKhB;;OAEG;IACH,mBAAmB,CACjB,KAAK,EAAE,UAAU,EACjB,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,EAAE,EAAE,QAAQ,EAAE,GACb,IAAI;IAKP;;;OAGG;IACI,eAAe,CAAC,QAAQ,EAAE,GAAG,GAAG,aAAa,CAAC,cAAc,CAAC;IAUpE;;OAEG;IACI,aAAa,IAAI,aAAa,CAAC,cAAc,CAAC;IAUrD;;;OAGG;IACG,kBAAkB,CAAC,SAAS,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC;IAuBzD;;OAEG;IACH,gBAAgB,CACd,KAAK,EAAE,UAAU,EACjB,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,kBAAkB,EAC7B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,EAAE,EAAE,QAAQ,EAAE,EACd,MAAM,CAAC,EAAE,MAAM,GACd,IAAI;CAIR"}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* The change log stores references to changes indexed by HLC timestamp,
|
|
5
5
|
* enabling efficient getChangesSince() queries without scanning all data.
|
|
6
6
|
*/
|
|
7
|
+
import { compareHLC } from '../clock/hlc.js';
|
|
7
8
|
import { buildChangeLogKey, buildChangeLogScanBoundsAfter, buildAllChangeLogScanBounds, parseChangeLogKey, } from './keys.js';
|
|
8
9
|
/**
|
|
9
10
|
* Change log store for HLC-indexed change tracking.
|
|
@@ -83,13 +84,12 @@ export class ChangeLogStore {
|
|
|
83
84
|
const parsed = parseChangeLogKey(entry.key);
|
|
84
85
|
if (!parsed)
|
|
85
86
|
continue;
|
|
86
|
-
//
|
|
87
|
-
|
|
87
|
+
// Prune entries strictly before the boundary HLC. Iteration is in HLC key
|
|
88
|
+
// order (lexicographic == compareHLC), so the first entry at-or-after the
|
|
89
|
+
// boundary means every remaining entry is too — stop. Comparing via
|
|
90
|
+
// compareHLC keeps opSeq (and siteId) participating consistently.
|
|
91
|
+
if (compareHLC(parsed.hlc, beforeHLC) >= 0)
|
|
88
92
|
break;
|
|
89
|
-
if (parsed.hlc.wallTime === beforeHLC.wallTime) {
|
|
90
|
-
if (parsed.hlc.counter >= beforeHLC.counter)
|
|
91
|
-
break;
|
|
92
|
-
}
|
|
93
93
|
batch.delete(entry.key);
|
|
94
94
|
count++;
|
|
95
95
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"change-log.js","sourceRoot":"","sources":["../../../src/metadata/change-log.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"change-log.js","sourceRoot":"","sources":["../../../src/metadata/change-log.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAY,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EACL,iBAAiB,EACjB,6BAA6B,EAC7B,2BAA2B,EAC3B,iBAAiB,GAElB,MAAM,WAAW,CAAC;AAcnB;;;;;;GAMG;AACH,MAAM,OAAO,cAAc;IACI;IAA7B,YAA6B,EAAW;QAAX,OAAE,GAAF,EAAE,CAAS;IAAG,CAAC;IAE5C;;OAEG;IACH,KAAK,CAAC,kBAAkB,CACtB,GAAQ,EACR,MAAc,EACd,KAAa,EACb,EAAc,EACd,MAAc;QAEd,MAAM,GAAG,GAAG,iBAAiB,CAAC,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC;QACxE,0CAA0C;QAC1C,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5C,CAAC;IAED;;OAEG;IACH,uBAAuB,CACrB,KAAiB,EACjB,GAAQ,EACR,MAAc,EACd,KAAa,EACb,EAAc,EACd,MAAc;QAEd,MAAM,GAAG,GAAG,iBAAiB,CAAC,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC;QACxE,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IACpC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,cAAc,CAClB,GAAQ,EACR,MAAc,EACd,KAAa,EACb,EAAc;QAEd,MAAM,GAAG,GAAG,iBAAiB,CAAC,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;QAChE,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5C,CAAC;IAED;;OAEG;IACH,mBAAmB,CACjB,KAAiB,EACjB,GAAQ,EACR,MAAc,EACd,KAAa,EACb,EAAc;QAEd,MAAM,GAAG,GAAG,iBAAiB,CAAC,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;QAChE,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IACpC,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,CAAC,eAAe,CAAC,QAAa;QAClC,MAAM,MAAM,GAAG,6BAA6B,CAAC,QAAQ,CAAC,CAAC;QACvD,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAClD,MAAM,MAAM,GAAG,iBAAiB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC5C,IAAI,MAAM,EAAE,CAAC;gBACX,MAAM,MAAM,CAAC;YACf,CAAC;QACH,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,CAAC,aAAa;QAClB,MAAM,MAAM,GAAG,2BAA2B,EAAE,CAAC;QAC7C,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAClD,MAAM,MAAM,GAAG,iBAAiB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC5C,IAAI,MAAM,EAAE,CAAC;gBACX,MAAM,MAAM,CAAC;YACf,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,kBAAkB,CAAC,SAAc;QACrC,MAAM,MAAM,GAAG,2BAA2B,EAAE,CAAC;QAC7C,MAAM,KAAK,GAAG,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;QAC9B,IAAI,KAAK,GAAG,CAAC,CAAC;QAEd,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAClD,MAAM,MAAM,GAAG,iBAAiB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC5C,IAAI,CAAC,MAAM;gBAAE,SAAS;YAEtB,0EAA0E;YAC1E,0EAA0E;YAC1E,oEAAoE;YACpE,kEAAkE;YAClE,IAAI,UAAU,CAAC,MAAM,CAAC,GAAG,EAAE,SAAS,CAAC,IAAI,CAAC;gBAAE,MAAM;YAElD,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACxB,KAAK,EAAE,CAAC;QACV,CAAC;QAED,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC;QACpB,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;OAEG;IACH,gBAAgB,CACd,KAAiB,EACjB,GAAQ,EACR,SAA6B,EAC7B,MAAc,EACd,KAAa,EACb,EAAc,EACd,MAAe;QAEf,MAAM,GAAG,GAAG,iBAAiB,CAAC,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC;QACzE,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACpB,CAAC;CACF"}
|
|
@@ -9,22 +9,31 @@ import type { KVStore, WriteBatch } from '@quereus/store';
|
|
|
9
9
|
import { type HLC } from '../clock/hlc.js';
|
|
10
10
|
/**
|
|
11
11
|
* Column version record stored in the KV store.
|
|
12
|
+
*
|
|
13
|
+
* `priorHlc`/`priorValue` are an optional per-cell before-image: the cell version
|
|
14
|
+
* this one replaced (its replica-local lineage). They are written together (both
|
|
15
|
+
* present or both absent) and are absent on the first write of a cell and on
|
|
16
|
+
* snapshot-reconstructed cells (a snapshot is a fresh basis with no history).
|
|
12
17
|
*/
|
|
13
18
|
export interface ColumnVersion {
|
|
14
19
|
hlc: HLC;
|
|
15
20
|
value: SqlValue;
|
|
21
|
+
priorHlc?: HLC;
|
|
22
|
+
priorValue?: SqlValue;
|
|
16
23
|
}
|
|
17
24
|
/**
|
|
18
25
|
* Serialize a column version for storage.
|
|
19
|
-
* Format:
|
|
26
|
+
* Format: 30 bytes HLC + JSON payload `{ v, pv?, ph? }`.
|
|
20
27
|
*
|
|
21
|
-
* Uint8Array values are encoded as `{"__bin":"<base64>"}`
|
|
22
|
-
* the JSON round-trip
|
|
23
|
-
*
|
|
28
|
+
* Uint8Array values are encoded as `{"__bin":"<base64>"}` (bigint as
|
|
29
|
+
* `{"__bigint":"..."}`) so they survive the JSON round-trip; the same encoding
|
|
30
|
+
* covers the before-image (`pv`). The before-image fields are omitted entirely
|
|
31
|
+
* when the version has no prior, keeping first-writes and snapshot cells compact.
|
|
24
32
|
*/
|
|
25
33
|
export declare function serializeColumnVersion(cv: ColumnVersion): Uint8Array;
|
|
26
34
|
/**
|
|
27
|
-
* Deserialize a column version from storage.
|
|
35
|
+
* Deserialize a column version from storage. Tolerant of the before-image being
|
|
36
|
+
* absent (first-writes and snapshot-reconstructed cells carry none).
|
|
28
37
|
*/
|
|
29
38
|
export declare function deserializeColumnVersion(buffer: Uint8Array): ColumnVersion;
|
|
30
39
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"column-version.d.ts","sourceRoot":"","sources":["../../../src/metadata/column-version.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,KAAK,GAAG,
|
|
1
|
+
{"version":3,"file":"column-version.d.ts","sourceRoot":"","sources":["../../../src/metadata/column-version.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,KAAK,GAAG,EAAwF,MAAM,iBAAiB,CAAC;AAGjI;;;;;;;GAOG;AACH,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,GAAG,CAAC;IACT,KAAK,EAAE,QAAQ,CAAC;IAChB,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,UAAU,CAAC,EAAE,QAAQ,CAAC;CACvB;AAcD;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,aAAa,GAAG,UAAU,CAapE;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,UAAU,GAAG,aAAa,CAS1E;AAMD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,QAAQ,GAAG,OAAO,CAUnD;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,OAAO,GAAG,QAAQ,CA2BnD;AAED;;GAEG;AACH,qBAAa,kBAAkB;IACjB,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,OAAO;IAExC;;OAEG;IACG,gBAAgB,CACpB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,EAAE,EAAE,QAAQ,EAAE,EACd,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC;IAOrC;;OAEG;IACG,gBAAgB,CACpB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,EAAE,EAAE,QAAQ,EAAE,EACd,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,IAAI,CAAC;IAKhB;;OAEG;IACH,qBAAqB,CACnB,KAAK,EAAE,UAAU,EACjB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,EAAE,EAAE,QAAQ,EAAE,EACd,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,aAAa,GACrB,IAAI;IAKP;;OAEG;IACG,cAAc,CAClB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,EAAE,EAAE,QAAQ,EAAE,GACb,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAgBtC;;OAEG;IACG,iBAAiB,CACrB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,EAAE,EAAE,QAAQ,EAAE,GACb,OAAO,CAAC,IAAI,CAAC;IAWhB;;;OAGG;IACG,gBAAgB,CACpB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,EAAE,EAAE,QAAQ,EAAE,EACd,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,GAAG,GACf,OAAO,CAAC,OAAO,CAAC;CAKpB"}
|
|
@@ -4,33 +4,43 @@
|
|
|
4
4
|
* Each column of each row has an associated HLC timestamp.
|
|
5
5
|
* When merging changes, the column with the higher HLC wins.
|
|
6
6
|
*/
|
|
7
|
-
import { serializeHLC, deserializeHLC, compareHLC } from '../clock/hlc.js';
|
|
7
|
+
import { serializeHLC, deserializeHLC, compareHLC, hlcToJson, hlcFromJson } from '../clock/hlc.js';
|
|
8
8
|
import { buildColumnVersionKey, buildColumnVersionScanBounds } from './keys.js';
|
|
9
9
|
/**
|
|
10
10
|
* Serialize a column version for storage.
|
|
11
|
-
* Format:
|
|
11
|
+
* Format: 30 bytes HLC + JSON payload `{ v, pv?, ph? }`.
|
|
12
12
|
*
|
|
13
|
-
* Uint8Array values are encoded as `{"__bin":"<base64>"}`
|
|
14
|
-
* the JSON round-trip
|
|
15
|
-
*
|
|
13
|
+
* Uint8Array values are encoded as `{"__bin":"<base64>"}` (bigint as
|
|
14
|
+
* `{"__bigint":"..."}`) so they survive the JSON round-trip; the same encoding
|
|
15
|
+
* covers the before-image (`pv`). The before-image fields are omitted entirely
|
|
16
|
+
* when the version has no prior, keeping first-writes and snapshot cells compact.
|
|
16
17
|
*/
|
|
17
18
|
export function serializeColumnVersion(cv) {
|
|
18
19
|
const hlcBytes = serializeHLC(cv.hlc);
|
|
19
|
-
const
|
|
20
|
-
|
|
20
|
+
const payload = { v: encodeSqlValue(cv.value) };
|
|
21
|
+
if (cv.priorHlc !== undefined) {
|
|
22
|
+
payload.ph = hlcToJson(cv.priorHlc);
|
|
23
|
+
payload.pv = encodeSqlValue(cv.priorValue ?? null);
|
|
24
|
+
}
|
|
25
|
+
const valueBytes = new TextEncoder().encode(JSON.stringify(payload));
|
|
21
26
|
const result = new Uint8Array(hlcBytes.length + valueBytes.length);
|
|
22
27
|
result.set(hlcBytes, 0);
|
|
23
28
|
result.set(valueBytes, hlcBytes.length);
|
|
24
29
|
return result;
|
|
25
30
|
}
|
|
26
31
|
/**
|
|
27
|
-
* Deserialize a column version from storage.
|
|
32
|
+
* Deserialize a column version from storage. Tolerant of the before-image being
|
|
33
|
+
* absent (first-writes and snapshot-reconstructed cells carry none).
|
|
28
34
|
*/
|
|
29
35
|
export function deserializeColumnVersion(buffer) {
|
|
30
|
-
const hlc = deserializeHLC(buffer.slice(0,
|
|
31
|
-
const
|
|
32
|
-
const
|
|
33
|
-
|
|
36
|
+
const hlc = deserializeHLC(buffer.slice(0, 30));
|
|
37
|
+
const payload = JSON.parse(new TextDecoder().decode(buffer.slice(30)));
|
|
38
|
+
const cv = { hlc, value: decodeSqlValue(payload.v) };
|
|
39
|
+
if (payload.ph !== undefined) {
|
|
40
|
+
cv.priorHlc = hlcFromJson(payload.ph);
|
|
41
|
+
cv.priorValue = decodeSqlValue(payload.pv);
|
|
42
|
+
}
|
|
43
|
+
return cv;
|
|
34
44
|
}
|
|
35
45
|
// ============================================================================
|
|
36
46
|
// SqlValue JSON encoding helpers
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"column-version.js","sourceRoot":"","sources":["../../../src/metadata/column-version.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,
|
|
1
|
+
{"version":3,"file":"column-version.js","sourceRoot":"","sources":["../../../src/metadata/column-version.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/metadata/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,WAAW,CAAC;AAC1B,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/metadata/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,WAAW,CAAC;AAC1B,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/metadata/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,WAAW,CAAC;AAC1B,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/metadata/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,WAAW,CAAC;AAC1B,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC"}
|