@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.
Files changed (92) hide show
  1. package/README.md +17 -7
  2. package/dist/src/clock/hlc.d.ts +43 -3
  3. package/dist/src/clock/hlc.d.ts.map +1 -1
  4. package/dist/src/clock/hlc.js +60 -10
  5. package/dist/src/clock/hlc.js.map +1 -1
  6. package/dist/src/create-sync-module.d.ts +46 -9
  7. package/dist/src/create-sync-module.d.ts.map +1 -1
  8. package/dist/src/create-sync-module.js +11 -8
  9. package/dist/src/create-sync-module.js.map +1 -1
  10. package/dist/src/index.d.ts +10 -8
  11. package/dist/src/index.d.ts.map +1 -1
  12. package/dist/src/index.js +8 -5
  13. package/dist/src/index.js.map +1 -1
  14. package/dist/src/metadata/basis-lifecycle.d.ts +180 -0
  15. package/dist/src/metadata/basis-lifecycle.d.ts.map +1 -0
  16. package/dist/src/metadata/basis-lifecycle.js +211 -0
  17. package/dist/src/metadata/basis-lifecycle.js.map +1 -0
  18. package/dist/src/metadata/change-log.d.ts +1 -1
  19. package/dist/src/metadata/change-log.d.ts.map +1 -1
  20. package/dist/src/metadata/change-log.js +6 -6
  21. package/dist/src/metadata/change-log.js.map +1 -1
  22. package/dist/src/metadata/column-version.d.ts +14 -5
  23. package/dist/src/metadata/column-version.d.ts.map +1 -1
  24. package/dist/src/metadata/column-version.js +22 -12
  25. package/dist/src/metadata/column-version.js.map +1 -1
  26. package/dist/src/metadata/index.d.ts +2 -0
  27. package/dist/src/metadata/index.d.ts.map +1 -1
  28. package/dist/src/metadata/index.js +2 -0
  29. package/dist/src/metadata/index.js.map +1 -1
  30. package/dist/src/metadata/keys.d.ts +52 -2
  31. package/dist/src/metadata/keys.d.ts.map +1 -1
  32. package/dist/src/metadata/keys.js +99 -14
  33. package/dist/src/metadata/keys.js.map +1 -1
  34. package/dist/src/metadata/peer-state.d.ts +1 -1
  35. package/dist/src/metadata/peer-state.js +5 -5
  36. package/dist/src/metadata/quarantine.d.ts +90 -0
  37. package/dist/src/metadata/quarantine.d.ts.map +1 -0
  38. package/dist/src/metadata/quarantine.js +167 -0
  39. package/dist/src/metadata/quarantine.js.map +1 -0
  40. package/dist/src/metadata/schema-migration.d.ts +1 -1
  41. package/dist/src/metadata/schema-migration.js +7 -7
  42. package/dist/src/metadata/schema-version.d.ts +1 -1
  43. package/dist/src/metadata/schema-version.js +7 -7
  44. package/dist/src/metadata/tombstones.d.ts +26 -9
  45. package/dist/src/metadata/tombstones.d.ts.map +1 -1
  46. package/dist/src/metadata/tombstones.js +42 -19
  47. package/dist/src/metadata/tombstones.js.map +1 -1
  48. package/dist/src/sql/basis-lifecycle-tvf.d.ts +34 -0
  49. package/dist/src/sql/basis-lifecycle-tvf.d.ts.map +1 -0
  50. package/dist/src/sql/basis-lifecycle-tvf.js +101 -0
  51. package/dist/src/sql/basis-lifecycle-tvf.js.map +1 -0
  52. package/dist/src/sync/admission.d.ts +81 -0
  53. package/dist/src/sync/admission.d.ts.map +1 -0
  54. package/dist/src/sync/admission.js +94 -0
  55. package/dist/src/sync/admission.js.map +1 -0
  56. package/dist/src/sync/change-applicator.d.ts +65 -2
  57. package/dist/src/sync/change-applicator.d.ts.map +1 -1
  58. package/dist/src/sync/change-applicator.js +493 -68
  59. package/dist/src/sync/change-applicator.js.map +1 -1
  60. package/dist/src/sync/change-grouping.d.ts +43 -0
  61. package/dist/src/sync/change-grouping.d.ts.map +1 -0
  62. package/dist/src/sync/change-grouping.js +103 -0
  63. package/dist/src/sync/change-grouping.js.map +1 -0
  64. package/dist/src/sync/events.d.ts +159 -1
  65. package/dist/src/sync/events.d.ts.map +1 -1
  66. package/dist/src/sync/events.js +50 -0
  67. package/dist/src/sync/events.js.map +1 -1
  68. package/dist/src/sync/manager.d.ts +87 -0
  69. package/dist/src/sync/manager.d.ts.map +1 -1
  70. package/dist/src/sync/protocol.d.ts +174 -11
  71. package/dist/src/sync/protocol.d.ts.map +1 -1
  72. package/dist/src/sync/protocol.js +4 -1
  73. package/dist/src/sync/protocol.js.map +1 -1
  74. package/dist/src/sync/snapshot-stream.d.ts.map +1 -1
  75. package/dist/src/sync/snapshot-stream.js +89 -19
  76. package/dist/src/sync/snapshot-stream.js.map +1 -1
  77. package/dist/src/sync/snapshot.d.ts.map +1 -1
  78. package/dist/src/sync/snapshot.js +63 -44
  79. package/dist/src/sync/snapshot.js.map +1 -1
  80. package/dist/src/sync/store-adapter.d.ts +117 -15
  81. package/dist/src/sync/store-adapter.d.ts.map +1 -1
  82. package/dist/src/sync/store-adapter.js +247 -91
  83. package/dist/src/sync/store-adapter.js.map +1 -1
  84. package/dist/src/sync/sync-context.d.ts +44 -1
  85. package/dist/src/sync/sync-context.d.ts.map +1 -1
  86. package/dist/src/sync/sync-context.js +26 -0
  87. package/dist/src/sync/sync-context.js.map +1 -1
  88. package/dist/src/sync/sync-manager-impl.d.ts +247 -13
  89. package/dist/src/sync/sync-manager-impl.d.ts.map +1 -1
  90. package/dist/src/sync/sync-manager-impl.js +788 -193
  91. package/dist/src/sync/sync-manager-impl.js.map +1 -1
  92. package/package.json +6 -6
@@ -18,7 +18,7 @@ export interface StoredMigration {
18
18
  }
19
19
  /**
20
20
  * Serialize a migration for storage.
21
- * Format: 26 bytes HLC + 4 bytes version + 1 byte type length + type + ddl
21
+ * Format: 30 bytes HLC + 4 bytes version + 1 byte type length + type + ddl
22
22
  */
23
23
  export declare function serializeMigration(migration: StoredMigration): Uint8Array;
24
24
  /**
@@ -8,18 +8,18 @@ import { serializeHLC, deserializeHLC, compareHLC } from '../clock/hlc.js';
8
8
  import { buildSchemaMigrationKey, buildSchemaMigrationScanBounds } from './keys.js';
9
9
  /**
10
10
  * Serialize a migration for storage.
11
- * Format: 26 bytes HLC + 4 bytes version + 1 byte type length + type + ddl
11
+ * Format: 30 bytes HLC + 4 bytes version + 1 byte type length + type + ddl
12
12
  */
13
13
  export function serializeMigration(migration) {
14
14
  const encoder = new TextEncoder();
15
15
  const typeBytes = encoder.encode(migration.type);
16
16
  const ddlBytes = encoder.encode(migration.ddl);
17
17
  const hlcBytes = serializeHLC(migration.hlc);
18
- const buffer = new Uint8Array(26 + 4 + 1 + typeBytes.length + ddlBytes.length);
18
+ const buffer = new Uint8Array(30 + 4 + 1 + typeBytes.length + ddlBytes.length);
19
19
  let offset = 0;
20
- // HLC (26 bytes)
20
+ // HLC (30 bytes)
21
21
  buffer.set(hlcBytes, offset);
22
- offset += 26;
22
+ offset += 30;
23
23
  // Schema version (4 bytes, big-endian)
24
24
  const view = new DataView(buffer.buffer);
25
25
  view.setUint32(offset, migration.schemaVersion, false);
@@ -39,9 +39,9 @@ export function serializeMigration(migration) {
39
39
  export function deserializeMigration(buffer) {
40
40
  const decoder = new TextDecoder();
41
41
  let offset = 0;
42
- // HLC (26 bytes)
43
- const hlc = deserializeHLC(buffer.slice(0, 26));
44
- offset += 26;
42
+ // HLC (30 bytes)
43
+ const hlc = deserializeHLC(buffer.slice(0, 30));
44
+ offset += 30;
45
45
  // Schema version (4 bytes)
46
46
  const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
47
47
  const schemaVersion = view.getUint32(offset, false);
@@ -5,7 +5,7 @@
5
5
  * "most destructive wins" conflict resolution for schema changes.
6
6
  *
7
7
  * Key format: sv:{schema}.{table}:{column}
8
- * Value: HLC (26 bytes) + 1 byte type + type-specific data
8
+ * Value: HLC (30 bytes) + 1 byte type + type-specific data
9
9
  *
10
10
  * Column types:
11
11
  * - 0x01: Regular column (type affinity, nullable, default)
@@ -5,7 +5,7 @@
5
5
  * "most destructive wins" conflict resolution for schema changes.
6
6
  *
7
7
  * Key format: sv:{schema}.{table}:{column}
8
- * Value: HLC (26 bytes) + 1 byte type + type-specific data
8
+ * Value: HLC (30 bytes) + 1 byte type + type-specific data
9
9
  *
10
10
  * Column types:
11
11
  * - 0x01: Regular column (type affinity, nullable, default)
@@ -65,20 +65,20 @@ export function serializeSchemaVersion(version) {
65
65
  if (version.ddl !== undefined)
66
66
  data.ddl = version.ddl;
67
67
  const dataBytes = encoder.encode(JSON.stringify(data));
68
- const buffer = new Uint8Array(26 + 1 + dataBytes.length);
68
+ const buffer = new Uint8Array(30 + 1 + dataBytes.length);
69
69
  buffer.set(hlcBytes, 0);
70
- buffer[26] = typeByte;
71
- buffer.set(dataBytes, 27);
70
+ buffer[30] = typeByte;
71
+ buffer.set(dataBytes, 31);
72
72
  return buffer;
73
73
  }
74
74
  /**
75
75
  * Deserialize a schema version from storage.
76
76
  */
77
77
  export function deserializeSchemaVersion(buffer) {
78
- const hlc = deserializeHLC(buffer.slice(0, 26));
79
- const typeByte = buffer[26];
78
+ const hlc = deserializeHLC(buffer.slice(0, 30));
79
+ const typeByte = buffer[30];
80
80
  const type = typeByte === 0x01 ? 'column' : typeByte === 0x02 ? 'dropped' : 'table';
81
- const dataJson = decoder.decode(buffer.slice(27));
81
+ const dataJson = decoder.decode(buffer.slice(31));
82
82
  const data = dataJson ? JSON.parse(dataJson) : {};
83
83
  return {
84
84
  hlc,
@@ -4,7 +4,7 @@
4
4
  * When a row is deleted, a tombstone is created with the deletion HLC.
5
5
  * Tombstones prevent deleted rows from being resurrected by older writes.
6
6
  */
7
- import type { SqlValue } from '@quereus/quereus';
7
+ import type { Row, SqlValue } from '@quereus/quereus';
8
8
  import type { KVStore, WriteBatch } from '@quereus/store';
9
9
  import { type HLC } from '../clock/hlc.js';
10
10
  /**
@@ -13,14 +13,29 @@ import { type HLC } from '../clock/hlc.js';
13
13
  export interface Tombstone {
14
14
  hlc: HLC;
15
15
  createdAt: number;
16
+ /**
17
+ * Optional last-known row image before deletion (the engine's `oldRow` at delete
18
+ * time). Persisted so it reaches a receiver via `getChangesSince`, which
19
+ * re-resolves deletions from the tombstone. Best-effort audit/undo metadata:
20
+ * absent when the delete carried no `oldRow` and on snapshot-reconstructed
21
+ * tombstones. A tombstone with no `priorRow` serializes to the fixed 38-byte head.
22
+ */
23
+ priorRow?: Row;
16
24
  }
17
25
  /**
18
26
  * Serialize a tombstone for storage.
19
- * Format: 26 bytes HLC + 8 bytes createdAt
27
+ *
28
+ * Format: 30 bytes HLC + 8 bytes createdAt, then — only when a `priorRow` is
29
+ * present — a trailing JSON array of the row's values, each through the column
30
+ * version `encodeSqlValue` helper so `Uint8Array`/`bigint`/`null` cells round-trip.
31
+ * A tombstone with no `priorRow` serializes to the unchanged 38-byte head.
20
32
  */
21
33
  export declare function serializeTombstone(tombstone: Tombstone): Uint8Array;
22
34
  /**
23
- * Deserialize a tombstone from storage.
35
+ * Deserialize a tombstone from storage. Absent-tolerant: bytes beyond the 38-byte
36
+ * head are the JSON-encoded `priorRow` (see {@link serializeTombstone}); a
37
+ * head-only buffer (no before-image, or a snapshot-reconstructed tombstone)
38
+ * deserializes with `priorRow` absent.
24
39
  */
25
40
  export declare function deserializeTombstone(buffer: Uint8Array): Tombstone;
26
41
  /**
@@ -28,20 +43,22 @@ export declare function deserializeTombstone(buffer: Uint8Array): Tombstone;
28
43
  */
29
44
  export declare class TombstoneStore {
30
45
  private readonly kv;
31
- private readonly tombstoneTTL;
32
- constructor(kv: KVStore, tombstoneTTL: number);
46
+ private readonly retentionHorizonMs;
47
+ constructor(kv: KVStore, retentionHorizonMs: number);
33
48
  /**
34
49
  * Get the tombstone for a row, if it exists.
35
50
  */
36
51
  getTombstone(schemaName: string, tableName: string, pk: SqlValue[]): Promise<Tombstone | undefined>;
37
52
  /**
38
- * Create a tombstone for a deleted row.
53
+ * Create a tombstone for a deleted row. `priorRow` (optional) is the row's
54
+ * last-known image, persisted as best-effort audit/undo metadata.
39
55
  */
40
- setTombstone(schemaName: string, tableName: string, pk: SqlValue[], hlc: HLC): Promise<void>;
56
+ setTombstone(schemaName: string, tableName: string, pk: SqlValue[], hlc: HLC, priorRow?: Row): Promise<void>;
41
57
  /**
42
- * Set tombstone in a batch.
58
+ * Set tombstone in a batch. `priorRow` (optional) is the row's last-known image,
59
+ * persisted as best-effort audit/undo metadata.
43
60
  */
44
- setTombstoneBatch(batch: WriteBatch, schemaName: string, tableName: string, pk: SqlValue[], hlc: HLC): void;
61
+ setTombstoneBatch(batch: WriteBatch, schemaName: string, tableName: string, pk: SqlValue[], hlc: HLC, priorRow?: Row): void;
45
62
  /**
46
63
  * Delete a tombstone (used when resurrecting a row).
47
64
  */
@@ -1 +1 @@
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,gBAAgB,CAAC;AAC1D,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
+ {"version":3,"file":"tombstones.d.ts","sourceRoot":"","sources":["../../../src/metadata/tombstones.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,KAAK,GAAG,EAA4C,MAAM,iBAAiB,CAAC;AAOrF;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,GAAG,CAAC;IACT,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,GAAG,CAAC;CAChB;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,SAAS,GAAG,UAAU,CAenE;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS,CAWlE;AAED;;GAEG;AACH,qBAAa,cAAc;IAEvB,OAAO,CAAC,QAAQ,CAAC,EAAE;IACnB,OAAO,CAAC,QAAQ,CAAC,kBAAkB;gBADlB,EAAE,EAAE,OAAO,EACX,kBAAkB,EAAE,MAAM;IAG7C;;OAEG;IACG,YAAY,CAChB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,EAAE,EAAE,QAAQ,EAAE,GACb,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;IAOjC;;;OAGG;IACG,YAAY,CAChB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,EAAE,EAAE,QAAQ,EAAE,EACd,GAAG,EAAE,GAAG,EACR,QAAQ,CAAC,EAAE,GAAG,GACb,OAAO,CAAC,IAAI,CAAC;IAMhB;;;OAGG;IACH,iBAAiB,CACf,KAAK,EAAE,UAAU,EACjB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,EAAE,EAAE,QAAQ,EAAE,EACd,GAAG,EAAE,GAAG,EACR,QAAQ,CAAC,EAAE,GAAG,GACb,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"}
@@ -5,37 +5,58 @@
5
5
  * Tombstones prevent deleted rows from being resurrected by older writes.
6
6
  */
7
7
  import { serializeHLC, deserializeHLC, compareHLC } from '../clock/hlc.js';
8
+ import { encodeSqlValue, decodeSqlValue } from './column-version.js';
8
9
  import { buildTombstoneKey, buildTombstoneScanBounds, decodePK } from './keys.js';
10
+ /** Fixed-size head of a serialized tombstone: 30 bytes HLC + 8 bytes createdAt. */
11
+ const TOMBSTONE_HEAD_BYTES = 38;
9
12
  /**
10
13
  * Serialize a tombstone for storage.
11
- * Format: 26 bytes HLC + 8 bytes createdAt
14
+ *
15
+ * Format: 30 bytes HLC + 8 bytes createdAt, then — only when a `priorRow` is
16
+ * present — a trailing JSON array of the row's values, each through the column
17
+ * version `encodeSqlValue` helper so `Uint8Array`/`bigint`/`null` cells round-trip.
18
+ * A tombstone with no `priorRow` serializes to the unchanged 38-byte head.
12
19
  */
13
20
  export function serializeTombstone(tombstone) {
14
- const result = new Uint8Array(34);
21
+ const head = new Uint8Array(TOMBSTONE_HEAD_BYTES);
15
22
  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);
23
+ head.set(hlcBytes, 0);
24
+ const view = new DataView(head.buffer);
25
+ view.setBigUint64(30, BigInt(tombstone.createdAt), false);
26
+ if (tombstone.priorRow === undefined)
27
+ return head;
28
+ const payload = new TextEncoder().encode(JSON.stringify(tombstone.priorRow.map(encodeSqlValue)));
29
+ const result = new Uint8Array(head.length + payload.length);
30
+ result.set(head, 0);
31
+ result.set(payload, head.length);
19
32
  return result;
20
33
  }
21
34
  /**
22
- * Deserialize a tombstone from storage.
35
+ * Deserialize a tombstone from storage. Absent-tolerant: bytes beyond the 38-byte
36
+ * head are the JSON-encoded `priorRow` (see {@link serializeTombstone}); a
37
+ * head-only buffer (no before-image, or a snapshot-reconstructed tombstone)
38
+ * deserializes with `priorRow` absent.
23
39
  */
24
40
  export function deserializeTombstone(buffer) {
25
- const hlc = deserializeHLC(buffer.slice(0, 26));
41
+ const hlc = deserializeHLC(buffer.slice(0, 30));
26
42
  const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
27
- const createdAt = Number(view.getBigUint64(26, false));
28
- return { hlc, createdAt };
43
+ const createdAt = Number(view.getBigUint64(30, false));
44
+ const tombstone = { hlc, createdAt };
45
+ if (buffer.byteLength > TOMBSTONE_HEAD_BYTES) {
46
+ const values = JSON.parse(new TextDecoder().decode(buffer.slice(TOMBSTONE_HEAD_BYTES)));
47
+ tombstone.priorRow = values.map(decodeSqlValue);
48
+ }
49
+ return tombstone;
29
50
  }
30
51
  /**
31
52
  * Tombstone store operations.
32
53
  */
33
54
  export class TombstoneStore {
34
55
  kv;
35
- tombstoneTTL;
36
- constructor(kv, tombstoneTTL) {
56
+ retentionHorizonMs;
57
+ constructor(kv, retentionHorizonMs) {
37
58
  this.kv = kv;
38
- this.tombstoneTTL = tombstoneTTL;
59
+ this.retentionHorizonMs = retentionHorizonMs;
39
60
  }
40
61
  /**
41
62
  * Get the tombstone for a row, if it exists.
@@ -48,19 +69,21 @@ export class TombstoneStore {
48
69
  return deserializeTombstone(data);
49
70
  }
50
71
  /**
51
- * Create a tombstone for a deleted row.
72
+ * Create a tombstone for a deleted row. `priorRow` (optional) is the row's
73
+ * last-known image, persisted as best-effort audit/undo metadata.
52
74
  */
53
- async setTombstone(schemaName, tableName, pk, hlc) {
75
+ async setTombstone(schemaName, tableName, pk, hlc, priorRow) {
54
76
  const key = buildTombstoneKey(schemaName, tableName, pk);
55
- const tombstone = { hlc, createdAt: Date.now() };
77
+ const tombstone = { hlc, createdAt: Date.now(), ...(priorRow !== undefined ? { priorRow } : {}) };
56
78
  await this.kv.put(key, serializeTombstone(tombstone));
57
79
  }
58
80
  /**
59
- * Set tombstone in a batch.
81
+ * Set tombstone in a batch. `priorRow` (optional) is the row's last-known image,
82
+ * persisted as best-effort audit/undo metadata.
60
83
  */
61
- setTombstoneBatch(batch, schemaName, tableName, pk, hlc) {
84
+ setTombstoneBatch(batch, schemaName, tableName, pk, hlc, priorRow) {
62
85
  const key = buildTombstoneKey(schemaName, tableName, pk);
63
- const tombstone = { hlc, createdAt: Date.now() };
86
+ const tombstone = { hlc, createdAt: Date.now(), ...(priorRow !== undefined ? { priorRow } : {}) };
64
87
  batch.put(key, serializeTombstone(tombstone));
65
88
  }
66
89
  /**
@@ -98,7 +121,7 @@ export class TombstoneStore {
98
121
  let count = 0;
99
122
  for await (const entry of this.kv.iterate(bounds)) {
100
123
  const tombstone = deserializeTombstone(entry.value);
101
- if (now - tombstone.createdAt > this.tombstoneTTL) {
124
+ if (now - tombstone.createdAt > this.retentionHorizonMs) {
102
125
  batch.delete(entry.key);
103
126
  count++;
104
127
  }
@@ -1 +1 @@
1
- {"version":3,"file":"tombstones.js","sourceRoot":"","sources":["../../../src/metadata/tombstones.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tombstones.js","sourceRoot":"","sources":["../../../src/metadata/tombstones.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * `quereus_basis_lifecycle()` — in-SQL introspection of the durable per-basis-table
3
+ * lifecycle records the sync layer maintains on each lens deploy
4
+ * (`docs/migration.md` § 2 Converge). A zero-argument table-valued function listing
5
+ * every stored {@link BasisTableLifecycleRecord}, one row per record, so a developer
6
+ * can surface legacy / retirement-candidate tables without writing host code:
7
+ *
8
+ * ```sql
9
+ * select "table", state, "unmappedSince"
10
+ * from quereus_basis_lifecycle()
11
+ * where state = 'derivation-source-only'
12
+ * order by "unmappedSince";
13
+ * ```
14
+ *
15
+ * Pure convenience over {@link SyncManager.getBasisTableLifecycle} — no engine change.
16
+ * The TVF closes over the `SyncManager` (the host's smallest registration seam), and
17
+ * the records are read programmatically from KV, so the rows survive a restart and a
18
+ * fresh `Database` over the same store reflects the prior deploy's classification.
19
+ */
20
+ import type { Database } from '@quereus/quereus';
21
+ import type { SyncManager } from '../sync/manager.js';
22
+ /**
23
+ * Register the `quereus_basis_lifecycle()` introspection TVF against `db`, reading
24
+ * from `syncManager`. Opt-in: the host calls this once after `createSyncModule(...)`
25
+ * (no auto-registration — `createSyncModule` takes no `Database`, and relay-only
26
+ * deployments need no SQL surface). The `quereus_`-prefixed name avoids collision
27
+ * with user tables/functions.
28
+ *
29
+ * Safe to call once per `Database`; a repeat call (same name/arity) **replaces** the
30
+ * prior registration rather than erroring or corrupting state (engine
31
+ * `registerFunction` → `Schema.addFunction` is a keyed overwrite).
32
+ */
33
+ export declare function registerBasisLifecycleTvf(db: Database, syncManager: SyncManager): void;
34
+ //# sourceMappingURL=basis-lifecycle-tvf.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"basis-lifecycle-tvf.d.ts","sourceRoot":"","sources":["../../../src/sql/basis-lifecycle-tvf.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAoB,MAAM,kBAAkB,CAAC;AAEnE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAoCtD;;;;;;;;;;GAUG;AACH,wBAAgB,yBAAyB,CAAC,EAAE,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,GAAG,IAAI,CAwCtF"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * `quereus_basis_lifecycle()` — in-SQL introspection of the durable per-basis-table
3
+ * lifecycle records the sync layer maintains on each lens deploy
4
+ * (`docs/migration.md` § 2 Converge). A zero-argument table-valued function listing
5
+ * every stored {@link BasisTableLifecycleRecord}, one row per record, so a developer
6
+ * can surface legacy / retirement-candidate tables without writing host code:
7
+ *
8
+ * ```sql
9
+ * select "table", state, "unmappedSince"
10
+ * from quereus_basis_lifecycle()
11
+ * where state = 'derivation-source-only'
12
+ * order by "unmappedSince";
13
+ * ```
14
+ *
15
+ * Pure convenience over {@link SyncManager.getBasisTableLifecycle} — no engine change.
16
+ * The TVF closes over the `SyncManager` (the host's smallest registration seam), and
17
+ * the records are read programmatically from KV, so the rows survive a restart and a
18
+ * fresh `Database` over the same store reflects the prior deploy's classification.
19
+ */
20
+ import { createTableValuedFunction, INTEGER_TYPE, TEXT_TYPE } from '@quereus/quereus';
21
+ /** A read-only generated column spec for the TVF's relation return type. */
22
+ function col(name, logicalType, nullable) {
23
+ return {
24
+ name,
25
+ type: { typeClass: 'scalar', logicalType, nullable, isReadOnly: true },
26
+ generated: true,
27
+ };
28
+ }
29
+ /**
30
+ * Project one lifecycle record onto its ordered SQL row. Column order MUST match
31
+ * the `returnType.columns` list below. Optional record fields coalesce to `null`
32
+ * (a `Row` cannot hold `undefined`); booleans emit as INTEGER 0/1 (engine
33
+ * convention, mirroring `table_info`'s `notnull`/`pk`); `mappedBy` renders as a
34
+ * JSON array string (empty ⇒ `"[]"`, never null); the `evictPolicy` union
35
+ * (`'never'` | `'immediate'` | a numeric ms horizon) collapses to its string form.
36
+ */
37
+ function rowFromRecord(r) {
38
+ return [
39
+ r.schema,
40
+ r.table,
41
+ r.state,
42
+ JSON.stringify(r.mappedBy ?? []),
43
+ r.derivationSource ? 1 : 0,
44
+ r.inBasis ? 1 : 0,
45
+ r.mappedSince ?? null,
46
+ r.unmappedSince ?? null,
47
+ r.detachedAt ?? null,
48
+ r.lastDirectlyMappedWriteAt ?? null,
49
+ r.evictPolicy == null ? null : String(r.evictPolicy),
50
+ ];
51
+ }
52
+ /**
53
+ * Register the `quereus_basis_lifecycle()` introspection TVF against `db`, reading
54
+ * from `syncManager`. Opt-in: the host calls this once after `createSyncModule(...)`
55
+ * (no auto-registration — `createSyncModule` takes no `Database`, and relay-only
56
+ * deployments need no SQL surface). The `quereus_`-prefixed name avoids collision
57
+ * with user tables/functions.
58
+ *
59
+ * Safe to call once per `Database`; a repeat call (same name/arity) **replaces** the
60
+ * prior registration rather than erroring or corrupting state (engine
61
+ * `registerFunction` → `Schema.addFunction` is a keyed overwrite).
62
+ */
63
+ export function registerBasisLifecycleTvf(db, syncManager) {
64
+ const schema = createTableValuedFunction({
65
+ name: 'quereus_basis_lifecycle',
66
+ numArgs: 0,
67
+ // Records change across deploys (and across restarts), so the result is not
68
+ // a pure function of its (empty) argument list.
69
+ deterministic: false,
70
+ returnType: {
71
+ typeClass: 'relation',
72
+ isReadOnly: true,
73
+ isSet: false,
74
+ columns: [
75
+ col('schema', TEXT_TYPE, false),
76
+ col('table', TEXT_TYPE, false),
77
+ col('state', TEXT_TYPE, false),
78
+ col('mappedBy', TEXT_TYPE, false),
79
+ col('derivationSource', INTEGER_TYPE, false),
80
+ col('inBasis', INTEGER_TYPE, false),
81
+ col('mappedSince', INTEGER_TYPE, true),
82
+ col('unmappedSince', INTEGER_TYPE, true),
83
+ col('detachedAt', INTEGER_TYPE, true),
84
+ col('lastDirectlyMappedWriteAt', INTEGER_TYPE, true),
85
+ col('evictPolicy', TEXT_TYPE, true),
86
+ ],
87
+ keys: [],
88
+ rowConstraints: [],
89
+ },
90
+ },
91
+ // Snapshot the full record array once, then yield — iteration is over a stable
92
+ // array, immune to a concurrent deploy mutating records mid-scan.
93
+ async function* () {
94
+ const records = await syncManager.getBasisTableLifecycle();
95
+ for (const record of records) {
96
+ yield rowFromRecord(record);
97
+ }
98
+ });
99
+ db.registerFunction(schema);
100
+ }
101
+ //# sourceMappingURL=basis-lifecycle-tvf.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"basis-lifecycle-tvf.js","sourceRoot":"","sources":["../../../src/sql/basis-lifecycle-tvf.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,EAAE,yBAAyB,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAItF,4EAA4E;AAC5E,SAAS,GAAG,CAAC,IAAY,EAAE,WAAwB,EAAE,QAAiB;IACpE,OAAO;QACL,IAAI;QACJ,IAAI,EAAE,EAAE,SAAS,EAAE,QAAiB,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE;QAC/E,SAAS,EAAE,IAAI;KAChB,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,aAAa,CAAC,CAA4B;IACjD,OAAO;QACL,CAAC,CAAC,MAAM;QACR,CAAC,CAAC,KAAK;QACP,CAAC,CAAC,KAAK;QACP,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAC;QAChC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1B,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACjB,CAAC,CAAC,WAAW,IAAI,IAAI;QACrB,CAAC,CAAC,aAAa,IAAI,IAAI;QACvB,CAAC,CAAC,UAAU,IAAI,IAAI;QACpB,CAAC,CAAC,yBAAyB,IAAI,IAAI;QACnC,CAAC,CAAC,WAAW,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC;KACrD,CAAC;AACJ,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,yBAAyB,CAAC,EAAY,EAAE,WAAwB;IAC9E,MAAM,MAAM,GAAG,yBAAyB,CACtC;QACE,IAAI,EAAE,yBAAyB;QAC/B,OAAO,EAAE,CAAC;QACV,4EAA4E;QAC5E,gDAAgD;QAChD,aAAa,EAAE,KAAK;QACpB,UAAU,EAAE;YACV,SAAS,EAAE,UAAU;YACrB,UAAU,EAAE,IAAI;YAChB,KAAK,EAAE,KAAK;YACZ,OAAO,EAAE;gBACP,GAAG,CAAC,QAAQ,EAAE,SAAS,EAAE,KAAK,CAAC;gBAC/B,GAAG,CAAC,OAAO,EAAE,SAAS,EAAE,KAAK,CAAC;gBAC9B,GAAG,CAAC,OAAO,EAAE,SAAS,EAAE,KAAK,CAAC;gBAC9B,GAAG,CAAC,UAAU,EAAE,SAAS,EAAE,KAAK,CAAC;gBACjC,GAAG,CAAC,kBAAkB,EAAE,YAAY,EAAE,KAAK,CAAC;gBAC5C,GAAG,CAAC,SAAS,EAAE,YAAY,EAAE,KAAK,CAAC;gBACnC,GAAG,CAAC,aAAa,EAAE,YAAY,EAAE,IAAI,CAAC;gBACtC,GAAG,CAAC,eAAe,EAAE,YAAY,EAAE,IAAI,CAAC;gBACxC,GAAG,CAAC,YAAY,EAAE,YAAY,EAAE,IAAI,CAAC;gBACrC,GAAG,CAAC,2BAA2B,EAAE,YAAY,EAAE,IAAI,CAAC;gBACpD,GAAG,CAAC,aAAa,EAAE,SAAS,EAAE,IAAI,CAAC;aACpC;YACD,IAAI,EAAE,EAAE;YACR,cAAc,EAAE,EAAE;SACnB;KACF;IACD,+EAA+E;IAC/E,kEAAkE;IAClE,KAAK,SAAS,CAAC;QACb,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,sBAAsB,EAAE,CAAC;QAC3D,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,MAAM,aAAa,CAAC,MAAM,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC,CACF,CAAC;IAEF,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Group-atomic admission core for the sync ingress data-apply seam.
3
+ *
4
+ * Centralizes the docs/sync.md § Transactional Integrity During Sync write
5
+ * ordering — **data first → metadata second → abort with no metadata** — that
6
+ * every ingress modality must uphold:
7
+ * - wire `applyChanges` (change-applicator.ts) → `admitGroup`
8
+ * - non-streaming `applySnapshot` (snapshot.ts) → `admitGroup`
9
+ * - each streaming flush in `applySnapshotStream` (snapshot-stream.ts)
10
+ * → `applyDataToStore`
11
+ *
12
+ * Streaming keeps its own checkpoint-based consistency model (interleaved
13
+ * metadata/data flushes, resume on a saved checkpoint) and so reuses only the
14
+ * `applyDataToStore` seam — for the same `status:'error'` emission on a
15
+ * whole-batch flush throw — rather than the full `admitGroup` unit.
16
+ */
17
+ import type { HLC } from '../clock/hlc.js';
18
+ import type { ApplyToStoreOptions, DataChangeToApply, SchemaChangeToApply } from './protocol.js';
19
+ import type { SyncContext } from './sync-context.js';
20
+ /**
21
+ * Data-first half of the admission invariant: apply this unit's data + schema to
22
+ * the store, emit `status:'error'` and rethrow on a whole-batch throw, surface any
23
+ * reported assertion violations, then abort (throw) on any per-change
24
+ * `ApplyToStoreResult.errors` — all BEFORE the caller commits any CRDT metadata.
25
+ * No-op when there is no `applyToStore` callback or nothing to apply.
26
+ *
27
+ * The two failure shapes are mutually exclusive (a throw never reaches
28
+ * `throwIfApplyErrors`), so `status:'error'` is emitted at most once. The
29
+ * violation emit does not touch sync-state, so it cannot affect that invariant.
30
+ *
31
+ * Assertion violations are emitted BEFORE the per-change abort gate. Whenever the
32
+ * seam reports a violation it ran in REPORT mode and the batch already COMMITTED —
33
+ * the violating row's data + derived effects (MV deltas, watch capture) are
34
+ * durably in storage. A later `throwIfApplyErrors` throw blocks only the CRDT-
35
+ * metadata commit; it does NOT roll back those storage writes. So a reported
36
+ * violation is a fact about already-committed data and must be surfaced even when
37
+ * an unrelated per-change error aborts the batch in the same invocation — the two
38
+ * facts are orthogonal: "B's data landed and broke a local invariant" and "the
39
+ * batch can't fully admit because A failed and will retry" are both true.
40
+ *
41
+ * Emitting before the abort closes a permanent-notification-loss gap: were the
42
+ * emit on the success branch only, a mixed batch (per-change error + reported
43
+ * violation) would throw past it, drop the event, and on retry the value-identical
44
+ * row is suppressed → empty seam batch → the assertion is never re-evaluated →
45
+ * the host is never notified about durably-committed violating data. That same
46
+ * value-identical suppression now correctly prevents DOUBLE-notification on retry
47
+ * (B is suppressed, so no second event fires), matching the idempotent-re-apply
48
+ * guarantee. On the pure-success path (no per-change errors) behavior is unchanged.
49
+ */
50
+ export declare function applyDataToStore(ctx: SyncContext, dataChanges: DataChangeToApply[], schemaChanges: SchemaChangeToApply[], options: ApplyToStoreOptions): Promise<void>;
51
+ /**
52
+ * One group-atomic admission unit: data + schema to apply, the CRDT metadata to
53
+ * commit only once that data landed, and the local HLC clock watermark to merge
54
+ * on full-unit success.
55
+ *
56
+ * A "group" is one *admission unit*, not necessarily one source transaction — the
57
+ * wire path admits the whole resolved `ChangeSet[]` as a single all-or-nothing
58
+ * unit (the single per-peer `lastSyncHLC` watermark cannot express a partial
59
+ * commit), and each snapshot path admits its wholesale load as one unit.
60
+ */
61
+ export interface AdmissionGroup {
62
+ readonly dataChanges: DataChangeToApply[];
63
+ readonly schemaChanges: SchemaChangeToApply[];
64
+ readonly applyOptions: ApplyToStoreOptions;
65
+ /** Commit this unit's CRDT metadata. Runs ONLY after the data write landed. */
66
+ readonly commitMetadata: () => Promise<void>;
67
+ /**
68
+ * Local HLC clock watermark to merge in on full-unit success. The per-PEER
69
+ * `lastSyncHLC` is the transport caller's concern (it differs per modality and
70
+ * transport) and is deliberately NOT advanced here.
71
+ */
72
+ readonly watermarkHLC?: HLC;
73
+ }
74
+ /**
75
+ * Full group-atomic admission: data first → metadata second → advance the local
76
+ * clock watermark, aborting (with no metadata committed) on any data-apply
77
+ * failure. The realization of "apply a transaction group atomically, advance the
78
+ * watermark idempotently".
79
+ */
80
+ export declare function admitGroup(ctx: SyncContext, group: AdmissionGroup): Promise<void>;
81
+ //# sourceMappingURL=admission.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admission.d.ts","sourceRoot":"","sources":["../../../src/sync/admission.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,KAAK,EACX,mBAAmB,EAEnB,iBAAiB,EACjB,mBAAmB,EACnB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAsB,gBAAgB,CACrC,GAAG,EAAE,WAAW,EAChB,WAAW,EAAE,iBAAiB,EAAE,EAChC,aAAa,EAAE,mBAAmB,EAAE,EACpC,OAAO,EAAE,mBAAmB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAgCf;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,cAAc;IAC9B,QAAQ,CAAC,WAAW,EAAE,iBAAiB,EAAE,CAAC;IAC1C,QAAQ,CAAC,aAAa,EAAE,mBAAmB,EAAE,CAAC;IAC9C,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAAC;IAC3C,+EAA+E;IAC/E,QAAQ,CAAC,cAAc,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C;;;;OAIG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,GAAG,CAAC;CAC5B;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAOvF"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Group-atomic admission core for the sync ingress data-apply seam.
3
+ *
4
+ * Centralizes the docs/sync.md § Transactional Integrity During Sync write
5
+ * ordering — **data first → metadata second → abort with no metadata** — that
6
+ * every ingress modality must uphold:
7
+ * - wire `applyChanges` (change-applicator.ts) → `admitGroup`
8
+ * - non-streaming `applySnapshot` (snapshot.ts) → `admitGroup`
9
+ * - each streaming flush in `applySnapshotStream` (snapshot-stream.ts)
10
+ * → `applyDataToStore`
11
+ *
12
+ * Streaming keeps its own checkpoint-based consistency model (interleaved
13
+ * metadata/data flushes, resume on a saved checkpoint) and so reuses only the
14
+ * `applyDataToStore` seam — for the same `status:'error'` emission on a
15
+ * whole-batch flush throw — rather than the full `admitGroup` unit.
16
+ */
17
+ import { persistHLCState, throwIfApplyErrors, toError } from './sync-context.js';
18
+ /**
19
+ * Data-first half of the admission invariant: apply this unit's data + schema to
20
+ * the store, emit `status:'error'` and rethrow on a whole-batch throw, surface any
21
+ * reported assertion violations, then abort (throw) on any per-change
22
+ * `ApplyToStoreResult.errors` — all BEFORE the caller commits any CRDT metadata.
23
+ * No-op when there is no `applyToStore` callback or nothing to apply.
24
+ *
25
+ * The two failure shapes are mutually exclusive (a throw never reaches
26
+ * `throwIfApplyErrors`), so `status:'error'` is emitted at most once. The
27
+ * violation emit does not touch sync-state, so it cannot affect that invariant.
28
+ *
29
+ * Assertion violations are emitted BEFORE the per-change abort gate. Whenever the
30
+ * seam reports a violation it ran in REPORT mode and the batch already COMMITTED —
31
+ * the violating row's data + derived effects (MV deltas, watch capture) are
32
+ * durably in storage. A later `throwIfApplyErrors` throw blocks only the CRDT-
33
+ * metadata commit; it does NOT roll back those storage writes. So a reported
34
+ * violation is a fact about already-committed data and must be surfaced even when
35
+ * an unrelated per-change error aborts the batch in the same invocation — the two
36
+ * facts are orthogonal: "B's data landed and broke a local invariant" and "the
37
+ * batch can't fully admit because A failed and will retry" are both true.
38
+ *
39
+ * Emitting before the abort closes a permanent-notification-loss gap: were the
40
+ * emit on the success branch only, a mixed batch (per-change error + reported
41
+ * violation) would throw past it, drop the event, and on retry the value-identical
42
+ * row is suppressed → empty seam batch → the assertion is never re-evaluated →
43
+ * the host is never notified about durably-committed violating data. That same
44
+ * value-identical suppression now correctly prevents DOUBLE-notification on retry
45
+ * (B is suppressed, so no second event fires), matching the idempotent-re-apply
46
+ * guarantee. On the pure-success path (no per-change errors) behavior is unchanged.
47
+ */
48
+ export async function applyDataToStore(ctx, dataChanges, schemaChanges, options) {
49
+ if (!ctx.applyToStore || (dataChanges.length === 0 && schemaChanges.length === 0))
50
+ return;
51
+ let result;
52
+ try {
53
+ result = await ctx.applyToStore(dataChanges, schemaChanges, options);
54
+ }
55
+ catch (error) {
56
+ // Emit error state so UI can react. CRDT metadata is NOT committed,
57
+ // allowing the same changes to be re-resolved on the next sync attempt.
58
+ ctx.syncEvents.emitSyncStateChange({ status: 'error', error: toError(error) });
59
+ throw error;
60
+ }
61
+ // Surface any local assertion violations the seam reported. A reported
62
+ // violation means the report-mode seam COMMITTED the violating row (data +
63
+ // derived effects durable); we notify the host once per violated assertion.
64
+ // This runs BEFORE the abort gate below so a co-occurring per-change error
65
+ // cannot drop the notification about data that is already committed.
66
+ if (result.assertionViolations) {
67
+ for (const violation of result.assertionViolations) {
68
+ ctx.syncEvents.emitAssertionViolation({
69
+ assertion: violation.assertion,
70
+ samples: violation.samples,
71
+ });
72
+ }
73
+ }
74
+ // Per-change storage failures (the adapter collects rather than throws) abort
75
+ // the apply identically to a whole-batch throw: emit error + throw, with no
76
+ // metadata committed, so the whole batch re-resolves and re-applies
77
+ // idempotently on the next sync. See throwIfApplyErrors / docs/sync.md.
78
+ throwIfApplyErrors(ctx, result);
79
+ }
80
+ /**
81
+ * Full group-atomic admission: data first → metadata second → advance the local
82
+ * clock watermark, aborting (with no metadata committed) on any data-apply
83
+ * failure. The realization of "apply a transaction group atomically, advance the
84
+ * watermark idempotently".
85
+ */
86
+ export async function admitGroup(ctx, group) {
87
+ await applyDataToStore(ctx, group.dataChanges, group.schemaChanges, group.applyOptions);
88
+ await group.commitMetadata(); // metadata SECOND
89
+ if (group.watermarkHLC) {
90
+ ctx.hlcManager.receive(group.watermarkHLC); // monotonic merge, idempotent
91
+ await persistHLCState(ctx);
92
+ }
93
+ }
94
+ //# sourceMappingURL=admission.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admission.js","sourceRoot":"","sources":["../../../src/sync/admission.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAUH,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAEjF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACrC,GAAgB,EAChB,WAAgC,EAChC,aAAoC,EACpC,OAA4B;IAE5B,IAAI,CAAC,GAAG,CAAC,YAAY,IAAI,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,CAAC;QAAE,OAAO;IAE1F,IAAI,MAA0B,CAAC;IAC/B,IAAI,CAAC;QACJ,MAAM,GAAG,MAAM,GAAG,CAAC,YAAY,CAAC,WAAW,EAAE,aAAa,EAAE,OAAO,CAAC,CAAC;IACtE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,oEAAoE;QACpE,wEAAwE;QACxE,GAAG,CAAC,UAAU,CAAC,mBAAmB,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC/E,MAAM,KAAK,CAAC;IACb,CAAC;IAED,uEAAuE;IACvE,2EAA2E;IAC3E,4EAA4E;IAC5E,2EAA2E;IAC3E,qEAAqE;IACrE,IAAI,MAAM,CAAC,mBAAmB,EAAE,CAAC;QAChC,KAAK,MAAM,SAAS,IAAI,MAAM,CAAC,mBAAmB,EAAE,CAAC;YACpD,GAAG,CAAC,UAAU,CAAC,sBAAsB,CAAC;gBACrC,SAAS,EAAE,SAAS,CAAC,SAAS;gBAC9B,OAAO,EAAE,SAAS,CAAC,OAAO;aAC1B,CAAC,CAAC;QACJ,CAAC;IACF,CAAC;IAED,8EAA8E;IAC9E,4EAA4E;IAC5E,oEAAoE;IACpE,wEAAwE;IACxE,kBAAkB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;AACjC,CAAC;AA0BD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAgB,EAAE,KAAqB;IACvE,MAAM,gBAAgB,CAAC,GAAG,EAAE,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,aAAa,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;IACxF,MAAM,KAAK,CAAC,cAAc,EAAE,CAAC,CAAoB,kBAAkB;IACnE,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;QACxB,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAI,8BAA8B;QAC7E,MAAM,eAAe,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;AACF,CAAC"}