@optimystic/db-p2p 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/block-transfer-service.d.ts +73 -1
- package/dist/src/cluster/block-transfer-service.d.ts.map +1 -1
- package/dist/src/cluster/block-transfer-service.js +70 -3
- package/dist/src/cluster/block-transfer-service.js.map +1 -1
- package/dist/src/cluster/block-transfer.d.ts +16 -1
- package/dist/src/cluster/block-transfer.d.ts.map +1 -1
- package/dist/src/cluster/block-transfer.js +73 -72
- package/dist/src/cluster/block-transfer.js.map +1 -1
- package/dist/src/cluster/client.d.ts +4 -6
- package/dist/src/cluster/client.d.ts.map +1 -1
- package/dist/src/cluster/client.js +8 -13
- package/dist/src/cluster/client.js.map +1 -1
- package/dist/src/cluster/cluster-policy.d.ts +2 -1
- package/dist/src/cluster/cluster-policy.d.ts.map +1 -1
- package/dist/src/cluster/cluster-policy.js.map +1 -1
- package/dist/src/cluster/cluster-repo.d.ts +126 -6
- package/dist/src/cluster/cluster-repo.d.ts.map +1 -1
- package/dist/src/cluster/cluster-repo.js +378 -50
- package/dist/src/cluster/cluster-repo.js.map +1 -1
- package/dist/src/cluster/commit-proof.js +2 -2
- package/dist/src/cluster/race-resolution.d.ts +51 -7
- package/dist/src/cluster/race-resolution.d.ts.map +1 -1
- package/dist/src/cluster/race-resolution.js +71 -7
- package/dist/src/cluster/race-resolution.js.map +1 -1
- package/dist/src/cluster/rebalance-monitor.d.ts +67 -5
- package/dist/src/cluster/rebalance-monitor.d.ts.map +1 -1
- package/dist/src/cluster/rebalance-monitor.js +120 -26
- package/dist/src/cluster/rebalance-monitor.js.map +1 -1
- package/dist/src/cluster/spread-on-churn.d.ts.map +1 -1
- package/dist/src/cluster/spread-on-churn.js +34 -47
- package/dist/src/cluster/spread-on-churn.js.map +1 -1
- package/dist/src/cohort-topic/host.d.ts.map +1 -1
- package/dist/src/cohort-topic/host.js +8 -6
- package/dist/src/cohort-topic/host.js.map +1 -1
- package/dist/src/cohort-topic/membership-source.js +1 -1
- package/dist/src/cohort-topic/membership-source.js.map +1 -1
- package/dist/src/cohort-topic/peer-codec.d.ts.map +1 -1
- package/dist/src/cohort-topic/peer-codec.js +5 -2
- package/dist/src/cohort-topic/peer-codec.js.map +1 -1
- package/dist/src/cohort-topic/stream-util.d.ts +24 -3
- package/dist/src/cohort-topic/stream-util.d.ts.map +1 -1
- package/dist/src/cohort-topic/stream-util.js +36 -3
- package/dist/src/cohort-topic/stream-util.js.map +1 -1
- package/dist/src/cohort-topic/topic-router.d.ts +9 -0
- package/dist/src/cohort-topic/topic-router.d.ts.map +1 -1
- package/dist/src/cohort-topic/topic-router.js +12 -2
- package/dist/src/cohort-topic/topic-router.js.map +1 -1
- package/dist/src/dispute/client.d.ts.map +1 -1
- package/dist/src/dispute/client.js +15 -3
- package/dist/src/dispute/client.js.map +1 -1
- package/dist/src/index.d.ts +5 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +5 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/libp2p-key-network.d.ts +78 -17
- package/dist/src/libp2p-key-network.d.ts.map +1 -1
- package/dist/src/libp2p-key-network.js +234 -147
- package/dist/src/libp2p-key-network.js.map +1 -1
- package/dist/src/libp2p-node-base.d.ts +35 -1
- package/dist/src/libp2p-node-base.d.ts.map +1 -1
- package/dist/src/libp2p-node-base.js +151 -26
- package/dist/src/libp2p-node-base.js.map +1 -1
- package/dist/src/libp2p-node-rn.d.ts +2 -2
- package/dist/src/libp2p-node-rn.d.ts.map +1 -1
- package/dist/src/libp2p-node-rn.js.map +1 -1
- package/dist/src/libp2p-node.d.ts +2 -2
- package/dist/src/libp2p-node.d.ts.map +1 -1
- package/dist/src/libp2p-node.js.map +1 -1
- package/dist/src/logger.d.ts.map +1 -1
- package/dist/src/logger.js +6 -1
- package/dist/src/logger.js.map +1 -1
- package/dist/src/matchmaking/query-transport.d.ts +3 -4
- package/dist/src/matchmaking/query-transport.d.ts.map +1 -1
- package/dist/src/matchmaking/query-transport.js +9 -9
- package/dist/src/matchmaking/query-transport.js.map +1 -1
- package/dist/src/network/network-manager-service.d.ts +10 -5
- package/dist/src/network/network-manager-service.d.ts.map +1 -1
- package/dist/src/network/network-manager-service.js +11 -2
- package/dist/src/network/network-manager-service.js.map +1 -1
- package/dist/src/network/relay-reservation.d.ts +170 -0
- package/dist/src/network/relay-reservation.d.ts.map +1 -0
- package/dist/src/network/relay-reservation.js +527 -0
- package/dist/src/network/relay-reservation.js.map +1 -0
- package/dist/src/pend-validation.d.ts +3 -2
- package/dist/src/pend-validation.d.ts.map +1 -1
- package/dist/src/pend-validation.js +3 -2
- package/dist/src/pend-validation.js.map +1 -1
- package/dist/src/protocol-client.d.ts +8 -1
- package/dist/src/protocol-client.d.ts.map +1 -1
- package/dist/src/protocol-client.js +11 -0
- package/dist/src/protocol-client.js.map +1 -1
- package/dist/src/reactivity/forwarder-host.d.ts +2 -1
- package/dist/src/reactivity/forwarder-host.d.ts.map +1 -1
- package/dist/src/reactivity/forwarder-host.js +2 -1
- package/dist/src/reactivity/forwarder-host.js.map +1 -1
- package/dist/src/reactivity/origination-manager.d.ts +3 -3
- package/dist/src/reactivity/origination-manager.js +3 -3
- package/dist/src/reactivity/recover-transport.d.ts +22 -14
- package/dist/src/reactivity/recover-transport.d.ts.map +1 -1
- package/dist/src/reactivity/recover-transport.js +32 -19
- package/dist/src/reactivity/recover-transport.js.map +1 -1
- package/dist/src/reactivity/subscription-manager.d.ts +2 -2
- package/dist/src/reactivity/topic-bytes.d.ts +6 -7
- package/dist/src/reactivity/topic-bytes.d.ts.map +1 -1
- package/dist/src/reactivity/topic-bytes.js +8 -9
- package/dist/src/reactivity/topic-bytes.js.map +1 -1
- package/dist/src/repo/client.d.ts +5 -2
- package/dist/src/repo/client.d.ts.map +1 -1
- package/dist/src/repo/client.js +49 -40
- package/dist/src/repo/client.js.map +1 -1
- package/dist/src/repo/cluster-coordinator.d.ts +77 -5
- package/dist/src/repo/cluster-coordinator.d.ts.map +1 -1
- package/dist/src/repo/cluster-coordinator.js +131 -20
- package/dist/src/repo/cluster-coordinator.js.map +1 -1
- package/dist/src/repo/coordinator-repo.d.ts +238 -122
- package/dist/src/repo/coordinator-repo.d.ts.map +1 -1
- package/dist/src/repo/coordinator-repo.js +625 -472
- package/dist/src/repo/coordinator-repo.js.map +1 -1
- package/dist/src/repo/i-under-replication-ledger.d.ts +87 -0
- package/dist/src/repo/i-under-replication-ledger.d.ts.map +1 -0
- package/dist/src/repo/i-under-replication-ledger.js +2 -0
- package/dist/src/repo/i-under-replication-ledger.js.map +1 -0
- package/dist/src/repo/kv-under-replication-ledger.d.ts +91 -0
- package/dist/src/repo/kv-under-replication-ledger.d.ts.map +1 -0
- package/dist/src/repo/kv-under-replication-ledger.js +287 -0
- package/dist/src/repo/kv-under-replication-ledger.js.map +1 -0
- package/dist/src/repo/responsibility.d.ts +37 -0
- package/dist/src/repo/responsibility.d.ts.map +1 -0
- package/dist/src/repo/responsibility.js +37 -0
- package/dist/src/repo/responsibility.js.map +1 -0
- package/dist/src/repo/service.d.ts +44 -15
- package/dist/src/repo/service.d.ts.map +1 -1
- package/dist/src/repo/service.js +64 -27
- package/dist/src/repo/service.js.map +1 -1
- package/dist/src/repo/stuck-reservation.d.ts +127 -0
- package/dist/src/repo/stuck-reservation.d.ts.map +1 -0
- package/dist/src/repo/stuck-reservation.js +179 -0
- package/dist/src/repo/stuck-reservation.js.map +1 -0
- package/dist/src/repo/under-replication-drain.d.ts +208 -0
- package/dist/src/repo/under-replication-drain.d.ts.map +1 -0
- package/dist/src/repo/under-replication-drain.js +461 -0
- package/dist/src/repo/under-replication-drain.js.map +1 -0
- package/dist/src/rn.d.ts +5 -0
- package/dist/src/rn.d.ts.map +1 -1
- package/dist/src/rn.js +5 -0
- package/dist/src/rn.js.map +1 -1
- package/dist/src/storage/block-latch.d.ts +3 -2
- package/dist/src/storage/block-latch.d.ts.map +1 -1
- package/dist/src/storage/block-latch.js +7 -4
- package/dist/src/storage/block-latch.js.map +1 -1
- package/dist/src/storage/block-storage.d.ts +45 -3
- package/dist/src/storage/block-storage.d.ts.map +1 -1
- package/dist/src/storage/block-storage.js +156 -9
- package/dist/src/storage/block-storage.js.map +1 -1
- package/dist/src/storage/i-block-storage.d.ts +57 -5
- package/dist/src/storage/i-block-storage.d.ts.map +1 -1
- package/dist/src/storage/i-block-storage.js.map +1 -1
- package/dist/src/storage/pending-claim.d.ts +167 -0
- package/dist/src/storage/pending-claim.d.ts.map +1 -0
- package/dist/src/storage/pending-claim.js +156 -0
- package/dist/src/storage/pending-claim.js.map +1 -0
- package/dist/src/storage/raw-store-codec.d.ts +13 -0
- package/dist/src/storage/raw-store-codec.d.ts.map +1 -1
- package/dist/src/storage/raw-store-codec.js +24 -3
- package/dist/src/storage/raw-store-codec.js.map +1 -1
- package/dist/src/storage/restoration-coordinator.d.ts.map +1 -1
- package/dist/src/storage/restoration-coordinator.js +2 -1
- package/dist/src/storage/restoration-coordinator.js.map +1 -1
- package/dist/src/storage/ring-shift-coordinator.d.ts.map +1 -1
- package/dist/src/storage/ring-shift-coordinator.js +3 -3
- package/dist/src/storage/ring-shift-coordinator.js.map +1 -1
- package/dist/src/storage/storage-repo.d.ts +122 -5
- package/dist/src/storage/storage-repo.d.ts.map +1 -1
- package/dist/src/storage/storage-repo.js +245 -68
- package/dist/src/storage/storage-repo.js.map +1 -1
- package/dist/src/storage/struct.d.ts +58 -0
- package/dist/src/storage/struct.d.ts.map +1 -1
- package/dist/src/testing/mesh-harness.d.ts +77 -11
- package/dist/src/testing/mesh-harness.d.ts.map +1 -1
- package/dist/src/testing/mesh-harness.js +226 -100
- package/dist/src/testing/mesh-harness.js.map +1 -1
- package/package.json +2 -2
- package/readme.md +27 -3
- package/src/cluster/block-transfer-service.ts +132 -4
- package/src/cluster/block-transfer.ts +79 -84
- package/src/cluster/client.ts +115 -119
- package/src/cluster/cluster-policy.ts +2 -1
- package/src/cluster/cluster-repo.ts +422 -56
- package/src/cluster/commit-proof.ts +2 -2
- package/src/cluster/race-resolution.ts +76 -7
- package/src/cluster/rebalance-monitor.ts +677 -539
- package/src/cluster/spread-on-churn.ts +34 -54
- package/src/cohort-topic/host.ts +8 -6
- package/src/cohort-topic/membership-source.ts +1 -1
- package/src/cohort-topic/peer-codec.ts +34 -31
- package/src/cohort-topic/stream-util.ts +39 -4
- package/src/cohort-topic/topic-router.ts +12 -2
- package/src/dispute/client.ts +17 -7
- package/src/index.ts +64 -59
- package/src/libp2p-key-network.ts +1377 -1260
- package/src/libp2p-node-base.ts +186 -27
- package/src/libp2p-node-rn.ts +31 -30
- package/src/libp2p-node.ts +37 -36
- package/src/logger.ts +6 -1
- package/src/matchmaking/query-transport.ts +9 -9
- package/src/network/network-manager-service.ts +16 -5
- package/src/network/relay-reservation.ts +636 -0
- package/src/pend-validation.ts +3 -2
- package/src/protocol-client.ts +13 -1
- package/src/reactivity/forwarder-host.ts +2 -1
- package/src/reactivity/origination-manager.ts +3 -3
- package/src/reactivity/recover-transport.ts +39 -22
- package/src/reactivity/subscription-manager.ts +2 -2
- package/src/reactivity/topic-bytes.ts +35 -37
- package/src/repo/client.ts +172 -173
- package/src/repo/cluster-coordinator.ts +145 -19
- package/src/repo/coordinator-repo.ts +652 -505
- package/src/repo/i-under-replication-ledger.ts +89 -0
- package/src/repo/kv-under-replication-ledger.ts +302 -0
- package/src/repo/responsibility.ts +48 -0
- package/src/repo/service.ts +76 -39
- package/src/repo/stuck-reservation.ts +224 -0
- package/src/repo/under-replication-drain.ts +582 -0
- package/src/rn.ts +74 -69
- package/src/storage/block-latch.ts +7 -4
- package/src/storage/block-storage.ts +161 -10
- package/src/storage/i-block-storage.ts +60 -5
- package/src/storage/pending-claim.ts +200 -0
- package/src/storage/raw-store-codec.ts +26 -3
- package/src/storage/restoration-coordinator.ts +212 -211
- package/src/storage/ring-shift-coordinator.ts +271 -271
- package/src/storage/storage-repo.ts +280 -72
- package/src/storage/struct.ts +58 -0
- package/src/testing/mesh-harness.ts +293 -112
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type { BlockId, IBlock, Transform, ActionId, ActionRev } from "@optimystic/db-core";
|
|
1
|
+
import type { BlockId, IBlock, Transform, ActionId, ActionRev, BlockLineage } from "@optimystic/db-core";
|
|
2
2
|
import type { BlockCommitProof } from "../cluster/commit-proof.js";
|
|
3
3
|
import type { BlockWriteLatch } from "./block-latch.js";
|
|
4
|
+
import type { PendingClaim } from "./pending-claim.js";
|
|
4
5
|
/**
|
|
5
6
|
* Thrown by {@link IBlockStorage.getBlock} when the block has metadata here but the target revision
|
|
6
7
|
* lies outside the locally held revision ranges — this node holds no local records that can serve
|
|
@@ -101,10 +102,40 @@ export interface IBlockStorage {
|
|
|
101
102
|
* under one multi-block write-latch hold, so every block it saves was observed under that same
|
|
102
103
|
* hold to satisfy `latest === undefined || latest.rev < rev`, and no writer can advance a block
|
|
103
104
|
* without its latch. A throw here means a caller reintroduced check-then-act.
|
|
105
|
+
*
|
|
106
|
+
* The revision is also KEPT, in the block's metadata (`BlockMetadata.pendingRevs`), so the record
|
|
107
|
+
* can later be read as a claim on a specific slot — see {@link listPendingClaims}.
|
|
108
|
+
*
|
|
109
|
+
* `baseRev` is the committed revision the record's update operations were computed against — the
|
|
110
|
+
* pend's `baseRevs[blockId]` — or `undefined` when the pend named none for this block (an
|
|
111
|
+
* inserted or deleted block, or a base the author did not know). Kept beside the revision
|
|
112
|
+
* (`BlockMetadata.pendingBases`), in the same metadata write, so that every later step that
|
|
113
|
+
* applies the record can refuse to apply it to a different version of the block — see
|
|
114
|
+
* {@link pendingClaimOf}. Stored as told: whether it matches this node's `latest` is decided
|
|
115
|
+
* where the record is APPLIED (`StorageRepo.internalCommit`, and the read-driven promotion in
|
|
116
|
+
* `StorageRepo.get`), never here.
|
|
104
117
|
*/
|
|
105
|
-
savePendingTransaction(actionId: ActionId, transform: Transform, rev: number | undefined, latch: BlockWriteLatch): Promise<void>;
|
|
106
|
-
/** Deletes a pending action */
|
|
118
|
+
savePendingTransaction(actionId: ActionId, transform: Transform, rev: number | undefined, baseRev: number | undefined, latch: BlockWriteLatch): Promise<void>;
|
|
119
|
+
/** Deletes a pending action, and the revision and base it was recorded as claiming. */
|
|
107
120
|
deletePendingTransaction(actionId: ActionId, latch: BlockWriteLatch): Promise<void>;
|
|
121
|
+
/**
|
|
122
|
+
* Every pending record on this block, each with the revision it was pended at and the base it
|
|
123
|
+
* was computed against when those are known — the pending namespace joined against
|
|
124
|
+
* `BlockMetadata.pendingRevs` and `pendingBases`. This is the view the rival-pend checks read
|
|
125
|
+
* (`StorageRepo.pend`'s apply-time scan and `ClusterMember.validatePendOperations`' promise
|
|
126
|
+
* vote), because whether a record reserves the block against a given pend depends on the slot
|
|
127
|
+
* it claims measured against the pend's revision — and, at the vote of a cohort that can leave a
|
|
128
|
+
* member out, its base (`isReservationAgainst`) — not on its mere presence. Read-only; no latch.
|
|
129
|
+
*/
|
|
130
|
+
listPendingClaims(): Promise<PendingClaim[]>;
|
|
131
|
+
/**
|
|
132
|
+
* The claim of ONE pending record — `actionId`'s entry of {@link listPendingClaims} — or
|
|
133
|
+
* `undefined` when this block holds no pending record for the action. For the two apply sites
|
|
134
|
+
* (`StorageRepo.internalCommit` and the read-driven promotion in `StorageRepo.get`), which need
|
|
135
|
+
* one record's base on the hot commit path and must not enumerate every record to get it.
|
|
136
|
+
* Read-only; no latch of its own: both callers already hold the block's write latch.
|
|
137
|
+
*/
|
|
138
|
+
pendingClaimOf(actionId: ActionId): Promise<PendingClaim | undefined>;
|
|
108
139
|
/** Lists revisions in ascending or descending order between startRev and endRev (inclusive) */
|
|
109
140
|
listRevisions(startRev: number, endRev: number): AsyncIterable<ActionRev>;
|
|
110
141
|
/** Saves a materialized block */
|
|
@@ -135,8 +166,29 @@ export interface IBlockStorage {
|
|
|
135
166
|
* record for a revision the block has already reached.
|
|
136
167
|
*/
|
|
137
168
|
promotePendingTransaction(actionId: ActionId, latch: BlockWriteLatch): Promise<void>;
|
|
138
|
-
/**
|
|
139
|
-
|
|
169
|
+
/**
|
|
170
|
+
* Sets the latest revision information, as the last step of committing `latest` here.
|
|
171
|
+
*
|
|
172
|
+
* Call it only after {@link promotePendingTransaction} has moved `latest.actionId`'s record: it
|
|
173
|
+
* drops that action's claim without deleting a record, so a caller that skipped promotion would
|
|
174
|
+
* leave a claim-less pending record behind (see `BlockMetadata.pendingRevs`).
|
|
175
|
+
*
|
|
176
|
+
* `builtOnPrior` says how the revision's content was produced, which is what the block's known
|
|
177
|
+
* lineage depends on (see `BlockMetadata.lineageFloor`): `true` when this node applied the
|
|
178
|
+
* revision's transform to the content of its previous revision (an update-only or delete
|
|
179
|
+
* transform); `false` when the content stands on its own because the transform carried an
|
|
180
|
+
* `insert`. Required rather than defaulted: a caller that guessed `true` for an insert would let
|
|
181
|
+
* {@link lineageOf} vouch for history the content never came from.
|
|
182
|
+
*/
|
|
183
|
+
setLatest(latest: ActionRev, builtOnPrior: boolean, latch: BlockWriteLatch): Promise<void>;
|
|
184
|
+
/**
|
|
185
|
+
* What THIS node's records say about whether the block's content at `latest` was built from the
|
|
186
|
+
* committed `target` — see `BlockLineage` in db-core for the four answers. Local and read-only:
|
|
187
|
+
* no latch, no peer fetch, no promotion. `unknown` is the honest answer whenever this node is
|
|
188
|
+
* past `target.rev` but took later content it did not derive itself (a replica, a restore);
|
|
189
|
+
* another cohort member that applied those revisions locally can still answer.
|
|
190
|
+
*/
|
|
191
|
+
lineageOf(target: ActionRev): Promise<BlockLineage>;
|
|
140
192
|
/**
|
|
141
193
|
* Persist a replica of a block received out-of-band (churn re-replication).
|
|
142
194
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"i-block-storage.d.ts","sourceRoot":"","sources":["../../../src/storage/i-block-storage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"i-block-storage.d.ts","sourceRoot":"","sources":["../../../src/storage/i-block-storage.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"i-block-storage.js","sourceRoot":"","sources":["../../../src/storage/i-block-storage.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"i-block-storage.js","sourceRoot":"","sources":["../../../src/storage/i-block-storage.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;GAUG;AACH,MAAM,OAAO,uBAAwB,SAAQ,KAAK;IAC5B;IAA2B;IAAhD,YAAqB,OAAgB,EAAW,GAAW;QAC1D,KAAK,CAAC,SAAS,OAAO,aAAa,GAAG,kCAAkC,CAAC,CAAC;QADtD,YAAO,GAAP,OAAO,CAAS;QAAW,QAAG,GAAH,GAAG,CAAQ;QAE1D,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;IACvC,CAAC;CACD;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,sBAAuB,SAAQ,KAAK;IAC3B;IAA2B;IAA6B;IAAsB;IAAnG,YAAqB,OAAgB,EAAW,QAAkB,EAAW,GAAW,EAAW,MAAiB;QACnH,KAAK,CAAC,SAAS,OAAO,wBAAwB,QAAQ,gBAAgB,GAAG,iBAAiB;cACvF,iCAAiC,MAAM,CAAC,GAAG,YAAY,MAAM,CAAC,QAAQ,YAAY;cAClF,wCAAwC,CAAC,CAAC;QAHzB,YAAO,GAAP,OAAO,CAAS;QAAW,aAAQ,GAAR,QAAQ,CAAU;QAAW,QAAG,GAAH,GAAG,CAAQ;QAAW,WAAM,GAAN,MAAM,CAAW;QAInH,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;IACtC,CAAC;CACD"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import type { ActionId, BlockId, PendRequest, Transform } from "@optimystic/db-core";
|
|
2
|
+
/**
|
|
3
|
+
* One pending record on a block, with the revision its pend asked for.
|
|
4
|
+
*
|
|
5
|
+
* `rev` is the `PendRequest.rev` the record was written under (see
|
|
6
|
+
* `IBlockStorage.savePendingTransaction`), kept in the block's metadata beside `latest`
|
|
7
|
+
* (`BlockMetadata.pendingRevs`). Absent for a record that named no revision — an insert-only pend,
|
|
8
|
+
* which no production caller sends — and for a record written before the revision was kept at all.
|
|
9
|
+
* Both read as "unknown", and an unknown claim is treated as the strongest one (see
|
|
10
|
+
* {@link isReservationAgainst}), so an old record can only refuse more than it should, never less.
|
|
11
|
+
*/
|
|
12
|
+
export interface PendingClaim {
|
|
13
|
+
actionId: ActionId;
|
|
14
|
+
rev?: number;
|
|
15
|
+
/**
|
|
16
|
+
* The committed revision the record's update operations were computed against — the pend's
|
|
17
|
+
* `baseRevs[blockId]`, kept in `BlockMetadata.pendingBases`. Absent for a record whose pend
|
|
18
|
+
* carried no base for this block (inserted, deleted, or unknown to the author) and for a record
|
|
19
|
+
* written before the field existed; both read as "base unknown". Unlike an unknown `rev`, an
|
|
20
|
+
* unknown base is NOT the strongest kind of anything: it is simply nothing to compare, and each
|
|
21
|
+
* apply site decides what that means for it (`StorageRepo.internalCommit` falls back to the
|
|
22
|
+
* commit's own declaration; the read-driven promotion in `StorageRepo.get` declines; the rival
|
|
23
|
+
* rule, {@link isReservationAgainst}, keeps the revision rule for it).
|
|
24
|
+
*/
|
|
25
|
+
baseRev?: number;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* What {@link isReservationAgainst} reads of an incoming pend, for one block: the revision it
|
|
29
|
+
* requests, and the committed base the block's update operations were computed against — built from
|
|
30
|
+
* the pend by {@link reservationRequestFor}, so the rule reads exactly the base storage would keep.
|
|
31
|
+
*/
|
|
32
|
+
export interface ReservationRequest {
|
|
33
|
+
rev?: number;
|
|
34
|
+
baseRev?: number;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Whether a rival's pending record is a RESERVATION against an incoming pend for the same block —
|
|
38
|
+
* the one question both rival scans ask (`StorageRepo.pend` at apply,
|
|
39
|
+
* `ClusterMember.validatePendOperations` at the promise vote).
|
|
40
|
+
*
|
|
41
|
+
* A pending record reserves the block for the revision it claims: it says "I am about to commit
|
|
42
|
+
* this block at revision `rev`", and it holds that slot from pend-apply until its commit or cancel.
|
|
43
|
+
* It stops reserving once the incoming writer has BUILT ON it — read the block with that change in
|
|
44
|
+
* it — because then admitting the newcomer cannot lose the change, whatever became of the record's
|
|
45
|
+
* action. The rule, first match wins:
|
|
46
|
+
*
|
|
47
|
+
* - Either side's revision unknown → reserves. A record predating revision recording keeps the
|
|
48
|
+
* old behaviour rather than silently admitting a rival, and a rev-less request cannot be placed
|
|
49
|
+
* past anything.
|
|
50
|
+
* - The record carries a base AND the request carries a usable one ({@link usableBase}: a number
|
|
51
|
+
* below the requested revision) → reserves iff `claim.rev > baseRev`. A base at or past the
|
|
52
|
+
* claimed slot means the newcomer's operations were computed against a version of the block that
|
|
53
|
+
* already holds the record's change (it committed there, and this member merely missed the
|
|
54
|
+
* commit — the newcomer's own commit brings it current), or against a version past a slot the
|
|
55
|
+
* record lost. A base below it means the newcomer read the block without that change, and
|
|
56
|
+
* admitting it would let its commit apply over the stale base and sweep the record — the rival's
|
|
57
|
+
* change lost while the log names it.
|
|
58
|
+
* - Otherwise → reserves iff `claim.rev >= rev` (the revision rule). Revisions are allocated per
|
|
59
|
+
* COLLECTION and a writer pends at one past the collection revision it read, so a claim below the
|
|
60
|
+
* requested revision is one the collection has moved past, which is taken as having been built
|
|
61
|
+
* on. That is sound when the newcomer read the block from a member that held the record
|
|
62
|
+
* (`StorageRepo.get` promotes a record for any action the reader's context names, with the block
|
|
63
|
+
* floor, `BlockGets.floors`, as the second line), and false in exactly one shape: a member that
|
|
64
|
+
* never received the rival's pend — possible only where the promise quorum can leave a member
|
|
65
|
+
* out, see {@link cohortCanMissAPend} — serving a floor-less handle while the rival's data-block
|
|
66
|
+
* commit is still in flight. It stays the rule for a request with no usable base (an inserted or
|
|
67
|
+
* deleted block, a sender that names none, or a malformed base), and for a record with no stored
|
|
68
|
+
* base (an inserted or deleted block, or a record written by a release that did not keep bases).
|
|
69
|
+
* A base-less record keeps clearing the moment the collection moves past its slot, as it always
|
|
70
|
+
* did: judged by the newcomer's base, one whose commit ran nowhere could never clear, since no
|
|
71
|
+
* member can promote it (the read-driven promotion declines a record with no base), and a node
|
|
72
|
+
* upgraded over its own leftovers would wedge on them. The price: a rival that DELETES the block
|
|
73
|
+
* keeps no base either, so the missed-pend shape below stays open for a rival delete, exactly as
|
|
74
|
+
* it was before the base arm existed.
|
|
75
|
+
*
|
|
76
|
+
* The base arm is never more permissive than the revision arm: an honest base is at most `rev - 1`,
|
|
77
|
+
* so a claim at or below the base is also below the requested revision. It can only hold more,
|
|
78
|
+
* which is why the safety argument of Theorem 1 does not weaken. It closes the missed-pend shape
|
|
79
|
+
* wherever the members still holding the rival's record are enough to deny the newcomer a
|
|
80
|
+
* super-majority — one member missing the pend leaves every other one holding it — and a member
|
|
81
|
+
* that has meanwhile taken the rival's change refuses the newcomer's commit at the fork guard
|
|
82
|
+
* (`StorageRepo.internalCommit`) instead. Liveness for the missed-commit
|
|
83
|
+
* shape (`a-member-that-missed-a-commit-refuses-every-later-write`) is preserved: a writer that read
|
|
84
|
+
* the block from a member that applied the rival's change declares at least that revision as its
|
|
85
|
+
* base, and one served by the missed-commit member itself is served after that member promotes the
|
|
86
|
+
* record, which it does whenever the record's stored base equals its latest.
|
|
87
|
+
*
|
|
88
|
+
* WHERE the base is read is the callers' decision, and deliberately narrow: only the promise vote
|
|
89
|
+
* reads it, and only for a cohort whose quorum can leave a member out ({@link cohortCanMissAPend});
|
|
90
|
+
* the apply-time scan in `StorageRepo.pend`, and the vote in every smaller cohort, pass no base. So
|
|
91
|
+
* the apply never refuses what the vote approved. Holding more costs liveness in two shapes, and the
|
|
92
|
+
* narrowing keeps both off cohorts that need unanimity (two and three members at the default
|
|
93
|
+
* threshold), where one member's hold sinks the pend: (1) a newcomer that read the block one change
|
|
94
|
+
* short is held until the rival commits, and its retries do not re-read the block today, so it then
|
|
95
|
+
* re-pends on the stale base and the fork guard refuses its commit — refused, never acknowledged over
|
|
96
|
+
* the rival (backlog `bug-a-writer-held-by-a-change-it-never-saw-retries-on-its-stale-copy`); (2) a
|
|
97
|
+
* record whose change no member will ever take — an abandoned action whose data-block pend landed,
|
|
98
|
+
* whose log-tail pend did not, and whose cancel never arrived — used to be superseded as soon as the
|
|
99
|
+
* collection moved past its slot, and under the base arm holds every newcomer instead.
|
|
100
|
+
*
|
|
101
|
+
* NOTE: from four members up, residual (2) wedges the block when the stray record stands on enough
|
|
102
|
+
* members to deny a super-majority (a writer that crashed after its data-block pend, before any
|
|
103
|
+
* cancel); a stray record on one member alone is outvoted, and that member's own apply (revision
|
|
104
|
+
* rule) then admits the newcomer, whose commit sweeps the record. Locally the member cannot tell the
|
|
105
|
+
* crashed writer's record from the missed-pend shape: both are a record claiming a slot past the
|
|
106
|
+
* block's latest, met by a newcomer whose base is that latest. Backlog
|
|
107
|
+
* `debt-unpromotable-pending-records-need-a-sweep` owns abandoned records, and both stuck-reservation
|
|
108
|
+
* lines name the block; if it shows up in the field, the cure is that sweep, not a looser rule here.
|
|
109
|
+
*/
|
|
110
|
+
export declare function isReservationAgainst(claim: PendingClaim, request: ReservationRequest): boolean;
|
|
111
|
+
/**
|
|
112
|
+
* Whether a cohort of `peerCount` members, promising at `superMajorityThreshold`, can reach its
|
|
113
|
+
* promise super-majority without one of its members — so a member can miss a pend the rest of the
|
|
114
|
+
* cohort stored, and later serve the block one change short. That is the only shape the base arm of
|
|
115
|
+
* {@link isReservationAgainst} closes, and it is also exactly where one member's hold cannot sink a
|
|
116
|
+
* pend by itself. Below it (two and three members at the default 0.75) every member's approval is
|
|
117
|
+
* needed, so the base arm could only add holds that no lost update justifies. The promise vote
|
|
118
|
+
* reads the incoming base only when this is true.
|
|
119
|
+
*/
|
|
120
|
+
export declare function cohortCanMissAPend(peerCount: number, superMajorityThreshold: number): boolean;
|
|
121
|
+
/**
|
|
122
|
+
* `request.baseRev` when {@link isReservationAgainst} can read it: a number strictly below the
|
|
123
|
+
* requested revision. Anything else — absent, not a number (untrusted wire data), or at or past
|
|
124
|
+
* `rev`, which no honest writer sends since its base is a revision it read and it pends past what it
|
|
125
|
+
* read — is `undefined`, and the rule falls back to the requested revision alone.
|
|
126
|
+
*/
|
|
127
|
+
export declare function usableBase(request: ReservationRequest): number | undefined;
|
|
128
|
+
/**
|
|
129
|
+
* The {@link ReservationRequest} `pend` makes of `blockId`, whose transform within the pend is
|
|
130
|
+
* `transform`: the pend's revision, and the base {@link declaredBaseFor} keeps for the block — so a
|
|
131
|
+
* base on an inserted or deleted block, or a malformed one, is read by the rule exactly as storage
|
|
132
|
+
* keeps it: not at all. `ignoredBase` carries a base the pend named for the block that the rule does
|
|
133
|
+
* not read (malformed, not below the revision, or on a base-independent transform), for the caller's
|
|
134
|
+
* log line; no producer sends one.
|
|
135
|
+
*/
|
|
136
|
+
export declare function reservationRequestFor(pend: Pick<PendRequest, 'rev' | 'baseRevs'>, blockId: BlockId, transform: Transform): {
|
|
137
|
+
request: ReservationRequest;
|
|
138
|
+
ignoredBase?: unknown;
|
|
139
|
+
};
|
|
140
|
+
/**
|
|
141
|
+
* Whether `transform`'s result does not depend on the block's prior content: an insert replaces the
|
|
142
|
+
* block wholesale and a delete materializes to nothing (delete-last-wins in `applyTransform`), so
|
|
143
|
+
* neither can fork on a different base, and no base is ever named for them (`Tracker.stagedBaseRevs`
|
|
144
|
+
* names update-only blocks alone). Every base check keys on this, on the member's OWN pended
|
|
145
|
+
* transform (or the incoming pend's own transform, at the rival scans), never on what a request
|
|
146
|
+
* declares.
|
|
147
|
+
*/
|
|
148
|
+
export declare function isBaseIndependent(transform: Transform): boolean;
|
|
149
|
+
/**
|
|
150
|
+
* The base a pend declares for `blockId`, as storage will keep it: `baseRevs[blockId]` when it is a
|
|
151
|
+
* number and the block's transform is update-only, else nothing. Untrusted wire data with no ingress
|
|
152
|
+
* schema (the posture `validateCommitOperations` takes toward `blockDigests`): a malformed or surplus
|
|
153
|
+
* entry is ignored for that id, never thrown on; an entry for an inserted or deleted block — which no
|
|
154
|
+
* producer sends — is dropped, so a base-independent record can never read as base-dependent later.
|
|
155
|
+
*
|
|
156
|
+
* NOTE: the base is stored AS TOLD, and the pend never refuses on it — not when it is behind this
|
|
157
|
+
* member's latest, and not when it is ahead. A member has no grounds to second-guess the author's
|
|
158
|
+
* claim about the author's own computation (the client is what makes an honest claim correct:
|
|
159
|
+
* `Tracker` pins the base at the first staged update and re-stages over a moved one). Refusing here
|
|
160
|
+
* would also be the wrong tier: a member holding a torn or abandoned HIGHER revision would cast a
|
|
161
|
+
* reject that, at three members, fails every honest retry — the writer re-reads the majority's
|
|
162
|
+
* revision and declares it again — whereas the same mismatch at commit time is one member's refusal
|
|
163
|
+
* (`StorageRepo.internalCommit`), heals by reconcile, and the cohort still commits on majority
|
|
164
|
+
* durability.
|
|
165
|
+
*/
|
|
166
|
+
export declare function declaredBaseFor(baseRevs: PendRequest['baseRevs'], blockId: BlockId, transform: Transform): number | undefined;
|
|
167
|
+
//# sourceMappingURL=pending-claim.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pending-claim.d.ts","sourceRoot":"","sources":["../../../src/storage/pending-claim.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAErF;;;;;;;;;GASG;AACH,MAAM,WAAW,YAAY;IAC5B,QAAQ,EAAE,QAAQ,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;;;;;;OASG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IAClC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyEG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAM9F;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,sBAAsB,EAAE,MAAM,GAAG,OAAO,CAE7F;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,kBAAkB,GAAG,MAAM,GAAG,SAAS,CAG1E;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACpC,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,KAAK,GAAG,UAAU,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,GACjF;IAAE,OAAO,EAAE,kBAAkB,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE,CAQxD;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAE/D;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,WAAW,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,GAAG,MAAM,GAAG,SAAS,CAM7H"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether a rival's pending record is a RESERVATION against an incoming pend for the same block —
|
|
3
|
+
* the one question both rival scans ask (`StorageRepo.pend` at apply,
|
|
4
|
+
* `ClusterMember.validatePendOperations` at the promise vote).
|
|
5
|
+
*
|
|
6
|
+
* A pending record reserves the block for the revision it claims: it says "I am about to commit
|
|
7
|
+
* this block at revision `rev`", and it holds that slot from pend-apply until its commit or cancel.
|
|
8
|
+
* It stops reserving once the incoming writer has BUILT ON it — read the block with that change in
|
|
9
|
+
* it — because then admitting the newcomer cannot lose the change, whatever became of the record's
|
|
10
|
+
* action. The rule, first match wins:
|
|
11
|
+
*
|
|
12
|
+
* - Either side's revision unknown → reserves. A record predating revision recording keeps the
|
|
13
|
+
* old behaviour rather than silently admitting a rival, and a rev-less request cannot be placed
|
|
14
|
+
* past anything.
|
|
15
|
+
* - The record carries a base AND the request carries a usable one ({@link usableBase}: a number
|
|
16
|
+
* below the requested revision) → reserves iff `claim.rev > baseRev`. A base at or past the
|
|
17
|
+
* claimed slot means the newcomer's operations were computed against a version of the block that
|
|
18
|
+
* already holds the record's change (it committed there, and this member merely missed the
|
|
19
|
+
* commit — the newcomer's own commit brings it current), or against a version past a slot the
|
|
20
|
+
* record lost. A base below it means the newcomer read the block without that change, and
|
|
21
|
+
* admitting it would let its commit apply over the stale base and sweep the record — the rival's
|
|
22
|
+
* change lost while the log names it.
|
|
23
|
+
* - Otherwise → reserves iff `claim.rev >= rev` (the revision rule). Revisions are allocated per
|
|
24
|
+
* COLLECTION and a writer pends at one past the collection revision it read, so a claim below the
|
|
25
|
+
* requested revision is one the collection has moved past, which is taken as having been built
|
|
26
|
+
* on. That is sound when the newcomer read the block from a member that held the record
|
|
27
|
+
* (`StorageRepo.get` promotes a record for any action the reader's context names, with the block
|
|
28
|
+
* floor, `BlockGets.floors`, as the second line), and false in exactly one shape: a member that
|
|
29
|
+
* never received the rival's pend — possible only where the promise quorum can leave a member
|
|
30
|
+
* out, see {@link cohortCanMissAPend} — serving a floor-less handle while the rival's data-block
|
|
31
|
+
* commit is still in flight. It stays the rule for a request with no usable base (an inserted or
|
|
32
|
+
* deleted block, a sender that names none, or a malformed base), and for a record with no stored
|
|
33
|
+
* base (an inserted or deleted block, or a record written by a release that did not keep bases).
|
|
34
|
+
* A base-less record keeps clearing the moment the collection moves past its slot, as it always
|
|
35
|
+
* did: judged by the newcomer's base, one whose commit ran nowhere could never clear, since no
|
|
36
|
+
* member can promote it (the read-driven promotion declines a record with no base), and a node
|
|
37
|
+
* upgraded over its own leftovers would wedge on them. The price: a rival that DELETES the block
|
|
38
|
+
* keeps no base either, so the missed-pend shape below stays open for a rival delete, exactly as
|
|
39
|
+
* it was before the base arm existed.
|
|
40
|
+
*
|
|
41
|
+
* The base arm is never more permissive than the revision arm: an honest base is at most `rev - 1`,
|
|
42
|
+
* so a claim at or below the base is also below the requested revision. It can only hold more,
|
|
43
|
+
* which is why the safety argument of Theorem 1 does not weaken. It closes the missed-pend shape
|
|
44
|
+
* wherever the members still holding the rival's record are enough to deny the newcomer a
|
|
45
|
+
* super-majority — one member missing the pend leaves every other one holding it — and a member
|
|
46
|
+
* that has meanwhile taken the rival's change refuses the newcomer's commit at the fork guard
|
|
47
|
+
* (`StorageRepo.internalCommit`) instead. Liveness for the missed-commit
|
|
48
|
+
* shape (`a-member-that-missed-a-commit-refuses-every-later-write`) is preserved: a writer that read
|
|
49
|
+
* the block from a member that applied the rival's change declares at least that revision as its
|
|
50
|
+
* base, and one served by the missed-commit member itself is served after that member promotes the
|
|
51
|
+
* record, which it does whenever the record's stored base equals its latest.
|
|
52
|
+
*
|
|
53
|
+
* WHERE the base is read is the callers' decision, and deliberately narrow: only the promise vote
|
|
54
|
+
* reads it, and only for a cohort whose quorum can leave a member out ({@link cohortCanMissAPend});
|
|
55
|
+
* the apply-time scan in `StorageRepo.pend`, and the vote in every smaller cohort, pass no base. So
|
|
56
|
+
* the apply never refuses what the vote approved. Holding more costs liveness in two shapes, and the
|
|
57
|
+
* narrowing keeps both off cohorts that need unanimity (two and three members at the default
|
|
58
|
+
* threshold), where one member's hold sinks the pend: (1) a newcomer that read the block one change
|
|
59
|
+
* short is held until the rival commits, and its retries do not re-read the block today, so it then
|
|
60
|
+
* re-pends on the stale base and the fork guard refuses its commit — refused, never acknowledged over
|
|
61
|
+
* the rival (backlog `bug-a-writer-held-by-a-change-it-never-saw-retries-on-its-stale-copy`); (2) a
|
|
62
|
+
* record whose change no member will ever take — an abandoned action whose data-block pend landed,
|
|
63
|
+
* whose log-tail pend did not, and whose cancel never arrived — used to be superseded as soon as the
|
|
64
|
+
* collection moved past its slot, and under the base arm holds every newcomer instead.
|
|
65
|
+
*
|
|
66
|
+
* NOTE: from four members up, residual (2) wedges the block when the stray record stands on enough
|
|
67
|
+
* members to deny a super-majority (a writer that crashed after its data-block pend, before any
|
|
68
|
+
* cancel); a stray record on one member alone is outvoted, and that member's own apply (revision
|
|
69
|
+
* rule) then admits the newcomer, whose commit sweeps the record. Locally the member cannot tell the
|
|
70
|
+
* crashed writer's record from the missed-pend shape: both are a record claiming a slot past the
|
|
71
|
+
* block's latest, met by a newcomer whose base is that latest. Backlog
|
|
72
|
+
* `debt-unpromotable-pending-records-need-a-sweep` owns abandoned records, and both stuck-reservation
|
|
73
|
+
* lines name the block; if it shows up in the field, the cure is that sweep, not a looser rule here.
|
|
74
|
+
*/
|
|
75
|
+
export function isReservationAgainst(claim, request) {
|
|
76
|
+
if (claim.rev === undefined || request.rev === undefined) {
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
const base = claim.baseRev === undefined ? undefined : usableBase(request);
|
|
80
|
+
return base === undefined ? claim.rev >= request.rev : claim.rev > base;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Whether a cohort of `peerCount` members, promising at `superMajorityThreshold`, can reach its
|
|
84
|
+
* promise super-majority without one of its members — so a member can miss a pend the rest of the
|
|
85
|
+
* cohort stored, and later serve the block one change short. That is the only shape the base arm of
|
|
86
|
+
* {@link isReservationAgainst} closes, and it is also exactly where one member's hold cannot sink a
|
|
87
|
+
* pend by itself. Below it (two and three members at the default 0.75) every member's approval is
|
|
88
|
+
* needed, so the base arm could only add holds that no lost update justifies. The promise vote
|
|
89
|
+
* reads the incoming base only when this is true.
|
|
90
|
+
*/
|
|
91
|
+
export function cohortCanMissAPend(peerCount, superMajorityThreshold) {
|
|
92
|
+
return Math.ceil(peerCount * superMajorityThreshold) < peerCount;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* `request.baseRev` when {@link isReservationAgainst} can read it: a number strictly below the
|
|
96
|
+
* requested revision. Anything else — absent, not a number (untrusted wire data), or at or past
|
|
97
|
+
* `rev`, which no honest writer sends since its base is a revision it read and it pends past what it
|
|
98
|
+
* read — is `undefined`, and the rule falls back to the requested revision alone.
|
|
99
|
+
*/
|
|
100
|
+
export function usableBase(request) {
|
|
101
|
+
const { rev, baseRev } = request;
|
|
102
|
+
return typeof baseRev === 'number' && rev !== undefined && baseRev < rev ? baseRev : undefined;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* The {@link ReservationRequest} `pend` makes of `blockId`, whose transform within the pend is
|
|
106
|
+
* `transform`: the pend's revision, and the base {@link declaredBaseFor} keeps for the block — so a
|
|
107
|
+
* base on an inserted or deleted block, or a malformed one, is read by the rule exactly as storage
|
|
108
|
+
* keeps it: not at all. `ignoredBase` carries a base the pend named for the block that the rule does
|
|
109
|
+
* not read (malformed, not below the revision, or on a base-independent transform), for the caller's
|
|
110
|
+
* log line; no producer sends one.
|
|
111
|
+
*/
|
|
112
|
+
export function reservationRequestFor(pend, blockId, transform) {
|
|
113
|
+
const request = { rev: pend.rev };
|
|
114
|
+
const baseRev = declaredBaseFor(pend.baseRevs, blockId, transform);
|
|
115
|
+
if (baseRev !== undefined) {
|
|
116
|
+
request.baseRev = baseRev;
|
|
117
|
+
}
|
|
118
|
+
const named = pend.baseRevs?.[blockId];
|
|
119
|
+
return named !== undefined && usableBase(request) === undefined ? { request, ignoredBase: named } : { request };
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Whether `transform`'s result does not depend on the block's prior content: an insert replaces the
|
|
123
|
+
* block wholesale and a delete materializes to nothing (delete-last-wins in `applyTransform`), so
|
|
124
|
+
* neither can fork on a different base, and no base is ever named for them (`Tracker.stagedBaseRevs`
|
|
125
|
+
* names update-only blocks alone). Every base check keys on this, on the member's OWN pended
|
|
126
|
+
* transform (or the incoming pend's own transform, at the rival scans), never on what a request
|
|
127
|
+
* declares.
|
|
128
|
+
*/
|
|
129
|
+
export function isBaseIndependent(transform) {
|
|
130
|
+
return Boolean(transform.insert) || Boolean(transform.delete);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* The base a pend declares for `blockId`, as storage will keep it: `baseRevs[blockId]` when it is a
|
|
134
|
+
* number and the block's transform is update-only, else nothing. Untrusted wire data with no ingress
|
|
135
|
+
* schema (the posture `validateCommitOperations` takes toward `blockDigests`): a malformed or surplus
|
|
136
|
+
* entry is ignored for that id, never thrown on; an entry for an inserted or deleted block — which no
|
|
137
|
+
* producer sends — is dropped, so a base-independent record can never read as base-dependent later.
|
|
138
|
+
*
|
|
139
|
+
* NOTE: the base is stored AS TOLD, and the pend never refuses on it — not when it is behind this
|
|
140
|
+
* member's latest, and not when it is ahead. A member has no grounds to second-guess the author's
|
|
141
|
+
* claim about the author's own computation (the client is what makes an honest claim correct:
|
|
142
|
+
* `Tracker` pins the base at the first staged update and re-stages over a moved one). Refusing here
|
|
143
|
+
* would also be the wrong tier: a member holding a torn or abandoned HIGHER revision would cast a
|
|
144
|
+
* reject that, at three members, fails every honest retry — the writer re-reads the majority's
|
|
145
|
+
* revision and declares it again — whereas the same mismatch at commit time is one member's refusal
|
|
146
|
+
* (`StorageRepo.internalCommit`), heals by reconcile, and the cohort still commits on majority
|
|
147
|
+
* durability.
|
|
148
|
+
*/
|
|
149
|
+
export function declaredBaseFor(baseRevs, blockId, transform) {
|
|
150
|
+
if (isBaseIndependent(transform)) {
|
|
151
|
+
return undefined;
|
|
152
|
+
}
|
|
153
|
+
const declared = baseRevs?.[blockId];
|
|
154
|
+
return typeof declared === 'number' ? declared : undefined;
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=pending-claim.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pending-claim.js","sourceRoot":"","sources":["../../../src/storage/pending-claim.ts"],"names":[],"mappings":"AAsCA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyEG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAmB,EAAE,OAA2B;IACpF,IAAI,KAAK,CAAC,GAAG,KAAK,SAAS,IAAI,OAAO,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;QAC1D,OAAO,IAAI,CAAC;IACb,CAAC;IACD,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;IAC3E,OAAO,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC;AACzE,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB,CAAC,SAAiB,EAAE,sBAA8B;IACnF,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,GAAG,sBAAsB,CAAC,GAAG,SAAS,CAAC;AAClE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,OAA2B;IACrD,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IACjC,OAAO,OAAO,OAAO,KAAK,QAAQ,IAAI,GAAG,KAAK,SAAS,IAAI,OAAO,GAAG,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;AAChG,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB,CACpC,IAA2C,EAAE,OAAgB,EAAE,SAAoB;IAEnF,MAAM,OAAO,GAAuB,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC;IACtD,MAAM,OAAO,GAAG,eAAe,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;IACnE,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO,CAAC,OAAO,GAAG,OAAO,CAAC;IAC3B,CAAC;IACD,MAAM,KAAK,GAAY,IAAI,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,CAAC;IAChD,OAAO,KAAK,KAAK,SAAS,IAAI,UAAU,CAAC,OAAO,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC;AACjH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,SAAoB;IACrD,OAAO,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;AAC/D,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,eAAe,CAAC,QAAiC,EAAE,OAAgB,EAAE,SAAoB;IACxG,IAAI,iBAAiB,CAAC,SAAS,CAAC,EAAE,CAAC;QAClC,OAAO,SAAS,CAAC;IAClB,CAAC;IACD,MAAM,QAAQ,GAAG,QAAQ,EAAE,CAAC,OAAO,CAAC,CAAC;IACrC,OAAO,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;AAC5D,CAAC"}
|
|
@@ -7,4 +7,17 @@ export declare function decodeJson<T>(bytes: Uint8Array): T;
|
|
|
7
7
|
export declare function encodeActionId(actionId: ActionId): Uint8Array;
|
|
8
8
|
/** Decode UTF-8 bytes back into an `ActionId` string. */
|
|
9
9
|
export declare function decodeActionId(bytes: Uint8Array): ActionId;
|
|
10
|
+
/**
|
|
11
|
+
* Deep-copy a value this codec decoded (`IBlock` / `Transform`), by the same JSON round-trip the
|
|
12
|
+
* store applies. Used where a caller must mutate a stored value without touching the original, in
|
|
13
|
+
* place of `structuredClone` — which Hermes (React Native) does not provide.
|
|
14
|
+
*
|
|
15
|
+
* Lossless for exactly the values this module hands out: anything `decodeJson` returned is already
|
|
16
|
+
* JSON-shaped, so it carries none of what a JSON round-trip drops or rewrites (an `undefined` array
|
|
17
|
+
* slot, an `undefined`-valued property, a `Date`, a `Uint8Array`) — those were already rewritten when
|
|
18
|
+
* the value was stored. It is NOT a general-purpose `structuredClone` replacement: a live object
|
|
19
|
+
* that never crossed this codec can come back different. `undefined` passes through, since
|
|
20
|
+
* `JSON.parse(JSON.stringify(undefined))` throws.
|
|
21
|
+
*/
|
|
22
|
+
export declare function cloneDecoded<T>(value: T): T;
|
|
10
23
|
//# sourceMappingURL=raw-store-codec.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"raw-store-codec.d.ts","sourceRoot":"","sources":["../../../src/storage/raw-store-codec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"raw-store-codec.d.ts","sourceRoot":"","sources":["../../../src/storage/raw-store-codec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AA8BpD,qFAAqF;AACrF,wBAAgB,UAAU,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,UAAU,CAElD;AAED,6FAA6F;AAC7F,wBAAgB,UAAU,CAAC,CAAC,EAAE,KAAK,EAAE,UAAU,GAAG,CAAC,CAElD;AAED,wFAAwF;AACxF,wBAAgB,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,UAAU,CAE7D;AAED,yDAAyD;AACzD,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,GAAG,QAAQ,CAE1D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAE3C"}
|
|
@@ -15,15 +15,21 @@
|
|
|
15
15
|
* → `"[5]"` → `JSON.parse` → `[5]`, so the open-ended encoding survives byte-exact.
|
|
16
16
|
* Do NOT normalize ranges here.
|
|
17
17
|
*/
|
|
18
|
+
// The encoder stays module-scope: Hermes provides `TextEncoder` natively (React Native 0.74+).
|
|
18
19
|
const encoder = new TextEncoder();
|
|
19
|
-
|
|
20
|
+
// The decoder is built on first use, NOT at module load. Hermes has no native `TextDecoder`, and
|
|
21
|
+
// this module is loaded by the React Native entry (`rn.ts`, via `kv-raw-storage.ts`), so a
|
|
22
|
+
// module-scope `new TextDecoder()` made the import itself throw whenever it ran ahead of the host's
|
|
23
|
+
// polyfill (readme.md § React Native). Memoized, so every call shares one instance as before.
|
|
24
|
+
let decoderInstance;
|
|
25
|
+
const decoder = () => decoderInstance ??= new TextDecoder();
|
|
20
26
|
/** JSON-encode a value (`BlockMetadata` / `Transform` / `IBlock`) to UTF-8 bytes. */
|
|
21
27
|
export function encodeJson(value) {
|
|
22
28
|
return encoder.encode(JSON.stringify(value));
|
|
23
29
|
}
|
|
24
30
|
/** Decode UTF-8 JSON bytes back into a value. Callers guard the miss (`undefined`) first. */
|
|
25
31
|
export function decodeJson(bytes) {
|
|
26
|
-
return JSON.parse(decoder.decode(bytes));
|
|
32
|
+
return JSON.parse(decoder().decode(bytes));
|
|
27
33
|
}
|
|
28
34
|
/** Encode an `ActionId` string to UTF-8 bytes (stored as the revisions-store value). */
|
|
29
35
|
export function encodeActionId(actionId) {
|
|
@@ -31,6 +37,21 @@ export function encodeActionId(actionId) {
|
|
|
31
37
|
}
|
|
32
38
|
/** Decode UTF-8 bytes back into an `ActionId` string. */
|
|
33
39
|
export function decodeActionId(bytes) {
|
|
34
|
-
return decoder.decode(bytes);
|
|
40
|
+
return decoder().decode(bytes);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Deep-copy a value this codec decoded (`IBlock` / `Transform`), by the same JSON round-trip the
|
|
44
|
+
* store applies. Used where a caller must mutate a stored value without touching the original, in
|
|
45
|
+
* place of `structuredClone` — which Hermes (React Native) does not provide.
|
|
46
|
+
*
|
|
47
|
+
* Lossless for exactly the values this module hands out: anything `decodeJson` returned is already
|
|
48
|
+
* JSON-shaped, so it carries none of what a JSON round-trip drops or rewrites (an `undefined` array
|
|
49
|
+
* slot, an `undefined`-valued property, a `Date`, a `Uint8Array`) — those were already rewritten when
|
|
50
|
+
* the value was stored. It is NOT a general-purpose `structuredClone` replacement: a live object
|
|
51
|
+
* that never crossed this codec can come back different. `undefined` passes through, since
|
|
52
|
+
* `JSON.parse(JSON.stringify(undefined))` throws.
|
|
53
|
+
*/
|
|
54
|
+
export function cloneDecoded(value) {
|
|
55
|
+
return value === undefined ? value : JSON.parse(JSON.stringify(value));
|
|
35
56
|
}
|
|
36
57
|
//# sourceMappingURL=raw-store-codec.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"raw-store-codec.js","sourceRoot":"","sources":["../../../src/storage/raw-store-codec.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;GAgBG;AAEH,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"raw-store-codec.js","sourceRoot":"","sources":["../../../src/storage/raw-store-codec.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;GAgBG;AAEH,+FAA+F;AAC/F,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;AAElC,iGAAiG;AACjG,2FAA2F;AAC3F,oGAAoG;AACpG,8FAA8F;AAC9F,IAAI,eAAwC,CAAC;AAC7C,MAAM,OAAO,GAAG,GAAgB,EAAE,CAAC,eAAe,KAAK,IAAI,WAAW,EAAE,CAAC;AAEzE,qFAAqF;AACrF,MAAM,UAAU,UAAU,CAAI,KAAQ;IACrC,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;AAC9C,CAAC;AAED,6FAA6F;AAC7F,MAAM,UAAU,UAAU,CAAI,KAAiB;IAC9C,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAM,CAAC;AACjD,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,cAAc,CAAC,QAAkB;IAChD,OAAO,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;AACjC,CAAC;AAED,yDAAyD;AACzD,MAAM,UAAU,cAAc,CAAC,KAAiB;IAC/C,OAAO,OAAO,EAAE,CAAC,MAAM,CAAC,KAAK,CAAa,CAAC;AAC5C,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,YAAY,CAAI,KAAQ;IACvC,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAM,CAAC;AAC7E,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"restoration-coordinator.d.ts","sourceRoot":"","sources":["../../../src/storage/restoration-coordinator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"restoration-coordinator.d.ts","sourceRoot":"","sources":["../../../src/storage/restoration-coordinator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAInD,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAIxE;;;;;;;;GAQG;AACH,qBAAa,sBAAsB;IASjC,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,iFAAiF;IACjF,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC;IAZ7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAKtB;gBAGgB,WAAW,EAAE,oBAAoB,EACjC,WAAW,EAAE,YAAY,EACzB,cAAc,EAAE,MAAM;IACvC,iFAAiF;IAChE,UAAU,CAAC,EAAE,MAAM,YAAA;IAGrC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAsC;IAE1D;;OAEG;IACG,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC;IA4DhF;;OAEG;IACH,qBAAqB,IAAI,eAAe;IAMxC;;;OAGG;IACH,OAAO,CAAC,cAAc;IAItB;;OAEG;IACH,OAAO,CAAC,cAAc;IAKtB;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IAazB;;OAEG;YACW,SAAS;IAiBvB;;OAEG;IACH,OAAO,CAAC,aAAa;IAarB;;;;;OAKG;IACH,OAAO,CAAC,aAAa;IAKrB;;OAEG;IACH,UAAU,IAAI;QACb,aAAa,EAAE,MAAM,CAAC;QACtB,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACnC,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACnC,iBAAiB,EAAE,MAAM,CAAC;KAC1B;CAWD"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { routingKeyForBlock } from '@optimystic/db-core';
|
|
1
2
|
import { hashKey } from 'p2p-fret';
|
|
2
3
|
import { peerIdFromString } from '@libp2p/peer-id';
|
|
3
4
|
import { SyncClient } from '../sync/client.js';
|
|
@@ -42,7 +43,7 @@ export class RestorationCoordinator {
|
|
|
42
43
|
// (RingSelector.calculatePartition) and cohort assembly both operate on hashed
|
|
43
44
|
// coords, so restoration must filter in the same space — see getMyRingPeers and
|
|
44
45
|
// filterByPartition below, which reuse this value.
|
|
45
|
-
const blockCoord = await hashKey(
|
|
46
|
+
const blockCoord = await hashKey(routingKeyForBlock(blockId));
|
|
46
47
|
// 1. Try my transaction ring peers first
|
|
47
48
|
const myPeers = this.getMyRingPeers(blockCoord);
|
|
48
49
|
const myRingDepth = this.getMyRingDepth();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"restoration-coordinator.js","sourceRoot":"","sources":["../../../src/storage/restoration-coordinator.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAkB,MAAM,UAAU,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAG/C,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C;;;;;;;;GAQG;AACH,MAAM,OAAO,sBAAsB;IAShB;IACA;IACA;IAEA;IAZD,OAAO,GAAG;QAC1B,aAAa,EAAE,CAAC;QAChB,aAAa,EAAE,IAAI,GAAG,EAAkB;QACxC,aAAa,EAAE,IAAI,GAAG,EAAkB;QACxC,iBAAiB,EAAE,CAAC;KACpB,CAAC;IAEF,YACkB,WAAiC,EACjC,WAAyB,EACzB,cAAsB;IACvC,iFAAiF;IAChE,UAAmB;QAJnB,gBAAW,GAAX,WAAW,CAAsB;QACjC,gBAAW,GAAX,WAAW,CAAc;QACzB,mBAAc,GAAd,cAAc,CAAQ;QAEtB,eAAU,GAAV,UAAU,CAAS;IAClC,CAAC;IAEa,GAAG,GAAG,YAAY,CAAC,qBAAqB,CAAC,CAAA;IAE1D;;OAEG;IACH,KAAK,CAAC,OAAO,CAAC,OAAgB,EAAE,GAAY;QAC3C,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;QAE7B,+EAA+E;QAC/E,+EAA+E;QAC/E,gFAAgF;QAChF,mDAAmD;QACnD,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"restoration-coordinator.js","sourceRoot":"","sources":["../../../src/storage/restoration-coordinator.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ring-shift-coordinator.d.ts","sourceRoot":"","sources":["../../../src/storage/ring-shift-coordinator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"ring-shift-coordinator.d.ts","sourceRoot":"","sources":["../../../src/storage/ring-shift-coordinator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAC1E,OAAO,KAAK,EAAE,oBAAoB,EAAiB,MAAM,6BAA6B,CAAC;AACvF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAMvD;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACpC,iBAAiB,CAChB,QAAQ,EAAE,MAAM,EAAE,EAClB,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EAC7B,KAAK,EAAE,MAAM,GACX,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,EAAE,CAAC;QAAC,WAAW,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;CAC3D;AAED,MAAM,WAAW,aAAa;IAC7B,WAAW,EAAE,oBAAoB,CAAC;IAClC,YAAY,EAAE,YAAY,CAAC;IAC3B,IAAI,EAAE,WAAW,CAAC;IAClB,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,4EAA4E;IAC5E,SAAS,EAAE,oBAAoB,CAAC;IAChC,8FAA8F;IAC9F,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACzB,kFAAkF;IAClF,UAAU,EAAE,MAAM,CAAC;IACnB,+FAA+F;IAC/F,QAAQ,EAAE,MAAM,MAAM,CAAC;IACvB;;;;OAIG;IACH,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;CACxC;AAED,MAAM,WAAW,eAAe;IAC/B;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,wFAAwF;AACxF,MAAM,MAAM,YAAY,GACrB;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,GACrE;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAChD;IAAE,MAAM,EAAE,aAAa,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACvD;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzC;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,oBAAoB;IAM/B,OAAO,CAAC,QAAQ,CAAC,IAAI;IALtB,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,yFAAyF;IACzF,OAAO,CAAC,QAAQ,CAAS;gBAGP,IAAI,EAAE,aAAa,EACpC,MAAM,GAAE,eAAoB;IAK7B;;;;OAIG;IACG,YAAY,CAAC,UAAU,EAAE;QAAE,SAAS,EAAE,IAAI,GAAG,KAAK,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,YAAY,CAAC;IAmBxG;;;;;;OAMG;IACH,gBAAgB,IAAI;QAAE,UAAU,EAAE,OAAO,CAAA;KAAE;YAiB7B,OAAO;IAgCrB;;;OAGG;YACW,gBAAgB;IAiB9B;;;OAGG;YACW,iBAAiB;IAc/B;;;;;OAKG;YACW,cAAc;YAkBd,MAAM;IAapB,wFAAwF;IACxF,OAAO,CAAC,QAAQ;IAkBhB,kGAAkG;IAClG,OAAO,CAAC,SAAS;CAIjB"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { hashKey } from 'p2p-fret';
|
|
2
|
+
import { routingKeyForBlock } from '@optimystic/db-core';
|
|
2
3
|
import { partitionCovers, qualifiesForFloor } from './arachnode-partition.js';
|
|
3
4
|
import { createLogger } from '../logger.js';
|
|
4
5
|
const log = createLogger('ring-shift');
|
|
5
|
-
const textEncoder = new TextEncoder();
|
|
6
6
|
/**
|
|
7
7
|
* Drives a single damped ring transition through the **advertise → confirm-replication → release**
|
|
8
8
|
* handoff (`docs/arachnode-ring-handoff.md` § Part 2), so a ring shift never drops a key below its
|
|
@@ -127,7 +127,7 @@ export class RingShiftCoordinator {
|
|
|
127
127
|
async computeShedBlocks(oldPartition, newPartition) {
|
|
128
128
|
const shed = [];
|
|
129
129
|
for (const blockId of this.deps.ownedBlocks) {
|
|
130
|
-
const coord = await hashKey(
|
|
130
|
+
const coord = await hashKey(routingKeyForBlock(blockId));
|
|
131
131
|
if (partitionCovers(oldPartition, coord) && !partitionCovers(newPartition, coord)) {
|
|
132
132
|
shed.push(blockId);
|
|
133
133
|
}
|
|
@@ -144,7 +144,7 @@ export class RingShiftCoordinator {
|
|
|
144
144
|
const owners = new Map();
|
|
145
145
|
const want = floor + 1 + this.candidateMargin; // headroom for self + excluded movers
|
|
146
146
|
for (const blockId of shed) {
|
|
147
|
-
const coord = await hashKey(
|
|
147
|
+
const coord = await hashKey(routingKeyForBlock(blockId));
|
|
148
148
|
const cohort = this.deps.fret.assembleCohort(coord, want);
|
|
149
149
|
const qualifying = cohort.filter(peerId => {
|
|
150
150
|
if (peerId === this.deps.selfPeerId)
|