@optimystic/db-core 0.14.1 → 0.16.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/blocks/block-store.d.ts +18 -1
- package/dist/src/blocks/block-store.d.ts.map +1 -1
- package/dist/src/blocks/helpers.d.ts +2 -2
- package/dist/src/blocks/helpers.d.ts.map +1 -1
- package/dist/src/blocks/helpers.js +2 -2
- package/dist/src/blocks/helpers.js.map +1 -1
- package/dist/src/btree/btree.d.ts +27 -6
- package/dist/src/btree/btree.d.ts.map +1 -1
- package/dist/src/btree/btree.js +104 -61
- package/dist/src/btree/btree.js.map +1 -1
- package/dist/src/chain/chain.d.ts.map +1 -1
- package/dist/src/chain/chain.js +11 -1
- package/dist/src/chain/chain.js.map +1 -1
- package/dist/src/cluster/index.d.ts +1 -0
- package/dist/src/cluster/index.d.ts.map +1 -1
- package/dist/src/cluster/index.js +1 -0
- package/dist/src/cluster/index.js.map +1 -1
- package/dist/src/cluster/membership.d.ts +49 -0
- package/dist/src/cluster/membership.d.ts.map +1 -0
- package/dist/src/cluster/membership.js +75 -0
- package/dist/src/cluster/membership.js.map +1 -0
- package/dist/src/cluster/structs.d.ts +50 -1
- package/dist/src/cluster/structs.d.ts.map +1 -1
- package/dist/src/cluster/structs.js +9 -1
- package/dist/src/cluster/structs.js.map +1 -1
- package/dist/src/cohort-topic/addressing.d.ts +8 -2
- package/dist/src/cohort-topic/addressing.d.ts.map +1 -1
- package/dist/src/cohort-topic/addressing.js +11 -3
- package/dist/src/cohort-topic/addressing.js.map +1 -1
- package/dist/src/cohort-topic/antidos/bootstrap-evidence.d.ts +13 -7
- package/dist/src/cohort-topic/antidos/bootstrap-evidence.d.ts.map +1 -1
- package/dist/src/cohort-topic/antidos/bootstrap-evidence.js +17 -6
- package/dist/src/cohort-topic/antidos/bootstrap-evidence.js.map +1 -1
- package/dist/src/cohort-topic/antidos/replay-guard.d.ts +17 -0
- package/dist/src/cohort-topic/antidos/replay-guard.d.ts.map +1 -1
- package/dist/src/cohort-topic/antidos/replay-guard.js +33 -0
- package/dist/src/cohort-topic/antidos/replay-guard.js.map +1 -1
- package/dist/src/cohort-topic/antidos/topic-budget.d.ts +7 -0
- package/dist/src/cohort-topic/antidos/topic-budget.d.ts.map +1 -1
- package/dist/src/cohort-topic/antidos/topic-budget.js +8 -2
- package/dist/src/cohort-topic/antidos/topic-budget.js.map +1 -1
- package/dist/src/cohort-topic/coldstart.d.ts +34 -14
- package/dist/src/cohort-topic/coldstart.d.ts.map +1 -1
- package/dist/src/cohort-topic/coldstart.js +25 -11
- package/dist/src/cohort-topic/coldstart.js.map +1 -1
- package/dist/src/cohort-topic/gossip/bus.d.ts +12 -1
- package/dist/src/cohort-topic/gossip/bus.d.ts.map +1 -1
- package/dist/src/cohort-topic/gossip/bus.js +27 -1
- package/dist/src/cohort-topic/gossip/bus.js.map +1 -1
- package/dist/src/cohort-topic/gossip/view.d.ts +8 -0
- package/dist/src/cohort-topic/gossip/view.d.ts.map +1 -1
- package/dist/src/cohort-topic/gossip/view.js +17 -1
- package/dist/src/cohort-topic/gossip/view.js.map +1 -1
- package/dist/src/cohort-topic/member-engine.d.ts +10 -3
- package/dist/src/cohort-topic/member-engine.d.ts.map +1 -1
- package/dist/src/cohort-topic/member-engine.js +29 -14
- package/dist/src/cohort-topic/member-engine.js.map +1 -1
- package/dist/src/cohort-topic/membership/publisher.d.ts +14 -7
- package/dist/src/cohort-topic/membership/publisher.d.ts.map +1 -1
- package/dist/src/cohort-topic/membership/publisher.js +15 -27
- package/dist/src/cohort-topic/membership/publisher.js.map +1 -1
- package/dist/src/cohort-topic/membership/verifier.d.ts +35 -0
- package/dist/src/cohort-topic/membership/verifier.d.ts.map +1 -1
- package/dist/src/cohort-topic/membership/verifier.js +88 -3
- package/dist/src/cohort-topic/membership/verifier.js.map +1 -1
- package/dist/src/cohort-topic/promotion.d.ts +7 -0
- package/dist/src/cohort-topic/promotion.d.ts.map +1 -1
- package/dist/src/cohort-topic/promotion.js +16 -2
- package/dist/src/cohort-topic/promotion.js.map +1 -1
- package/dist/src/cohort-topic/registration/renewal.d.ts +18 -0
- package/dist/src/cohort-topic/registration/renewal.d.ts.map +1 -1
- package/dist/src/cohort-topic/registration/renewal.js +54 -0
- package/dist/src/cohort-topic/registration/renewal.js.map +1 -1
- package/dist/src/cohort-topic/registration/types.d.ts +12 -0
- package/dist/src/cohort-topic/registration/types.d.ts.map +1 -1
- package/dist/src/cohort-topic/registration/types.js +14 -0
- package/dist/src/cohort-topic/registration/types.js.map +1 -1
- package/dist/src/cohort-topic/service.d.ts +4 -3
- package/dist/src/cohort-topic/service.d.ts.map +1 -1
- package/dist/src/cohort-topic/service.js +38 -12
- package/dist/src/cohort-topic/service.js.map +1 -1
- package/dist/src/cohort-topic/sig/payloads.d.ts +23 -7
- package/dist/src/cohort-topic/sig/payloads.d.ts.map +1 -1
- package/dist/src/cohort-topic/sig/payloads.js +22 -6
- package/dist/src/cohort-topic/sig/payloads.js.map +1 -1
- package/dist/src/cohort-topic/traffic.d.ts +6 -0
- package/dist/src/cohort-topic/traffic.d.ts.map +1 -1
- package/dist/src/cohort-topic/traffic.js +16 -1
- package/dist/src/cohort-topic/traffic.js.map +1 -1
- package/dist/src/cohort-topic/walk.d.ts +22 -7
- package/dist/src/cohort-topic/walk.d.ts.map +1 -1
- package/dist/src/cohort-topic/walk.js +78 -18
- package/dist/src/cohort-topic/walk.js.map +1 -1
- package/dist/src/cohort-topic/wire/codec.d.ts +3 -1
- package/dist/src/cohort-topic/wire/codec.d.ts.map +1 -1
- package/dist/src/cohort-topic/wire/codec.js +7 -1
- package/dist/src/cohort-topic/wire/codec.js.map +1 -1
- package/dist/src/cohort-topic/wire/index.d.ts +1 -1
- package/dist/src/cohort-topic/wire/index.d.ts.map +1 -1
- package/dist/src/cohort-topic/wire/index.js +1 -1
- package/dist/src/cohort-topic/wire/index.js.map +1 -1
- package/dist/src/cohort-topic/wire/payloads.d.ts +5 -4
- package/dist/src/cohort-topic/wire/payloads.d.ts.map +1 -1
- package/dist/src/cohort-topic/wire/payloads.js +14 -5
- package/dist/src/cohort-topic/wire/payloads.js.map +1 -1
- package/dist/src/cohort-topic/wire/primitives.d.ts +65 -0
- package/dist/src/cohort-topic/wire/primitives.d.ts.map +1 -0
- package/dist/src/cohort-topic/wire/primitives.js +173 -0
- package/dist/src/cohort-topic/wire/primitives.js.map +1 -0
- package/dist/src/cohort-topic/wire/types.d.ts +132 -5
- package/dist/src/cohort-topic/wire/types.d.ts.map +1 -1
- package/dist/src/cohort-topic/wire/validate.d.ts +15 -5
- package/dist/src/cohort-topic/wire/validate.d.ts.map +1 -1
- package/dist/src/cohort-topic/wire/validate.js +146 -123
- package/dist/src/cohort-topic/wire/validate.js.map +1 -1
- package/dist/src/collection/collection.d.ts +23 -12
- package/dist/src/collection/collection.d.ts.map +1 -1
- package/dist/src/collection/collection.js +111 -35
- package/dist/src/collection/collection.js.map +1 -1
- package/dist/src/collection/struct.d.ts +37 -2
- package/dist/src/collection/struct.d.ts.map +1 -1
- package/dist/src/collection/struct.js +16 -1
- package/dist/src/collection/struct.js.map +1 -1
- package/dist/src/collections/tree/tree.d.ts +18 -1
- package/dist/src/collections/tree/tree.d.ts.map +1 -1
- package/dist/src/collections/tree/tree.js +36 -6
- package/dist/src/collections/tree/tree.js.map +1 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/log/log.d.ts +26 -3
- package/dist/src/log/log.d.ts.map +1 -1
- package/dist/src/log/log.js +34 -7
- package/dist/src/log/log.js.map +1 -1
- package/dist/src/log/struct.d.ts +5 -4
- package/dist/src/log/struct.d.ts.map +1 -1
- package/dist/src/log/struct.js.map +1 -1
- package/dist/src/matchmaking/wire.d.ts +2 -1
- package/dist/src/matchmaking/wire.d.ts.map +1 -1
- package/dist/src/matchmaking/wire.js +13 -92
- package/dist/src/matchmaking/wire.js.map +1 -1
- package/dist/src/network/i-key-network.d.ts +9 -0
- package/dist/src/network/i-key-network.d.ts.map +1 -1
- package/dist/src/network/i-repo.d.ts +8 -0
- package/dist/src/network/i-repo.d.ts.map +1 -1
- package/dist/src/network/struct.d.ts +10 -0
- package/dist/src/network/struct.d.ts.map +1 -1
- package/dist/src/reactivity/push-state.d.ts.map +1 -1
- package/dist/src/reactivity/push-state.js +4 -33
- package/dist/src/reactivity/push-state.js.map +1 -1
- package/dist/src/reactivity/wire-validate.d.ts +7 -22
- package/dist/src/reactivity/wire-validate.d.ts.map +1 -1
- package/dist/src/reactivity/wire-validate.js +7 -73
- package/dist/src/reactivity/wire-validate.js.map +1 -1
- package/dist/src/reactivity/wire.js +3 -3
- package/dist/src/reactivity/wire.js.map +1 -1
- package/dist/src/testing/async-wait.d.ts +23 -0
- package/dist/src/testing/async-wait.d.ts.map +1 -0
- package/dist/src/testing/async-wait.js +42 -0
- package/dist/src/testing/async-wait.js.map +1 -0
- package/dist/src/testing/index.d.ts +3 -0
- package/dist/src/testing/index.d.ts.map +1 -0
- package/dist/src/testing/index.js +3 -0
- package/dist/src/testing/index.js.map +1 -0
- package/dist/src/testing/test-transactor.d.ts +44 -0
- package/dist/src/testing/test-transactor.d.ts.map +1 -0
- package/dist/src/testing/test-transactor.js +423 -0
- package/dist/src/testing/test-transactor.js.map +1 -0
- package/dist/src/transaction/actions-engine.d.ts +6 -3
- package/dist/src/transaction/actions-engine.d.ts.map +1 -1
- package/dist/src/transaction/actions-engine.js +8 -7
- package/dist/src/transaction/actions-engine.js.map +1 -1
- package/dist/src/transaction/coordinator.d.ts +43 -22
- package/dist/src/transaction/coordinator.d.ts.map +1 -1
- package/dist/src/transaction/coordinator.js +443 -178
- package/dist/src/transaction/coordinator.js.map +1 -1
- package/dist/src/transaction/errors.d.ts +82 -0
- package/dist/src/transaction/errors.d.ts.map +1 -0
- package/dist/src/transaction/errors.js +93 -0
- package/dist/src/transaction/errors.js.map +1 -0
- package/dist/src/transaction/index.d.ts +6 -3
- package/dist/src/transaction/index.d.ts.map +1 -1
- package/dist/src/transaction/index.js +4 -2
- package/dist/src/transaction/index.js.map +1 -1
- package/dist/src/transaction/operations-hash.d.ts +119 -0
- package/dist/src/transaction/operations-hash.d.ts.map +1 -0
- package/dist/src/transaction/operations-hash.js +180 -0
- package/dist/src/transaction/operations-hash.js.map +1 -0
- package/dist/src/transaction/read-dependency-collector.d.ts +43 -0
- package/dist/src/transaction/read-dependency-collector.d.ts.map +1 -0
- package/dist/src/transaction/read-dependency-collector.js +69 -0
- package/dist/src/transaction/read-dependency-collector.js.map +1 -0
- package/dist/src/transaction/session.d.ts +12 -3
- package/dist/src/transaction/session.d.ts.map +1 -1
- package/dist/src/transaction/session.js +35 -9
- package/dist/src/transaction/session.js.map +1 -1
- package/dist/src/transaction/transaction.d.ts +162 -1
- package/dist/src/transaction/transaction.d.ts.map +1 -1
- package/dist/src/transaction/transaction.js +85 -3
- package/dist/src/transaction/transaction.js.map +1 -1
- package/dist/src/transaction/validator.d.ts +3 -11
- package/dist/src/transaction/validator.d.ts.map +1 -1
- package/dist/src/transaction/validator.js +69 -28
- package/dist/src/transaction/validator.js.map +1 -1
- package/dist/src/transactor/network-transactor.d.ts +35 -0
- package/dist/src/transactor/network-transactor.d.ts.map +1 -1
- package/dist/src/transactor/network-transactor.js +146 -40
- package/dist/src/transactor/network-transactor.js.map +1 -1
- package/dist/src/transactor/transactor-source.d.ts +19 -5
- package/dist/src/transactor/transactor-source.d.ts.map +1 -1
- package/dist/src/transactor/transactor-source.js +43 -11
- package/dist/src/transactor/transactor-source.js.map +1 -1
- package/dist/src/transform/atomic-proxy.d.ts +35 -5
- package/dist/src/transform/atomic-proxy.d.ts.map +1 -1
- package/dist/src/transform/atomic-proxy.js +39 -7
- package/dist/src/transform/atomic-proxy.js.map +1 -1
- package/dist/src/transform/cache-source.d.ts +36 -5
- package/dist/src/transform/cache-source.d.ts.map +1 -1
- package/dist/src/transform/cache-source.js +84 -8
- package/dist/src/transform/cache-source.js.map +1 -1
- package/dist/src/transform/helpers.d.ts.map +1 -1
- package/dist/src/transform/helpers.js +8 -2
- package/dist/src/transform/helpers.js.map +1 -1
- package/dist/src/transform/tracker.d.ts +17 -2
- package/dist/src/transform/tracker.d.ts.map +1 -1
- package/dist/src/transform/tracker.js +66 -11
- package/dist/src/transform/tracker.js.map +1 -1
- package/dist/src/utility/backoff.d.ts +48 -0
- package/dist/src/utility/backoff.d.ts.map +1 -0
- package/dist/src/utility/backoff.js +60 -0
- package/dist/src/utility/backoff.js.map +1 -0
- package/dist/src/utility/pending.d.ts +1 -0
- package/dist/src/utility/pending.d.ts.map +1 -1
- package/dist/src/utility/pending.js +3 -1
- package/dist/src/utility/pending.js.map +1 -1
- package/package.json +4 -4
- package/src/blocks/block-store.ts +19 -1
- package/src/blocks/helpers.ts +3 -3
- package/src/btree/btree.ts +108 -63
- package/src/chain/chain.ts +11 -1
- package/src/cluster/index.ts +1 -0
- package/src/cluster/membership.ts +85 -0
- package/src/cluster/structs.ts +51 -1
- package/src/cohort-topic/addressing.ts +12 -4
- package/src/cohort-topic/antidos/bootstrap-evidence.ts +21 -9
- package/src/cohort-topic/antidos/replay-guard.ts +37 -0
- package/src/cohort-topic/antidos/topic-budget.ts +17 -2
- package/src/cohort-topic/coldstart.ts +48 -15
- package/src/cohort-topic/gossip/bus.ts +39 -2
- package/src/cohort-topic/gossip/view.ts +26 -1
- package/src/cohort-topic/member-engine.ts +36 -15
- package/src/cohort-topic/membership/publisher.ts +25 -33
- package/src/cohort-topic/membership/verifier.ts +119 -3
- package/src/cohort-topic/promotion.ts +23 -2
- package/src/cohort-topic/registration/renewal.ts +73 -1
- package/src/cohort-topic/registration/types.ts +15 -0
- package/src/cohort-topic/service.ts +41 -15
- package/src/cohort-topic/sig/payloads.ts +29 -9
- package/src/cohort-topic/traffic.ts +23 -1
- package/src/cohort-topic/walk.ts +95 -24
- package/src/cohort-topic/wire/codec.ts +12 -0
- package/src/cohort-topic/wire/index.ts +2 -0
- package/src/cohort-topic/wire/payloads.ts +14 -5
- package/src/cohort-topic/wire/primitives.ts +188 -0
- package/src/cohort-topic/wire/types.ts +136 -4
- package/src/cohort-topic/wire/validate.ts +168 -134
- package/src/collection/collection.ts +123 -40
- package/src/collection/struct.ts +44 -2
- package/src/collections/tree/tree.ts +42 -5
- package/src/index.ts +1 -0
- package/src/log/log.ts +37 -9
- package/src/log/struct.ts +5 -4
- package/src/matchmaking/wire.ts +25 -102
- package/src/network/i-key-network.ts +10 -0
- package/src/network/i-repo.ts +8 -0
- package/src/network/struct.ts +10 -0
- package/src/reactivity/push-state.ts +4 -37
- package/src/reactivity/wire-validate.ts +7 -81
- package/src/reactivity/wire.ts +3 -3
- package/src/testing/async-wait.ts +65 -0
- package/src/testing/index.ts +2 -0
- package/src/testing/test-transactor.ts +468 -0
- package/src/transaction/actions-engine.ts +8 -6
- package/src/transaction/coordinator.ts +498 -229
- package/src/transaction/errors.ts +91 -0
- package/src/transaction/index.ts +23 -3
- package/src/transaction/operations-hash.ts +196 -0
- package/src/transaction/read-dependency-collector.ts +78 -0
- package/src/transaction/session.ts +37 -9
- package/src/transaction/transaction.ts +211 -4
- package/src/transaction/validator.ts +73 -48
- package/src/transactor/network-transactor.ts +164 -49
- package/src/transactor/transactor-source.ts +47 -12
- package/src/transform/atomic-proxy.ts +92 -49
- package/src/transform/cache-source.ts +87 -9
- package/src/transform/helpers.ts +8 -2
- package/src/transform/tracker.ts +69 -11
- package/src/utility/backoff.ts +95 -0
- package/src/utility/pending.ts +3 -1
- package/src/transaction/context.ts +0 -103
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
import { ensuredMap, Latches } from "../index.js";
|
|
2
|
+
import { applyTransform, blockIdsForTransforms, transformForBlockId, emptyTransforms, concatTransform, transformsFromTransform } from "../transform/index.js";
|
|
3
|
+
// Simple in-memory transactor for testing that maintains materialized blocks for every revision
|
|
4
|
+
export class TestTransactor {
|
|
5
|
+
blocks = new Map();
|
|
6
|
+
available = true;
|
|
7
|
+
getLocks = new Map(); // Track lock releases
|
|
8
|
+
constructor() { }
|
|
9
|
+
async get(blockGets) {
|
|
10
|
+
this.checkAvailable();
|
|
11
|
+
const results = {};
|
|
12
|
+
const uniqueBlockIds = [...new Set(blockGets.blockIds)].sort(); // Ensure consistent lock order if needed, though get is read-only
|
|
13
|
+
const releases = [];
|
|
14
|
+
try {
|
|
15
|
+
// Acquire locks for all requested blocks to ensure consistent read
|
|
16
|
+
for (const blockId of uniqueBlockIds) {
|
|
17
|
+
const lockId = `TestTransactor.commit:${blockId}`; // Use the same lock as commit
|
|
18
|
+
// Wait for any existing lock promise to resolve before acquiring the next
|
|
19
|
+
let release = await this.getLocks.get(lockId);
|
|
20
|
+
if (release)
|
|
21
|
+
await Promise.resolve(release); // Ensure previous lock released if overlapping calls happen
|
|
22
|
+
const releasePromise = Latches.acquire(lockId);
|
|
23
|
+
this.getLocks.set(blockId, releasePromise.then(r => () => {
|
|
24
|
+
r();
|
|
25
|
+
this.getLocks.delete(blockId); // Clean up map entry after release
|
|
26
|
+
}));
|
|
27
|
+
release = await releasePromise;
|
|
28
|
+
releases.push(release);
|
|
29
|
+
}
|
|
30
|
+
// --- Start of Critical Section (Read) ---
|
|
31
|
+
for (const blockId of blockGets.blockIds) {
|
|
32
|
+
const blockState = this.blocks.get(blockId);
|
|
33
|
+
if (!blockState) {
|
|
34
|
+
// Block doesn't exist yet
|
|
35
|
+
results[blockId] = {
|
|
36
|
+
block: undefined,
|
|
37
|
+
state: { latest: undefined, pendings: [] }
|
|
38
|
+
};
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
// Get the appropriate materialized block based on context
|
|
42
|
+
let block;
|
|
43
|
+
if (blockGets.context?.actionId !== undefined) {
|
|
44
|
+
// If requesting a specific action, apply pending transform if it exists
|
|
45
|
+
const pendingTransform = blockState.pendingActions.get(blockGets.context.actionId);
|
|
46
|
+
if (pendingTransform) {
|
|
47
|
+
// Read latest committed block as base for pending transform
|
|
48
|
+
const baseBlock = blockState.materializedBlocks.get(blockState.latestRev);
|
|
49
|
+
block = applyTransformSafe(baseBlock, pendingTransform);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
// Action not pending, maybe committed? Or maybe invalid actionId for context.
|
|
53
|
+
// For simplicity, return undefined block if specific pending action not found.
|
|
54
|
+
// A more complex impl might check committedActions history.
|
|
55
|
+
block = undefined;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
else if (blockGets.context?.committed) {
|
|
59
|
+
// Check context.committed for matching pending actions — mirrors coordinator
|
|
60
|
+
// behavior: context.committed proves the action succeeded, so pending blocks
|
|
61
|
+
// for that action should be served.
|
|
62
|
+
for (const { actionId: cId } of blockGets.context.committed) {
|
|
63
|
+
const pendingTransform = blockState.pendingActions.get(cId);
|
|
64
|
+
if (pendingTransform) {
|
|
65
|
+
const baseBlock = blockState.materializedBlocks.get(blockState.latestRev);
|
|
66
|
+
block = applyTransformSafe(baseBlock, pendingTransform);
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// Fall through to standard resolution if no pending match
|
|
71
|
+
if (block === undefined) {
|
|
72
|
+
if (blockGets.context.rev !== undefined) {
|
|
73
|
+
block = structuredClone(latestMaterializedAt(blockState, blockGets.context.rev));
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
block = structuredClone(blockState.materializedBlocks.get(blockState.latestRev));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
else if (blockGets.context?.rev !== undefined) {
|
|
81
|
+
// Return the materialized block at the highest revision ≤ requested
|
|
82
|
+
block = structuredClone(latestMaterializedAt(blockState, blockGets.context.rev));
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
// Otherwise return latest materialized block
|
|
86
|
+
block = structuredClone(blockState.materializedBlocks.get(blockState.latestRev));
|
|
87
|
+
}
|
|
88
|
+
const actionId = blockState.revisionActions.get(blockState.latestRev);
|
|
89
|
+
results[blockId] = {
|
|
90
|
+
block,
|
|
91
|
+
state: {
|
|
92
|
+
latest: actionId !== undefined ? {
|
|
93
|
+
rev: blockState.latestRev,
|
|
94
|
+
actionId
|
|
95
|
+
} : undefined,
|
|
96
|
+
pendings: Array.from(blockState.pendingActions.keys())
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
// --- End of Critical Section (Read) ---
|
|
101
|
+
}
|
|
102
|
+
finally {
|
|
103
|
+
// Release locks in reverse order
|
|
104
|
+
releases.reverse().forEach(release => release());
|
|
105
|
+
}
|
|
106
|
+
return results;
|
|
107
|
+
}
|
|
108
|
+
async getStatus(actionRefs) {
|
|
109
|
+
return actionRefs.map(ref => ({
|
|
110
|
+
...ref,
|
|
111
|
+
statuses: ref.blockIds.map(blockId => {
|
|
112
|
+
const blockState = this.blocks.get(blockId);
|
|
113
|
+
if (!blockState)
|
|
114
|
+
return 'aborted';
|
|
115
|
+
return blockState.pendingActions.has(ref.actionId) ? 'pending'
|
|
116
|
+
: Array.from(blockState.revisionActions.values()).some(actionId => actionId === ref.actionId) ? 'committed'
|
|
117
|
+
: 'aborted';
|
|
118
|
+
})
|
|
119
|
+
}));
|
|
120
|
+
}
|
|
121
|
+
async pend(request) {
|
|
122
|
+
this.checkAvailable();
|
|
123
|
+
const { actionId, transforms, policy, rev } = request;
|
|
124
|
+
const blockIds = blockIdsForTransforms(transforms);
|
|
125
|
+
const conflictingPendings = [];
|
|
126
|
+
const missing = [];
|
|
127
|
+
// Check for conflicts (pending or committed based on rev/insert)
|
|
128
|
+
for (const blockId of blockIds) {
|
|
129
|
+
const blockState = this.blocks.get(blockId);
|
|
130
|
+
const blockTransform = transformForBlockId(transforms, blockId);
|
|
131
|
+
if (!blockTransform)
|
|
132
|
+
continue; // Should not happen
|
|
133
|
+
if (blockState) {
|
|
134
|
+
// Check for existing pending actions
|
|
135
|
+
if (blockState.pendingActions.size > 0) {
|
|
136
|
+
blockState.pendingActions.forEach((_, pendingActionId) => {
|
|
137
|
+
conflictingPendings.push({ blockId, actionId: pendingActionId });
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
// Check for conflicting committed revisions (if rev specified or it's an insert)
|
|
141
|
+
if (rev !== undefined || blockTransform.insert) {
|
|
142
|
+
const checkRev = rev ?? 0; // Check from revision 0 if it's an insert
|
|
143
|
+
if (blockState.latestRev >= checkRev) {
|
|
144
|
+
// Collect conflicting committed actions
|
|
145
|
+
const missingForBlock = new Map();
|
|
146
|
+
for (let r = checkRev; r <= blockState.latestRev; r++) {
|
|
147
|
+
const committedActionId = blockState.revisionActions.get(r);
|
|
148
|
+
if (committedActionId !== undefined) {
|
|
149
|
+
const committedTransform = blockState.committedActions.get(committedActionId);
|
|
150
|
+
if (committedTransform) {
|
|
151
|
+
missingForBlock.set(committedActionId, { rev: r, transform: committedTransform });
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
// Add collected missing transforms for this block to the main missing list
|
|
156
|
+
for (const [mActionId, data] of missingForBlock.entries()) {
|
|
157
|
+
let existing = missing.find(m => m.actionId === mActionId);
|
|
158
|
+
if (!existing) {
|
|
159
|
+
existing = { actionId: mActionId, rev: data.rev, transforms: emptyTransforms() };
|
|
160
|
+
missing.push(existing);
|
|
161
|
+
}
|
|
162
|
+
existing.rev = Math.max(existing.rev ?? 0, data.rev);
|
|
163
|
+
existing.transforms = concatTransform(existing.transforms, blockId, data.transform);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
// Handle failure due to committed conflicts first
|
|
170
|
+
if (missing.length > 0) {
|
|
171
|
+
return {
|
|
172
|
+
success: false,
|
|
173
|
+
missing
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
// Handle failure/retry due to pending conflicts
|
|
177
|
+
if (conflictingPendings.length > 0) {
|
|
178
|
+
if (policy === 'f') {
|
|
179
|
+
return { success: false, pending: conflictingPendings };
|
|
180
|
+
}
|
|
181
|
+
else if (policy === 'r') {
|
|
182
|
+
// Simulate fetching pending transforms for 'r' policy
|
|
183
|
+
const pendingWithTransforms = conflictingPendings
|
|
184
|
+
.map(({ blockId: pBlockId, actionId: pActionId }) => {
|
|
185
|
+
const pBlockState = this.blocks.get(pBlockId);
|
|
186
|
+
const pTransform = pBlockState?.pendingActions.get(pActionId)
|
|
187
|
+
?? pBlockState?.committedActions.get(pActionId); // Might have been committed since check
|
|
188
|
+
if (pTransform) {
|
|
189
|
+
return { blockId: pBlockId, actionId: pActionId, transform: pTransform };
|
|
190
|
+
}
|
|
191
|
+
return null; // Handle case where it disappeared (cancelled?)
|
|
192
|
+
})
|
|
193
|
+
.filter(p => p !== null);
|
|
194
|
+
return {
|
|
195
|
+
success: false,
|
|
196
|
+
pending: pendingWithTransforms
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
// Policy 'w' allows proceeding despite pending transactions
|
|
200
|
+
}
|
|
201
|
+
// No fatal conflicts found, proceed to pend
|
|
202
|
+
for (const blockId of blockIds) {
|
|
203
|
+
const blockTransform = transformForBlockId(transforms, blockId);
|
|
204
|
+
if (blockTransform) {
|
|
205
|
+
const blockState = ensuredMap(this.blocks, blockId, () => newBlockState());
|
|
206
|
+
blockState.pendingActions.set(actionId, blockTransform);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
// Return success, include pending list as per StorageRepo behavior
|
|
210
|
+
return {
|
|
211
|
+
success: true,
|
|
212
|
+
pending: conflictingPendings,
|
|
213
|
+
blockIds
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
async cancel(actionRef) {
|
|
217
|
+
this.checkAvailable();
|
|
218
|
+
for (const blockId of actionRef.blockIds) {
|
|
219
|
+
const blockState = this.blocks.get(blockId);
|
|
220
|
+
if (blockState) {
|
|
221
|
+
blockState.pendingActions.delete(actionRef.actionId);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
async commit(request) {
|
|
226
|
+
this.checkAvailable();
|
|
227
|
+
const { actionId, rev, blockIds } = request;
|
|
228
|
+
const uniqueBlockIds = [...new Set(blockIds)].sort();
|
|
229
|
+
const releases = [];
|
|
230
|
+
try {
|
|
231
|
+
// Simulate acquiring locks sequentially like StorageRepo
|
|
232
|
+
for (const id of uniqueBlockIds) {
|
|
233
|
+
const lockId = `TestTransactor.commit:${id}`;
|
|
234
|
+
const release = await Latches.acquire(lockId);
|
|
235
|
+
releases.push(release);
|
|
236
|
+
}
|
|
237
|
+
// --- Start of Critical Section (Simulated) ---
|
|
238
|
+
// Check for stale revisions
|
|
239
|
+
const staleBlocks = blockIds.filter(blockId => {
|
|
240
|
+
const blockState = this.blocks.get(blockId);
|
|
241
|
+
return blockState && blockState.latestRev >= rev;
|
|
242
|
+
});
|
|
243
|
+
if (staleBlocks.length > 0) {
|
|
244
|
+
// Collect missing actions for stale blocks
|
|
245
|
+
const missingByAction = new Map();
|
|
246
|
+
for (const blockId of staleBlocks) {
|
|
247
|
+
const blockState = this.blocks.get(blockId);
|
|
248
|
+
for (let r = rev; r <= blockState.latestRev; r++) {
|
|
249
|
+
const committedActionId = blockState.revisionActions.get(r);
|
|
250
|
+
if (committedActionId) {
|
|
251
|
+
const transform = blockState.committedActions.get(committedActionId);
|
|
252
|
+
if (transform) {
|
|
253
|
+
const existing = missingByAction.get(committedActionId) ?? emptyTransforms();
|
|
254
|
+
missingByAction.set(committedActionId, concatTransform(existing, blockId, transform));
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
const missing = Array.from(missingByAction.entries()).map(([actionId, transforms]) => ({
|
|
260
|
+
actionId,
|
|
261
|
+
rev: Array.from(this.blocks.values())
|
|
262
|
+
.flatMap(bs => Array.from(bs.revisionActions.entries()))
|
|
263
|
+
.find(([, aId]) => aId === actionId)?.[0] ?? rev,
|
|
264
|
+
transforms
|
|
265
|
+
}));
|
|
266
|
+
return { success: false, missing };
|
|
267
|
+
}
|
|
268
|
+
// Verify all blocks have the pending action
|
|
269
|
+
for (const blockId of blockIds) {
|
|
270
|
+
const blockState = this.blocks.get(blockId);
|
|
271
|
+
if (!blockState || !blockState.pendingActions.has(actionId)) {
|
|
272
|
+
return {
|
|
273
|
+
success: false,
|
|
274
|
+
reason: `Action ${actionId} not found or not pending for block ${blockId}`
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
// Commit the action for each block
|
|
279
|
+
for (const blockId of blockIds) {
|
|
280
|
+
const blockState = this.blocks.get(blockId);
|
|
281
|
+
const transform = blockState.pendingActions.get(actionId);
|
|
282
|
+
// Get base block to apply transform to
|
|
283
|
+
const baseBlock = blockState.materializedBlocks.get(blockState.latestRev);
|
|
284
|
+
let newBlock;
|
|
285
|
+
if (!baseBlock) {
|
|
286
|
+
if (!transform.insert) {
|
|
287
|
+
throw new Error(`Commit Error: Action ${actionId} has no insert for new block ${blockId}`);
|
|
288
|
+
}
|
|
289
|
+
newBlock = structuredClone(transform.insert);
|
|
290
|
+
}
|
|
291
|
+
else {
|
|
292
|
+
newBlock = applyTransformSafe(baseBlock, transform);
|
|
293
|
+
if (!newBlock && !transform.delete) {
|
|
294
|
+
throw new Error(`Commit Error: Action ${actionId} resulted in undefined block but had no delete flag for block ${blockId}`);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
if (newBlock) {
|
|
298
|
+
blockState.materializedBlocks.set(rev, newBlock);
|
|
299
|
+
}
|
|
300
|
+
// Update block state
|
|
301
|
+
blockState.latestRev = rev;
|
|
302
|
+
blockState.revisionActions.set(rev, actionId);
|
|
303
|
+
blockState.committedActions.set(actionId, transform);
|
|
304
|
+
blockState.pendingActions.delete(actionId);
|
|
305
|
+
}
|
|
306
|
+
// --- End of Critical Section (Simulated) ---
|
|
307
|
+
return { success: true };
|
|
308
|
+
}
|
|
309
|
+
finally {
|
|
310
|
+
// Release locks in reverse order
|
|
311
|
+
releases.reverse().forEach(release => release());
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
// Helper methods for testing
|
|
315
|
+
reset() {
|
|
316
|
+
this.blocks.clear();
|
|
317
|
+
}
|
|
318
|
+
getPendingActions() {
|
|
319
|
+
const allPending = new Map();
|
|
320
|
+
for (const [blockId, blockState] of this.blocks.entries()) {
|
|
321
|
+
for (const [actionId, transform] of blockState.pendingActions) {
|
|
322
|
+
const existing = allPending.get(actionId);
|
|
323
|
+
if (!existing) {
|
|
324
|
+
allPending.set(actionId, { actionId, transforms: transformsFromTransform(transform, blockId) });
|
|
325
|
+
}
|
|
326
|
+
else {
|
|
327
|
+
existing.transforms = concatTransform(existing.transforms, blockId, transform);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
return allPending;
|
|
332
|
+
}
|
|
333
|
+
getCommittedActions() {
|
|
334
|
+
const allCommitted = new Map();
|
|
335
|
+
for (const [blockId, blockState] of this.blocks.entries()) {
|
|
336
|
+
for (const [rev, actionId] of blockState.revisionActions) {
|
|
337
|
+
const transform = blockState.committedActions.get(actionId);
|
|
338
|
+
if (transform) {
|
|
339
|
+
const existing = allCommitted.get(actionId);
|
|
340
|
+
if (!existing) {
|
|
341
|
+
allCommitted.set(actionId, {
|
|
342
|
+
actionId,
|
|
343
|
+
rev,
|
|
344
|
+
transforms: transformsFromTransform(transform, blockId)
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
else {
|
|
348
|
+
existing.transforms = concatTransform(existing.transforms, blockId, transform);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
return allCommitted;
|
|
354
|
+
}
|
|
355
|
+
setAvailable(available) {
|
|
356
|
+
this.available = available;
|
|
357
|
+
}
|
|
358
|
+
checkAvailable() {
|
|
359
|
+
if (!this.available) {
|
|
360
|
+
throw new Error('Transactor is not available');
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
/** Optional method for querying cluster nominees (used in GATHER phase for multi-collection transactions) */
|
|
364
|
+
queryClusterNominees;
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Wraps a {@link TestTransactor} and forces its commit phase to fail a bounded (or unbounded)
|
|
368
|
+
* number of times before delegating, so tests can exercise the sync retry / backoff / give-up
|
|
369
|
+
* path deterministically. pend/get/getStatus/cancel delegate unchanged, so the pend→commit→cancel
|
|
370
|
+
* round-trip runs exactly as in production.
|
|
371
|
+
*/
|
|
372
|
+
export class FlakyCommitTransactor {
|
|
373
|
+
inner;
|
|
374
|
+
failFirstN;
|
|
375
|
+
reason;
|
|
376
|
+
/** Number of commit() calls observed so far (across success and forced failure). */
|
|
377
|
+
commitAttempts = 0;
|
|
378
|
+
/**
|
|
379
|
+
* @param inner delegate transactor
|
|
380
|
+
* @param failFirstN number of initial commit() calls to fail; Infinity to always fail
|
|
381
|
+
* @param reason the StaleFailure.reason returned on a forced failure
|
|
382
|
+
*/
|
|
383
|
+
constructor(inner, failFirstN, reason = 'forced stale') {
|
|
384
|
+
this.inner = inner;
|
|
385
|
+
this.failFirstN = failFirstN;
|
|
386
|
+
this.reason = reason;
|
|
387
|
+
}
|
|
388
|
+
get(b) { return this.inner.get(b); }
|
|
389
|
+
getStatus(a) { return this.inner.getStatus(a); }
|
|
390
|
+
pend(r) { return this.inner.pend(r); }
|
|
391
|
+
cancel(a) { return this.inner.cancel(a); }
|
|
392
|
+
async commit(request) {
|
|
393
|
+
this.commitAttempts++;
|
|
394
|
+
if (this.commitAttempts <= this.failFirstN) {
|
|
395
|
+
return { success: false, reason: this.reason };
|
|
396
|
+
}
|
|
397
|
+
return this.inner.commit(request);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
function newBlockState() {
|
|
401
|
+
return {
|
|
402
|
+
materializedBlocks: new Map(),
|
|
403
|
+
latestRev: 0,
|
|
404
|
+
revisionActions: new Map(),
|
|
405
|
+
pendingActions: new Map(),
|
|
406
|
+
committedActions: new Map()
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
/** Returns the materialized block at the highest revision ≤ the given revision */
|
|
410
|
+
function latestMaterializedAt(blockState, maxRev) {
|
|
411
|
+
for (let rev = maxRev; rev >= 0; rev--) {
|
|
412
|
+
const block = blockState.materializedBlocks.get(rev);
|
|
413
|
+
if (block)
|
|
414
|
+
return block;
|
|
415
|
+
}
|
|
416
|
+
return undefined;
|
|
417
|
+
}
|
|
418
|
+
function applyTransformSafe(block, transform) {
|
|
419
|
+
if (!block)
|
|
420
|
+
return undefined;
|
|
421
|
+
return applyTransform(structuredClone(block), transform);
|
|
422
|
+
}
|
|
423
|
+
//# sourceMappingURL=test-transactor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-transactor.js","sourceRoot":"","sources":["../../../src/testing/test-transactor.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { ITransactionEngine, Transaction, ExecutionResult } from './transaction.js';
|
|
2
|
-
import type { TransactionCoordinator } from './coordinator.js';
|
|
3
2
|
export declare const ACTIONS_ENGINE_ID = "actions@1.0.0";
|
|
4
3
|
/**
|
|
5
4
|
* Built-in action-based transaction engine for testing.
|
|
@@ -7,6 +6,11 @@ export declare const ACTIONS_ENGINE_ID = "actions@1.0.0";
|
|
|
7
6
|
* This engine treats each statement as a JSON-encoded CollectionActions object.
|
|
8
7
|
* It's useful for testing the transaction infrastructure without needing SQL.
|
|
9
8
|
*
|
|
9
|
+
* This is a PURE TRANSLATOR (model (a) of the {@link ITransactionEngine} contract):
|
|
10
|
+
* execute() parses statements into CollectionActions[] and RETURNS them. It never
|
|
11
|
+
* touches a coordinator or mutates any collection state — application is the sole
|
|
12
|
+
* responsibility of the session/coordinator that receives the returned actions.
|
|
13
|
+
*
|
|
10
14
|
* Each statement format:
|
|
11
15
|
* ```json
|
|
12
16
|
* {
|
|
@@ -18,8 +22,7 @@ export declare const ACTIONS_ENGINE_ID = "actions@1.0.0";
|
|
|
18
22
|
* ```
|
|
19
23
|
*/
|
|
20
24
|
export declare class ActionsEngine implements ITransactionEngine {
|
|
21
|
-
|
|
22
|
-
constructor(coordinator: TransactionCoordinator);
|
|
25
|
+
readonly id = "actions@1.0.0";
|
|
23
26
|
execute(transaction: Transaction): Promise<ExecutionResult>;
|
|
24
27
|
}
|
|
25
28
|
//# sourceMappingURL=actions-engine.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actions-engine.d.ts","sourceRoot":"","sources":["../../../src/transaction/actions-engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,eAAe,EAAqB,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"actions-engine.d.ts","sourceRoot":"","sources":["../../../src/transaction/actions-engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,eAAe,EAAqB,MAAM,kBAAkB,CAAC;AAE5G,eAAO,MAAM,iBAAiB,kBAAkB,CAAC;AAEjD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,aAAc,YAAW,kBAAkB;IACvD,QAAQ,CAAC,EAAE,mBAAqB;IAE1B,OAAO,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,eAAe,CAAC;CAuCjE"}
|
|
@@ -5,6 +5,11 @@ export const ACTIONS_ENGINE_ID = "actions@1.0.0";
|
|
|
5
5
|
* This engine treats each statement as a JSON-encoded CollectionActions object.
|
|
6
6
|
* It's useful for testing the transaction infrastructure without needing SQL.
|
|
7
7
|
*
|
|
8
|
+
* This is a PURE TRANSLATOR (model (a) of the {@link ITransactionEngine} contract):
|
|
9
|
+
* execute() parses statements into CollectionActions[] and RETURNS them. It never
|
|
10
|
+
* touches a coordinator or mutates any collection state — application is the sole
|
|
11
|
+
* responsibility of the session/coordinator that receives the returned actions.
|
|
12
|
+
*
|
|
8
13
|
* Each statement format:
|
|
9
14
|
* ```json
|
|
10
15
|
* {
|
|
@@ -16,10 +21,7 @@ export const ACTIONS_ENGINE_ID = "actions@1.0.0";
|
|
|
16
21
|
* ```
|
|
17
22
|
*/
|
|
18
23
|
export class ActionsEngine {
|
|
19
|
-
|
|
20
|
-
constructor(coordinator) {
|
|
21
|
-
this.coordinator = coordinator;
|
|
22
|
-
}
|
|
24
|
+
id = ACTIONS_ENGINE_ID;
|
|
23
25
|
async execute(transaction) {
|
|
24
26
|
try {
|
|
25
27
|
// Parse each statement as a CollectionActions object
|
|
@@ -40,10 +42,9 @@ export class ActionsEngine {
|
|
|
40
42
|
};
|
|
41
43
|
}
|
|
42
44
|
allActions.push(collectionActions);
|
|
43
|
-
// Apply actions through coordinator (for validation/replay)
|
|
44
|
-
await this.coordinator.applyActions([collectionActions], transaction.stamp.id);
|
|
45
45
|
}
|
|
46
|
-
//
|
|
46
|
+
// Pure translation: return parsed actions WITHOUT applying them. The caller
|
|
47
|
+
// (session.execute / coordinator.execute) applies them exactly once.
|
|
47
48
|
return {
|
|
48
49
|
success: true,
|
|
49
50
|
actions: allActions
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actions-engine.js","sourceRoot":"","sources":["../../../src/transaction/actions-engine.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"actions-engine.js","sourceRoot":"","sources":["../../../src/transaction/actions-engine.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,iBAAiB,GAAG,eAAe,CAAC;AAEjD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,OAAO,aAAa;IAChB,EAAE,GAAG,iBAAiB,CAAC;IAEhC,KAAK,CAAC,OAAO,CAAC,WAAwB;QACrC,IAAI,CAAC;YACJ,qDAAqD;YACrD,MAAM,UAAU,GAAwB,EAAE,CAAC;YAE3C,KAAK,MAAM,SAAS,IAAI,WAAW,CAAC,UAAU,EAAE,CAAC;gBAChD,MAAM,iBAAiB,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAsB,CAAC;gBAErE,qBAAqB;gBACrB,IAAI,CAAC,iBAAiB,CAAC,YAAY,IAAI,OAAO,iBAAiB,CAAC,YAAY,KAAK,QAAQ,EAAE,CAAC;oBAC3F,OAAO;wBACN,OAAO,EAAE,KAAK;wBACd,KAAK,EAAE,yCAAyC;qBAChD,CAAC;gBACH,CAAC;gBAED,IAAI,CAAC,iBAAiB,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,iBAAiB,CAAC,OAAO,CAAC,EAAE,CAAC;oBAC7E,OAAO;wBACN,OAAO,EAAE,KAAK;wBACd,KAAK,EAAE,iCAAiC,iBAAiB,CAAC,YAAY,mCAAmC;qBACzG,CAAC;gBACH,CAAC;gBAED,UAAU,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YACpC,CAAC;YAED,4EAA4E;YAC5E,qEAAqE;YACrE,OAAO;gBACN,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE,UAAU;aACnB,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO;gBACN,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,kCAAkC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;aACjG,CAAC;QACH,CAAC;IACF,CAAC;CACD"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ITransactor, CollectionId, Transforms } from "../index.js";
|
|
2
2
|
import type { Transaction, ExecutionResult, ITransactionEngine, CollectionActions, ReadDependency } from "./transaction.js";
|
|
3
3
|
import type { Collection } from "../collection/collection.js";
|
|
4
|
-
import {
|
|
4
|
+
import type { SyncOptions } from "../collection/index.js";
|
|
5
5
|
/**
|
|
6
6
|
* Coordinates multi-collection transactions.
|
|
7
7
|
*
|
|
@@ -35,19 +35,45 @@ export declare class TransactionCoordinator {
|
|
|
35
35
|
*/
|
|
36
36
|
private applyActionsRaw;
|
|
37
37
|
/**
|
|
38
|
-
* Commit a transaction
|
|
38
|
+
* Commit a transaction with a bounded, jittered backoff retry around a CLEAN stale loss.
|
|
39
|
+
*
|
|
40
|
+
* The single-attempt work lives in {@link commitOnce}; this wrapper re-drives it when the attempt
|
|
41
|
+
* fails as a clean optimistic-concurrency loss ({@link CoordinatorStaleLossError} — nothing
|
|
42
|
+
* durably committed, every tracker restored to its pre-append state). Before each re-attempt it
|
|
43
|
+
* re-reads each collection to fresh revisions (so the retry pends against current state rather
|
|
44
|
+
* than immediately re-failing stale), then backs off with the same jitter policy as
|
|
45
|
+
* {@link Collection.sync}. Retry is bounded by `maxAttempts` and an optional wall-clock
|
|
46
|
+
* `deadlineMs`, and honours an abort `signal`.
|
|
47
|
+
*
|
|
48
|
+
* A {@link CoordinatorPartialCommitError} (a partial landing — some collection durably committed)
|
|
49
|
+
* is NOT retryable and escapes immediately: blindly retrying would re-log already-durable actions.
|
|
50
|
+
* Any other failure (expired transaction, unavailable transactor, unreachable cluster) also
|
|
51
|
+
* propagates without retry — only genuine clean stale losses are re-driven.
|
|
52
|
+
*
|
|
53
|
+
* Defaults are safe out of the box: a caller that passes no options gets bounded, jittered retry.
|
|
54
|
+
*
|
|
55
|
+
* @param transaction - The transaction to commit
|
|
56
|
+
* @param options - Retry knobs; shares the {@link SyncOptions} vocabulary with `Collection.sync`.
|
|
57
|
+
*/
|
|
58
|
+
commit(transaction: Transaction, options?: SyncOptions): Promise<void>;
|
|
59
|
+
/**
|
|
60
|
+
* Commit a transaction (single attempt): materialise a log entry from each collection's staged
|
|
39
61
|
* pending actions, then orchestrate the distributed consensus (GATHER/PEND/COMMIT).
|
|
40
62
|
*
|
|
41
|
-
* Called by
|
|
63
|
+
* Called by {@link commit} (which wraps it in the backoff+jitter retry loop). The
|
|
42
64
|
* staged mutations already live in each collection's tracker — applied either via
|
|
43
65
|
* applyActions() (engine-driven path) or directly via Collection.act()/Tree.stage
|
|
44
66
|
* (the vtab's deferred-DML path) — but in BOTH cases without a log entry yet, so
|
|
45
67
|
* this method appends that entry here (see the inline note below) before pending,
|
|
46
68
|
* and folds the committed transforms back into each collection's read cache.
|
|
47
69
|
*
|
|
70
|
+
* On a clean stale loss (nothing durable, every tracker restored) it throws
|
|
71
|
+
* {@link CoordinatorStaleLossError} so the caller can retry; on a partial landing it throws
|
|
72
|
+
* {@link CoordinatorPartialCommitError} (not retryable).
|
|
73
|
+
*
|
|
48
74
|
* @param transaction - The transaction to commit
|
|
49
75
|
*/
|
|
50
|
-
|
|
76
|
+
private commitOnce;
|
|
51
77
|
/**
|
|
52
78
|
* Rollback a transaction (undo only the given stampId's applied actions).
|
|
53
79
|
*
|
|
@@ -81,27 +107,10 @@ export declare class TransactionCoordinator {
|
|
|
81
107
|
* Clear read dependencies from all collections.
|
|
82
108
|
*/
|
|
83
109
|
clearReadDependencies(): void;
|
|
84
|
-
/**
|
|
85
|
-
* Compute hash of all operations in a transaction.
|
|
86
|
-
* This hash is used for validation - validators re-execute the transaction
|
|
87
|
-
* and compare their computed operations hash with this one.
|
|
88
|
-
*/
|
|
89
|
-
private hashOperations;
|
|
90
|
-
/**
|
|
91
|
-
* Commit a transaction context.
|
|
92
|
-
*
|
|
93
|
-
* @deprecated Use TransactionSession instead of TransactionContext
|
|
94
|
-
* This is called by TransactionContext.commit().
|
|
95
|
-
*
|
|
96
|
-
* @param context - The transaction context to commit
|
|
97
|
-
* @returns Execution result with actions and results
|
|
98
|
-
*/
|
|
99
|
-
commitTransaction(context: TransactionContext): Promise<ExecutionResult>;
|
|
100
110
|
/**
|
|
101
111
|
* Execute a fully-formed transaction.
|
|
102
112
|
*
|
|
103
|
-
* This
|
|
104
|
-
* or indirectly via commitTransaction().
|
|
113
|
+
* This is called with a complete transaction (e.g., from Quereus).
|
|
105
114
|
*
|
|
106
115
|
* @param transaction - The transaction to execute
|
|
107
116
|
* @param engine - The engine to use for executing the transaction
|
|
@@ -141,6 +150,12 @@ export declare class TransactionCoordinator {
|
|
|
141
150
|
* @param superclusterNominees - Nominees for multi-collection consensus (null for single-collection)
|
|
142
151
|
*/
|
|
143
152
|
private pendPhase;
|
|
153
|
+
/**
|
|
154
|
+
* Pend a single collection's transforms. Resolves with the collection id and its
|
|
155
|
+
* pended block ids on success; throws with a per-collection reason on failure so the
|
|
156
|
+
* fan-out in {@link pendPhase} can settle it as a rejection.
|
|
157
|
+
*/
|
|
158
|
+
private pendCollection;
|
|
144
159
|
/**
|
|
145
160
|
* COMMIT phase: Commit to all critical blocks with retry for transient failures.
|
|
146
161
|
*
|
|
@@ -149,6 +164,12 @@ export declare class TransactionCoordinator {
|
|
|
149
164
|
* Returns which collections committed vs failed so the caller can do targeted cancel.
|
|
150
165
|
*/
|
|
151
166
|
private commitPhase;
|
|
167
|
+
/**
|
|
168
|
+
* Commit a single collection's pended blocks, retrying transient failures up to three
|
|
169
|
+
* times (forward recovery). Always resolves — success is carried in the returned
|
|
170
|
+
* `committed` flag — so the fan-out in {@link commitPhase} can aggregate every result.
|
|
171
|
+
*/
|
|
172
|
+
private commitCollection;
|
|
152
173
|
/**
|
|
153
174
|
* CANCEL phase: Cancel pending actions on affected blocks.
|
|
154
175
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"coordinator.d.ts","sourceRoot":"","sources":["../../../src/transaction/coordinator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAW,YAAY,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"coordinator.d.ts","sourceRoot":"","sources":["../../../src/transaction/coordinator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAW,YAAY,EAAE,UAAU,EAAwC,MAAM,aAAa,CAAC;AACxH,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAE5H,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAgC1D;;;;;;;;;GASG;AACH,qBAAa,sBAAsB;IAUjC,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAV7B,yFAAyF;IACzF,OAAO,CAAC,SAAS,CAIZ;IACL,OAAO,CAAC,cAAc,CAAK;gBAGT,UAAU,EAAE,WAAW,EACvB,WAAW,EAAE,GAAG,CAAC,YAAY,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC;IAGjE;;;;;;;;;OASG;IACG,YAAY,CACjB,OAAO,EAAE,iBAAiB,EAAE,EAC5B,OAAO,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC;IAkBhB;;OAEG;YACW,eAAe;IAiB7B;;;;;;;;;;;;;;;;;;;;OAoBG;IACG,MAAM,CAAC,WAAW,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IA6D5E;;;;;;;;;;;;;;;;OAgBG;YACW,UAAU;IA0KxB;;;;;;;;OAQG;IACG,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA6C9C;;;;;;OAMG;IACH,aAAa,IAAI,GAAG,CAAC,YAAY,EAAE,UAAU,CAAC;IAe9C;;;;;OAKG;IACH,eAAe,IAAI,IAAI;IAMvB;;OAEG;IACH,mBAAmB,IAAI,cAAc,EAAE;IAQvC;;OAEG;IACH,qBAAqB,IAAI,IAAI;IAM7B;;;;;;;;OAQG;IACG,OAAO,CAAC,WAAW,EAAE,WAAW,EAAE,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,eAAe,CAAC;IA8I7F;;;;OAIG;YACW,wBAAwB;IA+DtC;;;;;;;OAOG;YACW,qBAAqB;IAwEnC;;;;;;;OAOG;YACW,WAAW;IAmCzB;;;;;;;OAOG;YACW,SAAS;IA2DvB;;;;OAIG;YACW,cAAc;IAuC5B;;;;;;OAMG;YACW,WAAW;IA2DzB;;;;OAIG;YACW,gBAAgB;IAuD9B;;;;;OAKG;YACW,WAAW;CAkBzB"}
|