@serfab/cadre-core 0.12.0 → 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/README.md +23 -8
- package/dist/bootstrap-peer-store-file.js +2 -2
- package/dist/bootstrap-peer-store.d.ts +32 -12
- package/dist/bootstrap-peer-store.js +41 -15
- package/dist/bootstrap-peer-store.js.map +1 -1
- package/dist/cadre-node.d.ts +883 -102
- package/dist/cadre-node.js +1800 -209
- package/dist/cadre-node.js.map +1 -1
- package/dist/control-authorization.d.ts +2 -2
- package/dist/control-authorization.js +1 -0
- package/dist/control-authorization.js.map +1 -1
- package/dist/control-cohort.d.ts +13 -26
- package/dist/control-cohort.js +0 -26
- package/dist/control-cohort.js.map +1 -1
- package/dist/control-database.d.ts +318 -44
- package/dist/control-database.js +516 -74
- package/dist/control-database.js.map +1 -1
- package/dist/control-read-retry.d.ts +40 -11
- package/dist/control-read-retry.js +48 -15
- package/dist/control-read-retry.js.map +1 -1
- package/dist/control-retry.d.ts +58 -3
- package/dist/control-retry.js +58 -3
- package/dist/control-retry.js.map +1 -1
- package/dist/control-schema.d.ts +1 -1
- package/dist/control-schema.js +133 -21
- package/dist/control-schema.js.map +1 -1
- package/dist/control-write-retry.d.ts +80 -11
- package/dist/control-write-retry.js +168 -29
- package/dist/control-write-retry.js.map +1 -1
- package/dist/enrolled-machine-store-file.d.ts +13 -0
- package/dist/enrolled-machine-store-file.js +41 -0
- package/dist/enrolled-machine-store-file.js.map +1 -0
- package/dist/enrolled-machine-store.d.ts +81 -0
- package/dist/enrolled-machine-store.js +225 -0
- package/dist/enrolled-machine-store.js.map +1 -0
- package/dist/file-durable-slot.js +5 -3
- package/dist/file-durable-slot.js.map +1 -1
- package/dist/index.d.ts +17 -8
- package/dist/index.js +54 -9
- package/dist/index.js.map +1 -1
- package/dist/membership-connection-gater.d.ts +15 -1
- package/dist/membership-connection-gater.js +9 -3
- package/dist/membership-connection-gater.js.map +1 -1
- package/dist/node-local-snapshot.d.ts +21 -7
- package/dist/node-local-snapshot.js +30 -9
- package/dist/node-local-snapshot.js.map +1 -1
- package/dist/peer-dial.d.ts +143 -0
- package/dist/peer-dial.js +176 -0
- package/dist/peer-dial.js.map +1 -0
- package/dist/{strand-backfill.d.ts → peer-join-backfill.d.ts} +49 -20
- package/dist/{strand-backfill.js → peer-join-backfill.js} +133 -52
- package/dist/peer-join-backfill.js.map +1 -0
- package/dist/relay-addrs.d.ts +160 -49
- package/dist/relay-addrs.js +287 -60
- package/dist/relay-addrs.js.map +1 -1
- package/dist/relay-reservation.d.ts +71 -3
- package/dist/relay-reservation.js +116 -8
- package/dist/relay-reservation.js.map +1 -1
- package/dist/seed-bootstrap.d.ts +30 -1
- package/dist/seed-bootstrap.js +62 -17
- package/dist/seed-bootstrap.js.map +1 -1
- package/dist/storage-scope.d.ts +62 -0
- package/dist/storage-scope.js +75 -0
- package/dist/storage-scope.js.map +1 -0
- package/dist/strand-database.d.ts +41 -11
- package/dist/strand-database.js +48 -18
- package/dist/strand-database.js.map +1 -1
- package/dist/strand-first-sync-gate.d.ts +152 -0
- package/dist/strand-first-sync-gate.js +208 -0
- package/dist/strand-first-sync-gate.js.map +1 -0
- package/dist/strand-formation-manager.d.ts +99 -5
- package/dist/strand-formation-manager.js +119 -8
- package/dist/strand-formation-manager.js.map +1 -1
- package/dist/strand-formation-protocol.d.ts +97 -3
- package/dist/strand-formation-protocol.js +108 -2
- package/dist/strand-formation-protocol.js.map +1 -1
- package/dist/strand-instance-manager.d.ts +389 -19
- package/dist/strand-instance-manager.js +678 -65
- package/dist/strand-instance-manager.js.map +1 -1
- package/dist/strand-member-key.d.ts +20 -12
- package/dist/strand-member-key.js +20 -12
- package/dist/strand-member-key.js.map +1 -1
- package/dist/strand-member-registry.js +3 -0
- package/dist/strand-member-registry.js.map +1 -1
- package/dist/strand-membership-reconciler.d.ts +361 -0
- package/dist/strand-membership-reconciler.js +548 -0
- package/dist/strand-membership-reconciler.js.map +1 -0
- package/dist/strand-membership-writer.d.ts +143 -11
- package/dist/strand-membership-writer.js +419 -135
- package/dist/strand-membership-writer.js.map +1 -1
- package/dist/strand-network-config.d.ts +116 -0
- package/dist/strand-network-config.js +192 -0
- package/dist/strand-network-config.js.map +1 -0
- package/dist/strand-revocation-enforcer.d.ts +392 -0
- package/dist/strand-revocation-enforcer.js +533 -0
- package/dist/strand-revocation-enforcer.js.map +1 -0
- package/dist/strand-solicitation.d.ts +17 -1
- package/dist/strand-solicitation.js +13 -2
- package/dist/strand-solicitation.js.map +1 -1
- package/dist/strand-wake-protocol.d.ts +11 -7
- package/dist/strand-wake-protocol.js +20 -52
- package/dist/strand-wake-protocol.js.map +1 -1
- package/dist/strand-watcher.js +12 -1
- package/dist/strand-watcher.js.map +1 -1
- package/dist/timed-step.d.ts +12 -0
- package/dist/timed-step.js +28 -0
- package/dist/timed-step.js.map +1 -0
- package/dist/timeout-scheduler.d.ts +19 -0
- package/dist/timeout-scheduler.js +22 -0
- package/dist/timeout-scheduler.js.map +1 -0
- package/dist/types.d.ts +472 -46
- package/dist/types.js +7 -1
- package/dist/types.js.map +1 -1
- package/package.json +16 -8
- package/src/bootstrap-peer-store-file.ts +2 -2
- package/src/bootstrap-peer-store.ts +69 -27
- package/src/cadre-node.ts +1926 -228
- package/src/control-authorization.ts +2 -1
- package/src/control-cohort.ts +122 -130
- package/src/control-database.ts +586 -74
- package/src/control-read-retry.ts +202 -167
- package/src/control-retry.ts +297 -190
- package/src/control-schema.ts +133 -21
- package/src/control-write-retry.ts +525 -383
- package/src/enrolled-machine-store-file.ts +43 -0
- package/src/enrolled-machine-store.ts +280 -0
- package/src/file-durable-slot.ts +5 -3
- package/src/index.ts +134 -15
- package/src/membership-connection-gater.ts +9 -3
- package/src/node-local-snapshot.ts +38 -9
- package/src/peer-addr-book.ts +251 -250
- package/src/peer-dial.ts +215 -0
- package/src/{strand-backfill.ts → peer-join-backfill.ts} +478 -389
- package/src/relay-addrs.ts +458 -218
- package/src/relay-reservation.ts +951 -828
- package/src/seed-bootstrap.ts +76 -18
- package/src/storage-scope.ts +78 -0
- package/src/strand-database.ts +61 -21
- package/src/strand-first-sync-gate.ts +258 -0
- package/src/strand-formation-manager.ts +162 -8
- package/src/strand-formation-protocol.ts +850 -692
- package/src/strand-instance-manager.ts +877 -74
- package/src/strand-member-key.ts +20 -12
- package/src/strand-member-registry.ts +3 -0
- package/src/strand-membership-reconciler.ts +680 -0
- package/src/strand-membership-writer.ts +550 -190
- package/src/strand-network-config.ts +250 -0
- package/src/strand-revocation-enforcer.ts +653 -0
- package/src/strand-solicitation.ts +499 -471
- package/src/strand-wake-protocol.ts +21 -66
- package/src/strand-watcher.ts +325 -314
- package/src/timed-step.ts +28 -0
- package/src/timeout-scheduler.ts +28 -0
- package/src/types.ts +487 -52
- package/dist/strand-backfill.js.map +0 -1
|
@@ -30,7 +30,8 @@ import type { Libp2p, Connection } from '@libp2p/interface';
|
|
|
30
30
|
import type { Multiaddr } from '@multiformats/multiaddr';
|
|
31
31
|
import type { StrandInstance, WakeRequest, WakeAck } from './types.js';
|
|
32
32
|
import { decodeLengthPrefixedFrame } from './seed-bootstrap.js';
|
|
33
|
-
import { type ControlStream, writeFrame,
|
|
33
|
+
import { type ControlStream, writeFrame, exchangeFrame, readStreamToEnd } from './control-stream.js';
|
|
34
|
+
import { tryAddrsInTurn } from './peer-dial.js';
|
|
34
35
|
|
|
35
36
|
const log = debug('sereus:cadre:strand-wake');
|
|
36
37
|
|
|
@@ -60,8 +61,10 @@ const DEFAULT_WAKE_TIMEOUT_MS = 10_000;
|
|
|
60
61
|
*
|
|
61
62
|
* This makes the TARGET PEER the unit rather than the address — the same
|
|
62
63
|
* decision, for the same reason, as
|
|
63
|
-
* `DEFAULT_CONTROL_COHORT_DIAL_TIMEOUT_MS` in `
|
|
64
|
-
*
|
|
64
|
+
* `DEFAULT_CONTROL_COHORT_DIAL_TIMEOUT_MS` in `peer-dial.ts`, though not the same
|
|
65
|
+
* number: that one is sized to fit several dead addresses ahead of a working one,
|
|
66
|
+
* while a wake target is expected to be awake and reachable on its first or second
|
|
67
|
+
* address. 20 s is deliberately wider than one attempt timeout so a
|
|
65
68
|
* reachable peer whose signaling address is stale still gets a genuine try at
|
|
66
69
|
* its direct one; a peer needing longer than that is not "asleep and reachable",
|
|
67
70
|
* which is the only case a wake is for. The last attempt inside the budget gets
|
|
@@ -271,12 +274,6 @@ export interface DialWakeOptions {
|
|
|
271
274
|
protocolId?: string;
|
|
272
275
|
}
|
|
273
276
|
|
|
274
|
-
/** One candidate's outcome, kept so the thrown error can name every attempt. */
|
|
275
|
-
interface WakeDialFailure {
|
|
276
|
-
addr: Multiaddr;
|
|
277
|
-
error: Error;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
277
|
/**
|
|
281
278
|
* Sender side: dial a target's control-network address(es), send a
|
|
282
279
|
* {@link WakeRequest} over `WAKE_PROTOCOL`, and return the peer's {@link WakeAck}.
|
|
@@ -289,16 +286,18 @@ interface WakeDialFailure {
|
|
|
289
286
|
* dropped.
|
|
290
287
|
*
|
|
291
288
|
* Throws if no address is dialable — with an error naming EVERY candidate and
|
|
292
|
-
* why it failed, not merely the last one. That
|
|
293
|
-
* with only the last candidate's message the
|
|
294
|
-
* signaling address, tried first) is
|
|
295
|
-
*
|
|
289
|
+
* why it failed, not merely the last one ({@link tryAddrsInTurn}). That
|
|
290
|
+
* distinction is not cosmetic: with only the last candidate's message the
|
|
291
|
+
* failure that mattered (usually the signaling address, tried first) is
|
|
292
|
+
* invisible outside a debug log, and the surfaced message points at whichever
|
|
293
|
+
* address happened to be tried last.
|
|
296
294
|
*
|
|
297
295
|
* The candidate loop is deliberately explicit rather than one
|
|
298
296
|
* `dialProtocol(addrs)` call. libp2p sorts any multi-address dial with
|
|
299
297
|
* `defaultAddressSorter`, whose `circuitRelayAddressesLast` pass would demote
|
|
300
298
|
* exactly the signaling address this ordering puts first — silently inverting
|
|
301
|
-
* it, with no per-dial sorter override to opt out of.
|
|
299
|
+
* it, with no per-dial sorter override to opt out of. For the same reason this
|
|
300
|
+
* does not use `dialPeerAddrs`, which puts relayed addresses last.
|
|
302
301
|
*/
|
|
303
302
|
export async function dialWake(
|
|
304
303
|
node: Libp2p,
|
|
@@ -310,58 +309,14 @@ export async function dialWake(
|
|
|
310
309
|
throw new Error('No dialable address for wake target');
|
|
311
310
|
}
|
|
312
311
|
const protocolId = options.protocolId ?? WAKE_PROTOCOL;
|
|
313
|
-
const
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
const remaining = deadline - Date.now();
|
|
322
|
-
if (remaining <= 0) {
|
|
323
|
-
failures.push({ addr, error: new Error(`not tried — the ${budgetMs}ms wake dial budget was spent on earlier addresses`) });
|
|
324
|
-
continue;
|
|
325
|
-
}
|
|
326
|
-
const attemptMs = Math.min(timeoutMs, remaining);
|
|
327
|
-
try {
|
|
328
|
-
// One deadline per attempt: its signal aborts the in-flight dialProtocol and
|
|
329
|
-
// resets the live stream, so neither the connect nor the ack-read leaks.
|
|
330
|
-
return await withDeadline(
|
|
331
|
-
attemptMs,
|
|
332
|
-
`Wake dial ${addr.toString()}`,
|
|
333
|
-
(signal) => sendWake(node, addr, protocolId, request, attemptMs, signal),
|
|
334
|
-
);
|
|
335
|
-
} catch (err) {
|
|
336
|
-
failures.push({ addr, error: err instanceof Error ? err : new Error(String(err)) });
|
|
337
|
-
log('Wake dial to %s failed: %o', addr.toString(), err);
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
throw wakeDialError(failures);
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
/**
|
|
344
|
-
* Fold every candidate's failure into the one error {@link dialWake} throws.
|
|
345
|
-
*
|
|
346
|
-
* A single candidate throws its own error unchanged, so a one-address wake reads
|
|
347
|
-
* exactly as it always has (and `rejects.toThrow(/timed out/)` still means what
|
|
348
|
-
* it says). Several candidates produce one message naming each address and its
|
|
349
|
-
* cause, with the FIRST failure as `cause` — the first candidate is the
|
|
350
|
-
* signaling address, which is the one that matters when a relayed peer goes
|
|
351
|
-
* unreachable.
|
|
352
|
-
*/
|
|
353
|
-
function wakeDialError(failures: WakeDialFailure[]): Error {
|
|
354
|
-
if (failures.length === 0) {
|
|
355
|
-
return new Error('Wake dial failed');
|
|
356
|
-
}
|
|
357
|
-
if (failures.length === 1) {
|
|
358
|
-
return failures[0].error;
|
|
359
|
-
}
|
|
360
|
-
const detail = failures.map((f) => `${f.addr.toString()} — ${f.error.message}`).join('; ');
|
|
361
|
-
return new Error(
|
|
362
|
-
`Wake dial failed for all ${failures.length} candidate addresses: ${detail}`,
|
|
363
|
-
{ cause: failures[0].error },
|
|
364
|
-
);
|
|
312
|
+
const budget = {
|
|
313
|
+
perAddressMs: options.timeoutMs ?? DEFAULT_WAKE_TIMEOUT_MS,
|
|
314
|
+
totalMs: options.budgetMs ?? DEFAULT_WAKE_DIAL_BUDGET_MS,
|
|
315
|
+
};
|
|
316
|
+
// The attempt's signal aborts the in-flight dialProtocol and resets the live
|
|
317
|
+
// stream, so neither the connect nor the ack-read leaks.
|
|
318
|
+
return await tryAddrsInTurn(addrs, budget, 'Wake dial', (addr, signal, attemptMs) =>
|
|
319
|
+
sendWake(node, addr, protocolId, request, attemptMs, signal));
|
|
365
320
|
}
|
|
366
321
|
|
|
367
322
|
/**
|