@optimystic/db-core 1.0.0-beta.3 → 1.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 (171) hide show
  1. package/dist/src/cluster/structs.d.ts +30 -6
  2. package/dist/src/cluster/structs.d.ts.map +1 -1
  3. package/dist/src/cluster/structs.js +5 -3
  4. package/dist/src/cluster/structs.js.map +1 -1
  5. package/dist/src/cohort-topic/antidos/bootstrap-evidence-envelope.d.ts +2 -1
  6. package/dist/src/cohort-topic/antidos/bootstrap-evidence-envelope.d.ts.map +1 -1
  7. package/dist/src/cohort-topic/antidos/bootstrap-evidence-envelope.js +10 -3
  8. package/dist/src/cohort-topic/antidos/bootstrap-evidence-envelope.js.map +1 -1
  9. package/dist/src/cohort-topic/wire/codec.d.ts.map +1 -1
  10. package/dist/src/cohort-topic/wire/codec.js +8 -2
  11. package/dist/src/cohort-topic/wire/codec.js.map +1 -1
  12. package/dist/src/collection/collection.d.ts +439 -34
  13. package/dist/src/collection/collection.d.ts.map +1 -1
  14. package/dist/src/collection/collection.js +843 -148
  15. package/dist/src/collection/collection.js.map +1 -1
  16. package/dist/src/collection/struct.d.ts +109 -4
  17. package/dist/src/collection/struct.d.ts.map +1 -1
  18. package/dist/src/collection/struct.js +88 -1
  19. package/dist/src/collection/struct.js.map +1 -1
  20. package/dist/src/collections/diary/diary.d.ts +6 -2
  21. package/dist/src/collections/diary/diary.d.ts.map +1 -1
  22. package/dist/src/collections/diary/diary.js +5 -2
  23. package/dist/src/collections/diary/diary.js.map +1 -1
  24. package/dist/src/collections/tree/struct.d.ts +124 -16
  25. package/dist/src/collections/tree/struct.d.ts.map +1 -1
  26. package/dist/src/collections/tree/struct.js +86 -11
  27. package/dist/src/collections/tree/struct.js.map +1 -1
  28. package/dist/src/collections/tree/tree.d.ts +13 -3
  29. package/dist/src/collections/tree/tree.d.ts.map +1 -1
  30. package/dist/src/collections/tree/tree.js +106 -40
  31. package/dist/src/collections/tree/tree.js.map +1 -1
  32. package/dist/src/index.d.ts +1 -1
  33. package/dist/src/index.d.ts.map +1 -1
  34. package/dist/src/index.js +1 -1
  35. package/dist/src/index.js.map +1 -1
  36. package/dist/src/matchmaking/wire.d.ts.map +1 -1
  37. package/dist/src/matchmaking/wire.js +8 -2
  38. package/dist/src/matchmaking/wire.js.map +1 -1
  39. package/dist/src/network/durability.d.ts +45 -0
  40. package/dist/src/network/durability.d.ts.map +1 -0
  41. package/dist/src/network/durability.js +114 -0
  42. package/dist/src/network/durability.js.map +1 -0
  43. package/dist/src/network/i-key-network.d.ts +14 -6
  44. package/dist/src/network/i-key-network.d.ts.map +1 -1
  45. package/dist/src/network/index.d.ts +3 -0
  46. package/dist/src/network/index.d.ts.map +1 -1
  47. package/dist/src/network/index.js +3 -0
  48. package/dist/src/network/index.js.map +1 -1
  49. package/dist/src/network/lineage.d.ts +39 -0
  50. package/dist/src/network/lineage.d.ts.map +1 -0
  51. package/dist/src/network/lineage.js +61 -0
  52. package/dist/src/network/lineage.js.map +1 -0
  53. package/dist/src/network/routing-key.d.ts +24 -0
  54. package/dist/src/network/routing-key.d.ts.map +1 -0
  55. package/dist/src/network/routing-key.js +9 -0
  56. package/dist/src/network/routing-key.js.map +1 -0
  57. package/dist/src/network/stale-failure.d.ts +5 -1
  58. package/dist/src/network/stale-failure.d.ts.map +1 -1
  59. package/dist/src/network/stale-failure.js +5 -1
  60. package/dist/src/network/stale-failure.js.map +1 -1
  61. package/dist/src/network/struct.d.ts +151 -8
  62. package/dist/src/network/struct.d.ts.map +1 -1
  63. package/dist/src/network/struct.js.map +1 -1
  64. package/dist/src/reactivity/wire.d.ts.map +1 -1
  65. package/dist/src/reactivity/wire.js +8 -2
  66. package/dist/src/reactivity/wire.js.map +1 -1
  67. package/dist/src/testing/test-transactor.d.ts +64 -7
  68. package/dist/src/testing/test-transactor.d.ts.map +1 -1
  69. package/dist/src/testing/test-transactor.js +150 -23
  70. package/dist/src/testing/test-transactor.js.map +1 -1
  71. package/dist/src/transaction/coordinator.d.ts +141 -21
  72. package/dist/src/transaction/coordinator.d.ts.map +1 -1
  73. package/dist/src/transaction/coordinator.js +408 -122
  74. package/dist/src/transaction/coordinator.js.map +1 -1
  75. package/dist/src/transaction/errors.d.ts +39 -10
  76. package/dist/src/transaction/errors.d.ts.map +1 -1
  77. package/dist/src/transaction/errors.js +34 -9
  78. package/dist/src/transaction/errors.js.map +1 -1
  79. package/dist/src/transaction/index.d.ts +1 -0
  80. package/dist/src/transaction/index.d.ts.map +1 -1
  81. package/dist/src/transaction/index.js.map +1 -1
  82. package/dist/src/transactor/block-floors.d.ts +78 -0
  83. package/dist/src/transactor/block-floors.d.ts.map +1 -0
  84. package/dist/src/transactor/block-floors.js +62 -0
  85. package/dist/src/transactor/block-floors.js.map +1 -0
  86. package/dist/src/transactor/change-notifier.d.ts +43 -0
  87. package/dist/src/transactor/change-notifier.d.ts.map +1 -1
  88. package/dist/src/transactor/change-notifier.js +3 -0
  89. package/dist/src/transactor/change-notifier.js.map +1 -1
  90. package/dist/src/transactor/index.d.ts +1 -0
  91. package/dist/src/transactor/index.d.ts.map +1 -1
  92. package/dist/src/transactor/index.js +1 -0
  93. package/dist/src/transactor/index.js.map +1 -1
  94. package/dist/src/transactor/network-transactor.d.ts +43 -6
  95. package/dist/src/transactor/network-transactor.d.ts.map +1 -1
  96. package/dist/src/transactor/network-transactor.js +279 -86
  97. package/dist/src/transactor/network-transactor.js.map +1 -1
  98. package/dist/src/transactor/transactor-source.d.ts +94 -4
  99. package/dist/src/transactor/transactor-source.d.ts.map +1 -1
  100. package/dist/src/transactor/transactor-source.js +120 -42
  101. package/dist/src/transactor/transactor-source.js.map +1 -1
  102. package/dist/src/transactor/transactor.d.ts +14 -1
  103. package/dist/src/transactor/transactor.d.ts.map +1 -1
  104. package/dist/src/transform/atomic.d.ts.map +1 -1
  105. package/dist/src/transform/atomic.js +12 -9
  106. package/dist/src/transform/atomic.js.map +1 -1
  107. package/dist/src/transform/base-pins.d.ts +50 -17
  108. package/dist/src/transform/base-pins.d.ts.map +1 -1
  109. package/dist/src/transform/base-pins.js +58 -11
  110. package/dist/src/transform/base-pins.js.map +1 -1
  111. package/dist/src/transform/cache-source.d.ts +75 -11
  112. package/dist/src/transform/cache-source.d.ts.map +1 -1
  113. package/dist/src/transform/cache-source.js +162 -36
  114. package/dist/src/transform/cache-source.js.map +1 -1
  115. package/dist/src/transform/digest.d.ts +8 -1
  116. package/dist/src/transform/digest.d.ts.map +1 -1
  117. package/dist/src/transform/digest.js +19 -9
  118. package/dist/src/transform/digest.js.map +1 -1
  119. package/dist/src/transform/helpers.d.ts +6 -2
  120. package/dist/src/transform/helpers.d.ts.map +1 -1
  121. package/dist/src/transform/helpers.js +8 -3
  122. package/dist/src/transform/helpers.js.map +1 -1
  123. package/dist/src/transform/tracker.d.ts +94 -14
  124. package/dist/src/transform/tracker.d.ts.map +1 -1
  125. package/dist/src/transform/tracker.js +222 -68
  126. package/dist/src/transform/tracker.js.map +1 -1
  127. package/dist/src/utility/structural-equals.d.ts +38 -0
  128. package/dist/src/utility/structural-equals.d.ts.map +1 -0
  129. package/dist/src/utility/structural-equals.js +77 -0
  130. package/dist/src/utility/structural-equals.js.map +1 -0
  131. package/package.json +2 -2
  132. package/src/cluster/structs.ts +28 -7
  133. package/src/cohort-topic/antidos/bootstrap-evidence-envelope.ts +260 -253
  134. package/src/cohort-topic/wire/codec.ts +222 -216
  135. package/src/collection/collection.ts +960 -157
  136. package/src/collection/struct.ts +99 -4
  137. package/src/collections/diary/diary.ts +71 -68
  138. package/src/collections/tree/struct.ts +155 -23
  139. package/src/collections/tree/tree.ts +127 -40
  140. package/src/index.ts +1 -1
  141. package/src/matchmaking/wire.ts +8 -2
  142. package/src/network/durability.ts +123 -0
  143. package/src/network/i-key-network.ts +60 -52
  144. package/src/network/index.ts +10 -7
  145. package/src/network/lineage.ts +80 -0
  146. package/src/network/routing-key.ts +27 -0
  147. package/src/network/stale-failure.ts +5 -1
  148. package/src/network/struct.ts +156 -8
  149. package/src/reactivity/wire.ts +230 -224
  150. package/src/testing/test-transactor.ts +152 -24
  151. package/src/transaction/coordinator.ts +470 -131
  152. package/src/transaction/errors.ts +34 -9
  153. package/src/transaction/index.ts +1 -0
  154. package/src/transactor/block-floors.ts +105 -0
  155. package/src/transactor/change-notifier.ts +129 -80
  156. package/src/transactor/index.ts +1 -0
  157. package/src/transactor/network-transactor.ts +297 -89
  158. package/src/transactor/transactor-source.ts +131 -42
  159. package/src/transactor/transactor.ts +13 -1
  160. package/src/transform/atomic.ts +25 -22
  161. package/src/transform/base-pins.ts +76 -18
  162. package/src/transform/cache-source.ts +327 -194
  163. package/src/transform/digest.ts +21 -10
  164. package/src/transform/helpers.ts +8 -3
  165. package/src/transform/tracker.ts +423 -270
  166. package/src/utility/structural-equals.ts +72 -0
  167. package/dist/src/utility/block-id-to-bytes.d.ts +0 -3
  168. package/dist/src/utility/block-id-to-bytes.d.ts.map +0 -1
  169. package/dist/src/utility/block-id-to-bytes.js +0 -7
  170. package/dist/src/utility/block-id-to-bytes.js.map +0 -1
  171. package/src/utility/block-id-to-bytes.ts +0 -8
@@ -9,7 +9,8 @@ export declare class Tracker<T extends IBlock> implements IBlockStore<T> {
9
9
  /** The collected set of transformations to be applied. Treat as immutable */
10
10
  transforms: import("./struct.js").Transforms;
11
11
  /** Committed bases pinned at the moment each update was staged, so the digest pass can
12
- * describe every updated block even after the read cache evicts its base. Shared by
12
+ * describe every updated block even after the read cache evicts its base, and so the pend
13
+ * can name the revision each block's operations were computed against. Shared by
13
14
  * reference across the trackers of one transaction (see {@link BasePins}); pass an
14
15
  * existing store to join a transaction, omit for a private one. */
15
16
  readonly pins: BasePins;
@@ -25,7 +26,8 @@ export declare class Tracker<T extends IBlock> implements IBlockStore<T> {
25
26
  /** The collected set of transformations to be applied. Treat as immutable */
26
27
  transforms?: import("./struct.js").Transforms,
27
28
  /** Committed bases pinned at the moment each update was staged, so the digest pass can
28
- * describe every updated block even after the read cache evicts its base. Shared by
29
+ * describe every updated block even after the read cache evicts its base, and so the pend
30
+ * can name the revision each block's operations were computed against. Shared by
29
31
  * reference across the trackers of one transaction (see {@link BasePins}); pass an
30
32
  * existing store to join a transaction, omit for a private one. */
31
33
  pins?: BasePins);
@@ -35,35 +37,87 @@ export declare class Tracker<T extends IBlock> implements IBlockStore<T> {
35
37
  private baseSource;
36
38
  /** The source's generation for an id, or undefined if the source cannot report drift. */
37
39
  private sourceGeneration;
40
+ /** Whether the source will answer the next read of `id` from memory with the base it just served.
41
+ * A source that cannot say is taken to — the behaviour before the probe, and right for every
42
+ * source but a CacheSource handing an answer through unkept.
43
+ *
44
+ * The generation cannot carry this. A memo is stamped with the generation read AFTER the load
45
+ * (see {@link tryGet}), so however the source bumps while handing an unkept answer through, the
46
+ * stamp matches on the next read and the memo is served — freezing, under this tracker's staged
47
+ * ops, exactly the base the source declined to freeze. */
48
+ private sourceRetains;
38
49
  /** The drift generation from the same authority {@link probeBase} pins from — the base source,
39
50
  * so an Atomic validates its pins against the collection's read cache rather than against the
40
51
  * drift-blind tracker in between. */
41
52
  protected baseGeneration(id: BlockId): number | undefined;
42
- /** The committed base for `id` as the base source can report it, plus that source's revision and
43
- * drift generation. Duck-typed (CacheSource supplies all three) and taken from
53
+ /** The base for `id` as the base source describes it now: its committed revision, its content
54
+ * when the source still has it, and the source's drift generation. Taken from
44
55
  * {@link baseSource}, so an Atomic staged over a Collection's tracker pins from the collection's
45
- * read cache instead of finding nothing. Returns undefined unless ALL THREE probes are
46
- * available, which keeps drift-blind sources (test doubles) on exactly the pre-pin behaviour.
47
- * Recency-neutral: uses CacheSource.peek. */
56
+ * read cache instead of finding nothing. Returns undefined unless the source reports drift and a
57
+ * revision which keeps drift-blind sources (test doubles) on exactly the pre-pin behaviour,
58
+ * and leaves a blind update (a block never read, or read and since cleared) unpinned. A
59
+ * revision without content is a REV-ONLY pin: the block was read and then evicted, so the base
60
+ * can be named but not materialized (see {@link PinnedBase.block}). Recency-neutral. */
48
61
  protected probeBase(id: BlockId): PinnedBase | undefined;
62
+ /** Re-judge `pin` against what the base source describes for `id` NOW, if the source's
63
+ * generation for the id has advanced since the pin was last judged. The source's content for
64
+ * the id changed hands; whether the BASE moved is a question of revision, not generation:
65
+ *
66
+ * - the same revision (a re-load of an evicted id, a refresh that re-read identical content, a
67
+ * below-floor answer served again) is the same committed content, so the pin is refreshed in
68
+ * place — the clone filled or replaced, the generation restamped — and stays declarable;
69
+ * - a different revision, or none (the id cleared, folded away, or handed through at another
70
+ * revision), means the staged operations were computed on content the source no longer
71
+ * describes. The pin is marked {@link PinnedBase.moved} and is never repaired here: re-pinning
72
+ * would put the new revision on operations built for the old one, which is precisely the wrong
73
+ * base the storage guard cannot catch. Only a re-stage (which resets this tracker) recovers.
74
+ *
75
+ * Cheap — one generation compare on the common path, two probes on drift — so every consumer of
76
+ * a pin runs it first. */
77
+ private revalidatePin;
49
78
  tryGet(id: BlockId, purpose?: ReadPurpose): Promise<T | undefined>;
50
79
  /** The block `id` materializes to under the staged transforms, computed WITHOUT loading from the
51
80
  * source, plus the committed revision of the base used. `undefined` when not computable here —
52
- * nothing staged for the id, the result is a delete, or an update's base is neither pinned
53
- * (see {@link pins}) nor locally cached (a commit must not pay a network round trip to
54
- * describe itself).
81
+ * nothing staged for the id, the result is a delete, or an update's base cannot be materialized:
82
+ * unpinned over a drift-blind source and not locally cached (a commit must not pay a network
83
+ * round trip to describe itself), pinned rev-only (the content was evicted before the update was
84
+ * staged — the base is still named by {@link stagedBaseRevs}, only its digest is undeclared), or
85
+ * pinned but MOVED (the operations no longer describe any content; see {@link revalidatePin}).
55
86
  *
56
87
  * Materializes with the canonical {@link applyTransform} — the exact function the member side
57
88
  * uses at commit — so client and member can never disagree on semantics (insert replaces the
58
89
  * block, then updates apply, then delete wins). An insert makes the result base-independent, so
59
- * `baseRev` is absent; updates-only returns the base's cached committed revision, probed from the
60
- * source via `peek`/`getCachedRevision` (duck-typed like {@link sourceGeneration}, because Tracker
61
- * layers over test doubles; `peek` must return a clone CacheSource's does). Recency-neutral and
62
- * memo-neutral: observably changes no tracker or source state. */
90
+ * `baseRev` is absent; updates-only returns the pinned base's revision, which is the revision the
91
+ * staged operations were computed against never the live cache's, which may have moved on.
92
+ * Memo-neutral and recency-neutral: reads observe no change. The one thing it may record is the
93
+ * discovery that a pinned base has moved. */
63
94
  peekMaterialized(id: BlockId): {
64
95
  block: IBlock;
65
96
  baseRev?: number;
66
97
  } | undefined;
98
+ /** Per block in `blockIds`, the committed revision its staged UPDATE operations were computed
99
+ * against — the pinned base, fixed when the first of them was staged and unchanged since, even
100
+ * if the base has moved (a moved base is still the truth about the operations; the pend
101
+ * carrying it is refused, which is the point). Only update-only blocks are named: an inserted
102
+ * block is base-independent, a deleted one materializes to nothing, and a block updated
103
+ * without a pin (a blind update, or a drift-blind source) has no base to name. */
104
+ stagedBaseRevs(blockIds: readonly BlockId[]): Record<BlockId, number>;
105
+ /** The staged update-only blocks whose pinned base has MOVED — the base source no longer
106
+ * describes the id at the revision the operations were computed against — after re-judging
107
+ * every such pin against the source (one generation compare each; see {@link revalidatePin}).
108
+ * Restricted to ids THIS tracker stages as updates: the shared store can also hold pins an
109
+ * abandoned per-attempt tracker took for its log blocks, which describe operations this tracker
110
+ * does not carry. A non-empty answer means the pending actions must be re-staged before they
111
+ * are pended (Collection.restageIfBasesMoved). */
112
+ movedBases(): BlockId[];
113
+ /** The staged update-only blocks whose pinned base the base source describes but does not RETAIN
114
+ * — content handed through unkept (a below-floor answer), which the source re-asks for on every
115
+ * read. The pin names the revision last served; storage may have caught up since without any
116
+ * log movement to say so, and only a read can tell. The candidates for a pre-pend re-read. */
117
+ unretainedBases(): BlockId[];
118
+ /** Whether `id` is staged as updates alone — not inserted (base-independent) and not deleted
119
+ * (materializes to nothing), the two shapes for which no base is ever named. */
120
+ private isUpdateOnly;
67
121
  /** Forward a leaf-value upgrade down to the source's read collector (duck-typed: only the
68
122
  * CacheSource layer implements it). Lets the B-tree point-lookup descent, which reads through
69
123
  * this tracker, pin its terminal leaf as a `value` read after tagging interior nodes
@@ -73,6 +127,32 @@ export declare class Tracker<T extends IBlock> implements IBlockStore<T> {
73
127
  createBlockHeader(type: BlockType, newId?: BlockId): BlockHeader;
74
128
  insert(block: T): void;
75
129
  update(blockId: BlockId, op: BlockOperation): void;
130
+ /** Fold a child tracker's staged transform into this one — the flush behind {@link Atomic.commit}
131
+ * — and empty the child. The child's pins are adopted first ({@link BasePins.adopt}), and an
132
+ * update whose id the child pinned keeps that pin as the base of its first operation here rather
133
+ * than probing the base source: the child's pin IS the base those operations were computed
134
+ * against, while the source may have moved on since (a concurrent unlatched read that reloaded
135
+ * the block at a newer revision), and probing would put the newer revision on operations built
136
+ * for the older one — the wrong base the storage-side guard cannot catch. An adopted pin the
137
+ * source no longer describes at its revision is judged moved on its next use, like any pin. An
138
+ * update the child did NOT pin (a blind one) is pinned here exactly as a direct update would be. */
139
+ absorb(child: Tracker<T>): void;
140
+ /** Stage `op` for `blockId` — folded into a staged insert if there is one, else appended to the
141
+ * id's update list — and keep the materialized memo current. Returns whether this was the FIRST
142
+ * update staged for the id here: the moment its base is fixed (see {@link pinBase}). */
143
+ private stageUpdate;
144
+ /** Fix the base of `id`'s staged operations at the moment the FIRST of them is staged in this
145
+ * tracker: the caller just read the block, so the base source describes what the operation was
146
+ * computed against. Whatever the store held for the id before is replaced (or dropped, when the
147
+ * source can pin nothing): no operations of THIS tracker's list were computed on it — a pin that
148
+ * outlived its tracker, such as an abandoned per-attempt tracker's log-block pin from before a
149
+ * refresh cleared the block, would otherwise speak for operations built on something else.
150
+ * (The one pre-existing pin that IS this list's base, an atomic's, is kept by {@link absorb},
151
+ * which never comes through here for it.) A later operation for the same id never re-pins: it
152
+ * re-judges the pin ({@link recheckPin}), and a base found to have moved stays moved. */
153
+ private pinBase;
154
+ /** Re-judge `id`'s pin, if it has one, against the base source (see {@link revalidatePin}). */
155
+ private recheckPin;
76
156
  delete(blockId: BlockId): void;
77
157
  reset(newTransform?: import("./struct.js").Transforms): import("./struct.js").Transforms;
78
158
  transformedBlockIds(): BlockId[];
@@ -1 +1 @@
1
- {"version":3,"file":"tracker.d.ts","sourceRoot":"","sources":["../../../src/transform/tracker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,IAAI,WAAW,EAAE,WAAW,EAAE,cAAc,EAAE,SAAS,EAAE,WAAW,IAAI,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEhK,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAsBjD;;GAEG;AACH,qBAAa,OAAO,CAAC,CAAC,SAAS,MAAM,CAAE,YAAW,WAAW,CAAC,CAAC,CAAC;IAW9D,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,6EAA6E;IACtE,UAAU;IACjB;;;uEAGmE;aACnD,IAAI,EAAE,QAAQ;IAjB/B;;;;;;yDAMqD;IACrD,OAAO,CAAC,YAAY,CAAiD;gBAGnD,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;IACxC,6EAA6E;IACtE,UAAU,mCAAoB;IACrC;;;uEAGmE;IACnD,IAAI,GAAE,QAAyB;IAUhD;;kGAE8F;IAC9F,OAAO,CAAC,UAAU;IAMlB,yFAAyF;IACzF,OAAO,CAAC,gBAAgB;IAKxB;;yCAEqC;IACrC,SAAS,CAAC,cAAc,CAAC,EAAE,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS;IAKzD;;;;;iDAK6C;IAC7C,SAAS,CAAC,SAAS,CAAC,EAAE,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS;IAQlD,MAAM,CAAC,EAAE,EAAE,OAAO,EAAE,OAAO,GAAE,WAAqB,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;IAsCjF;;;;;;;;;;;;sEAYkE;IAClE,gBAAgB,CAAC,EAAE,EAAE,OAAO,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS;IAoC9E;;;+FAG2F;IAC3F,aAAa,CAAC,EAAE,EAAE,OAAO,GAAG,IAAI;IAIhC,UAAU,IAAI,OAAO;IAIrB,iBAAiB,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,WAAW;IAIhE,MAAM,CAAC,KAAK,EAAE,CAAC;IAcf,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,cAAc;IAgC3C,MAAM,CAAC,OAAO,EAAE,OAAO;IAUvB,KAAK,CAAC,YAAY,mCAAoB;IAUtC,mBAAmB,IAAI,OAAO,EAAE;IAIhC,SAAS,CAAC,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC;CAGhC"}
1
+ {"version":3,"file":"tracker.d.ts","sourceRoot":"","sources":["../../../src/transform/tracker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,IAAI,WAAW,EAAE,WAAW,EAAE,cAAc,EAAE,SAAS,EAAE,WAAW,IAAI,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEhK,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAuBjD;;GAEG;AACH,qBAAa,OAAO,CAAC,CAAC,SAAS,MAAM,CAAE,YAAW,WAAW,CAAC,CAAC,CAAC;IAW9D,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,6EAA6E;IACtE,UAAU;IACjB;;;;uEAImE;aACnD,IAAI,EAAE,QAAQ;IAlB/B;;;;;;yDAMqD;IACrD,OAAO,CAAC,YAAY,CAAiD;gBAGnD,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;IACxC,6EAA6E;IACtE,UAAU,mCAAoB;IACrC;;;;uEAImE;IACnD,IAAI,GAAE,QAAyB;IAUhD;;kGAE8F;IAC9F,OAAO,CAAC,UAAU;IAMlB,yFAAyF;IACzF,OAAO,CAAC,gBAAgB;IAKxB;;;;;;;8DAO0D;IAC1D,OAAO,CAAC,aAAa;IAKrB;;yCAEqC;IACrC,SAAS,CAAC,cAAc,CAAC,EAAE,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS;IAKzD;;;;;;;4FAOwF;IACxF,SAAS,CAAC,SAAS,CAAC,EAAE,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS;IAUxD;;;;;;;;;;;;;;8BAc0B;IAC1B,OAAO,CAAC,aAAa;IAef,MAAM,CAAC,EAAE,EAAE,OAAO,EAAE,OAAO,GAAE,WAAqB,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;IA6CjF;;;;;;;;;;;;;;iDAc6C;IAC7C,gBAAgB,CAAC,EAAE,EAAE,OAAO,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS;IAmC9E;;;;;sFAKkF;IAClF,cAAc,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,GAAG,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC;IAUrE;;;;;;sDAMkD;IAClD,UAAU,IAAI,OAAO,EAAE;IASvB;;;kGAG8F;IAC9F,eAAe,IAAI,OAAO,EAAE;IAU5B;oFACgF;IAChF,OAAO,CAAC,YAAY;IAMpB;;;+FAG2F;IAC3F,aAAa,CAAC,EAAE,EAAE,OAAO,GAAG,IAAI;IAIhC,UAAU,IAAI,OAAO;IAIrB,iBAAiB,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,WAAW;IAIhE,MAAM,CAAC,KAAK,EAAE,CAAC;IAcf,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,cAAc;IAK3C;;;;;;;;wGAQoG;IACpG,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI;IAc/B;;4FAEwF;IACxF,OAAO,CAAC,WAAW;IAqBnB;;;;;;;;6FAQyF;IACzF,OAAO,CAAC,OAAO;IAMf,+FAA+F;IAC/F,OAAO,CAAC,UAAU;IAKlB,MAAM,CAAC,OAAO,EAAE,OAAO;IAUvB,KAAK,CAAC,YAAY,mCAAoB;IAWtC,mBAAmB,IAAI,OAAO,EAAE;IAIhC,SAAS,CAAC,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC;CAGhC"}
@@ -2,13 +2,8 @@ import { applyOperation, applyOperations, applyTransform, emptyTransforms, block
2
2
  import { BasePins } from "./base-pins.js";
3
3
  import { ensured } from "../utility/ensured.js";
4
4
  /** The base a source can answer from memory, with the committed revision of that content — the
5
- * shared probe behind both {@link Tracker.probeBase} (pin time) and {@link Tracker.peekMaterialized}
6
- * (declare time), so the two can never disagree about what "locally answerable" means. Duck-typed,
7
- * because Tracker layers over test doubles as well as CacheSource.
8
- *
9
- * Returns undefined unless BOTH probes answer: an LRU-evicted id can leave a stale cached revision
10
- * behind (see the NOTE on CacheSource's `revisions` map), and `peek` returning undefined for that id
11
- * is what keeps the stale revision from pairing with a block. */
5
+ * shared probe behind the unpinned {@link Tracker.peekMaterialized} path, for a source that cannot
6
+ * report drift and so takes no pins. Returns undefined unless BOTH probes answer. */
12
7
  function cachedBase(source, id) {
13
8
  const src = source;
14
9
  if (typeof src.peek !== 'function' || typeof src.getCachedRevision !== 'function')
@@ -36,7 +31,8 @@ export class Tracker {
36
31
  /** The collected set of transformations to be applied. Treat as immutable */
37
32
  transforms = emptyTransforms(),
38
33
  /** Committed bases pinned at the moment each update was staged, so the digest pass can
39
- * describe every updated block even after the read cache evicts its base. Shared by
34
+ * describe every updated block even after the read cache evicts its base, and so the pend
35
+ * can name the revision each block's operations were computed against. Shared by
40
36
  * reference across the trackers of one transaction (see {@link BasePins}); pass an
41
37
  * existing store to join a transaction, omit for a private one. */
42
38
  pins = new BasePins()) {
@@ -64,6 +60,18 @@ export class Tracker {
64
60
  const src = this.source;
65
61
  return typeof src.getGeneration === 'function' ? src.getGeneration(id) : undefined;
66
62
  }
63
+ /** Whether the source will answer the next read of `id` from memory with the base it just served.
64
+ * A source that cannot say is taken to — the behaviour before the probe, and right for every
65
+ * source but a CacheSource handing an answer through unkept.
66
+ *
67
+ * The generation cannot carry this. A memo is stamped with the generation read AFTER the load
68
+ * (see {@link tryGet}), so however the source bumps while handing an unkept answer through, the
69
+ * stamp matches on the next read and the memo is served — freezing, under this tracker's staged
70
+ * ops, exactly the base the source declined to freeze. */
71
+ sourceRetains(id) {
72
+ const src = this.source;
73
+ return typeof src.retains !== 'function' || src.retains(id);
74
+ }
67
75
  /** The drift generation from the same authority {@link probeBase} pins from — the base source,
68
76
  * so an Atomic validates its pins against the collection's read cache rather than against the
69
77
  * drift-blind tracker in between. */
@@ -71,19 +79,54 @@ export class Tracker {
71
79
  const src = this.baseSource();
72
80
  return typeof src.getGeneration === 'function' ? src.getGeneration(id) : undefined;
73
81
  }
74
- /** The committed base for `id` as the base source can report it, plus that source's revision and
75
- * drift generation. Duck-typed (CacheSource supplies all three) and taken from
82
+ /** The base for `id` as the base source describes it now: its committed revision, its content
83
+ * when the source still has it, and the source's drift generation. Taken from
76
84
  * {@link baseSource}, so an Atomic staged over a Collection's tracker pins from the collection's
77
- * read cache instead of finding nothing. Returns undefined unless ALL THREE probes are
78
- * available, which keeps drift-blind sources (test doubles) on exactly the pre-pin behaviour.
79
- * Recency-neutral: uses CacheSource.peek. */
85
+ * read cache instead of finding nothing. Returns undefined unless the source reports drift and a
86
+ * revision which keeps drift-blind sources (test doubles) on exactly the pre-pin behaviour,
87
+ * and leaves a blind update (a block never read, or read and since cleared) unpinned. A
88
+ * revision without content is a REV-ONLY pin: the block was read and then evicted, so the base
89
+ * can be named but not materialized (see {@link PinnedBase.block}). Recency-neutral. */
80
90
  probeBase(id) {
81
91
  const src = this.baseSource();
82
- // Without a drift signal a pin could never be proven fresh, so never take one.
83
- if (typeof src.getGeneration !== 'function')
92
+ // Without a drift signal a pin could never be re-judged, so never take one.
93
+ if (typeof src.getGeneration !== 'function' || typeof src.getCachedRevision !== 'function')
94
+ return undefined;
95
+ const rev = src.getCachedRevision(id);
96
+ if (rev === undefined)
84
97
  return undefined;
85
- const base = cachedBase(src, id);
86
- return base && { ...base, gen: src.getGeneration(id) };
98
+ const block = typeof src.peek === 'function' ? src.peek(id) : undefined;
99
+ return { rev, gen: src.getGeneration(id), ...(block === undefined ? {} : { block }) };
100
+ }
101
+ /** Re-judge `pin` against what the base source describes for `id` NOW, if the source's
102
+ * generation for the id has advanced since the pin was last judged. The source's content for
103
+ * the id changed hands; whether the BASE moved is a question of revision, not generation:
104
+ *
105
+ * - the same revision (a re-load of an evicted id, a refresh that re-read identical content, a
106
+ * below-floor answer served again) is the same committed content, so the pin is refreshed in
107
+ * place — the clone filled or replaced, the generation restamped — and stays declarable;
108
+ * - a different revision, or none (the id cleared, folded away, or handed through at another
109
+ * revision), means the staged operations were computed on content the source no longer
110
+ * describes. The pin is marked {@link PinnedBase.moved} and is never repaired here: re-pinning
111
+ * would put the new revision on operations built for the old one, which is precisely the wrong
112
+ * base the storage guard cannot catch. Only a re-stage (which resets this tracker) recovers.
113
+ *
114
+ * Cheap — one generation compare on the common path, two probes on drift — so every consumer of
115
+ * a pin runs it first. */
116
+ revalidatePin(id, pin) {
117
+ const gen = this.baseGeneration(id);
118
+ if (pin.moved || gen === undefined || pin.gen === gen)
119
+ return pin;
120
+ const src = this.baseSource();
121
+ const rev = typeof src.getCachedRevision === 'function' ? src.getCachedRevision(id) : undefined;
122
+ if (rev !== pin.rev) {
123
+ this.pins.markMoved(id);
124
+ return pin;
125
+ }
126
+ const block = typeof src.peek === 'function' ? src.peek(id) : undefined;
127
+ const refreshed = { rev, gen, ...(block ?? pin.block ? { block: block ?? pin.block } : {}) };
128
+ this.pins.set(id, refreshed);
129
+ return refreshed;
87
130
  }
88
131
  async tryGet(id, purpose = 'value') {
89
132
  // NOTE: precedence here is insert > delete > source+updates. In a well-formed transform an id is
@@ -109,14 +152,22 @@ export class Tracker {
109
152
  if (block) {
110
153
  const ops = this.transforms.updates?.[id] ?? [];
111
154
  if (ops.length > 0) {
155
+ // A read of a block whose base has MOVED under its staged ops is served as the live
156
+ // content plus those ops all the same — never refused. The pend is what pays for a
157
+ // moved base (Collection.restageIfBasesMoved), with one replay.
112
158
  applyOperations(block, ops);
113
159
  // Memoize only when the source can report drift, and stamp with the generation read
114
160
  // AFTER the load — the source may bump during tryGet (a cache miss-load), and stamping
115
161
  // with the pre-load generation would force a needless reload on the very next read.
162
+ // And only over a base the source kept: one it will re-ask for must be re-asked for
163
+ // here too, or this memo outlives the source's own refusal to remember it.
116
164
  const freshGen = this.sourceGeneration(id);
117
- if (freshGen !== undefined) {
165
+ if (freshGen !== undefined && this.sourceRetains(id)) {
118
166
  this.materialized.set(id, { block, gen: freshGen });
119
167
  }
168
+ else {
169
+ this.materialized.delete(id);
170
+ }
120
171
  return structuredClone(block); // clone so callers can't mutate the memo
121
172
  }
122
173
  }
@@ -124,17 +175,19 @@ export class Tracker {
124
175
  }
125
176
  /** The block `id` materializes to under the staged transforms, computed WITHOUT loading from the
126
177
  * source, plus the committed revision of the base used. `undefined` when not computable here —
127
- * nothing staged for the id, the result is a delete, or an update's base is neither pinned
128
- * (see {@link pins}) nor locally cached (a commit must not pay a network round trip to
129
- * describe itself).
178
+ * nothing staged for the id, the result is a delete, or an update's base cannot be materialized:
179
+ * unpinned over a drift-blind source and not locally cached (a commit must not pay a network
180
+ * round trip to describe itself), pinned rev-only (the content was evicted before the update was
181
+ * staged — the base is still named by {@link stagedBaseRevs}, only its digest is undeclared), or
182
+ * pinned but MOVED (the operations no longer describe any content; see {@link revalidatePin}).
130
183
  *
131
184
  * Materializes with the canonical {@link applyTransform} — the exact function the member side
132
185
  * uses at commit — so client and member can never disagree on semantics (insert replaces the
133
186
  * block, then updates apply, then delete wins). An insert makes the result base-independent, so
134
- * `baseRev` is absent; updates-only returns the base's cached committed revision, probed from the
135
- * source via `peek`/`getCachedRevision` (duck-typed like {@link sourceGeneration}, because Tracker
136
- * layers over test doubles; `peek` must return a clone CacheSource's does). Recency-neutral and
137
- * memo-neutral: observably changes no tracker or source state. */
187
+ * `baseRev` is absent; updates-only returns the pinned base's revision, which is the revision the
188
+ * staged operations were computed against never the live cache's, which may have moved on.
189
+ * Memo-neutral and recency-neutral: reads observe no change. The one thing it may record is the
190
+ * discovery that a pinned base has moved. */
138
191
  peekMaterialized(id) {
139
192
  const transform = transformForBlockId(this.transforms, id);
140
193
  if (transform.insert === undefined && transform.updates === undefined && transform.delete === undefined) {
@@ -144,33 +197,89 @@ export class Tracker {
144
197
  return undefined; // delete-last-wins: materializes to nothing
145
198
  }
146
199
  if (transform.insert) {
147
- // applyTransform mutates the insert in place when updates ride along; transformForBlockId
148
- // clones `updates` but NOT `insert`, so clone here to keep the staged transform pristine.
149
- transform.insert = structuredClone(transform.insert);
200
+ // No clone needed: transformForBlockId already deep-cloned `insert`, which applyTransform mutates.
150
201
  const block = applyTransform(undefined, transform);
151
202
  return block ? { block } : undefined;
152
203
  }
153
- // Prefer the base pinned when the update was staged — it survives read-cache eviction, which
154
- // is what keeps digest coverage a function of the transaction rather than of cache residency.
155
- // The freshness check is correctness-critical, not an optimisation: a stale pin would declare
156
- // a digest the member disagrees with, turning a blind-but-passing vote into a REJECT — an
157
- // inaccurate declaration is strictly worse than no declaration, so a drifted pin falls through
158
- // to the live peek below (which re-answers from the refreshed cache, or omits). The clone on
159
- // use is also required, not defensive: applyTransform mutates, and syncAttempts re-runs the
160
- // digest pass on every retry attempt against the same pin.
161
204
  const pin = this.pins.get(id);
162
- if (pin && pin.gen === this.baseGeneration(id)) {
163
- const block = applyTransform(structuredClone(pin.block), transform);
164
- return block ? { block, baseRev: pin.rev } : undefined;
205
+ if (pin) {
206
+ const current = this.revalidatePin(id, pin);
207
+ if (current.moved || current.block === undefined)
208
+ return undefined;
209
+ // The clone on use is required, not defensive: applyTransform mutates, and syncAttempts
210
+ // re-runs the digest pass on every retry attempt against the same pin.
211
+ const block = applyTransform(structuredClone(current.block), transform);
212
+ return block ? { block, baseRev: current.rev } : undefined;
165
213
  }
166
- // Unpinned fallback: the IMMEDIATE source, not {@link baseSource} — a drift-blind source that
167
- // can still peek keeps exactly its pre-pin behaviour here.
214
+ // Unpinned. Over a drift-aware base source that is a blind update (the block was never read,
215
+ // or was cleared before the update was staged): nothing is known about what the operations
216
+ // were computed against, so nothing is declared — the live cache may hold the block by now,
217
+ // but declaring ITS revision would name a base the operations were not built on. Only a
218
+ // drift-blind source, which takes no pins, keeps its pre-pin behaviour: the IMMEDIATE source's
219
+ // live peek, not {@link baseSource}, exactly as before pins existed.
220
+ if (typeof this.baseSource().getGeneration === 'function')
221
+ return undefined;
168
222
  const base = cachedBase(this.source, id);
169
223
  if (!base)
170
224
  return undefined;
171
225
  const block = applyTransform(base.block, transform); // base already a clone (peek contract)
172
226
  return block ? { block, baseRev: base.rev } : undefined;
173
227
  }
228
+ /** Per block in `blockIds`, the committed revision its staged UPDATE operations were computed
229
+ * against — the pinned base, fixed when the first of them was staged and unchanged since, even
230
+ * if the base has moved (a moved base is still the truth about the operations; the pend
231
+ * carrying it is refused, which is the point). Only update-only blocks are named: an inserted
232
+ * block is base-independent, a deleted one materializes to nothing, and a block updated
233
+ * without a pin (a blind update, or a drift-blind source) has no base to name. */
234
+ stagedBaseRevs(blockIds) {
235
+ const revs = {};
236
+ for (const id of blockIds) {
237
+ if (!this.isUpdateOnly(id))
238
+ continue;
239
+ const pin = this.pins.get(id);
240
+ if (pin)
241
+ revs[id] = pin.rev;
242
+ }
243
+ return revs;
244
+ }
245
+ /** The staged update-only blocks whose pinned base has MOVED — the base source no longer
246
+ * describes the id at the revision the operations were computed against — after re-judging
247
+ * every such pin against the source (one generation compare each; see {@link revalidatePin}).
248
+ * Restricted to ids THIS tracker stages as updates: the shared store can also hold pins an
249
+ * abandoned per-attempt tracker took for its log blocks, which describe operations this tracker
250
+ * does not carry. A non-empty answer means the pending actions must be re-staged before they
251
+ * are pended (Collection.restageIfBasesMoved). */
252
+ movedBases() {
253
+ const moved = [];
254
+ for (const id of Object.keys(this.transforms.updates ?? {})) {
255
+ const pin = this.pins.get(id);
256
+ if (pin && this.isUpdateOnly(id) && this.revalidatePin(id, pin).moved)
257
+ moved.push(id);
258
+ }
259
+ return moved;
260
+ }
261
+ /** The staged update-only blocks whose pinned base the base source describes but does not RETAIN
262
+ * — content handed through unkept (a below-floor answer), which the source re-asks for on every
263
+ * read. The pin names the revision last served; storage may have caught up since without any
264
+ * log movement to say so, and only a read can tell. The candidates for a pre-pend re-read. */
265
+ unretainedBases() {
266
+ const src = this.baseSource();
267
+ if (typeof src.retains !== 'function' || typeof src.peek !== 'function')
268
+ return [];
269
+ const ids = [];
270
+ for (const id of Object.keys(this.transforms.updates ?? {})) {
271
+ if (this.isUpdateOnly(id) && this.pins.get(id) && !src.retains(id) && src.peek(id) !== undefined)
272
+ ids.push(id);
273
+ }
274
+ return ids;
275
+ }
276
+ /** Whether `id` is staged as updates alone — not inserted (base-independent) and not deleted
277
+ * (materializes to nothing), the two shapes for which no base is ever named. */
278
+ isUpdateOnly(id) {
279
+ return (this.transforms.updates?.[id]?.length ?? 0) > 0
280
+ && !(this.transforms.inserts && Object.hasOwn(this.transforms.inserts, id))
281
+ && !this.transforms.deletes?.includes(id);
282
+ }
174
283
  /** Forward a leaf-value upgrade down to the source's read collector (duck-typed: only the
175
284
  * CacheSource layer implements it). Lets the B-tree point-lookup descent, which reads through
176
285
  * this tracker, pin its terminal leaf as a `value` read after tagging interior nodes
@@ -198,37 +307,81 @@ export class Tracker {
198
307
  }
199
308
  }
200
309
  update(blockId, op) {
310
+ if (this.stageUpdate(blockId, op))
311
+ this.pinBase(blockId);
312
+ else
313
+ this.recheckPin(blockId);
314
+ }
315
+ /** Fold a child tracker's staged transform into this one — the flush behind {@link Atomic.commit}
316
+ * — and empty the child. The child's pins are adopted first ({@link BasePins.adopt}), and an
317
+ * update whose id the child pinned keeps that pin as the base of its first operation here rather
318
+ * than probing the base source: the child's pin IS the base those operations were computed
319
+ * against, while the source may have moved on since (a concurrent unlatched read that reloaded
320
+ * the block at a newer revision), and probing would put the newer revision on operations built
321
+ * for the older one — the wrong base the storage-side guard cannot catch. An adopted pin the
322
+ * source no longer describes at its revision is judged moved on its next use, like any pin. An
323
+ * update the child did NOT pin (a blind one) is pinned here exactly as a direct update would be. */
324
+ absorb(child) {
325
+ this.pins.adopt(child.pins);
326
+ const adopted = new Set(child.pins.ids());
327
+ const transform = child.reset();
328
+ for (const blockId of transform.deletes ?? [])
329
+ this.delete(blockId);
330
+ for (const block of Object.values(transform.inserts ?? {}))
331
+ this.insert(block);
332
+ for (const [blockId, ops] of Object.entries(transform.updates ?? {})) {
333
+ for (const op of ops) {
334
+ if (this.stageUpdate(blockId, op) && !adopted.has(blockId))
335
+ this.pinBase(blockId);
336
+ else
337
+ this.recheckPin(blockId);
338
+ }
339
+ }
340
+ }
341
+ /** Stage `op` for `blockId` — folded into a staged insert if there is one, else appended to the
342
+ * id's update list — and keep the materialized memo current. Returns whether this was the FIRST
343
+ * update staged for the id here: the moment its base is fixed (see {@link pinBase}). */
344
+ stageUpdate(blockId, op) {
201
345
  const inserted = this.transforms.inserts?.[blockId];
202
346
  if (inserted) {
203
347
  applyOperation(inserted, op);
348
+ return false;
204
349
  }
205
- else {
206
- const updates = this.transforms.updates ??= {};
207
- ensured(updates, blockId, () => []).push(structuredClone(op));
208
- // The memo already equals (base source content + prior ops); applying just the new op
209
- // keeps it equal to the full ops list O(1), no full replay. Leave `gen` untouched: it
210
- // still records the base-content generation, so a later external source change still
211
- // forces a reload. (Refreshing gen here would mask stale base content.)
212
- const memo = this.materialized.get(blockId);
213
- if (memo) {
214
- applyOperation(memo.block, op);
215
- }
216
- // Pin the committed base NOW — the caller just read this block, so it is resident — and
217
- // only when there is no still-fresh pin, so a block updated 50 times pays one base clone.
218
- // A generation change (an external commit folded into the cache) re-pins against the new
219
- // base, which is the base the member will apply the whole op list to.
220
- // NOTE: read-far-then-update stays unpinned — a block read, then evicted by 128+ other
221
- // reads, and only then updated, probes an already-evicted cache here and is omitted from
222
- // the digest (pre-existing behaviour; digest.spec.ts pins it). If a workload ever reads a
223
- // large batch before writing any of it, the closure is to pin on READ for ids that later
224
- // get updated, at retention proportional to reads rather than to writes.
225
- const existing = this.pins.get(blockId);
226
- if (!existing || existing.gen !== this.baseGeneration(blockId)) {
227
- const pin = this.probeBase(blockId);
228
- if (pin)
229
- this.pins.set(blockId, pin);
230
- }
350
+ const updates = this.transforms.updates ??= {};
351
+ const ops = ensured(updates, blockId, () => []);
352
+ const first = ops.length === 0;
353
+ ops.push(structuredClone(op));
354
+ // The memo already equals (base source content + prior ops); applying just the new op
355
+ // keeps it equal to the full ops list — O(1), no full replay. Leave `gen` untouched: it
356
+ // still records the base-content generation, so a later external source change still
357
+ // forces a reload. (Refreshing gen here would mask stale base content.)
358
+ const memo = this.materialized.get(blockId);
359
+ if (memo) {
360
+ applyOperation(memo.block, op);
231
361
  }
362
+ return first;
363
+ }
364
+ /** Fix the base of `id`'s staged operations at the moment the FIRST of them is staged in this
365
+ * tracker: the caller just read the block, so the base source describes what the operation was
366
+ * computed against. Whatever the store held for the id before is replaced (or dropped, when the
367
+ * source can pin nothing): no operations of THIS tracker's list were computed on it — a pin that
368
+ * outlived its tracker, such as an abandoned per-attempt tracker's log-block pin from before a
369
+ * refresh cleared the block, would otherwise speak for operations built on something else.
370
+ * (The one pre-existing pin that IS this list's base, an atomic's, is kept by {@link absorb},
371
+ * which never comes through here for it.) A later operation for the same id never re-pins: it
372
+ * re-judges the pin ({@link recheckPin}), and a base found to have moved stays moved. */
373
+ pinBase(id) {
374
+ const pin = this.probeBase(id);
375
+ if (pin)
376
+ this.pins.set(id, pin);
377
+ else
378
+ this.pins.delete(id);
379
+ }
380
+ /** Re-judge `id`'s pin, if it has one, against the base source (see {@link revalidatePin}). */
381
+ recheckPin(id) {
382
+ const existing = this.pins.get(id);
383
+ if (existing)
384
+ this.revalidatePin(id, existing);
232
385
  }
233
386
  delete(blockId) {
234
387
  if (this.transforms.inserts)
@@ -246,7 +399,8 @@ export class Tracker {
246
399
  this.transforms = newTransform;
247
400
  this.materialized.clear();
248
401
  // The single reclamation point for pins: a plain reset clears them (empty updates), a
249
- // rollback-style reset(transforms) keeps exactly the pins for ids still staged as updates.
402
+ // rollback-style reset(transforms) keeps exactly the pins moved marks included for ids
403
+ // still staged as updates.
250
404
  this.pins.retainOnly(Object.keys(newTransform.updates ?? {}));
251
405
  return oldTransform;
252
406
  }
@@ -1 +1 @@
1
- {"version":3,"file":"tracker.js","sourceRoot":"","sources":["../../../src/transform/tracker.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tracker.js","sourceRoot":"","sources":["../../../src/transform/tracker.ts"],"names":[],"mappings":"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"}