@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.
- package/dist/src/cluster/structs.d.ts +30 -6
- package/dist/src/cluster/structs.d.ts.map +1 -1
- package/dist/src/cluster/structs.js +5 -3
- package/dist/src/cluster/structs.js.map +1 -1
- package/dist/src/cohort-topic/antidos/bootstrap-evidence-envelope.d.ts +2 -1
- package/dist/src/cohort-topic/antidos/bootstrap-evidence-envelope.d.ts.map +1 -1
- package/dist/src/cohort-topic/antidos/bootstrap-evidence-envelope.js +10 -3
- package/dist/src/cohort-topic/antidos/bootstrap-evidence-envelope.js.map +1 -1
- package/dist/src/cohort-topic/wire/codec.d.ts.map +1 -1
- package/dist/src/cohort-topic/wire/codec.js +8 -2
- package/dist/src/cohort-topic/wire/codec.js.map +1 -1
- package/dist/src/collection/collection.d.ts +439 -34
- package/dist/src/collection/collection.d.ts.map +1 -1
- package/dist/src/collection/collection.js +843 -148
- package/dist/src/collection/collection.js.map +1 -1
- package/dist/src/collection/struct.d.ts +109 -4
- package/dist/src/collection/struct.d.ts.map +1 -1
- package/dist/src/collection/struct.js +88 -1
- package/dist/src/collection/struct.js.map +1 -1
- package/dist/src/collections/diary/diary.d.ts +6 -2
- package/dist/src/collections/diary/diary.d.ts.map +1 -1
- package/dist/src/collections/diary/diary.js +5 -2
- package/dist/src/collections/diary/diary.js.map +1 -1
- package/dist/src/collections/tree/struct.d.ts +124 -16
- package/dist/src/collections/tree/struct.d.ts.map +1 -1
- package/dist/src/collections/tree/struct.js +86 -11
- package/dist/src/collections/tree/struct.js.map +1 -1
- package/dist/src/collections/tree/tree.d.ts +13 -3
- package/dist/src/collections/tree/tree.d.ts.map +1 -1
- package/dist/src/collections/tree/tree.js +106 -40
- package/dist/src/collections/tree/tree.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/matchmaking/wire.d.ts.map +1 -1
- package/dist/src/matchmaking/wire.js +8 -2
- package/dist/src/matchmaking/wire.js.map +1 -1
- package/dist/src/network/durability.d.ts +45 -0
- package/dist/src/network/durability.d.ts.map +1 -0
- package/dist/src/network/durability.js +114 -0
- package/dist/src/network/durability.js.map +1 -0
- package/dist/src/network/i-key-network.d.ts +14 -6
- package/dist/src/network/i-key-network.d.ts.map +1 -1
- package/dist/src/network/index.d.ts +3 -0
- package/dist/src/network/index.d.ts.map +1 -1
- package/dist/src/network/index.js +3 -0
- package/dist/src/network/index.js.map +1 -1
- package/dist/src/network/lineage.d.ts +39 -0
- package/dist/src/network/lineage.d.ts.map +1 -0
- package/dist/src/network/lineage.js +61 -0
- package/dist/src/network/lineage.js.map +1 -0
- package/dist/src/network/routing-key.d.ts +24 -0
- package/dist/src/network/routing-key.d.ts.map +1 -0
- package/dist/src/network/routing-key.js +9 -0
- package/dist/src/network/routing-key.js.map +1 -0
- package/dist/src/network/stale-failure.d.ts +5 -1
- package/dist/src/network/stale-failure.d.ts.map +1 -1
- package/dist/src/network/stale-failure.js +5 -1
- package/dist/src/network/stale-failure.js.map +1 -1
- package/dist/src/network/struct.d.ts +151 -8
- package/dist/src/network/struct.d.ts.map +1 -1
- package/dist/src/network/struct.js.map +1 -1
- package/dist/src/reactivity/wire.d.ts.map +1 -1
- package/dist/src/reactivity/wire.js +8 -2
- package/dist/src/reactivity/wire.js.map +1 -1
- package/dist/src/testing/test-transactor.d.ts +64 -7
- package/dist/src/testing/test-transactor.d.ts.map +1 -1
- package/dist/src/testing/test-transactor.js +150 -23
- package/dist/src/testing/test-transactor.js.map +1 -1
- package/dist/src/transaction/coordinator.d.ts +141 -21
- package/dist/src/transaction/coordinator.d.ts.map +1 -1
- package/dist/src/transaction/coordinator.js +408 -122
- package/dist/src/transaction/coordinator.js.map +1 -1
- package/dist/src/transaction/errors.d.ts +39 -10
- package/dist/src/transaction/errors.d.ts.map +1 -1
- package/dist/src/transaction/errors.js +34 -9
- package/dist/src/transaction/errors.js.map +1 -1
- package/dist/src/transaction/index.d.ts +1 -0
- package/dist/src/transaction/index.d.ts.map +1 -1
- package/dist/src/transaction/index.js.map +1 -1
- package/dist/src/transactor/block-floors.d.ts +78 -0
- package/dist/src/transactor/block-floors.d.ts.map +1 -0
- package/dist/src/transactor/block-floors.js +62 -0
- package/dist/src/transactor/block-floors.js.map +1 -0
- package/dist/src/transactor/change-notifier.d.ts +43 -0
- package/dist/src/transactor/change-notifier.d.ts.map +1 -1
- package/dist/src/transactor/change-notifier.js +3 -0
- package/dist/src/transactor/change-notifier.js.map +1 -1
- package/dist/src/transactor/index.d.ts +1 -0
- package/dist/src/transactor/index.d.ts.map +1 -1
- package/dist/src/transactor/index.js +1 -0
- package/dist/src/transactor/index.js.map +1 -1
- package/dist/src/transactor/network-transactor.d.ts +43 -6
- package/dist/src/transactor/network-transactor.d.ts.map +1 -1
- package/dist/src/transactor/network-transactor.js +279 -86
- package/dist/src/transactor/network-transactor.js.map +1 -1
- package/dist/src/transactor/transactor-source.d.ts +94 -4
- package/dist/src/transactor/transactor-source.d.ts.map +1 -1
- package/dist/src/transactor/transactor-source.js +120 -42
- package/dist/src/transactor/transactor-source.js.map +1 -1
- package/dist/src/transactor/transactor.d.ts +14 -1
- package/dist/src/transactor/transactor.d.ts.map +1 -1
- package/dist/src/transform/atomic.d.ts.map +1 -1
- package/dist/src/transform/atomic.js +12 -9
- package/dist/src/transform/atomic.js.map +1 -1
- package/dist/src/transform/base-pins.d.ts +50 -17
- package/dist/src/transform/base-pins.d.ts.map +1 -1
- package/dist/src/transform/base-pins.js +58 -11
- package/dist/src/transform/base-pins.js.map +1 -1
- package/dist/src/transform/cache-source.d.ts +75 -11
- package/dist/src/transform/cache-source.d.ts.map +1 -1
- package/dist/src/transform/cache-source.js +162 -36
- package/dist/src/transform/cache-source.js.map +1 -1
- package/dist/src/transform/digest.d.ts +8 -1
- package/dist/src/transform/digest.d.ts.map +1 -1
- package/dist/src/transform/digest.js +19 -9
- package/dist/src/transform/digest.js.map +1 -1
- package/dist/src/transform/helpers.d.ts +6 -2
- package/dist/src/transform/helpers.d.ts.map +1 -1
- package/dist/src/transform/helpers.js +8 -3
- package/dist/src/transform/helpers.js.map +1 -1
- package/dist/src/transform/tracker.d.ts +94 -14
- package/dist/src/transform/tracker.d.ts.map +1 -1
- package/dist/src/transform/tracker.js +222 -68
- package/dist/src/transform/tracker.js.map +1 -1
- package/dist/src/utility/structural-equals.d.ts +38 -0
- package/dist/src/utility/structural-equals.d.ts.map +1 -0
- package/dist/src/utility/structural-equals.js +77 -0
- package/dist/src/utility/structural-equals.js.map +1 -0
- package/package.json +2 -2
- package/src/cluster/structs.ts +28 -7
- package/src/cohort-topic/antidos/bootstrap-evidence-envelope.ts +260 -253
- package/src/cohort-topic/wire/codec.ts +222 -216
- package/src/collection/collection.ts +960 -157
- package/src/collection/struct.ts +99 -4
- package/src/collections/diary/diary.ts +71 -68
- package/src/collections/tree/struct.ts +155 -23
- package/src/collections/tree/tree.ts +127 -40
- package/src/index.ts +1 -1
- package/src/matchmaking/wire.ts +8 -2
- package/src/network/durability.ts +123 -0
- package/src/network/i-key-network.ts +60 -52
- package/src/network/index.ts +10 -7
- package/src/network/lineage.ts +80 -0
- package/src/network/routing-key.ts +27 -0
- package/src/network/stale-failure.ts +5 -1
- package/src/network/struct.ts +156 -8
- package/src/reactivity/wire.ts +230 -224
- package/src/testing/test-transactor.ts +152 -24
- package/src/transaction/coordinator.ts +470 -131
- package/src/transaction/errors.ts +34 -9
- package/src/transaction/index.ts +1 -0
- package/src/transactor/block-floors.ts +105 -0
- package/src/transactor/change-notifier.ts +129 -80
- package/src/transactor/index.ts +1 -0
- package/src/transactor/network-transactor.ts +297 -89
- package/src/transactor/transactor-source.ts +131 -42
- package/src/transactor/transactor.ts +13 -1
- package/src/transform/atomic.ts +25 -22
- package/src/transform/base-pins.ts +76 -18
- package/src/transform/cache-source.ts +327 -194
- package/src/transform/digest.ts +21 -10
- package/src/transform/helpers.ts +8 -3
- package/src/transform/tracker.ts +423 -270
- package/src/utility/structural-equals.ts +72 -0
- package/dist/src/utility/block-id-to-bytes.d.ts +0 -3
- package/dist/src/utility/block-id-to-bytes.d.ts.map +0 -1
- package/dist/src/utility/block-id-to-bytes.js +0 -7
- package/dist/src/utility/block-id-to-bytes.js.map +0 -1
- package/src/utility/block-id-to-bytes.ts +0 -8
|
@@ -14,7 +14,10 @@ export declare const rootId$: string;
|
|
|
14
14
|
*
|
|
15
15
|
* - `absent` — the key must not exist (SQL INSERT): a hit throws {@link TreeKeyTakenError},
|
|
16
16
|
* discarding the whole action's staged writes.
|
|
17
|
-
* - `keepExisting` — if the key exists, skip this entry silently
|
|
17
|
+
* - `keepExisting` — if the key exists, skip this entry silently. No SQL statement stages
|
|
18
|
+
* it any more (INSERT OR IGNORE is guarded `absent`, because skipping only the main-table
|
|
19
|
+
* entry would leave the statement's index entries beside a rival's row — see the
|
|
20
|
+
* `unchanged` paragraph in docs/internals.md); kept as a serialized log form.
|
|
18
21
|
* - `absentRange` — no entry OTHER THAN this action's own key may exist in `range`
|
|
19
22
|
* (secondary-UNIQUE enforcement, where uniqueness is a property of a framed key
|
|
20
23
|
* PREFIX rather than one exact key: an index tree keys `indexKey ‖ primaryKey`, so
|
|
@@ -22,42 +25,101 @@ export declare const rootId$: string;
|
|
|
22
25
|
* foreign hit throws {@link TreeRangeTakenError}. The entry being staged lands inside
|
|
23
26
|
* its own range, so the scan excludes its exact key — otherwise every guarded
|
|
24
27
|
* re-stage of a present key (a replay after a clean refresh) would refuse itself.
|
|
28
|
+
* - `unchanged` — see {@link TreeUnchangedGuard}: the only kind that says something must
|
|
29
|
+
* still BE here, rather than that nothing may be.
|
|
25
30
|
*
|
|
26
31
|
* MIXED VERSIONS: a peer running a build that predates guards destructures `[key, entry]`
|
|
27
32
|
* and ignores the third slot — its replays revert to today's silent overwrite. No version
|
|
28
33
|
* gating exists yet (see backlog ticket `debt-mixed-version-identify-incompatibility`).
|
|
29
34
|
*/
|
|
30
|
-
export type TreeEntryGuard<TKey> = {
|
|
35
|
+
export type TreeEntryGuard<TKey, TEntry = unknown> = {
|
|
31
36
|
kind: 'absent';
|
|
32
37
|
} | {
|
|
33
38
|
kind: 'keepExisting';
|
|
34
39
|
} | {
|
|
35
40
|
kind: 'absentRange';
|
|
36
41
|
range: KeyRange<TKey>;
|
|
42
|
+
} | TreeUnchangedGuard<TEntry>;
|
|
43
|
+
/**
|
|
44
|
+
* "The entry I am replacing must still be exactly the one I read" — the optimistic-concurrency
|
|
45
|
+
* (lost-update) guard, and the only {@link TreeEntryGuard} kind that also applies to a DELETE.
|
|
46
|
+
* The entry at the key must be PRESENT and structurally equal to `expected` (`structuralEquals`
|
|
47
|
+
* in `packages/db-core/src/utility/structural-equals.ts`); otherwise the handler throws
|
|
48
|
+
* {@link TreeEntryChangedError}.
|
|
49
|
+
*
|
|
50
|
+
* ABSENT COUNTS AS CHANGED. The staged effect was computed from an entry image that no longer
|
|
51
|
+
* exists, so re-applying it is never right: an upsert would resurrect a row a rival deleted, and
|
|
52
|
+
* a delete would be the second of two racing deletes. Refusing both is the optimistic answer —
|
|
53
|
+
* the writer read a row that is now gone, and an application-level retry then affects zero rows
|
|
54
|
+
* sequentially. If tolerating absence on deletes is ever genuinely wanted, add a separate
|
|
55
|
+
* `unchangedOrAbsent` kind rather than weakening this one's contract.
|
|
56
|
+
*
|
|
57
|
+
* `expected` is the entry AS STORED, not a digest: a guard rides in the log beside its action
|
|
58
|
+
* under the same encoding entries already use, so a full copy round-trips by construction and no
|
|
59
|
+
* digest scheme has to be invented, versioned, or kept in sync with the entry encoding.
|
|
60
|
+
*
|
|
61
|
+
* NOTE: that choice roughly doubles the row bytes of every guarded log entry (the new entry plus
|
|
62
|
+
* a full copy of the old one). If log volume ever becomes the binding constraint, replace
|
|
63
|
+
* `expected` with a content digest — the block-digest utilities under
|
|
64
|
+
* `packages/db-core/src/transaction/` are the starting point — and accept the versioning burden
|
|
65
|
+
* that comes with it.
|
|
66
|
+
*/
|
|
67
|
+
export type TreeUnchangedGuard<TEntry = unknown> = {
|
|
68
|
+
kind: 'unchanged';
|
|
69
|
+
/** The entry image the staged write read, as stored. */
|
|
70
|
+
expected: TEntry;
|
|
37
71
|
};
|
|
38
|
-
/**
|
|
39
|
-
|
|
72
|
+
/** An element that writes (inserts or replaces) an entry. Any {@link TreeEntryGuard} kind is
|
|
73
|
+
* meaningful here. */
|
|
74
|
+
export type TreeUpsertElement<TKey, TEntry> = [
|
|
40
75
|
key: TKey,
|
|
41
|
-
entry
|
|
42
|
-
guard?: TreeEntryGuard<TKey>
|
|
43
|
-
]
|
|
76
|
+
entry: TEntry,
|
|
77
|
+
guard?: TreeEntryGuard<TKey, TEntry>
|
|
78
|
+
];
|
|
79
|
+
/** An element that deletes the entry at a key. Only {@link TreeUnchangedGuard} says anything a
|
|
80
|
+
* delete can act on — the other kinds all assert that nothing is present, which would make the
|
|
81
|
+
* delete a no-op by construction. The handler rejects any other kind at runtime too, since a
|
|
82
|
+
* replayed log entry is deserialized data that this type never policed. */
|
|
83
|
+
export type TreeDeleteElement<TKey, TEntry> = [
|
|
84
|
+
key: TKey,
|
|
85
|
+
entry?: undefined,
|
|
86
|
+
guard?: TreeUnchangedGuard<TEntry>
|
|
87
|
+
];
|
|
88
|
+
/** Represents a unit of change to a tree collection. */
|
|
89
|
+
export type TreeReplaceAction<TKey, TEntry> = (TreeUpsertElement<TKey, TEntry> | TreeDeleteElement<TKey, TEntry>)[];
|
|
44
90
|
/**
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
91
|
+
* Base of every refusal a {@link TreeEntryGuard} raises out of the tree `replace` handler — at
|
|
92
|
+
* initial staging, or (the load-bearing case) at conflict replay after a rival writer's commit
|
|
93
|
+
* was adopted. One contract, stated once for every subclass:
|
|
94
|
+
*
|
|
95
|
+
* - The throw **discards the whole action's staged writes** — the handler runs inside an
|
|
96
|
+
* all-or-nothing Atomic wrapper, so not one entry of a multi-entry action lands.
|
|
97
|
+
* - It is **not a `StaleFailure`**, so neither `Collection.sync`'s retry loop nor
|
|
98
|
+
* `TransactionCoordinator.commit`'s stale-loss re-drive absorbs it; it propagates out of the
|
|
99
|
+
* losing commit, and it must never be downgraded to a retryable condition.
|
|
100
|
+
*
|
|
101
|
+
* Subclasses split by WHAT was refused, because consumers map them differently: a
|
|
102
|
+
* {@link TreeKeyTakenError} is a uniqueness violation (the Quereus bridge renders it as
|
|
103
|
+
* `UNIQUE constraint failed`), while a {@link TreeEntryChangedError} is a lost update. Catch
|
|
104
|
+
* this base to treat any guard refusal uniformly; catch a subclass to say which happened.
|
|
51
105
|
*/
|
|
52
|
-
export declare class
|
|
106
|
+
export declare class TreeGuardRefusedError<TKey = unknown> extends Error {
|
|
53
107
|
/** The collection whose tree refused the entry. */
|
|
54
108
|
readonly collectionId: CollectionId;
|
|
55
|
-
/** The key
|
|
56
|
-
* key this action was staging, whose claimed range a rival occupies). */
|
|
109
|
+
/** The key whose staged entry was refused. */
|
|
57
110
|
readonly key: TKey;
|
|
58
111
|
constructor(
|
|
59
112
|
/** The collection whose tree refused the entry. */
|
|
60
113
|
collectionId: CollectionId,
|
|
114
|
+
/** The key whose staged entry was refused. */
|
|
115
|
+
key: TKey, message: string);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Thrown when an entry guarded `absent` finds its key already present: a duplicate-key
|
|
119
|
+
* refusal. See {@link TreeGuardRefusedError} for the contract every guard refusal shares.
|
|
120
|
+
*/
|
|
121
|
+
export declare class TreeKeyTakenError<TKey = unknown> extends TreeGuardRefusedError<TKey> {
|
|
122
|
+
constructor(collectionId: CollectionId,
|
|
61
123
|
/** The key some other writer already committed (for the `absentRange` subclass: the
|
|
62
124
|
* key this action was staging, whose claimed range a rival occupies). */
|
|
63
125
|
key: TKey,
|
|
@@ -88,4 +150,50 @@ export declare class TreeRangeTakenError<TKey = unknown> extends TreeKeyTakenErr
|
|
|
88
150
|
/** The committed key found inside `range` that is not `key`. */
|
|
89
151
|
occupant: TKey);
|
|
90
152
|
}
|
|
153
|
+
/**
|
|
154
|
+
* The {@link TreeUnchangedGuard} refusal: the entry at `key` is no longer the one the staged
|
|
155
|
+
* write read — a rival committed a different entry there, or removed it (`actual` is
|
|
156
|
+
* `undefined`). A lost update, NOT a uniqueness violation, which is why this deliberately does
|
|
157
|
+
* NOT subclass {@link TreeKeyTakenError}: the Quereus bridge renders every `TreeKeyTakenError`
|
|
158
|
+
* as that collection's registered `UNIQUE constraint failed` message (`mapCommitRefusal` in
|
|
159
|
+
* `packages/quereus-plugin-optimystic/src/optimystic-adapter/txn-bridge.ts`), and reporting a
|
|
160
|
+
* concurrent-update refusal as a uniqueness failure would mislead every client that reads it.
|
|
161
|
+
* The shared contract lives on {@link TreeGuardRefusedError}.
|
|
162
|
+
*/
|
|
163
|
+
export declare class TreeEntryChangedError<TKey = unknown, TEntry = unknown> extends TreeGuardRefusedError<TKey> {
|
|
164
|
+
/** The entry image the staged write read, as carried by its guard. */
|
|
165
|
+
readonly expected: TEntry;
|
|
166
|
+
/** What is committed at `key` now; `undefined` when the entry is gone entirely. */
|
|
167
|
+
readonly actual: TEntry | undefined;
|
|
168
|
+
constructor(collectionId: CollectionId,
|
|
169
|
+
/** The key whose entry the staged write was replacing or deleting. */
|
|
170
|
+
key: TKey,
|
|
171
|
+
/** The entry image the staged write read, as carried by its guard. */
|
|
172
|
+
expected: TEntry,
|
|
173
|
+
/** What is committed at `key` now; `undefined` when the entry is gone entirely. */
|
|
174
|
+
actual: TEntry | undefined);
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* A DELETE element carries a guard kind no delete can act on. NOT a concurrency refusal and
|
|
178
|
+
* deliberately not a {@link TreeGuardRefusedError}: every other kind asserts that nothing is
|
|
179
|
+
* present, which would make the delete a no-op by construction, so this is a malformed action —
|
|
180
|
+
* a caller bug, or a log entry written by a build whose element types disagree with this one.
|
|
181
|
+
* The handler raises it rather than ignoring the guard (the pre-guard behaviour) so a writer
|
|
182
|
+
* never believes an unenforceable guard is being enforced.
|
|
183
|
+
*/
|
|
184
|
+
export declare class TreeDeleteGuardKindError<TKey = unknown> extends Error {
|
|
185
|
+
/** The collection whose tree rejected the element. */
|
|
186
|
+
readonly collectionId: CollectionId;
|
|
187
|
+
/** The key the malformed delete named. */
|
|
188
|
+
readonly key: TKey;
|
|
189
|
+
/** The `kind` that was carried; only `'unchanged'` is meaningful on a delete. */
|
|
190
|
+
readonly guardKind: string;
|
|
191
|
+
constructor(
|
|
192
|
+
/** The collection whose tree rejected the element. */
|
|
193
|
+
collectionId: CollectionId,
|
|
194
|
+
/** The key the malformed delete named. */
|
|
195
|
+
key: TKey,
|
|
196
|
+
/** The `kind` that was carried; only `'unchanged'` is meaningful on a delete. */
|
|
197
|
+
guardKind: string);
|
|
198
|
+
}
|
|
91
199
|
//# sourceMappingURL=struct.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"struct.d.ts","sourceRoot":"","sources":["../../../../src/collections/tree/struct.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAKrD,eAAO,MAAM,mBAAmB,QAA8C,CAAC;AAO/E,MAAM,MAAM,yBAAyB,GAAG,qBAAqB,GAAG;IAC/D,MAAM,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,eAAO,MAAM,OAAO,QAA8C,CAAC;AAEnE
|
|
1
|
+
{"version":3,"file":"struct.d.ts","sourceRoot":"","sources":["../../../../src/collections/tree/struct.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,27 +8,47 @@ registerCollectionType({
|
|
|
8
8
|
});
|
|
9
9
|
export const rootId$ = nameof("rootId");
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
11
|
+
* Base of every refusal a {@link TreeEntryGuard} raises out of the tree `replace` handler — at
|
|
12
|
+
* initial staging, or (the load-bearing case) at conflict replay after a rival writer's commit
|
|
13
|
+
* was adopted. One contract, stated once for every subclass:
|
|
14
|
+
*
|
|
15
|
+
* - The throw **discards the whole action's staged writes** — the handler runs inside an
|
|
16
|
+
* all-or-nothing Atomic wrapper, so not one entry of a multi-entry action lands.
|
|
17
|
+
* - It is **not a `StaleFailure`**, so neither `Collection.sync`'s retry loop nor
|
|
18
|
+
* `TransactionCoordinator.commit`'s stale-loss re-drive absorbs it; it propagates out of the
|
|
19
|
+
* losing commit, and it must never be downgraded to a retryable condition.
|
|
20
|
+
*
|
|
21
|
+
* Subclasses split by WHAT was refused, because consumers map them differently: a
|
|
22
|
+
* {@link TreeKeyTakenError} is a uniqueness violation (the Quereus bridge renders it as
|
|
23
|
+
* `UNIQUE constraint failed`), while a {@link TreeEntryChangedError} is a lost update. Catch
|
|
24
|
+
* this base to treat any guard refusal uniformly; catch a subclass to say which happened.
|
|
17
25
|
*/
|
|
18
|
-
export class
|
|
26
|
+
export class TreeGuardRefusedError extends Error {
|
|
19
27
|
collectionId;
|
|
20
28
|
key;
|
|
21
29
|
constructor(
|
|
22
30
|
/** The collection whose tree refused the entry. */
|
|
23
31
|
collectionId,
|
|
32
|
+
/** The key whose staged entry was refused. */
|
|
33
|
+
key, message) {
|
|
34
|
+
super(message);
|
|
35
|
+
this.collectionId = collectionId;
|
|
36
|
+
this.key = key;
|
|
37
|
+
this.name = 'TreeGuardRefusedError';
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Thrown when an entry guarded `absent` finds its key already present: a duplicate-key
|
|
42
|
+
* refusal. See {@link TreeGuardRefusedError} for the contract every guard refusal shares.
|
|
43
|
+
*/
|
|
44
|
+
export class TreeKeyTakenError extends TreeGuardRefusedError {
|
|
45
|
+
constructor(collectionId,
|
|
24
46
|
/** The key some other writer already committed (for the `absentRange` subclass: the
|
|
25
47
|
* key this action was staging, whose claimed range a rival occupies). */
|
|
26
48
|
key,
|
|
27
49
|
/** Subclass override of the rendered message; the default names the exact-key refusal. */
|
|
28
50
|
message) {
|
|
29
|
-
super(message ?? `Tree collection ${collectionId}: key ${renderKey(key)} is already taken by a committed entry`);
|
|
30
|
-
this.collectionId = collectionId;
|
|
31
|
-
this.key = key;
|
|
51
|
+
super(collectionId, key, message ?? `Tree collection ${collectionId}: key ${renderKey(key)} is already taken by a committed entry`);
|
|
32
52
|
this.name = 'TreeKeyTakenError';
|
|
33
53
|
}
|
|
34
54
|
}
|
|
@@ -60,9 +80,64 @@ export class TreeRangeTakenError extends TreeKeyTakenError {
|
|
|
60
80
|
this.name = 'TreeRangeTakenError';
|
|
61
81
|
}
|
|
62
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* The {@link TreeUnchangedGuard} refusal: the entry at `key` is no longer the one the staged
|
|
85
|
+
* write read — a rival committed a different entry there, or removed it (`actual` is
|
|
86
|
+
* `undefined`). A lost update, NOT a uniqueness violation, which is why this deliberately does
|
|
87
|
+
* NOT subclass {@link TreeKeyTakenError}: the Quereus bridge renders every `TreeKeyTakenError`
|
|
88
|
+
* as that collection's registered `UNIQUE constraint failed` message (`mapCommitRefusal` in
|
|
89
|
+
* `packages/quereus-plugin-optimystic/src/optimystic-adapter/txn-bridge.ts`), and reporting a
|
|
90
|
+
* concurrent-update refusal as a uniqueness failure would mislead every client that reads it.
|
|
91
|
+
* The shared contract lives on {@link TreeGuardRefusedError}.
|
|
92
|
+
*/
|
|
93
|
+
export class TreeEntryChangedError extends TreeGuardRefusedError {
|
|
94
|
+
expected;
|
|
95
|
+
actual;
|
|
96
|
+
constructor(collectionId,
|
|
97
|
+
/** The key whose entry the staged write was replacing or deleting. */
|
|
98
|
+
key,
|
|
99
|
+
/** The entry image the staged write read, as carried by its guard. */
|
|
100
|
+
expected,
|
|
101
|
+
/** What is committed at `key` now; `undefined` when the entry is gone entirely. */
|
|
102
|
+
actual) {
|
|
103
|
+
super(collectionId, key, `Tree collection ${collectionId}: the entry at key ${renderKey(key)} was `
|
|
104
|
+
+ `${actual === undefined ? 'removed' : 'changed'} by another writer since this change read it`);
|
|
105
|
+
this.expected = expected;
|
|
106
|
+
this.actual = actual;
|
|
107
|
+
this.name = 'TreeEntryChangedError';
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* A DELETE element carries a guard kind no delete can act on. NOT a concurrency refusal and
|
|
112
|
+
* deliberately not a {@link TreeGuardRefusedError}: every other kind asserts that nothing is
|
|
113
|
+
* present, which would make the delete a no-op by construction, so this is a malformed action —
|
|
114
|
+
* a caller bug, or a log entry written by a build whose element types disagree with this one.
|
|
115
|
+
* The handler raises it rather than ignoring the guard (the pre-guard behaviour) so a writer
|
|
116
|
+
* never believes an unenforceable guard is being enforced.
|
|
117
|
+
*/
|
|
118
|
+
export class TreeDeleteGuardKindError extends Error {
|
|
119
|
+
collectionId;
|
|
120
|
+
key;
|
|
121
|
+
guardKind;
|
|
122
|
+
constructor(
|
|
123
|
+
/** The collection whose tree rejected the element. */
|
|
124
|
+
collectionId,
|
|
125
|
+
/** The key the malformed delete named. */
|
|
126
|
+
key,
|
|
127
|
+
/** The `kind` that was carried; only `'unchanged'` is meaningful on a delete. */
|
|
128
|
+
guardKind) {
|
|
129
|
+
super(`Tree collection ${collectionId}: the delete of key ${renderKey(key)} carries a `
|
|
130
|
+
+ `'${guardKind}' guard; only 'unchanged' is meaningful on a delete`);
|
|
131
|
+
this.collectionId = collectionId;
|
|
132
|
+
this.key = key;
|
|
133
|
+
this.guardKind = guardKind;
|
|
134
|
+
this.name = 'TreeDeleteGuardKindError';
|
|
135
|
+
}
|
|
136
|
+
}
|
|
63
137
|
/** String keys render JSON-quoted so framing control bytes stay visible/escaped in logs;
|
|
64
138
|
* everything else via String() — JSON.stringify would throw on a bigint key, and an error
|
|
65
|
-
* constructor must never be the second failure.
|
|
139
|
+
* constructor must never be the second failure. Module-private on purpose: every tree message
|
|
140
|
+
* renders a key the same way because every one of them is constructed in this file. */
|
|
66
141
|
function renderKey(key) {
|
|
67
142
|
return typeof key === 'string' ? JSON.stringify(key) : String(key);
|
|
68
143
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"struct.js","sourceRoot":"","sources":["../../../../src/collections/tree/struct.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAAE,MAAM,8CAA8C,CAAC;AACtF,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAEjD,MAAM,CAAC,MAAM,mBAAmB,GAAG,iBAAiB,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC;AAE/E,sBAAsB,CAAC;IACtB,SAAS,EAAE,mBAAmB;IAC9B,IAAI,EAAE,MAAM;CACZ,CAAC,CAAC;AAMH,MAAM,CAAC,MAAM,OAAO,GAAG,MAAM,CAA4B,QAAQ,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"struct.js","sourceRoot":"","sources":["../../../../src/collections/tree/struct.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Collection, type CollectionId, type CollectionSnapshot, type ReadViewOptions } from "../../collection/index.js";
|
|
2
|
-
import type { ITransactor, ActionId } from "../../index.js";
|
|
2
|
+
import type { ITransactor, ActionId, WriteDurability } from "../../index.js";
|
|
3
3
|
import { type Path, type KeyRange } from "../../btree/index.js";
|
|
4
4
|
import { type TreeReplaceAction } from "./struct.js";
|
|
5
5
|
/**
|
|
@@ -52,7 +52,17 @@ export declare class Tree<TKey, TEntry> implements TreeReadView<TKey, TEntry> {
|
|
|
52
52
|
* over the collection's existing tracker. Either way the result is written back into `held` so
|
|
53
53
|
* the `replace` handler's path-invalidation targets the very btree reads go through. */
|
|
54
54
|
private static attach;
|
|
55
|
-
|
|
55
|
+
/** Stage a mutation and flush it. Forwards the collection's answer verbatim — see
|
|
56
|
+
* {@link Collection.sync} for what `undefined` means and why a torn commit's `torn` list must
|
|
57
|
+
* survive the trip. This layer never interprets the value.
|
|
58
|
+
*
|
|
59
|
+
* A call that throws leaves nothing staged (see {@link Collection.actAndSync}), so the mutation
|
|
60
|
+
* cannot ride along with a later `replace`. Whether it reached STORAGE is what the error says:
|
|
61
|
+
* a `TornActionError` with `final: true` means it did not and submitting it again stores it
|
|
62
|
+
* once; `final: false` means that could not be established. A `SyncRetryExhaustedError` is not
|
|
63
|
+
* a promise either way — the write path's last budgeted attempt, and a deadline, are not
|
|
64
|
+
* followed by the refresh that would have settled it (see `Collection.syncAttempts`). */
|
|
65
|
+
replace(data: TreeReplaceAction<TKey, TEntry>): Promise<WriteDurability | undefined>;
|
|
56
66
|
/** Stage a mutation into the collection's tracker WITHOUT flushing it to the
|
|
57
67
|
* transactor. Reads through this same Tree instance see the staged change;
|
|
58
68
|
* call {@link sync} to persist it, or {@link snapshot}/{@link restore} to drop it. This
|
|
@@ -62,7 +72,7 @@ export declare class Tree<TKey, TEntry> implements TreeReadView<TKey, TEntry> {
|
|
|
62
72
|
stage(data: TreeReplaceAction<TKey, TEntry>): Promise<void>;
|
|
63
73
|
/** Flush all staged (and any other pending) changes to the transactor.
|
|
64
74
|
* Equivalent to the flush half of {@link replace}. */
|
|
65
|
-
sync(): Promise<
|
|
75
|
+
sync(): Promise<WriteDurability | undefined>;
|
|
66
76
|
/** Whether {@link sync} has anything to push — see
|
|
67
77
|
* {@link Collection.hasUnsyncedChanges}. `false` means the commit half of
|
|
68
78
|
* {@link sync} is a no-op, so a caller flushing several trees can skip the ones
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tree.d.ts","sourceRoot":"","sources":["../../../../src/collections/tree/tree.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAA8B,KAAK,YAAY,EAAE,KAAK,kBAAkB,EAAE,KAAK,eAAe,EAAE,MAAM,2BAA2B,CAAC;AACrJ,OAAO,KAAK,EAAE,WAAW,EAA+B,QAAQ,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"tree.d.ts","sourceRoot":"","sources":["../../../../src/collections/tree/tree.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,69 @@
|
|
|
1
1
|
import { Collection } from "../../collection/index.js";
|
|
2
2
|
import { BTree } from "../../btree/index.js";
|
|
3
3
|
import { CollectionTrunk } from "./collection-trunk.js";
|
|
4
|
-
import {
|
|
4
|
+
import { structuralEquals } from "../../utility/structural-equals.js";
|
|
5
|
+
import { TreeHeaderBlockType, TreeDeleteGuardKindError, TreeEntryChangedError, TreeKeyTakenError, TreeRangeTakenError, } from "./struct.js";
|
|
6
|
+
/**
|
|
7
|
+
* Enforce a guard carried by an UPSERT element against the CURRENT content of `actionTree` —
|
|
8
|
+
* the same Atomic store the upsert writes to, so it sees what earlier elements of this same
|
|
9
|
+
* replay already staged or deleted (an UPDATE's delete-old half runs before its guarded insert
|
|
10
|
+
* half). Throws the guard's refusal, which discards the whole action's staged writes.
|
|
11
|
+
*
|
|
12
|
+
* @returns `'skip'` when the element must be left unwritten (`keepExisting` found the key
|
|
13
|
+
* occupied — the INSERT OR IGNORE disposition), `'proceed'` otherwise.
|
|
14
|
+
*/
|
|
15
|
+
async function enforceUpsertGuard(actionTree, id, key, guard, keyFromEntry, compare) {
|
|
16
|
+
switch (guard.kind) {
|
|
17
|
+
case 'absentRange': {
|
|
18
|
+
// Secondary-UNIQUE: the claimed range (a unique index's framed value prefix) must hold
|
|
19
|
+
// no entry other than this action's own key. Two short descents (range start and end)
|
|
20
|
+
// plus an early-exit walk. The guard is plain data (it is serialized into the log with
|
|
21
|
+
// its action), and BTree.range reads the range's fields only — so a KeyRange that has
|
|
22
|
+
// round-tripped through JSON is scanned exactly like a live instance.
|
|
23
|
+
for await (const path of actionTree.range(guard.range)) {
|
|
24
|
+
const occupant = actionTree.at(path);
|
|
25
|
+
if (occupant === undefined)
|
|
26
|
+
continue;
|
|
27
|
+
const occupantKey = keyFromEntry(occupant);
|
|
28
|
+
if (compare(occupantKey, key) === 0)
|
|
29
|
+
continue; // self-exclusion
|
|
30
|
+
throw new TreeRangeTakenError(id, key, guard.range, occupantKey);
|
|
31
|
+
}
|
|
32
|
+
return 'proceed';
|
|
33
|
+
}
|
|
34
|
+
case 'unchanged': {
|
|
35
|
+
assertEntryUnchanged(id, key, guard.expected, actionTree.at(await actionTree.find(key)));
|
|
36
|
+
return 'proceed';
|
|
37
|
+
}
|
|
38
|
+
case 'absent':
|
|
39
|
+
case 'keepExisting': {
|
|
40
|
+
if (!(await actionTree.find(key)).on)
|
|
41
|
+
return 'proceed';
|
|
42
|
+
if (guard.kind === 'absent')
|
|
43
|
+
throw new TreeKeyTakenError(id, key);
|
|
44
|
+
// keepExisting: leave the present (rival's) entry in place and skip this element.
|
|
45
|
+
return 'skip';
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/** The lost-update check shared by guarded upserts and guarded deletes: the committed entry must
|
|
50
|
+
* be present AND structurally equal to what the staged write read. Absence counts as changed —
|
|
51
|
+
* see {@link TreeUnchangedGuard} for why that is the contract on both dispositions. */
|
|
52
|
+
function assertEntryUnchanged(id, key, expected, actual) {
|
|
53
|
+
if (actual === undefined || !structuralEquals(actual, expected)) {
|
|
54
|
+
throw new TreeEntryChangedError(id, key, expected, actual);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/** Narrow a DELETE element's guard to the only kind a delete can act on. The element type already
|
|
58
|
+
* says this ({@link TreeDeleteElement}), but a replayed log entry is deserialized data that no
|
|
59
|
+
* type policed, so the handler re-checks it and throws {@link TreeDeleteGuardKindError} rather
|
|
60
|
+
* than silently ignoring a guard the writer believed was being enforced. */
|
|
61
|
+
function deleteGuardExpected(id, key, guard) {
|
|
62
|
+
if (guard.kind !== 'unchanged') {
|
|
63
|
+
throw new TreeDeleteGuardKindError(id, key, guard.kind);
|
|
64
|
+
}
|
|
65
|
+
return guard.expected;
|
|
66
|
+
}
|
|
5
67
|
export class Tree {
|
|
6
68
|
collection;
|
|
7
69
|
btree;
|
|
@@ -59,48 +121,43 @@ export class Tree {
|
|
|
59
121
|
// public constructor; no btree API change needed.
|
|
60
122
|
const actionTree = new BTree(trx, new CollectionTrunk(trx, id), keyFromEntry, compare, nodeCapacity);
|
|
61
123
|
for (const [key, entry, guard] of actions) {
|
|
124
|
+
// NOTE: an element is a DELETE when its entry slot is falsy, not when it is
|
|
125
|
+
// strictly `undefined`. That is deliberate and load-bearing: JSON encodes the
|
|
126
|
+
// empty slot of `[key, undefined]` as `null`, so a replayed log entry arrives
|
|
127
|
+
// as `[key, null]` and a `!== undefined` test would upsert `null` over the row.
|
|
128
|
+
// JSON really is the live encoding, not just a hypothetical: the p2p repo
|
|
129
|
+
// protocol stringifies and parses every message (`protocol-client.ts` and
|
|
130
|
+
// `repo/service.ts` in `packages/db-p2p/src/`). The in-process test transactors
|
|
131
|
+
// use `structuredClone`, which preserves `undefined` — so no test that goes
|
|
132
|
+
// only through them can reach this shape; the round-trip spec below stages the
|
|
133
|
+
// JSON shape explicitly for that reason.
|
|
134
|
+
// The cost is that a falsy-but-real entry (`''`, `0`, `false`) reads as a
|
|
135
|
+
// delete. No entry type in this repo is falsy today (rows encode to a non-empty
|
|
136
|
+
// string or Uint8Array; index entries are arrays); if one ever is, this needs an
|
|
137
|
+
// explicit delete marker in the tuple rather than a tighter comparison.
|
|
62
138
|
if (entry) {
|
|
63
139
|
// Enforce the entry's guard (if any) on EVERY handler run — initial staging
|
|
64
|
-
// and every conflict replay — so the
|
|
65
|
-
//
|
|
66
|
-
//
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
// delete-old half runs before its guarded insert half). The guard
|
|
75
|
-
// is plain data (it is serialized into the log with its action), and
|
|
76
|
-
// BTree.range reads the range's fields only — so a KeyRange that has
|
|
77
|
-
// round-tripped through JSON is scanned exactly like a live instance.
|
|
78
|
-
for await (const path of actionTree.range(guard.range)) {
|
|
79
|
-
const occupant = actionTree.at(path);
|
|
80
|
-
if (occupant === undefined)
|
|
81
|
-
continue;
|
|
82
|
-
const occupantKey = keyFromEntry(occupant);
|
|
83
|
-
if (compare(occupantKey, key) === 0)
|
|
84
|
-
continue; // self-exclusion
|
|
85
|
-
throw new TreeRangeTakenError(id, key, guard.range, occupantKey);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
else {
|
|
89
|
-
const found = await actionTree.find(key);
|
|
90
|
-
if (found.on) {
|
|
91
|
-
if (guard.kind === 'absent') {
|
|
92
|
-
throw new TreeKeyTakenError(id, key);
|
|
93
|
-
}
|
|
94
|
-
// keepExisting: leave the present (rival's) entry in place and
|
|
95
|
-
// skip this entry silently — the INSERT OR IGNORE disposition.
|
|
96
|
-
continue;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
140
|
+
// and every conflict replay — so the decision is re-made against the newest
|
|
141
|
+
// adopted committed state, not just the stage-time snapshot. A throw here
|
|
142
|
+
// discards the whole action's staged writes (Atomic wrapper).
|
|
143
|
+
// Truthiness, not `!== undefined`, for the same round-trip reason as the entry
|
|
144
|
+
// slot above: an explicitly-passed `undefined` guard (the shape every unguarded
|
|
145
|
+
// index write stages) comes back from JSON as `null`, and reading `.kind` off it
|
|
146
|
+
// would throw a TypeError mid-replay instead of meaning "no guard".
|
|
147
|
+
if (guard
|
|
148
|
+
&& await enforceUpsertGuard(actionTree, id, key, guard, keyFromEntry, compare) === 'skip') {
|
|
149
|
+
continue;
|
|
99
150
|
}
|
|
100
151
|
await actionTree.upsert(entry);
|
|
101
152
|
}
|
|
102
153
|
else {
|
|
103
|
-
|
|
154
|
+
// The path is found once and reused: the guard check reads it and `deleteAt`
|
|
155
|
+
// consumes it, with no mutation in between to invalidate it.
|
|
156
|
+
const path = await actionTree.find(key);
|
|
157
|
+
if (guard) {
|
|
158
|
+
assertEntryUnchanged(id, key, deleteGuardExpected(id, key, guard), actionTree.at(path));
|
|
159
|
+
}
|
|
160
|
+
await actionTree.deleteAt(path);
|
|
104
161
|
}
|
|
105
162
|
}
|
|
106
163
|
// Mutations landed in `trx`, not the read btree, so its version counter never moved.
|
|
@@ -133,9 +190,18 @@ export class Tree {
|
|
|
133
190
|
?? new BTree(collection.tracker, new CollectionTrunk(collection.tracker, collection.id), keyFromEntry, compare, nodeCapacity);
|
|
134
191
|
return new Tree(collection, held.btree, keyFromEntry, compare);
|
|
135
192
|
}
|
|
193
|
+
/** Stage a mutation and flush it. Forwards the collection's answer verbatim — see
|
|
194
|
+
* {@link Collection.sync} for what `undefined` means and why a torn commit's `torn` list must
|
|
195
|
+
* survive the trip. This layer never interprets the value.
|
|
196
|
+
*
|
|
197
|
+
* A call that throws leaves nothing staged (see {@link Collection.actAndSync}), so the mutation
|
|
198
|
+
* cannot ride along with a later `replace`. Whether it reached STORAGE is what the error says:
|
|
199
|
+
* a `TornActionError` with `final: true` means it did not and submitting it again stores it
|
|
200
|
+
* once; `final: false` means that could not be established. A `SyncRetryExhaustedError` is not
|
|
201
|
+
* a promise either way — the write path's last budgeted attempt, and a deadline, are not
|
|
202
|
+
* followed by the refresh that would have settled it (see `Collection.syncAttempts`). */
|
|
136
203
|
async replace(data) {
|
|
137
|
-
await this.collection.
|
|
138
|
-
await this.collection.updateAndSync();
|
|
204
|
+
return await this.collection.actAndSync([{ type: "replace", data }]);
|
|
139
205
|
}
|
|
140
206
|
/** Stage a mutation into the collection's tracker WITHOUT flushing it to the
|
|
141
207
|
* transactor. Reads through this same Tree instance see the staged change;
|
|
@@ -149,7 +215,7 @@ export class Tree {
|
|
|
149
215
|
/** Flush all staged (and any other pending) changes to the transactor.
|
|
150
216
|
* Equivalent to the flush half of {@link replace}. */
|
|
151
217
|
async sync() {
|
|
152
|
-
await this.collection.updateAndSync();
|
|
218
|
+
return await this.collection.updateAndSync();
|
|
153
219
|
}
|
|
154
220
|
/** Whether {@link sync} has anything to push — see
|
|
155
221
|
* {@link Collection.hasUnsyncedChanges}. `false` means the commit half of
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tree.js","sourceRoot":"","sources":["../../../../src/collections/tree/tree.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAgG,MAAM,2BAA2B,CAAC;AAErJ,OAAO,EAAE,KAAK,EAA4B,MAAM,sBAAsB,CAAC;AACvE,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,
|
|
1
|
+
{"version":3,"file":"tree.js","sourceRoot":"","sources":["../../../../src/collections/tree/tree.ts"],"names":[],"mappings":"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"}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -18,9 +18,9 @@ export * from "./utility/groupby.js";
|
|
|
18
18
|
export * from "./utility/hash-string.js";
|
|
19
19
|
export * from "./utility/latches.js";
|
|
20
20
|
export * from "./utility/nameof.js";
|
|
21
|
+
export * from "./utility/structural-equals.js";
|
|
21
22
|
export * from "./utility/ensured.js";
|
|
22
23
|
export * from "./utility/pending.js";
|
|
23
|
-
export * from "./utility/block-id-to-bytes.js";
|
|
24
24
|
export * from "./utility/lru-map.js";
|
|
25
25
|
export * from "./utility/backoff.js";
|
|
26
26
|
//# sourceMappingURL=index.d.ts.map
|