@quereus/plugin-sync 0.3.1 → 0.3.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/README.md +2 -1
- package/package.json +4 -4
- package/dist/src/clock/hlc.d.ts +0 -105
- package/dist/src/clock/hlc.d.ts.map +0 -1
- package/dist/src/clock/hlc.js +0 -251
- package/dist/src/clock/hlc.js.map +0 -1
- package/dist/src/clock/index.d.ts +0 -6
- package/dist/src/clock/index.d.ts.map +0 -1
- package/dist/src/clock/index.js +0 -6
- package/dist/src/clock/index.js.map +0 -1
- package/dist/src/clock/site.d.ts +0 -58
- package/dist/src/clock/site.d.ts.map +0 -1
- package/dist/src/clock/site.js +0 -137
- package/dist/src/clock/site.js.map +0 -1
- package/dist/src/create-sync-module.d.ts +0 -85
- package/dist/src/create-sync-module.d.ts.map +0 -1
- package/dist/src/create-sync-module.js +0 -54
- package/dist/src/create-sync-module.js.map +0 -1
- package/dist/src/index.d.ts +0 -31
- package/dist/src/index.d.ts.map +0 -1
- package/dist/src/index.js +0 -42
- package/dist/src/index.js.map +0 -1
- package/dist/src/metadata/change-log.d.ts +0 -67
- package/dist/src/metadata/change-log.d.ts.map +0 -1
- package/dist/src/metadata/change-log.js +0 -107
- package/dist/src/metadata/change-log.js.map +0 -1
- package/dist/src/metadata/column-version.d.ts +0 -58
- package/dist/src/metadata/column-version.d.ts.map +0 -1
- package/dist/src/metadata/column-version.js +0 -100
- package/dist/src/metadata/column-version.js.map +0 -1
- package/dist/src/metadata/index.d.ts +0 -11
- package/dist/src/metadata/index.d.ts.map +0 -1
- package/dist/src/metadata/index.js +0 -11
- package/dist/src/metadata/index.js.map +0 -1
- package/dist/src/metadata/keys.d.ts +0 -180
- package/dist/src/metadata/keys.d.ts.map +0 -1
- package/dist/src/metadata/keys.js +0 -390
- package/dist/src/metadata/keys.js.map +0 -1
- package/dist/src/metadata/peer-state.d.ts +0 -52
- package/dist/src/metadata/peer-state.d.ts.map +0 -1
- package/dist/src/metadata/peer-state.js +0 -87
- package/dist/src/metadata/peer-state.js.map +0 -1
- package/dist/src/metadata/schema-migration.d.ts +0 -60
- package/dist/src/metadata/schema-migration.d.ts.map +0 -1
- package/dist/src/metadata/schema-migration.js +0 -126
- package/dist/src/metadata/schema-migration.js.map +0 -1
- package/dist/src/metadata/schema-version.d.ts +0 -163
- package/dist/src/metadata/schema-version.d.ts.map +0 -1
- package/dist/src/metadata/schema-version.js +0 -307
- package/dist/src/metadata/schema-version.js.map +0 -1
- package/dist/src/metadata/tombstones.d.ts +0 -67
- package/dist/src/metadata/tombstones.d.ts.map +0 -1
- package/dist/src/metadata/tombstones.js +0 -125
- package/dist/src/metadata/tombstones.js.map +0 -1
- package/dist/src/sync/events.d.ts +0 -117
- package/dist/src/sync/events.d.ts.map +0 -1
- package/dist/src/sync/events.js +0 -56
- package/dist/src/sync/events.js.map +0 -1
- package/dist/src/sync/index.d.ts +0 -8
- package/dist/src/sync/index.d.ts.map +0 -1
- package/dist/src/sync/index.js +0 -8
- package/dist/src/sync/index.js.map +0 -1
- package/dist/src/sync/manager.d.ts +0 -146
- package/dist/src/sync/manager.d.ts.map +0 -1
- package/dist/src/sync/manager.js +0 -8
- package/dist/src/sync/manager.js.map +0 -1
- package/dist/src/sync/protocol.d.ts +0 -282
- package/dist/src/sync/protocol.d.ts.map +0 -1
- package/dist/src/sync/protocol.js +0 -16
- package/dist/src/sync/protocol.js.map +0 -1
- package/dist/src/sync/store-adapter.d.ts +0 -42
- package/dist/src/sync/store-adapter.d.ts.map +0 -1
- package/dist/src/sync/store-adapter.js +0 -232
- package/dist/src/sync/store-adapter.js.map +0 -1
- package/dist/src/sync/sync-manager-impl.d.ts +0 -91
- package/dist/src/sync/sync-manager-impl.d.ts.map +0 -1
- package/dist/src/sync/sync-manager-impl.js +0 -1123
- package/dist/src/sync/sync-manager-impl.js.map +0 -1
|
@@ -1,307 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Column-level schema versioning for sync.
|
|
3
|
-
*
|
|
4
|
-
* Tracks the HLC timestamp of each column's definition to enable
|
|
5
|
-
* "most destructive wins" conflict resolution for schema changes.
|
|
6
|
-
*
|
|
7
|
-
* Key format: sv:{schema}.{table}:{column}
|
|
8
|
-
* Value: HLC (26 bytes) + 1 byte type + type-specific data
|
|
9
|
-
*
|
|
10
|
-
* Column types:
|
|
11
|
-
* - 0x01: Regular column (type affinity, nullable, default)
|
|
12
|
-
* - 0x02: Dropped column (tombstone)
|
|
13
|
-
* - 0x03: Table-level (for CREATE/DROP TABLE)
|
|
14
|
-
*
|
|
15
|
-
* Destructiveness hierarchy (higher wins in conflicts):
|
|
16
|
-
* - DROP TABLE/COLUMN: 3 (most destructive)
|
|
17
|
-
* - ALTER COLUMN: 2
|
|
18
|
-
* - ADD COLUMN/CREATE TABLE: 1 (least destructive)
|
|
19
|
-
*/
|
|
20
|
-
import { serializeHLC, deserializeHLC, compareHLC } from '../clock/hlc.js';
|
|
21
|
-
const encoder = new TextEncoder();
|
|
22
|
-
const decoder = new TextDecoder();
|
|
23
|
-
/**
|
|
24
|
-
* Build a schema version key.
|
|
25
|
-
* Format: sv:{schema}.{table}:{column}
|
|
26
|
-
* For table-level entries, column is '__table__'.
|
|
27
|
-
*/
|
|
28
|
-
export function buildSchemaVersionKey(schemaName, tableName, columnName = '__table__') {
|
|
29
|
-
return encoder.encode(`sv:${schemaName}.${tableName}:${columnName}`);
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* Build scan bounds for all schema versions of a table.
|
|
33
|
-
*/
|
|
34
|
-
export function buildSchemaVersionScanBounds(schemaName, tableName) {
|
|
35
|
-
const prefix = `sv:${schemaName}.${tableName}:`;
|
|
36
|
-
return {
|
|
37
|
-
gte: encoder.encode(prefix),
|
|
38
|
-
lt: incrementLastByte(encoder.encode(prefix)),
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Build scan bounds for ALL schema versions across all tables.
|
|
43
|
-
*/
|
|
44
|
-
export function buildAllSchemaVersionsScanBounds() {
|
|
45
|
-
const prefix = encoder.encode('sv:');
|
|
46
|
-
return {
|
|
47
|
-
gte: prefix,
|
|
48
|
-
lt: incrementLastByte(prefix),
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Serialize a schema version for storage.
|
|
53
|
-
*/
|
|
54
|
-
export function serializeSchemaVersion(version) {
|
|
55
|
-
const hlcBytes = serializeHLC(version.hlc);
|
|
56
|
-
const typeByte = version.type === 'column' ? 0x01 : version.type === 'dropped' ? 0x02 : 0x03;
|
|
57
|
-
// Serialize type-specific data as JSON
|
|
58
|
-
const data = {};
|
|
59
|
-
if (version.affinity !== undefined)
|
|
60
|
-
data.affinity = version.affinity;
|
|
61
|
-
if (version.nullable !== undefined)
|
|
62
|
-
data.nullable = version.nullable;
|
|
63
|
-
if (version.defaultExpr !== undefined)
|
|
64
|
-
data.defaultExpr = version.defaultExpr;
|
|
65
|
-
if (version.ddl !== undefined)
|
|
66
|
-
data.ddl = version.ddl;
|
|
67
|
-
const dataBytes = encoder.encode(JSON.stringify(data));
|
|
68
|
-
const buffer = new Uint8Array(26 + 1 + dataBytes.length);
|
|
69
|
-
buffer.set(hlcBytes, 0);
|
|
70
|
-
buffer[26] = typeByte;
|
|
71
|
-
buffer.set(dataBytes, 27);
|
|
72
|
-
return buffer;
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Deserialize a schema version from storage.
|
|
76
|
-
*/
|
|
77
|
-
export function deserializeSchemaVersion(buffer) {
|
|
78
|
-
const hlc = deserializeHLC(buffer.slice(0, 26));
|
|
79
|
-
const typeByte = buffer[26];
|
|
80
|
-
const type = typeByte === 0x01 ? 'column' : typeByte === 0x02 ? 'dropped' : 'table';
|
|
81
|
-
const dataJson = decoder.decode(buffer.slice(27));
|
|
82
|
-
const data = dataJson ? JSON.parse(dataJson) : {};
|
|
83
|
-
return {
|
|
84
|
-
hlc,
|
|
85
|
-
type,
|
|
86
|
-
affinity: data.affinity,
|
|
87
|
-
nullable: data.nullable,
|
|
88
|
-
defaultExpr: data.defaultExpr,
|
|
89
|
-
ddl: data.ddl,
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Parse a schema version key to extract components.
|
|
94
|
-
*/
|
|
95
|
-
export function parseSchemaVersionKey(key) {
|
|
96
|
-
const keyStr = decoder.decode(key);
|
|
97
|
-
if (!keyStr.startsWith('sv:'))
|
|
98
|
-
return null;
|
|
99
|
-
const rest = keyStr.slice(3);
|
|
100
|
-
const firstDot = rest.indexOf('.');
|
|
101
|
-
if (firstDot === -1)
|
|
102
|
-
return null;
|
|
103
|
-
const schema = rest.slice(0, firstDot);
|
|
104
|
-
const afterDot = rest.slice(firstDot + 1);
|
|
105
|
-
const firstColon = afterDot.indexOf(':');
|
|
106
|
-
if (firstColon === -1)
|
|
107
|
-
return null;
|
|
108
|
-
const table = afterDot.slice(0, firstColon);
|
|
109
|
-
const column = afterDot.slice(firstColon + 1);
|
|
110
|
-
return { schema, table, column };
|
|
111
|
-
}
|
|
112
|
-
function incrementLastByte(key) {
|
|
113
|
-
const result = new Uint8Array(key.length);
|
|
114
|
-
result.set(key);
|
|
115
|
-
for (let i = result.length - 1; i >= 0; i--) {
|
|
116
|
-
if (result[i] < 255) {
|
|
117
|
-
result[i]++;
|
|
118
|
-
break;
|
|
119
|
-
}
|
|
120
|
-
result[i] = 0;
|
|
121
|
-
}
|
|
122
|
-
return result;
|
|
123
|
-
}
|
|
124
|
-
/**
|
|
125
|
-
* Schema version store operations.
|
|
126
|
-
*/
|
|
127
|
-
export class SchemaVersionStore {
|
|
128
|
-
kv;
|
|
129
|
-
constructor(kv) {
|
|
130
|
-
this.kv = kv;
|
|
131
|
-
}
|
|
132
|
-
/**
|
|
133
|
-
* Get the schema version for a column.
|
|
134
|
-
*/
|
|
135
|
-
async getColumnVersion(schemaName, tableName, columnName) {
|
|
136
|
-
const key = buildSchemaVersionKey(schemaName, tableName, columnName);
|
|
137
|
-
const data = await this.kv.get(key);
|
|
138
|
-
if (!data)
|
|
139
|
-
return undefined;
|
|
140
|
-
return deserializeSchemaVersion(data);
|
|
141
|
-
}
|
|
142
|
-
/**
|
|
143
|
-
* Get the schema version for a table.
|
|
144
|
-
*/
|
|
145
|
-
async getTableVersion(schemaName, tableName) {
|
|
146
|
-
return this.getColumnVersion(schemaName, tableName, '__table__');
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* Set the schema version for a column.
|
|
150
|
-
*/
|
|
151
|
-
async setColumnVersion(schemaName, tableName, columnName, version) {
|
|
152
|
-
const key = buildSchemaVersionKey(schemaName, tableName, columnName);
|
|
153
|
-
await this.kv.put(key, serializeSchemaVersion(version));
|
|
154
|
-
}
|
|
155
|
-
/**
|
|
156
|
-
* Set the schema version for a column in a batch.
|
|
157
|
-
*/
|
|
158
|
-
setColumnVersionBatch(batch, schemaName, tableName, columnName, version) {
|
|
159
|
-
const key = buildSchemaVersionKey(schemaName, tableName, columnName);
|
|
160
|
-
batch.put(key, serializeSchemaVersion(version));
|
|
161
|
-
}
|
|
162
|
-
/**
|
|
163
|
-
* Set the schema version for a table.
|
|
164
|
-
*/
|
|
165
|
-
async setTableVersion(schemaName, tableName, version) {
|
|
166
|
-
return this.setColumnVersion(schemaName, tableName, '__table__', version);
|
|
167
|
-
}
|
|
168
|
-
/**
|
|
169
|
-
* Get all column versions for a table.
|
|
170
|
-
*/
|
|
171
|
-
async *getAllColumnVersions(schemaName, tableName) {
|
|
172
|
-
const bounds = buildSchemaVersionScanBounds(schemaName, tableName);
|
|
173
|
-
for await (const entry of this.kv.iterate(bounds)) {
|
|
174
|
-
const parsed = parseSchemaVersionKey(entry.key);
|
|
175
|
-
if (!parsed)
|
|
176
|
-
continue;
|
|
177
|
-
yield {
|
|
178
|
-
column: parsed.column,
|
|
179
|
-
version: deserializeSchemaVersion(entry.value),
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
/**
|
|
184
|
-
* Get all schema versions across all tables.
|
|
185
|
-
*/
|
|
186
|
-
async *getAllSchemaVersions() {
|
|
187
|
-
const bounds = buildAllSchemaVersionsScanBounds();
|
|
188
|
-
for await (const entry of this.kv.iterate(bounds)) {
|
|
189
|
-
const parsed = parseSchemaVersionKey(entry.key);
|
|
190
|
-
if (!parsed)
|
|
191
|
-
continue;
|
|
192
|
-
yield {
|
|
193
|
-
schema: parsed.schema,
|
|
194
|
-
table: parsed.table,
|
|
195
|
-
column: parsed.column,
|
|
196
|
-
version: deserializeSchemaVersion(entry.value),
|
|
197
|
-
};
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
/**
|
|
201
|
-
* Check if a schema change should be applied based on HLC comparison.
|
|
202
|
-
* Returns true if the incoming change should win.
|
|
203
|
-
*/
|
|
204
|
-
async shouldApplyChange(schemaName, tableName, columnName, incomingHLC) {
|
|
205
|
-
const existing = await this.getColumnVersion(schemaName, tableName, columnName);
|
|
206
|
-
if (!existing)
|
|
207
|
-
return true; // No existing version, apply the change
|
|
208
|
-
// LWW: higher HLC wins
|
|
209
|
-
return compareHLC(incomingHLC, existing.hlc) > 0;
|
|
210
|
-
}
|
|
211
|
-
/**
|
|
212
|
-
* Check if a schema change should be applied using "most destructive wins" semantics.
|
|
213
|
-
*
|
|
214
|
-
* When two schema changes conflict (same HLC or concurrent changes):
|
|
215
|
-
* 1. More destructive changes win over less destructive ones
|
|
216
|
-
* 2. If same destructiveness, higher HLC wins
|
|
217
|
-
*
|
|
218
|
-
* Destructiveness hierarchy:
|
|
219
|
-
* - DROP (column or table): 3
|
|
220
|
-
* - ALTER (type change, constraint change): 2
|
|
221
|
-
* - ADD (new column, create table): 1
|
|
222
|
-
*
|
|
223
|
-
* @returns true if the incoming change should be applied
|
|
224
|
-
*/
|
|
225
|
-
async shouldApplySchemaChange(schemaName, tableName, columnName, incomingVersion) {
|
|
226
|
-
const existing = await this.getColumnVersion(schemaName, tableName, columnName);
|
|
227
|
-
if (!existing)
|
|
228
|
-
return true; // No existing version, apply the change
|
|
229
|
-
const incomingDestructiveness = getDestructiveness(incomingVersion.type);
|
|
230
|
-
const existingDestructiveness = getDestructiveness(existing.type);
|
|
231
|
-
// More destructive wins
|
|
232
|
-
if (incomingDestructiveness > existingDestructiveness) {
|
|
233
|
-
return true;
|
|
234
|
-
}
|
|
235
|
-
if (incomingDestructiveness < existingDestructiveness) {
|
|
236
|
-
return false;
|
|
237
|
-
}
|
|
238
|
-
// Same destructiveness: LWW (higher HLC wins)
|
|
239
|
-
return compareHLC(incomingVersion.hlc, existing.hlc) > 0;
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
/**
|
|
243
|
-
* Get the destructiveness level of a schema version type.
|
|
244
|
-
* Higher values are more destructive.
|
|
245
|
-
*/
|
|
246
|
-
export function getDestructiveness(type) {
|
|
247
|
-
switch (type) {
|
|
248
|
-
case 'dropped':
|
|
249
|
-
return 3; // Most destructive
|
|
250
|
-
case 'table':
|
|
251
|
-
// Table type can be either CREATE or DROP, but we treat it as moderate
|
|
252
|
-
// The actual destructiveness depends on whether it's a create or drop
|
|
253
|
-
return 2;
|
|
254
|
-
case 'column':
|
|
255
|
-
return 1; // Least destructive (add/alter)
|
|
256
|
-
default:
|
|
257
|
-
return 0;
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
/**
|
|
261
|
-
* Get the destructiveness level of a schema change operation.
|
|
262
|
-
* Higher values are more destructive.
|
|
263
|
-
*/
|
|
264
|
-
export function getOperationDestructiveness(operation) {
|
|
265
|
-
switch (operation) {
|
|
266
|
-
case 'drop_table':
|
|
267
|
-
return 5; // Most destructive
|
|
268
|
-
case 'drop_column':
|
|
269
|
-
return 4;
|
|
270
|
-
case 'alter_column':
|
|
271
|
-
return 3;
|
|
272
|
-
case 'add_column':
|
|
273
|
-
return 2;
|
|
274
|
-
case 'create_table':
|
|
275
|
-
return 1; // Least destructive
|
|
276
|
-
default:
|
|
277
|
-
return 0;
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
/**
|
|
281
|
-
* Determine if an incoming schema change should be applied based on
|
|
282
|
-
* "most destructive wins" semantics.
|
|
283
|
-
*
|
|
284
|
-
* @param incomingOp The incoming schema change operation
|
|
285
|
-
* @param incomingHLC The HLC of the incoming change
|
|
286
|
-
* @param existingOp The existing schema change operation (if any)
|
|
287
|
-
* @param existingHLC The HLC of the existing change (if any)
|
|
288
|
-
* @returns true if the incoming change should be applied
|
|
289
|
-
*/
|
|
290
|
-
export function shouldApplySchemaChangeByOperation(incomingOp, incomingHLC, existingOp, existingHLC) {
|
|
291
|
-
// No existing change, apply the incoming one
|
|
292
|
-
if (!existingOp || !existingHLC) {
|
|
293
|
-
return true;
|
|
294
|
-
}
|
|
295
|
-
const incomingDestructiveness = getOperationDestructiveness(incomingOp);
|
|
296
|
-
const existingDestructiveness = getOperationDestructiveness(existingOp);
|
|
297
|
-
// More destructive wins
|
|
298
|
-
if (incomingDestructiveness > existingDestructiveness) {
|
|
299
|
-
return true;
|
|
300
|
-
}
|
|
301
|
-
if (incomingDestructiveness < existingDestructiveness) {
|
|
302
|
-
return false;
|
|
303
|
-
}
|
|
304
|
-
// Same destructiveness: LWW (higher HLC wins)
|
|
305
|
-
return compareHLC(incomingHLC, existingHLC) > 0;
|
|
306
|
-
}
|
|
307
|
-
//# sourceMappingURL=schema-version.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"schema-version.js","sourceRoot":"","sources":["../../../src/metadata/schema-version.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tombstone tracking for deletion synchronization.
|
|
3
|
-
*
|
|
4
|
-
* When a row is deleted, a tombstone is created with the deletion HLC.
|
|
5
|
-
* Tombstones prevent deleted rows from being resurrected by older writes.
|
|
6
|
-
*/
|
|
7
|
-
import type { SqlValue } from '@quereus/quereus';
|
|
8
|
-
import type { KVStore, WriteBatch } from '@quereus/plugin-store';
|
|
9
|
-
import { type HLC } from '../clock/hlc.js';
|
|
10
|
-
/**
|
|
11
|
-
* Tombstone record.
|
|
12
|
-
*/
|
|
13
|
-
export interface Tombstone {
|
|
14
|
-
hlc: HLC;
|
|
15
|
-
createdAt: number;
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Serialize a tombstone for storage.
|
|
19
|
-
* Format: 26 bytes HLC + 8 bytes createdAt
|
|
20
|
-
*/
|
|
21
|
-
export declare function serializeTombstone(tombstone: Tombstone): Uint8Array;
|
|
22
|
-
/**
|
|
23
|
-
* Deserialize a tombstone from storage.
|
|
24
|
-
*/
|
|
25
|
-
export declare function deserializeTombstone(buffer: Uint8Array): Tombstone;
|
|
26
|
-
/**
|
|
27
|
-
* Tombstone store operations.
|
|
28
|
-
*/
|
|
29
|
-
export declare class TombstoneStore {
|
|
30
|
-
private readonly kv;
|
|
31
|
-
private readonly tombstoneTTL;
|
|
32
|
-
constructor(kv: KVStore, tombstoneTTL: number);
|
|
33
|
-
/**
|
|
34
|
-
* Get the tombstone for a row, if it exists.
|
|
35
|
-
*/
|
|
36
|
-
getTombstone(schemaName: string, tableName: string, pk: SqlValue[]): Promise<Tombstone | undefined>;
|
|
37
|
-
/**
|
|
38
|
-
* Create a tombstone for a deleted row.
|
|
39
|
-
*/
|
|
40
|
-
setTombstone(schemaName: string, tableName: string, pk: SqlValue[], hlc: HLC): Promise<void>;
|
|
41
|
-
/**
|
|
42
|
-
* Set tombstone in a batch.
|
|
43
|
-
*/
|
|
44
|
-
setTombstoneBatch(batch: WriteBatch, schemaName: string, tableName: string, pk: SqlValue[], hlc: HLC): void;
|
|
45
|
-
/**
|
|
46
|
-
* Delete a tombstone (used when resurrecting a row).
|
|
47
|
-
*/
|
|
48
|
-
deleteTombstone(schemaName: string, tableName: string, pk: SqlValue[]): Promise<void>;
|
|
49
|
-
/**
|
|
50
|
-
* Check if a row is deleted and the deletion should block a write.
|
|
51
|
-
* Returns true if the row is deleted and the incoming HLC is older than the deletion.
|
|
52
|
-
*/
|
|
53
|
-
isDeletedAndBlocking(schemaName: string, tableName: string, pk: SqlValue[], incomingHLC: HLC, allowResurrection: boolean): Promise<boolean>;
|
|
54
|
-
/**
|
|
55
|
-
* Prune expired tombstones.
|
|
56
|
-
* Returns the number of tombstones deleted.
|
|
57
|
-
*/
|
|
58
|
-
pruneExpired(schemaName: string, tableName: string): Promise<number>;
|
|
59
|
-
/**
|
|
60
|
-
* Get all tombstones for a table (for sync).
|
|
61
|
-
*/
|
|
62
|
-
getAllTombstones(schemaName: string, tableName: string): AsyncIterable<{
|
|
63
|
-
pk: SqlValue[];
|
|
64
|
-
tombstone: Tombstone;
|
|
65
|
-
}>;
|
|
66
|
-
}
|
|
67
|
-
//# sourceMappingURL=tombstones.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tombstones.d.ts","sourceRoot":"","sources":["../../../src/metadata/tombstones.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,EAAE,KAAK,GAAG,EAA4C,MAAM,iBAAiB,CAAC;AAGrF;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,GAAG,CAAC;IACT,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,SAAS,GAAG,UAAU,CASnE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS,CAKlE;AAED;;GAEG;AACH,qBAAa,cAAc;IAEvB,OAAO,CAAC,QAAQ,CAAC,EAAE;IACnB,OAAO,CAAC,QAAQ,CAAC,YAAY;gBADZ,EAAE,EAAE,OAAO,EACX,YAAY,EAAE,MAAM;IAGvC;;OAEG;IACG,YAAY,CAChB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,EAAE,EAAE,QAAQ,EAAE,GACb,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;IAOjC;;OAEG;IACG,YAAY,CAChB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,EAAE,EAAE,QAAQ,EAAE,EACd,GAAG,EAAE,GAAG,GACP,OAAO,CAAC,IAAI,CAAC;IAMhB;;OAEG;IACH,iBAAiB,CACf,KAAK,EAAE,UAAU,EACjB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,EAAE,EAAE,QAAQ,EAAE,EACd,GAAG,EAAE,GAAG,GACP,IAAI;IAMP;;OAEG;IACG,eAAe,CACnB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,EAAE,EAAE,QAAQ,EAAE,GACb,OAAO,CAAC,IAAI,CAAC;IAKhB;;;OAGG;IACG,oBAAoB,CACxB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,EAAE,EAAE,QAAQ,EAAE,EACd,WAAW,EAAE,GAAG,EAChB,iBAAiB,EAAE,OAAO,GACzB,OAAO,CAAC,OAAO,CAAC;IAanB;;;OAGG;IACG,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAkB1E;;OAEG;IACI,gBAAgB,CACrB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB,aAAa,CAAC;QAAE,EAAE,EAAE,QAAQ,EAAE,CAAC;QAAC,SAAS,EAAE,SAAS,CAAA;KAAE,CAAC;CAc3D"}
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tombstone tracking for deletion synchronization.
|
|
3
|
-
*
|
|
4
|
-
* When a row is deleted, a tombstone is created with the deletion HLC.
|
|
5
|
-
* Tombstones prevent deleted rows from being resurrected by older writes.
|
|
6
|
-
*/
|
|
7
|
-
import { serializeHLC, deserializeHLC, compareHLC } from '../clock/hlc.js';
|
|
8
|
-
import { buildTombstoneKey, buildTombstoneScanBounds, decodePK } from './keys.js';
|
|
9
|
-
/**
|
|
10
|
-
* Serialize a tombstone for storage.
|
|
11
|
-
* Format: 26 bytes HLC + 8 bytes createdAt
|
|
12
|
-
*/
|
|
13
|
-
export function serializeTombstone(tombstone) {
|
|
14
|
-
const result = new Uint8Array(34);
|
|
15
|
-
const hlcBytes = serializeHLC(tombstone.hlc);
|
|
16
|
-
result.set(hlcBytes, 0);
|
|
17
|
-
const view = new DataView(result.buffer);
|
|
18
|
-
view.setBigUint64(26, BigInt(tombstone.createdAt), false);
|
|
19
|
-
return result;
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Deserialize a tombstone from storage.
|
|
23
|
-
*/
|
|
24
|
-
export function deserializeTombstone(buffer) {
|
|
25
|
-
const hlc = deserializeHLC(buffer.slice(0, 26));
|
|
26
|
-
const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
27
|
-
const createdAt = Number(view.getBigUint64(26, false));
|
|
28
|
-
return { hlc, createdAt };
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Tombstone store operations.
|
|
32
|
-
*/
|
|
33
|
-
export class TombstoneStore {
|
|
34
|
-
kv;
|
|
35
|
-
tombstoneTTL;
|
|
36
|
-
constructor(kv, tombstoneTTL) {
|
|
37
|
-
this.kv = kv;
|
|
38
|
-
this.tombstoneTTL = tombstoneTTL;
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Get the tombstone for a row, if it exists.
|
|
42
|
-
*/
|
|
43
|
-
async getTombstone(schemaName, tableName, pk) {
|
|
44
|
-
const key = buildTombstoneKey(schemaName, tableName, pk);
|
|
45
|
-
const data = await this.kv.get(key);
|
|
46
|
-
if (!data)
|
|
47
|
-
return undefined;
|
|
48
|
-
return deserializeTombstone(data);
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Create a tombstone for a deleted row.
|
|
52
|
-
*/
|
|
53
|
-
async setTombstone(schemaName, tableName, pk, hlc) {
|
|
54
|
-
const key = buildTombstoneKey(schemaName, tableName, pk);
|
|
55
|
-
const tombstone = { hlc, createdAt: Date.now() };
|
|
56
|
-
await this.kv.put(key, serializeTombstone(tombstone));
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Set tombstone in a batch.
|
|
60
|
-
*/
|
|
61
|
-
setTombstoneBatch(batch, schemaName, tableName, pk, hlc) {
|
|
62
|
-
const key = buildTombstoneKey(schemaName, tableName, pk);
|
|
63
|
-
const tombstone = { hlc, createdAt: Date.now() };
|
|
64
|
-
batch.put(key, serializeTombstone(tombstone));
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Delete a tombstone (used when resurrecting a row).
|
|
68
|
-
*/
|
|
69
|
-
async deleteTombstone(schemaName, tableName, pk) {
|
|
70
|
-
const key = buildTombstoneKey(schemaName, tableName, pk);
|
|
71
|
-
await this.kv.delete(key);
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Check if a row is deleted and the deletion should block a write.
|
|
75
|
-
* Returns true if the row is deleted and the incoming HLC is older than the deletion.
|
|
76
|
-
*/
|
|
77
|
-
async isDeletedAndBlocking(schemaName, tableName, pk, incomingHLC, allowResurrection) {
|
|
78
|
-
const tombstone = await this.getTombstone(schemaName, tableName, pk);
|
|
79
|
-
if (!tombstone)
|
|
80
|
-
return false;
|
|
81
|
-
if (allowResurrection) {
|
|
82
|
-
// Resurrection allowed: only block if incoming is older
|
|
83
|
-
return compareHLC(incomingHLC, tombstone.hlc) <= 0;
|
|
84
|
-
}
|
|
85
|
-
else {
|
|
86
|
-
// No resurrection: any tombstone blocks writes
|
|
87
|
-
return true;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
/**
|
|
91
|
-
* Prune expired tombstones.
|
|
92
|
-
* Returns the number of tombstones deleted.
|
|
93
|
-
*/
|
|
94
|
-
async pruneExpired(schemaName, tableName) {
|
|
95
|
-
const bounds = buildTombstoneScanBounds(schemaName, tableName);
|
|
96
|
-
const now = Date.now();
|
|
97
|
-
const batch = this.kv.batch();
|
|
98
|
-
let count = 0;
|
|
99
|
-
for await (const entry of this.kv.iterate(bounds)) {
|
|
100
|
-
const tombstone = deserializeTombstone(entry.value);
|
|
101
|
-
if (now - tombstone.createdAt > this.tombstoneTTL) {
|
|
102
|
-
batch.delete(entry.key);
|
|
103
|
-
count++;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
await batch.write();
|
|
107
|
-
return count;
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* Get all tombstones for a table (for sync).
|
|
111
|
-
*/
|
|
112
|
-
async *getAllTombstones(schemaName, tableName) {
|
|
113
|
-
const bounds = buildTombstoneScanBounds(schemaName, tableName);
|
|
114
|
-
for await (const entry of this.kv.iterate(bounds)) {
|
|
115
|
-
// Extract PK from key: tb:{schema}.{table}:{pk_json}
|
|
116
|
-
const keyStr = new TextDecoder().decode(entry.key);
|
|
117
|
-
const firstColon = keyStr.indexOf(':');
|
|
118
|
-
const secondColon = keyStr.indexOf(':', firstColon + 1);
|
|
119
|
-
const pkJson = keyStr.slice(secondColon + 1);
|
|
120
|
-
const pk = decodePK(pkJson);
|
|
121
|
-
yield { pk, tombstone: deserializeTombstone(entry.value) };
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
//# sourceMappingURL=tombstones.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tombstones.js","sourceRoot":"","sources":["../../../src/metadata/tombstones.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Sync event types for reactive UI integration.
|
|
3
|
-
*
|
|
4
|
-
* These events allow applications to react to sync state changes,
|
|
5
|
-
* remote data updates, and conflict resolution.
|
|
6
|
-
*/
|
|
7
|
-
import type { SqlValue } from '@quereus/quereus';
|
|
8
|
-
import type { HLC } from '../clock/hlc.js';
|
|
9
|
-
import type { SiteId } from '../clock/site.js';
|
|
10
|
-
import type { Change } from './protocol.js';
|
|
11
|
-
/**
|
|
12
|
-
* Fired when remote changes are applied locally.
|
|
13
|
-
*/
|
|
14
|
-
export interface RemoteChangeEvent {
|
|
15
|
-
/** Origin replica */
|
|
16
|
-
readonly siteId: SiteId;
|
|
17
|
-
/** Transaction ID */
|
|
18
|
-
readonly transactionId: string;
|
|
19
|
-
/** Changes that were applied */
|
|
20
|
-
readonly changes: Change[];
|
|
21
|
-
/** When changes were applied locally */
|
|
22
|
-
readonly appliedAt: HLC;
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* Fired when local changes are made.
|
|
26
|
-
*/
|
|
27
|
-
export interface LocalChangeEvent {
|
|
28
|
-
/** Transaction ID */
|
|
29
|
-
readonly transactionId: string;
|
|
30
|
-
/** Changes made locally */
|
|
31
|
-
readonly changes: Change[];
|
|
32
|
-
/** True if not yet synced to any peer */
|
|
33
|
-
readonly pendingSync: boolean;
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Fired when a conflict is resolved.
|
|
37
|
-
*/
|
|
38
|
-
export interface ConflictEvent {
|
|
39
|
-
/** Table where conflict occurred */
|
|
40
|
-
readonly table: string;
|
|
41
|
-
/** Primary key of the row */
|
|
42
|
-
readonly pk: SqlValue[];
|
|
43
|
-
/** Column where conflict occurred */
|
|
44
|
-
readonly column: string;
|
|
45
|
-
/** Local value that was in conflict */
|
|
46
|
-
readonly localValue: SqlValue;
|
|
47
|
-
/** Remote value that was in conflict */
|
|
48
|
-
readonly remoteValue: SqlValue;
|
|
49
|
-
/** Which value won */
|
|
50
|
-
readonly winner: 'local' | 'remote';
|
|
51
|
-
/** HLC of the winning value */
|
|
52
|
-
readonly winningHLC: HLC;
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Sync connection state.
|
|
56
|
-
*/
|
|
57
|
-
export type SyncState = {
|
|
58
|
-
readonly status: 'disconnected';
|
|
59
|
-
} | {
|
|
60
|
-
readonly status: 'connecting';
|
|
61
|
-
} | {
|
|
62
|
-
readonly status: 'syncing';
|
|
63
|
-
readonly progress: number;
|
|
64
|
-
} | {
|
|
65
|
-
readonly status: 'synced';
|
|
66
|
-
readonly lastSyncHLC: HLC;
|
|
67
|
-
} | {
|
|
68
|
-
readonly status: 'error';
|
|
69
|
-
readonly error: Error;
|
|
70
|
-
};
|
|
71
|
-
/**
|
|
72
|
-
* Unsubscribe function returned by event listeners.
|
|
73
|
-
*/
|
|
74
|
-
export type Unsubscribe = () => void;
|
|
75
|
-
/**
|
|
76
|
-
* Sync event emitter for reactive UI integration.
|
|
77
|
-
*/
|
|
78
|
-
export interface SyncEventEmitter {
|
|
79
|
-
/**
|
|
80
|
-
* Subscribe to remote change events.
|
|
81
|
-
* Fired when changes from another replica are applied locally.
|
|
82
|
-
*/
|
|
83
|
-
onRemoteChange(listener: (event: RemoteChangeEvent) => void): Unsubscribe;
|
|
84
|
-
/**
|
|
85
|
-
* Subscribe to local change events.
|
|
86
|
-
* Fired when local mutations occur.
|
|
87
|
-
*/
|
|
88
|
-
onLocalChange(listener: (event: LocalChangeEvent) => void): Unsubscribe;
|
|
89
|
-
/**
|
|
90
|
-
* Subscribe to sync state changes.
|
|
91
|
-
* Fired when connection state changes.
|
|
92
|
-
*/
|
|
93
|
-
onSyncStateChange(listener: (state: SyncState) => void): Unsubscribe;
|
|
94
|
-
/**
|
|
95
|
-
* Subscribe to conflict resolution events.
|
|
96
|
-
* Fired when a conflict is resolved via LWW.
|
|
97
|
-
*/
|
|
98
|
-
onConflictResolved(listener: (event: ConflictEvent) => void): Unsubscribe;
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* Default implementation of SyncEventEmitter.
|
|
102
|
-
*/
|
|
103
|
-
export declare class SyncEventEmitterImpl implements SyncEventEmitter {
|
|
104
|
-
private remoteChangeListeners;
|
|
105
|
-
private localChangeListeners;
|
|
106
|
-
private syncStateListeners;
|
|
107
|
-
private conflictListeners;
|
|
108
|
-
onRemoteChange(listener: (event: RemoteChangeEvent) => void): Unsubscribe;
|
|
109
|
-
onLocalChange(listener: (event: LocalChangeEvent) => void): Unsubscribe;
|
|
110
|
-
onSyncStateChange(listener: (state: SyncState) => void): Unsubscribe;
|
|
111
|
-
onConflictResolved(listener: (event: ConflictEvent) => void): Unsubscribe;
|
|
112
|
-
emitRemoteChange(event: RemoteChangeEvent): void;
|
|
113
|
-
emitLocalChange(event: LocalChangeEvent): void;
|
|
114
|
-
emitSyncStateChange(state: SyncState): void;
|
|
115
|
-
emitConflictResolved(event: ConflictEvent): void;
|
|
116
|
-
}
|
|
117
|
-
//# sourceMappingURL=events.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../../src/sync/events.ts"],"names":[],"mappings":"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"}
|