@serfab/cadre-core 1.4.0 → 1.6.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/cadre-node.d.ts +38 -15
- package/dist/cadre-node.js +81 -29
- package/dist/cadre-node.js.map +1 -1
- package/dist/control-database.d.ts +24 -10
- package/dist/control-database.js +48 -16
- package/dist/control-database.js.map +1 -1
- package/dist/control-read-retry.d.ts +12 -0
- package/dist/control-read-retry.js +12 -0
- package/dist/control-read-retry.js.map +1 -1
- package/dist/control-write-retry.d.ts +5 -4
- package/dist/control-write-retry.js +24 -7
- package/dist/control-write-retry.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/link-budget.d.ts +224 -0
- package/dist/link-budget.js +239 -0
- package/dist/link-budget.js.map +1 -0
- package/dist/peer-dial.d.ts +36 -17
- package/dist/peer-dial.js +37 -17
- package/dist/peer-dial.js.map +1 -1
- package/dist/peer-join-backfill.d.ts +58 -4
- package/dist/peer-join-backfill.js +166 -20
- package/dist/peer-join-backfill.js.map +1 -1
- package/dist/relay-reservation.d.ts +59 -11
- package/dist/relay-reservation.js +169 -43
- package/dist/relay-reservation.js.map +1 -1
- package/dist/seed-bootstrap.js +2 -1
- package/dist/seed-bootstrap.js.map +1 -1
- package/dist/strand-first-sync-gate.d.ts +105 -22
- package/dist/strand-first-sync-gate.js +121 -27
- package/dist/strand-first-sync-gate.js.map +1 -1
- package/dist/strand-instance-manager.d.ts +27 -2
- package/dist/strand-instance-manager.js +60 -13
- package/dist/strand-instance-manager.js.map +1 -1
- package/dist/strand-membership-reconciler.d.ts +200 -45
- package/dist/strand-membership-reconciler.js +302 -86
- package/dist/strand-membership-reconciler.js.map +1 -1
- package/dist/strand-membership-writer.d.ts +3 -2
- package/dist/strand-membership-writer.js +67 -90
- package/dist/strand-membership-writer.js.map +1 -1
- package/dist/strand-network-config.d.ts +2 -2
- package/dist/strand-network-config.js +2 -2
- package/dist/types.d.ts +105 -9
- package/dist/types.js +20 -4
- package/dist/types.js.map +1 -1
- package/package.json +8 -8
- package/src/cadre-node.ts +7449 -7397
- package/src/control-database.ts +48 -16
- package/src/control-read-retry.ts +214 -202
- package/src/control-write-retry.ts +24 -7
- package/src/index.ts +582 -563
- package/src/link-budget.ts +264 -0
- package/src/peer-dial.ts +39 -17
- package/src/peer-join-backfill.ts +648 -478
- package/src/relay-reservation.ts +1119 -951
- package/src/seed-bootstrap.ts +2 -1
- package/src/strand-first-sync-gate.ts +352 -258
- package/src/strand-instance-manager.ts +1520 -1458
- package/src/strand-membership-reconciler.ts +334 -92
- package/src/strand-membership-writer.ts +1962 -1987
- package/src/strand-network-config.ts +2 -2
- package/src/types.ts +104 -8
|
@@ -40,8 +40,8 @@
|
|
|
40
40
|
* absorbed by the per-relay entries when one is.
|
|
41
41
|
*
|
|
42
42
|
* Everything else in `NetworkConfig` — `transports`, `noiseCrypto`, `connectionMonitor`,
|
|
43
|
-
* `connectionGater`, `enableRelay` — is inherited by the caller; this
|
|
44
|
-
* the two host-endpoint fields above and the relay listen shape. One caveat on
|
|
43
|
+
* `cohortQueryTimeoutMs`, `connectionGater`, `enableRelay` — is inherited by the caller; this
|
|
44
|
+
* module only owns the two host-endpoint fields above and the relay listen shape. One caveat on
|
|
45
45
|
* `connectionGater`: an OPEN strand's node gets it unchanged, while a CLOSED strand's
|
|
46
46
|
* node composes revoked-peer denial onto it in `strand-instance-manager.ts` (every
|
|
47
47
|
* supplied hook still honored — see `strand-revocation-enforcer.ts`).
|
package/src/types.ts
CHANGED
|
@@ -316,7 +316,8 @@ export interface NetworkConfig {
|
|
|
316
316
|
*
|
|
317
317
|
* It buys a node that BOOTS, not a node that boots fast: `start()` still waits
|
|
318
318
|
* out that first attempt, which costs the drive's whole timeout
|
|
319
|
-
* (`DEFAULT_RELAY_RESERVE_TIMEOUT_MS`,
|
|
319
|
+
* (`DEFAULT_RELAY_RESERVE_TIMEOUT_MS`, four link round trips at
|
|
320
|
+
* {@link linkRoundTripMs} — 14 s at its default) against a relay that is unreachable
|
|
320
321
|
* rather than merely refusing (`relay-reservation.ts` polls to the deadline, in
|
|
321
322
|
* case libp2p's own discovery lands a reservation independently).
|
|
322
323
|
*
|
|
@@ -406,6 +407,59 @@ export interface NetworkConfig {
|
|
|
406
407
|
* see {@link DEFAULT_CONNECTION_MONITOR} for why.
|
|
407
408
|
*/
|
|
408
409
|
connectionMonitor?: Libp2pConnectionMonitorInit;
|
|
410
|
+
/**
|
|
411
|
+
* How long ONE cohort peer gets to answer ONE read-path request, in milliseconds, for the
|
|
412
|
+
* control node and every strand node — as {@link connectionMonitor} is, and for the same
|
|
413
|
+
* reason: the setting describes the LINK, and a phone's control node and its strand nodes
|
|
414
|
+
* ride the same one. Omitted takes {@link COHORT_READ_DEADLINE_MS} (5000 ms), chosen for two
|
|
415
|
+
* parties reaching each other only through a relay; Optimystic's own default is 1000 ms.
|
|
416
|
+
*
|
|
417
|
+
* Raise it for a link slower still, lower it for a deployment that is all LAN and wants a
|
|
418
|
+
* departed peer to stop holding up a read sooner. The cost of a larger value is that a peer
|
|
419
|
+
* which is truly gone holds a read of a block missing locally for that long before the read
|
|
420
|
+
* is declined and retried, and a joining machine's first sync runs several such consults —
|
|
421
|
+
* so a change here should be weighed against
|
|
422
|
+
* {@link CadreNodeConfig.strandFirstSync}'s budget. The measurement behind the default, and
|
|
423
|
+
* what it costs, are on {@link COHORT_READ_DEADLINE_MS}.
|
|
424
|
+
*
|
|
425
|
+
* Handed to db-p2p's `clusterPolicy.cohortQueryTimeoutMs` unchanged and NOT re-validated
|
|
426
|
+
* here. Optimystic refuses a value that is not a finite number above zero, or is above its
|
|
427
|
+
* `MAX_COHORT_QUERY_TIMEOUT_MS` (about 4.97 days — the ceiling exists because a unit mix-up
|
|
428
|
+
* is the one way to exceed it), by throwing where the libp2p node is built: inside
|
|
429
|
+
* `CadreNode.start()` for the control network, and inside `CadreNode.addStrand` for a strand.
|
|
430
|
+
* Fractional values are accepted — this is a duration, not a count of peers.
|
|
431
|
+
*/
|
|
432
|
+
cohortQueryTimeoutMs?: number;
|
|
433
|
+
/**
|
|
434
|
+
* The round trip this node assumes between itself and another machine, in milliseconds, for
|
|
435
|
+
* the control node and every strand node — as {@link cohortQueryTimeoutMs} is, and for the
|
|
436
|
+
* same reason: the setting describes the LINK, and a phone's control node and its strand
|
|
437
|
+
* nodes ride the same one. Omitted takes {@link DECLARED_LINK_ROUND_TRIP_MS} (3500 ms).
|
|
438
|
+
*
|
|
439
|
+
* This is NOT a timeout. It is the one stated assumption that cadre's own dial and
|
|
440
|
+
* reservation deadlines are DERIVED from, each by the number of round trips that operation
|
|
441
|
+
* was measured to cost: a peer-join catch-up's dial to one peer, its push response, one relay
|
|
442
|
+
* reservation drive, the control-cohort dial budgets, and libp2p's own `dialTimeout` and
|
|
443
|
+
* `inboundUpgradeTimeout` on every node. Reaching another machine through a relay costs a
|
|
444
|
+
* fixed number of exchanges, so a deadline written as milliseconds has a link speed above
|
|
445
|
+
* which it can never open a connection — which is the defect this declaration exists to make
|
|
446
|
+
* impossible to reintroduce one budget at a time. The counts, the measurement behind them,
|
|
447
|
+
* and what still fails at the supported link are in `link-budget.ts`.
|
|
448
|
+
*
|
|
449
|
+
* The default covers the slowest link sereus supports, a 3-second round trip through a relay.
|
|
450
|
+
* Raise it for a link slower still; the cost is the ordinary cost of longer deadlines, a peer
|
|
451
|
+
* that is genuinely gone holding each operation that much longer before it is abandoned and
|
|
452
|
+
* retried. Lower it only if EVERY machine of the party is that close: this node is also the
|
|
453
|
+
* listener for connections other machines open to it, and its `inboundUpgradeTimeout` comes
|
|
454
|
+
* from this value, so a node declaring a faster link than its peers discards their
|
|
455
|
+
* half-built connections — silently, from the dialer's side.
|
|
456
|
+
*
|
|
457
|
+
* Refused where the libp2p node is built — inside `CadreNode.start()` for the control
|
|
458
|
+
* network, inside `CadreNode.addStrand` for a strand — if it is not a finite number above
|
|
459
|
+
* zero, because every consumer multiplies it into a deadline where a zero means "give up at
|
|
460
|
+
* once" and a `NaN` means "never".
|
|
461
|
+
*/
|
|
462
|
+
linkRoundTripMs?: number;
|
|
409
463
|
/**
|
|
410
464
|
* Optional async resolver returning the multiaddrs to embed in invites
|
|
411
465
|
* (and other owner-address contexts). When unset, `libp2pNode.getMultiaddrs()`
|
|
@@ -518,6 +572,12 @@ export interface NetworkConfig {
|
|
|
518
572
|
* kept it (the same pair aborted at a 200ms stall only when the deadline was 300ms). An
|
|
519
573
|
* interval strictly above the deadline is what makes the 30 seconds real.
|
|
520
574
|
*
|
|
575
|
+
* WHAT THE LINK NEEDS OF IT. One ping opens a fresh stream and echoes over it: a protocol
|
|
576
|
+
* negotiation plus the echo, two link round trips by `link-budget.ts`'s counts (a `newStream`
|
|
577
|
+
* over a relayed circuit measured 3016 ms at 1500 ms one-way). At the slowest link sereus
|
|
578
|
+
* supports, a 3-second relayed round trip, that is about 6 s — well inside the 30 s deadline,
|
|
579
|
+
* which exists for the phone's CPU rather than the link.
|
|
580
|
+
*
|
|
521
581
|
* WHAT IT COSTS. A dead peer is reclaimed 30 to 65 seconds after it stops answering — the
|
|
522
582
|
* deadline, plus up to one interval of waiting for the ping that will fail — where
|
|
523
583
|
* libp2p's defaults took about 5 to 15 seconds. `db-p2p` caps a node at 16 connections,
|
|
@@ -594,12 +654,16 @@ export interface ControlNetworkConfig {
|
|
|
594
654
|
*
|
|
595
655
|
* The two `*ClusterPolicy` BUILDERS are the same objects with the block-repair
|
|
596
656
|
* corroboration yardstick declared from the machines enrolled in this party
|
|
597
|
-
* ({@link resolveRepairYardstick})
|
|
598
|
-
*
|
|
599
|
-
*
|
|
657
|
+
* ({@link resolveRepairYardstick}) and, if the host set one, its own per-peer read
|
|
658
|
+
* deadline in place of {@link COHORT_READ_DEADLINE_MS}. Both arrive in one named
|
|
659
|
+
* declarations object, because both are plain numbers meaning unrelated things;
|
|
660
|
+
* declaring neither returns the frozen base constant unchanged. A network picks the
|
|
661
|
+
* derived numbers up when its libp2p node is built, which for a strand is every wake
|
|
662
|
+
* from hibernation.
|
|
600
663
|
*/
|
|
601
664
|
export {
|
|
602
665
|
MIN_CLUSTER_SIZE,
|
|
666
|
+
COHORT_READ_DEADLINE_MS,
|
|
603
667
|
CONTROL_REPLICATION_BREADTH,
|
|
604
668
|
CONTROL_CLUSTER_POLICY,
|
|
605
669
|
DEFAULT_STRAND_CLUSTER_SIZE,
|
|
@@ -610,6 +674,14 @@ export {
|
|
|
610
674
|
strandClusterPolicy
|
|
611
675
|
} from '@serfab/quereus-plugin-sereus';
|
|
612
676
|
|
|
677
|
+
/**
|
|
678
|
+
* The declared link round trip every cadre-owned dial and reservation deadline is derived from,
|
|
679
|
+
* re-exported beside {@link NetworkConfig.linkRoundTripMs} so a host reading the setting finds
|
|
680
|
+
* the default it replaces. The counts, the measurement and the derivation live in
|
|
681
|
+
* `link-budget.ts`.
|
|
682
|
+
*/
|
|
683
|
+
export { DECLARED_LINK_ROUND_TRIP_MS } from './link-budget.js';
|
|
684
|
+
|
|
613
685
|
/**
|
|
614
686
|
* Main configuration for a CadreNode
|
|
615
687
|
*/
|
|
@@ -743,10 +815,12 @@ export interface CadreNodeConfig {
|
|
|
743
815
|
* to a table it has never fetched creates a private copy of it that never merges.
|
|
744
816
|
* `timeoutMs` bounds how long {@link CadreNode.addStrand} waits before rejecting with
|
|
745
817
|
* `StrandAwaitingFirstSyncError` (retryable — the launch stays up and keeps probing);
|
|
746
|
-
* `pollIntervalMs` is the probe cadence. Omit for the defaults (`DEFAULT_STRAND_FIRST_SYNC_TIMEOUT_MS`,
|
|
747
|
-
*
|
|
748
|
-
*
|
|
749
|
-
*
|
|
818
|
+
* `pollIntervalMs` is the probe cadence. Omit for the defaults (`DEFAULT_STRAND_FIRST_SYNC_TIMEOUT_MS`,
|
|
819
|
+
* sized for a machine re-attaching through a relay on a slow link, the slowest attach
|
|
820
|
+
* measured; that constant's doc comment carries the number, the measurement behind it and
|
|
821
|
+
* what the budget costs, and is the only copy of them; `DEFAULT_STRAND_FIRST_SYNC_POLL_MS`,
|
|
822
|
+
* 500 ms). There is deliberately no way to disable the gate: a machine whose store already
|
|
823
|
+
* holds the Header is never gated, so nothing that works today is blocked by it.
|
|
750
824
|
*/
|
|
751
825
|
strandFirstSync?: StrandFirstSyncConfig;
|
|
752
826
|
|
|
@@ -1322,6 +1396,28 @@ export interface CadreNodeEvents {
|
|
|
1322
1396
|
* revoked.
|
|
1323
1397
|
*/
|
|
1324
1398
|
'strand:revoked': { strandId: string };
|
|
1399
|
+
/**
|
|
1400
|
+
* Emitted when this node holds a staged membership invitation for a CLOSED strand
|
|
1401
|
+
* that its own writes cannot redeem — the shape a REMOVED party hits when a manager
|
|
1402
|
+
* hands it a fresh invitation. Redeeming means writing this party's `Strand.Member`
|
|
1403
|
+
* row into the strand, and the machines that would carry that write are the ones the
|
|
1404
|
+
* remaining members refuse, so the attempt is made and fails. Two triggers, reported
|
|
1405
|
+
* at most once per re-arm of the membership loop (a further invitation staged while the
|
|
1406
|
+
* loop is still running does not reset the report):
|
|
1407
|
+
*
|
|
1408
|
+
* - CONFIRMED: the revoked-peer gate already flags this node as removed (the
|
|
1409
|
+
* `strand:revoked` case) and an invitation is staged.
|
|
1410
|
+
* - PROBABLE: `UNFINISHED_PASSES_BEFORE_ESCALATION` consecutive attempts left the
|
|
1411
|
+
* invitation staged. This one is a SUSPICION, not a verdict — the invitation's row
|
|
1412
|
+
* may simply not have replicated here yet on a slow strand — and the accompanying
|
|
1413
|
+
* warning names both causes.
|
|
1414
|
+
*
|
|
1415
|
+
* Nothing is stopped or torn down. A fresh invitation cannot re-admit a removed
|
|
1416
|
+
* party by itself: the remedy is a remaining manager admitting this party's member
|
|
1417
|
+
* key directly (`addMemberByManager`), after which the membership loop, which keeps
|
|
1418
|
+
* retrying, finishes the join on its own.
|
|
1419
|
+
*/
|
|
1420
|
+
'strand:rejoin-blocked': { strandId: string };
|
|
1325
1421
|
/**
|
|
1326
1422
|
* Emitted when the control network advertises a strand this node has no
|
|
1327
1423
|
* registered `sAppConfig` for — i.e. a strand created by another member, or
|