first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,126 @@
# `parallel-puller.ts`
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
`ParallelPuller` is the chunk-fetch scheduler that turns "I want chunk
N of file F" into a verified `Uint8Array`. The puller asks the
`PeerRegistry` for ranked candidates, issues a request to the best
peer, waits `racingWindowMs`, then issues parallel requests to the
runners-up. The first response whose server signature verifies wins;
the other in-flight attempts are aborted via a shared
`AbortController`.
The puller is the mesh's primary trust enforcement point. Every byte
returned from a transport flows through `verifyChunkSig` before the
puller acknowledges success. A signature failure moves the offending
peer to the registry's denylist with `score = -Infinity` and surfaces
`DriveMeshError(SIG_VERIFY_FAILED)` — the orchestrator can choose to
fall back to the server rather than retry on peers.
## Features
- Top-K candidate selection (default 3).
- Racing-window staggered issuance (default 250 ms).
- Shared `AbortController` short-circuits losing attempts.
- Mandatory `verifyChunkSig` gate against the configured
`serverPubKey`.
- Bad-sig denylisting via `registry.recordBadSig`.
- Non-signature failures update success / failure counters so
ranking adapts.
- `maxParallelRequests` global cap.
## Usage: Basic Example
```ts
import { ParallelPuller } from "@suaveplan/drive-mesh/scheduler/parallel-puller";
const puller = new ParallelPuller({
registry,
transports: [httpsTransport],
serverPubKey,
});
const bytes = await puller.pull("file-id-hex", 0);
```
## Usage: Advanced Example
```ts
import { ParallelPuller } from "@suaveplan/drive-mesh/scheduler/parallel-puller";
const puller = new ParallelPuller({
registry,
transports: [webrtcTransport, httpsTransport],
serverPubKey,
racingWindowMs: 150,
topK: 4,
maxParallelRequests: 16,
clock: fakeClock,
onAttempt: (peerId, fileId, chunkId) =>
log.debug("attempt", peerId, fileId, chunkId),
onSuccess: (peerId, _f, _c, bytes, elapsedMs) =>
log.info("served", peerId, bytes, elapsedMs),
onBadSig: peerId => log.warn("denylisting", peerId),
});
const controller = new AbortController();
setTimeout(() => controller.abort(), 5_000);
try {
const bytes = await puller.pull(fileId, chunkId, controller.signal);
} catch (err) {
if (err instanceof DriveMeshError && err.code === DRIVE_MESH_CODES.ABORTED) {
// caller-driven cancellation
}
}
```
## API Reference
- `class ParallelPuller`:
- `constructor(options: ParallelPullerOptions)`.
- `pull(fileId, chunkId, signal?): Promise<Uint8Array>`.
- `inflight: number` (read-only) — in-flight request count.
- `ParallelPullerOptions`:
- `registry`, `transports`, `serverPubKey` (required).
- `maxParallelRequests?` (default `8`).
- `racingWindowMs?` (default `250`).
- `topK?` (default `3`).
- `clock?`.
- `onAttempt?(peerId, fileId, chunkId)`.
- `onSuccess?(peerId, fileId, chunkId, bytes, elapsedMs)`.
- `onFailure?(peerId, fileId, chunkId, reason)`.
- `onBadSig?(peerId, fileId, chunkId)`.
- Throws:
- `DRIVE_MESH.CHUNK_UNAVAILABLE` — no candidate peers.
- `DRIVE_MESH.SIG_VERIFY_FAILED` — winning peer returned bad sig.
- `DRIVE_MESH.TRANSPORT_FAILED` — single-attempt transport failure.
- `DRIVE_MESH.ALL_PEERS_FAILED` — every candidate failed.
- `DRIVE_MESH.ABORTED` — caller-provided signal aborted.
## Implementation Notes
`firstSettled` is hand-rolled rather than using `Promise.any`:
`Promise.any` resolves on first success but does NOT abort losing
attempts, leaving them in flight wastefully. The shared
`AbortController` is the cancellation primitive — `controller.abort()`
fires both when a winner appears and when the outer caller aborts.
`SIG_VERIFY_FAILED` short-circuits the "all peers failed" wrapping:
the orchestrator distinguishes "every peer failed transport" (try
server fallback) from "winning peer was Byzantine" (denylist + retry
on a different peer). Re-wrapping the bad-sig error inside
`ALL_PEERS_FAILED` would lose that distinction.
`maxParallelRequests` is enforced by a yielding micro-loop in
`#awaitSlot`. The loop is bounded by the number of concurrent `pull`
calls — drive-mesh issues `pull` from a small, controlled set of
async contexts so the loop never spins indefinitely. Under heavier
fan-in the orchestrator should queue requests in front of the puller
rather than issuing every chunk concurrently.
Bad-sig denylist is permanent within the registry's denylist scope:
`session` (default) clears on `mesh.stop()`, `persistent` survives.
The puller does not concern itself with scope — the registry is the
authority.