@quereus/sync 3.2.1 → 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
@@ -7,6 +7,7 @@
7
7
  * 3. commitChangeMetadata — persist CRDT metadata
8
8
  */
9
9
  import type { ColumnVersion } from '../metadata/column-version.js';
10
+ import type { Tombstone } from '../metadata/tombstones.js';
10
11
  import type { ChangeSet, Change, ApplyResult, DataChangeToApply } from './protocol.js';
11
12
  import type { SyncContext } from './sync-context.js';
12
13
  /**
@@ -19,16 +20,66 @@ export interface ResolvedChange {
19
20
  dataChange?: DataChangeToApply;
20
21
  /** For column changes: the old version to clean up in the change log. */
21
22
  oldColumnVersion?: ColumnVersion;
23
+ /** For delete changes: the prior tombstone whose stale delete entry to clean up in the change log. */
24
+ oldTombstone?: Tombstone;
22
25
  }
23
26
  /**
24
27
  * Apply change sets from a remote peer.
25
28
  *
26
29
  * Three-phase process:
27
- * 1. Resolve all changes (no writes)
30
+ * 1. Resolve all changes (no writes); divert out-of-basis straggler changes
28
31
  * 2. Apply data to store via callback
29
- * 3. Commit CRDT metadata
32
+ * 3. Commit CRDT metadata (+ durable quarantine of diverted changes)
33
+ *
34
+ * Unknown-table disposition: a change referencing a table outside the local basis
35
+ * (a retired-table straggler delta — see `docs/migration.md` § 4 Contract) is
36
+ * **diverted** during resolution — never resolved, applied, or recorded as CRDT
37
+ * metadata, so the change log stays clean (no survivor-HLC pollution). Diverted
38
+ * changes are held (durably, idempotently — `quarantine`, or `store-and-forward`
39
+ * which additionally marks them forwardable) or ignored per
40
+ * {@link SyncConfig.unknownTableDisposition}, and telemetered either way.
30
41
  */
31
42
  export declare function applyChanges(ctx: SyncContext, changes: ChangeSet[]): Promise<ApplyResult>;
43
+ /**
44
+ * Replay held out-of-basis changes (`quarantine` + forwardable `store-and-forward`
45
+ * entries) into tables that have since reappeared in the local basis — the revival
46
+ * half of the unknown-table contract (`docs/migration.md` § 4 Contract). The
47
+ * sibling of {@link applyChanges}' data branch, minus the schema-migration and
48
+ * unknown-table-divert machinery: held changes have no DDL and their table is, by
49
+ * the basis gate, already present.
50
+ *
51
+ * Driven two ways, never interleaved: the host calls {@link SyncManager.drainHeldChanges}
52
+ * from its periodic maintenance sweep, and {@link drainReappearedTables} calls it
53
+ * reactively from {@link applyChanges} the moment an inbound `create_table` revives a
54
+ * held table (gated by {@link SyncConfig.drainOnReappear}). Either way drain runs as a
55
+ * SEPARATE apply, after any re-creating batch has fully committed — fresh data is
56
+ * already in storage and the older held changes simply LWW-resolve against it. The
57
+ * invariant is "never INTERLEAVE drain into the admitting batch", not "never drain
58
+ * inline": a reactive post-commit drain is its own admission unit, distinct from the
59
+ * batch it follows.
60
+ *
61
+ * Scope mirrors {@link QuarantineStore.list}: `(schema, table)` drains one table,
62
+ * `(schema)` drains a schema, `()` sweeps every held entry whose table is back.
63
+ * Bounded by the held set (itself bounded by the retention horizon); zero-cost when
64
+ * nothing is held. With NO basis oracle every group's table reports `undefined`
65
+ * column names ⇒ every group is skipped ⇒ this returns 0 (the relay-only no-op).
66
+ *
67
+ * @returns the number of held entries cleared from the hold (across present tables).
68
+ */
69
+ export declare function drainHeldChanges(ctx: SyncContext, schema?: string, table?: string): Promise<number>;
70
+ /**
71
+ * Best-effort scoped drain of tables that just reappeared in the local basis, run as
72
+ * SEPARATE post-commit apply unit(s) after the re-creating batch committed. Advisory:
73
+ * each table is drained independently and any failure is logged + swallowed (the held
74
+ * entries stay held for the periodic sweep). No-op when {@link SyncConfig.drainOnReappear}
75
+ * is disabled or the list is empty. Each {@link drainHeldChanges} call is cheap when
76
+ * nothing is held (a scoped `quarantine.list` returning `[]`) and a no-op when the table
77
+ * is still absent (the oracle gate in {@link drainTableGroup}).
78
+ */
79
+ export declare function drainReappearedTables(ctx: SyncContext, tables: ReadonlyArray<{
80
+ schema: string;
81
+ table: string;
82
+ }>): Promise<void>;
32
83
  /**
33
84
  * Resolve CRDT conflicts for a single change WITHOUT writing metadata.
34
85
  *
@@ -39,6 +90,18 @@ export declare function resolveChange(ctx: SyncContext, change: Change): Promise
39
90
  * Commit CRDT metadata for resolved changes.
40
91
  *
41
92
  * Phase 3 of the 3-phase apply pattern: called AFTER data is written to store.
93
+ *
94
+ * In-batch repeats of one key are collapsed to the max-HLC winner before any write.
95
+ * Two versions of the same key can land in a single `applyChanges` batch (e.g.
96
+ * concurrent deletes of the same pk relayed together), and Phase 1 resolved BOTH
97
+ * against the same pre-batch prior version — neither saw the other. Writing both would
98
+ * leave two change-log entries for one key, re-attributing the older entry to the later
99
+ * HLC and breaking {@link SyncManagerImpl}'s `collectChangesSince` LOAD-BEARING
100
+ * INVARIANT (survivor's log HLC == its current version's HLC). So only the winner's
101
+ * metadata + change-log entry are written; losers are never written and the single
102
+ * pre-batch prior entry is deleted once. Mirrors the local write-path dedup in
103
+ * `recordDataEvent` / `recordColumnVersions`, keeping the delete and column paths
104
+ * symmetric.
42
105
  */
43
106
  export declare function commitChangeMetadata(ctx: SyncContext, resolvedChanges: ResolvedChange[]): Promise<void>;
44
107
  //# sourceMappingURL=change-applicator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"change-applicator.d.ts","sourceRoot":"","sources":["../../../src/sync/change-applicator.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,KAAK,EACX,SAAS,EACT,MAAM,EACN,WAAW,EACX,iBAAiB,EAGjB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrD;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC9B,OAAO,EAAE,SAAS,GAAG,SAAS,GAAG,UAAU,CAAC;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAC/B,yEAAyE;IACzE,gBAAgB,CAAC,EAAE,aAAa,CAAC;CACjC;AAED;;;;;;;GAOG;AACH,wBAAsB,YAAY,CACjC,GAAG,EAAE,WAAW,EAChB,OAAO,EAAE,SAAS,EAAE,GAClB,OAAO,CAAC,WAAW,CAAC,CA6HtB;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CAClC,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,MAAM,GACZ,OAAO,CAAC,cAAc,CAAC,CAwGzB;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,CACzC,GAAG,EAAE,WAAW,EAChB,eAAe,EAAE,cAAc,EAAE,GAC/B,OAAO,CAAC,IAAI,CAAC,CA2Df"}
1
+ {"version":3,"file":"change-applicator.d.ts","sourceRoot":"","sources":["../../../src/sync/change-applicator.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAE3D,OAAO,KAAK,EACX,SAAS,EACT,MAAM,EAGN,WAAW,EACX,iBAAiB,EAGjB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrD;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC9B,OAAO,EAAE,SAAS,GAAG,SAAS,GAAG,UAAU,CAAC;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAC/B,yEAAyE;IACzE,gBAAgB,CAAC,EAAE,aAAa,CAAC;IACjC,sGAAsG;IACtG,YAAY,CAAC,EAAE,SAAS,CAAC;CACzB;AA2CD;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,YAAY,CACjC,GAAG,EAAE,WAAW,EAChB,OAAO,EAAE,SAAS,EAAE,GAClB,OAAO,CAAC,WAAW,CAAC,CAoMtB;AAsCD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,gBAAgB,CACrC,GAAG,EAAE,WAAW,EAChB,MAAM,CAAC,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,MAAM,CAAC,CAsBjB;AAsFD;;;;;;;;GAQG;AACH,wBAAsB,qBAAqB,CAC1C,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,aAAa,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,GACtD,OAAO,CAAC,IAAI,CAAC,CAmBf;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CAClC,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,MAAM,GACZ,OAAO,CAAC,cAAc,CAAC,CAkHzB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,oBAAoB,CACzC,GAAG,EAAE,WAAW,EAChB,eAAe,EAAE,cAAc,EAAE,GAC/B,OAAO,CAAC,IAAI,CAAC,CAsCf"}