@serfab/cadre-core 0.9.0 → 0.11.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/README.md +255 -253
- package/dist/bootstrap-peer-store-file.d.ts +13 -0
- package/dist/bootstrap-peer-store-file.js +42 -0
- package/dist/bootstrap-peer-store-file.js.map +1 -0
- package/dist/bootstrap-peer-store.d.ts +73 -0
- package/dist/bootstrap-peer-store.js +128 -0
- package/dist/bootstrap-peer-store.js.map +1 -0
- package/dist/cadre-node.d.ts +1121 -81
- package/dist/cadre-node.js +2276 -262
- package/dist/cadre-node.js.map +1 -1
- package/dist/control-authorization.d.ts +93 -0
- package/dist/control-authorization.js +57 -0
- package/dist/control-authorization.js.map +1 -0
- package/dist/control-cohort.d.ts +26 -0
- package/dist/control-cohort.js +26 -0
- package/dist/control-cohort.js.map +1 -1
- package/dist/control-database.d.ts +959 -54
- package/dist/control-database.js +1421 -148
- package/dist/control-database.js.map +1 -1
- package/dist/control-formation-recorder.d.ts +90 -10
- package/dist/control-formation-recorder.js +130 -14
- package/dist/control-formation-recorder.js.map +1 -1
- package/dist/control-schema.d.ts +1 -1
- package/dist/control-schema.js +651 -72
- package/dist/control-schema.js.map +1 -1
- package/dist/control-stream.d.ts +38 -4
- package/dist/control-stream.js +70 -4
- package/dist/control-stream.js.map +1 -1
- package/dist/control-write-retry.d.ts +161 -0
- package/dist/control-write-retry.js +412 -0
- package/dist/control-write-retry.js.map +1 -0
- package/dist/delegate-admission.d.ts +134 -0
- package/dist/delegate-admission.js +244 -0
- package/dist/delegate-admission.js.map +1 -0
- package/dist/device-token.d.ts +11 -11
- package/dist/device-token.js +14 -13
- package/dist/device-token.js.map +1 -1
- package/dist/ed25519-key.d.ts +26 -0
- package/dist/ed25519-key.js +56 -1
- package/dist/ed25519-key.js.map +1 -1
- package/dist/file-durable-slot.d.ts +20 -0
- package/dist/file-durable-slot.js +53 -0
- package/dist/file-durable-slot.js.map +1 -0
- package/dist/formation-approval.d.ts +157 -0
- package/dist/formation-approval.js +375 -0
- package/dist/formation-approval.js.map +1 -0
- package/dist/fs-atomic.d.ts +38 -0
- package/dist/fs-atomic.js +97 -0
- package/dist/fs-atomic.js.map +1 -0
- package/dist/identity-key.d.ts +49 -0
- package/dist/identity-key.js +81 -0
- package/dist/identity-key.js.map +1 -0
- package/dist/index.d.ts +17 -7
- package/dist/index.js +40 -6
- package/dist/index.js.map +1 -1
- package/dist/key-store-file.d.ts +2 -24
- package/dist/key-store-file.js +10 -77
- package/dist/key-store-file.js.map +1 -1
- package/dist/membership-connection-gater.d.ts +146 -0
- package/dist/membership-connection-gater.js +180 -0
- package/dist/membership-connection-gater.js.map +1 -0
- package/dist/node-local-snapshot.d.ts +109 -0
- package/dist/node-local-snapshot.js +182 -0
- package/dist/node-local-snapshot.js.map +1 -0
- package/dist/peer-addr-book.d.ts +92 -0
- package/dist/peer-addr-book.js +220 -0
- package/dist/peer-addr-book.js.map +1 -0
- package/dist/peer-authorization.d.ts +135 -18
- package/dist/peer-authorization.js +152 -21
- package/dist/peer-authorization.js.map +1 -1
- package/dist/peer-record.d.ts +21 -8
- package/dist/peer-record.js +26 -10
- package/dist/peer-record.js.map +1 -1
- package/dist/relay-addrs.d.ts +45 -0
- package/dist/relay-addrs.js +103 -0
- package/dist/relay-addrs.js.map +1 -0
- package/dist/relay-reservation.d.ts +266 -0
- package/dist/relay-reservation.js +613 -0
- package/dist/relay-reservation.js.map +1 -0
- package/dist/seed-bootstrap.d.ts +228 -56
- package/dist/seed-bootstrap.js +340 -198
- package/dist/seed-bootstrap.js.map +1 -1
- package/dist/seed-trust-policy.d.ts +47 -21
- package/dist/seed-trust-policy.js +24 -15
- package/dist/seed-trust-policy.js.map +1 -1
- package/dist/strand-addr-protocol.d.ts +42 -13
- package/dist/strand-addr-protocol.js +58 -52
- package/dist/strand-addr-protocol.js.map +1 -1
- package/dist/strand-backfill.d.ts +109 -0
- package/dist/strand-backfill.js +279 -0
- package/dist/strand-backfill.js.map +1 -0
- package/dist/strand-cohort.d.ts +4 -37
- package/dist/strand-cohort.js +4 -15
- package/dist/strand-cohort.js.map +1 -1
- package/dist/strand-database.d.ts +11 -16
- package/dist/strand-database.js +19 -7
- package/dist/strand-database.js.map +1 -1
- package/dist/strand-formation-manager.d.ts +36 -7
- package/dist/strand-formation-manager.js +115 -15
- package/dist/strand-formation-manager.js.map +1 -1
- package/dist/strand-formation-protocol.d.ts +103 -4
- package/dist/strand-formation-protocol.js +232 -4
- package/dist/strand-formation-protocol.js.map +1 -1
- package/dist/strand-instance-manager.d.ts +88 -19
- package/dist/strand-instance-manager.js +178 -34
- package/dist/strand-instance-manager.js.map +1 -1
- package/dist/strand-member-registry.d.ts +5 -5
- package/dist/strand-member-registry.js +18 -10
- package/dist/strand-member-registry.js.map +1 -1
- package/dist/strand-membership-writer.d.ts +484 -88
- package/dist/strand-membership-writer.js +751 -128
- package/dist/strand-membership-writer.js.map +1 -1
- package/dist/strand-solicitation.d.ts +99 -33
- package/dist/strand-solicitation.js +100 -52
- package/dist/strand-solicitation.js.map +1 -1
- package/dist/strand-transport-key.d.ts +40 -0
- package/dist/strand-transport-key.js +56 -0
- package/dist/strand-transport-key.js.map +1 -0
- package/dist/strand-wake-protocol.d.ts +9 -7
- package/dist/strand-wake-protocol.js +22 -46
- package/dist/strand-wake-protocol.js.map +1 -1
- package/dist/strand-watcher.d.ts +17 -2
- package/dist/strand-watcher.js +47 -3
- package/dist/strand-watcher.js.map +1 -1
- package/dist/trusted-owner-store-file.d.ts +12 -0
- package/dist/trusted-owner-store-file.js +39 -0
- package/dist/trusted-owner-store-file.js.map +1 -0
- package/dist/trusted-owner-store.d.ts +64 -0
- package/dist/trusted-owner-store.js +126 -0
- package/dist/trusted-owner-store.js.map +1 -0
- package/dist/types.d.ts +307 -44
- package/dist/types.js +13 -0
- package/dist/types.js.map +1 -1
- package/package.json +20 -8
- package/src/arachnode-stub.ts +159 -159
- package/src/bootstrap-peer-store-file.ts +44 -0
- package/src/bootstrap-peer-store.ts +172 -0
- package/src/cadre-node.ts +5158 -2981
- package/src/canonical-json.ts +30 -30
- package/src/control-authorization.ts +114 -0
- package/src/control-cohort.ts +130 -103
- package/src/control-database.ts +2406 -948
- package/src/control-formation-recorder.ts +305 -151
- package/src/control-schema.ts +651 -72
- package/src/control-stream.ts +205 -128
- package/src/control-write-retry.ts +483 -0
- package/src/delegate-admission.ts +302 -0
- package/src/device-token.ts +94 -89
- package/src/diagnostics/connection-path.ts +277 -277
- package/src/diagnostics/webrtc-turn-tracker.ts +222 -222
- package/src/ed25519-key.ts +66 -1
- package/src/enrollment.ts +199 -199
- package/src/file-durable-slot.ts +61 -0
- package/src/formation-approval.ts +604 -0
- package/src/fs-atomic.ts +107 -0
- package/src/hibernation-manager.ts +437 -437
- package/src/identity-key.ts +109 -0
- package/src/index.ts +137 -5
- package/src/key-store-file.ts +132 -203
- package/src/key-store.ts +99 -99
- package/src/membership-connection-gater.ts +204 -0
- package/src/node-local-snapshot.ts +260 -0
- package/src/peer-addr-book.ts +250 -0
- package/src/peer-authorization.ts +259 -81
- package/src/peer-record.ts +164 -146
- package/src/push-credentials.ts +84 -84
- package/src/push-node.ts +64 -64
- package/src/push-notifier-apns.ts +247 -247
- package/src/push-notifier-fcm.ts +220 -220
- package/src/push-notifier-shared.ts +28 -28
- package/src/push-notifier.ts +52 -52
- package/src/relay-addrs.ts +111 -0
- package/src/relay-reservation.ts +823 -0
- package/src/seed-bootstrap.ts +409 -209
- package/src/seed-trust-policy.ts +140 -107
- package/src/strand-addr-protocol.ts +441 -410
- package/src/strand-backfill.ts +366 -0
- package/src/strand-cohort.ts +38 -77
- package/src/strand-database.ts +202 -204
- package/src/strand-formation-manager.ts +491 -368
- package/src/strand-formation-protocol.ts +692 -391
- package/src/strand-instance-manager.ts +201 -46
- package/src/strand-member-key.ts +39 -39
- package/src/strand-member-registry.ts +182 -177
- package/src/strand-membership-writer.ts +938 -146
- package/src/strand-solicitation.ts +472 -407
- package/src/strand-transport-key.ts +58 -0
- package/src/strand-wake-payload.ts +32 -32
- package/src/strand-wake-protocol.ts +314 -331
- package/src/strand-watcher.ts +314 -251
- package/src/trusted-owner-store-file.ts +41 -0
- package/src/trusted-owner-store.ts +171 -0
- package/src/types.ts +1309 -1032
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Relay reservation for nodes that reserve through the SEARCH listen addr — the
|
|
3
|
+
* dial, the explicit reservation request, the retry loop that keeps it, and the
|
|
4
|
+
* (live) status derivation.
|
|
5
|
+
*
|
|
6
|
+
* `@libp2p/circuit-relay-v2`'s listener branches on the SHAPE of the listen
|
|
7
|
+
* address, and the two shapes are alternatives, not layers:
|
|
8
|
+
*
|
|
9
|
+
* | listen addr | libp2p behaviour | unreachable relay |
|
|
10
|
+
* | ------------------------------------------------- | ------------------------------------------------------------------------------------ | -------------------------- |
|
|
11
|
+
* | `<dial addr>/p2p/<relayPeerId>/p2p-circuit` | CONFIGURED reservation: dial that exact relay and reserve, or fail | `listen()` throws |
|
|
12
|
+
* | bare `/p2p-circuit` | SEARCH mode: register a pending reservation, to be filled by relay discovery | nothing throws, no reserve |
|
|
13
|
+
*
|
|
14
|
+
* The configured shape is what `relay-addrs.ts` builds out of `network.relayAddrs`.
|
|
15
|
+
* It is **fail-fast by construction**: libp2p's transport manager throws
|
|
16
|
+
* `UnsupportedListenAddressesError` when any configured listen address fails to
|
|
17
|
+
* listen under the default `FATAL_ALL` fault tolerance, so naming a relay that is
|
|
18
|
+
* down means the node does not start. Good for a server; wrong for a browser tab,
|
|
19
|
+
* which must still boot (solo, undialable) when its relay is down.
|
|
20
|
+
*
|
|
21
|
+
* So a browser-shaped node listens on bare `/p2p-circuit` and needs someone to
|
|
22
|
+
* (a) dial the relay and (b) fill the pending reservation that listener created,
|
|
23
|
+
* then report whether one actually landed. That is this module. It is **fail-soft
|
|
24
|
+
* by construction**: nothing here throws.
|
|
25
|
+
*
|
|
26
|
+
* Do NOT "consolidate" the two by also setting `network.relayAddrs` on a node
|
|
27
|
+
* that reserves this way — that re-introduces the fatal configured listener
|
|
28
|
+
* alongside the search listener and the tab stops booting when the relay is down.
|
|
29
|
+
*
|
|
30
|
+
* ⚠️ WHY THE RESERVATION IS REQUESTED EXPLICITLY RATHER THAN LEFT TO DISCOVERY.
|
|
31
|
+
* libp2p fills a search listener's pending reservation from `RelayDiscovery`,
|
|
32
|
+
* which nominates a peer only once it can see the relay-hop protocol id in that
|
|
33
|
+
* peer's PEER-STORE protocol list — and that list is written exclusively by the
|
|
34
|
+
* IDENTIFY handshake. `@optimystic/db-p2p` gives every cadre node a
|
|
35
|
+
* network-namespaced identify protocol id (`/optimystic/control-<partyId>/id/1.0.0`)
|
|
36
|
+
* while the relay `ops/docker/libp2p-infra` deploys runs stock identify
|
|
37
|
+
* (`/ipfs/id/1.0.0`), so the two never identify each other, the peer store stays
|
|
38
|
+
* empty of protocols, and discovery never nominates the relay. The TCP/WebSocket
|
|
39
|
+
* connection itself is fine, which is why leaving it to discovery surfaced as a
|
|
40
|
+
* generic timeout.
|
|
41
|
+
*
|
|
42
|
+
* Identify is incidental to relaying, though: the reservation
|
|
43
|
+
* (`/libp2p/circuit/relay/0.2.0/hop`), a third peer's CONNECT through the relay,
|
|
44
|
+
* and the STOP handler on this node all use STOCK, un-namespaced protocol ids the
|
|
45
|
+
* deployed relay already serves. Discovery's only job is to GUESS which connected
|
|
46
|
+
* peer is a relay, and this module does not need to guess — it was handed the
|
|
47
|
+
* relay's address. So it asks the relay for a slot directly, via the
|
|
48
|
+
* circuit-relay transport's own reservation store.
|
|
49
|
+
*
|
|
50
|
+
* Status is derived from the node's LIVE multiaddrs on every read rather than
|
|
51
|
+
* cached at drive time: when a relay restarts or the connection drops, libp2p's
|
|
52
|
+
* listener clears its listening addrs and the circuit multiaddr disappears, so a
|
|
53
|
+
* cached snapshot would keep claiming `reserved` for a node nothing can dial.
|
|
54
|
+
*
|
|
55
|
+
* And because discovery is out of reach, nothing would ever ASK again either —
|
|
56
|
+
* so {@link driveRelayReservation} stays a single-shot primitive and
|
|
57
|
+
* {@link superviseRelayReservation} owns the retry cadence on top of it. That
|
|
58
|
+
* loop is what makes a lost reservation recover without a page reload.
|
|
59
|
+
*/
|
|
60
|
+
import type { Libp2p, PeerId } from '@libp2p/interface';
|
|
61
|
+
/**
|
|
62
|
+
* Relay-reservation posture for a node that reserves through the SEARCH listen
|
|
63
|
+
* addr (bare `/p2p-circuit`) rather than a configured `network.relayAddrs` entry.
|
|
64
|
+
* - `none` — no relay addrs supplied; the node is undialable by design.
|
|
65
|
+
* - `dialing` — a drive is in flight.
|
|
66
|
+
* - `reserved` — the node currently holds at least one `/p2p-circuit` addr.
|
|
67
|
+
* - `retrying` — no reservation right now, but a {@link RelayReservationSupervisor}
|
|
68
|
+
* has the next attempt scheduled. Recoverable without a caller.
|
|
69
|
+
* - `error` — no reservation, and NOBODY IS GOING TO TRY AGAIN: no supervisor
|
|
70
|
+
* is running (or there is no node at all).
|
|
71
|
+
*/
|
|
72
|
+
export type RelayReservationStatus = 'none' | 'dialing' | 'reserved' | 'retrying' | 'error';
|
|
73
|
+
export interface RelayReservationState {
|
|
74
|
+
status: RelayReservationStatus;
|
|
75
|
+
/** The relay multiaddrs this node was asked to reserve through. */
|
|
76
|
+
addrs: string[];
|
|
77
|
+
/** LIVE `/p2p-circuit` multiaddrs, recomputed on every read. */
|
|
78
|
+
circuitAddrs: string[];
|
|
79
|
+
error: string | null;
|
|
80
|
+
/**
|
|
81
|
+
* Epoch ms of the supervisor's next scheduled tick, or `null` when a drive is
|
|
82
|
+
* in flight, no supervisor is running, or no addrs were supplied. A UI can turn
|
|
83
|
+
* this into "reconnecting, next try in 8s" rather than showing a bare error for
|
|
84
|
+
* a node that is in fact recovering.
|
|
85
|
+
*/
|
|
86
|
+
retryAtMs: number | null;
|
|
87
|
+
}
|
|
88
|
+
/** How long {@link driveRelayReservation} waits for a reservation to appear. */
|
|
89
|
+
export declare const DEFAULT_RELAY_RESERVE_TIMEOUT_MS = 10000;
|
|
90
|
+
export declare const DEFAULT_RELAY_RESERVE_POLL_MS = 250;
|
|
91
|
+
export interface RelayReserveOptions {
|
|
92
|
+
timeoutMs?: number;
|
|
93
|
+
pollMs?: number;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* The slice of `@libp2p/utils`' `Filter` (a cuckoo filter) that the reservation
|
|
97
|
+
* store uses to remember relays whose reservation request failed. `remove` is
|
|
98
|
+
* OPTIONAL on that interface, so every use here has to cope with its absence —
|
|
99
|
+
* see {@link clearRelayFilterEntry}.
|
|
100
|
+
*/
|
|
101
|
+
export interface RelayFilterLike {
|
|
102
|
+
has(item: Uint8Array): boolean;
|
|
103
|
+
remove?(item: Uint8Array): boolean;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* The slice of `@libp2p/circuit-relay-v2`'s `ReservationStore` this module drives.
|
|
107
|
+
* Declared structurally because the class is internal to that package: naming only
|
|
108
|
+
* the members we call keeps the coupling small, explicit and greppable, and lets
|
|
109
|
+
* {@link findCircuitRelayTransport} duck-type rather than brand-match.
|
|
110
|
+
*
|
|
111
|
+
* `relayFilter` is optional because it is not required to DRIVE a reservation,
|
|
112
|
+
* only to RE-drive one (see {@link clearRelayFilterEntry}); a libp2p version that
|
|
113
|
+
* renames or drops it must degrade, not break.
|
|
114
|
+
*/
|
|
115
|
+
export interface RelayReservationStoreLike {
|
|
116
|
+
addRelay(peerId: PeerId, type: 'discovered' | 'configured'): Promise<unknown>;
|
|
117
|
+
hasReservation(peerId: PeerId): boolean;
|
|
118
|
+
relayFilter?: RelayFilterLike;
|
|
119
|
+
}
|
|
120
|
+
/** The slice of libp2p's circuit-relay transport that owns the reservation store. */
|
|
121
|
+
export interface CircuitRelayTransportLike {
|
|
122
|
+
reservationStore: RelayReservationStoreLike;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* The node's `/p2p-circuit` multiaddrs — the addresses a peer can dial it at
|
|
126
|
+
* while it holds a relay reservation. Empty means "not dialable via a relay
|
|
127
|
+
* right now", which is exactly what makes {@link resolveRelayReservationState}
|
|
128
|
+
* live rather than a stale snapshot.
|
|
129
|
+
*/
|
|
130
|
+
export declare function circuitMultiaddrs(node: Libp2p): string[];
|
|
131
|
+
/**
|
|
132
|
+
* The running node's circuit-relay transport, or `null` when it has none.
|
|
133
|
+
*
|
|
134
|
+
* There is no public libp2p API for "reserve on THIS specific relay", so this
|
|
135
|
+
* reaches through `node.components.transportManager` — libp2p's internal layout.
|
|
136
|
+
* That coupling is deliberate and bounded: every step is optional-chained and the
|
|
137
|
+
* whole thing returns `null` rather than throwing, and a spec pins the seam so a
|
|
138
|
+
* libp2p upgrade that moves it fails loudly instead of silently reverting this
|
|
139
|
+
* module to the discovery wait that never fires.
|
|
140
|
+
*/
|
|
141
|
+
export declare function findCircuitRelayTransport(node: Libp2p): CircuitRelayTransportLike | null;
|
|
142
|
+
/**
|
|
143
|
+
* Dial every relay in `addrs`, ask the first one that answers for a reservation
|
|
144
|
+
* slot, then wait until a `/p2p-circuit` address appears.
|
|
145
|
+
*
|
|
146
|
+
* Never throws — a dial rejection, a rejected reservation, a MALFORMED address,
|
|
147
|
+
* or a timeout all come back as an `error` string. A dial that throws does NOT
|
|
148
|
+
* cost the rest of the list: one dead relay among two must not cost the
|
|
149
|
+
* reservation on the live one, so every addr is dialed and the first error (in
|
|
150
|
+
* list order) is kept. A reservation that lands wins over any earlier error
|
|
151
|
+
* (`error: null`).
|
|
152
|
+
*
|
|
153
|
+
* `timeoutMs` bounds the WHOLE drive — dials, reservation requests and the wait
|
|
154
|
+
* share one deadline.
|
|
155
|
+
*/
|
|
156
|
+
export declare function driveRelayReservation(node: Libp2p, addrs: readonly string[], opts?: RelayReserveOptions): Promise<{
|
|
157
|
+
error: string | null;
|
|
158
|
+
}>;
|
|
159
|
+
/** Gap between liveness checks while a reservation is held. */
|
|
160
|
+
export declare const DEFAULT_RELAY_CHECK_MS = 5000;
|
|
161
|
+
/** Backoff before the first re-drive after a failed attempt. */
|
|
162
|
+
export declare const DEFAULT_RELAY_MIN_BACKOFF_MS = 2000;
|
|
163
|
+
/** Ceiling the backoff doubles up to. */
|
|
164
|
+
export declare const DEFAULT_RELAY_MAX_BACKOFF_MS = 60000;
|
|
165
|
+
export interface RelayReservationSupervisorOptions extends RelayReserveOptions {
|
|
166
|
+
/** Gap between liveness checks while a reservation is held. Default 5_000. */
|
|
167
|
+
checkMs?: number;
|
|
168
|
+
/** Backoff before the first re-drive after a failure. Default 2_000. */
|
|
169
|
+
minBackoffMs?: number;
|
|
170
|
+
/** Backoff ceiling. Default 60_000. */
|
|
171
|
+
maxBackoffMs?: number;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* A running retry loop for one node + relay list. Obtained from
|
|
175
|
+
* {@link superviseRelayReservation}; its only imperative is {@link stop}.
|
|
176
|
+
*/
|
|
177
|
+
export interface RelayReservationSupervisor {
|
|
178
|
+
/**
|
|
179
|
+
* Resolves once the FIRST attempt has settled — so a caller can await startup
|
|
180
|
+
* exactly as it awaited a single {@link driveRelayReservation}, and the retries
|
|
181
|
+
* carry on in the background afterwards. Also resolves on {@link stop}, so an
|
|
182
|
+
* awaiting caller is never left hanging.
|
|
183
|
+
*/
|
|
184
|
+
readonly firstAttempt: Promise<void>;
|
|
185
|
+
/** True while a drive is in flight. */
|
|
186
|
+
readonly driving: boolean;
|
|
187
|
+
/** Epoch ms of the next scheduled tick; `null` while a drive is running. */
|
|
188
|
+
readonly retryAtMs: number | null;
|
|
189
|
+
/** Reason the last drive produced no reservation; `null` once one is held. */
|
|
190
|
+
readonly lastError: string | null;
|
|
191
|
+
/**
|
|
192
|
+
* Idempotent. Clears the timer so no further drive is scheduled. A drive that
|
|
193
|
+
* is ALREADY in flight is not aborted — {@link driveRelayReservation} takes no
|
|
194
|
+
* signal — but its result is discarded and nothing follows it.
|
|
195
|
+
*/
|
|
196
|
+
stop(): void;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Keep asking for a relay reservation until one is held, then keep watching that
|
|
200
|
+
* it still is — the thing that makes a lost reservation recover on its own.
|
|
201
|
+
*
|
|
202
|
+
* Needed because nothing else re-drives: libp2p re-fills a search listener's
|
|
203
|
+
* freed slot from relay DISCOVERY, and a cadre node's namespaced identify puts
|
|
204
|
+
* discovery permanently out of reach (see the module header). Without this loop a
|
|
205
|
+
* relay restart left a browser tab undialable until the user reloaded the page.
|
|
206
|
+
*
|
|
207
|
+
* Per tick:
|
|
208
|
+
* - a reservation is held → reset the backoff, clear the error, re-check in
|
|
209
|
+
* `checkMs`. No drive: a healthy node must not re-request every few seconds.
|
|
210
|
+
* - otherwise → un-poison the reservation store's relay filter (see
|
|
211
|
+
* {@link clearRelayFilterEntry}) and run ONE {@link driveRelayReservation}.
|
|
212
|
+
* If that lands a reservation, rejoin the healthy path above; if not, sleep
|
|
213
|
+
* the current backoff and double it up to `maxBackoffMs`.
|
|
214
|
+
*
|
|
215
|
+
* Starts immediately; the first tick runs before this returns.
|
|
216
|
+
*/
|
|
217
|
+
export declare function superviseRelayReservation(node: Libp2p, addrs: readonly string[], opts?: RelayReservationSupervisorOptions): RelayReservationSupervisor;
|
|
218
|
+
/**
|
|
219
|
+
* Forget that `addr`'s peer ever failed a reservation request, so the next
|
|
220
|
+
* attempt is actually made rather than refused out of hand.
|
|
221
|
+
*
|
|
222
|
+
* `ReservationStore` records a peer in `relayFilter` when its reservation request
|
|
223
|
+
* fails with `DialError` or `UnsupportedProtocolError`, and NOTHING on that path
|
|
224
|
+
* ever clears it: the reset lives in `#checkReservationCount`, which only runs
|
|
225
|
+
* when a reservation is genuinely removed, and `#removeReservation` early-returns
|
|
226
|
+
* when there was never one. So a relay that was briefly not-a-relay (or died
|
|
227
|
+
* between our dial and the hop request) stays permanently rejected with
|
|
228
|
+
* `The relay was previously invalid` — measured, not inferred.
|
|
229
|
+
*
|
|
230
|
+
* Fails soft in every direction: no `relayFilter`, no `remove`, an addr with no
|
|
231
|
+
* peer id, a malformed addr — all mean "no un-poisoning", never a throw. The
|
|
232
|
+
* retry loop still recovers the common case without this, because a relay that is
|
|
233
|
+
* simply DOWN fails our own dial first and never reaches the filter.
|
|
234
|
+
*
|
|
235
|
+
* Returns whether an entry was actually removed (for specs; callers ignore it).
|
|
236
|
+
*/
|
|
237
|
+
export declare function clearRelayFilterEntry(store: RelayReservationStoreLike, addr: string): boolean;
|
|
238
|
+
/**
|
|
239
|
+
* Derive the reservation posture, reading the node's circuit addrs LIVE. Pure
|
|
240
|
+
* apart from that read, so the precedence is testable on its own:
|
|
241
|
+
*
|
|
242
|
+
* | condition | status |
|
|
243
|
+
* | ------------------------ | ----------------------------------------------- |
|
|
244
|
+
* | no addrs supplied | `none` |
|
|
245
|
+
* | live circuit addrs held | `reserved` (`error: null`) |
|
|
246
|
+
* | a drive is in flight | `dialing` |
|
|
247
|
+
* | a retry is scheduled | `retrying` |
|
|
248
|
+
* | otherwise | `error` |
|
|
249
|
+
*
|
|
250
|
+
* `reserved` is checked BEFORE `error` on purpose: the circuit addrs are read
|
|
251
|
+
* live, so a reservation that lands by ANY route supersedes a stale error string
|
|
252
|
+
* without a second drive.
|
|
253
|
+
*
|
|
254
|
+
* `retrying` sits between the two so that `error` carries a sharper meaning:
|
|
255
|
+
* NOBODY IS GOING TO TRY AGAIN. A lost reservation does come back on its own now,
|
|
256
|
+
* as long as a {@link RelayReservationSupervisor} is running — that loop is the
|
|
257
|
+
* only thing that re-drives, since libp2p re-fills a search listener's freed slot
|
|
258
|
+
* from relay DISCOVERY, which a cadre node's namespaced identify puts permanently
|
|
259
|
+
* out of reach (see the module header). So `error` means the supervisor was
|
|
260
|
+
* stopped, was never started, or there is no node at all.
|
|
261
|
+
*
|
|
262
|
+
* `retryAtMs` is the supervisor's next scheduled tick (`null` while a drive runs
|
|
263
|
+
* or when there is no supervisor); it both selects `retrying` and is passed
|
|
264
|
+
* through so a UI can count down to the next attempt.
|
|
265
|
+
*/
|
|
266
|
+
export declare function resolveRelayReservationState(node: Libp2p | null, addrs: readonly string[], lastError: string | null, driving: boolean, retryAtMs: number | null): RelayReservationState;
|