@blockcast/fec-worker 0.1.0-main.02dfe3276f87

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.
Files changed (48) hide show
  1. package/README.md +223 -0
  2. package/dist/.build-stamp +0 -0
  3. package/dist/block-order.d.ts +38 -0
  4. package/dist/block-order.d.ts.map +1 -0
  5. package/dist/block-order.js +78 -0
  6. package/dist/block-order.js.map +1 -0
  7. package/dist/fec-worker-client.d.ts +93 -0
  8. package/dist/fec-worker-client.d.ts.map +1 -0
  9. package/dist/fec-worker-client.js +346 -0
  10. package/dist/fec-worker-client.js.map +1 -0
  11. package/dist/fec-worker-types.d.ts +380 -0
  12. package/dist/fec-worker-types.d.ts.map +1 -0
  13. package/dist/fec-worker-types.js +11 -0
  14. package/dist/fec-worker-types.js.map +1 -0
  15. package/dist/fec-worker.d.ts +14 -0
  16. package/dist/fec-worker.d.ts.map +1 -0
  17. package/dist/fec-worker.js +859 -0
  18. package/dist/fec-worker.js.map +7 -0
  19. package/dist/index.d.ts +10 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +8 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/shred-fec-worker.d.ts +20 -0
  24. package/dist/shred-fec-worker.d.ts.map +1 -0
  25. package/dist/shred-fec-worker.js +370 -0
  26. package/dist/shred-fec-worker.js.map +7 -0
  27. package/dist/shred-worker-client.d.ts +104 -0
  28. package/dist/shred-worker-client.d.ts.map +1 -0
  29. package/dist/shred-worker-client.js +181 -0
  30. package/dist/shred-worker-client.js.map +1 -0
  31. package/dist/shred-worker-types.d.ts +194 -0
  32. package/dist/shred-worker-types.d.ts.map +1 -0
  33. package/dist/shred-worker-types.js +62 -0
  34. package/dist/shred-worker-types.js.map +1 -0
  35. package/dist/transfer.d.ts +9 -0
  36. package/dist/transfer.d.ts.map +1 -0
  37. package/dist/transfer.js +13 -0
  38. package/dist/transfer.js.map +1 -0
  39. package/package.json +59 -0
  40. package/src/block-order.ts +93 -0
  41. package/src/fec-worker-client.ts +392 -0
  42. package/src/fec-worker-types.ts +399 -0
  43. package/src/fec-worker.ts +1502 -0
  44. package/src/index.ts +35 -0
  45. package/src/shred-fec-worker.ts +589 -0
  46. package/src/shred-worker-client.ts +222 -0
  47. package/src/shred-worker-types.ts +209 -0
  48. package/src/transfer.ts +12 -0
@@ -0,0 +1,346 @@
1
+ /**
2
+ * @blockcast/fec-worker — Main-Thread Client
3
+ *
4
+ * Wraps one Worker per track instance. Provides typed API for the
5
+ * FecWorkerCommand/FecWorkerEvent protocol with zero-copy ArrayBuffer transfers.
6
+ *
7
+ * Constructor accepts either a URL (creates Worker internally) or a pre-created
8
+ * Worker instance (for testing via constructor injection).
9
+ */
10
+ export class FecWorkerClient {
11
+ #worker;
12
+ #onFrame = null;
13
+ #onSnapshot = null;
14
+ #onBlockUpdate = null;
15
+ #onCleanupComplete = null;
16
+ #onError = null;
17
+ #cleanupInFlight = null;
18
+ #queuedCleanupSbns = new Set();
19
+ #pendingResets = 0;
20
+ #resetFailed = false;
21
+ #disposed = false;
22
+ // Symbols fed during the current task, sent as one feedSymbols message
23
+ // when the task's microtasks run (BLO-36599). A packet stream delivers many
24
+ // symbols per task, and each postMessage is a structured-clone round trip
25
+ // on the page thread; the batch boundary is the task, not a size or timer.
26
+ #pendingSymbols = [];
27
+ #pendingTransfer = [];
28
+ #flushQueued = false;
29
+ // Batching starts only once the Worker announced it accepts feedSymbols.
30
+ #batchSymbols = false;
31
+ // The Worker posts blockUpdate events only to a client that subscribed,
32
+ // which this client does once a callback is registered and the Worker
33
+ // announced the command (BLO-36599).
34
+ #blockUpdatesAnnounced = false;
35
+ #blockUpdatesSubscribed = false;
36
+ /**
37
+ * Create a FecWorkerClient.
38
+ * @param workerOrUrl - Either a Worker instance (for testing) or a URL to create one
39
+ */
40
+ constructor(workerOrUrl) {
41
+ if (workerOrUrl instanceof URL) {
42
+ this.#worker = new Worker(workerOrUrl, { type: "module" });
43
+ }
44
+ else {
45
+ this.#worker = workerOrUrl;
46
+ }
47
+ this.#worker.onmessage = (e) => this.#handleEvent(e.data);
48
+ this.#worker.onerror = (e) => {
49
+ this.#onError?.(formatWorkerError(e), "worker-runtime");
50
+ };
51
+ this.#worker.onmessageerror = (e) => {
52
+ this.#onError?.(formatWorkerMessageError(e), "worker-message");
53
+ };
54
+ }
55
+ /**
56
+ * Configure the Worker with FEC parameters and WASM module.
57
+ * wasmModule is transferred (not neutered — WebAssembly.Module is shareable).
58
+ * altaPublicKey is PKCS#8 SPKI DER bytes (self-describing — algorithm detected from OID).
59
+ * Transferred (detached from sender).
60
+ * altaWasmModule is structured-cloneable (NOT transferable — do not add to transfer list).
61
+ */
62
+ configure(config, wasmModule, altaPublicKey, altaWasmModule) {
63
+ if (this.#disposed)
64
+ throw new Error("[FecWorkerClient] disposed");
65
+ this.#flushSymbols();
66
+ const cmd = {
67
+ type: "configure",
68
+ config,
69
+ wasmModule,
70
+ altaPublicKey,
71
+ altaWasmModule,
72
+ };
73
+ // WebAssembly.Module is structured-cloneable, NOT transferable.
74
+ // Pass it in the message body (Chrome clones it automatically).
75
+ // Only ArrayBuffers (like altaPublicKey) go in the transfer list.
76
+ const transferList = [];
77
+ if (altaPublicKey)
78
+ transferList.push(altaPublicKey);
79
+ // altaWasmModule is structured-cloneable — NOT added to transferList
80
+ this.#worker.postMessage(cmd, transferList);
81
+ }
82
+ /**
83
+ * Feed a source symbol to the Worker. data ArrayBuffer is transferred (zero-copy).
84
+ * Caller must not access data after this call — it is transferred with the
85
+ * task's symbol batch, before any later command of this client.
86
+ *
87
+ * Optional `alta` carries the detached ALTA authenticator bytes and the
88
+ * byte offset in `data` where the signed payload ends. The auth buffer is
89
+ * transferred zero-copy alongside `data`. Use {@link getMmtpAltaTrailer}
90
+ * upstream (mmtp-router) to extract it from the wire packet.
91
+ */
92
+ feedSource(ssId, data, ts, alta) {
93
+ if (this.#disposed)
94
+ throw new Error("[FecWorkerClient] feedSource on a disposed client");
95
+ if (alta) {
96
+ this.#queueSymbol({
97
+ type: "feedSource",
98
+ ssId,
99
+ data,
100
+ ts,
101
+ altaAuth: alta.auth,
102
+ altaPayloadEnd: alta.payloadEnd,
103
+ }, data, alta.auth);
104
+ }
105
+ else {
106
+ this.#queueSymbol({ type: "feedSource", ssId, data, ts }, data);
107
+ }
108
+ }
109
+ /**
110
+ * Feed a repair symbol to the Worker. data ArrayBuffer is transferred (zero-copy).
111
+ * Caller must not access data after this call — it is detached.
112
+ *
113
+ * Carries the wire-level Repair FEC Payload ID fields (ISO 23008-1 §C.5.3):
114
+ * - ssStart: SS_ID of first source symbol in the block (= SBN * configured K
115
+ * under `k-padded-v1`; any uint32, the block key, under `iso-ssbg1-v1`)
116
+ * - ssbLength: authored source-symbol count (1..configured K)
117
+ * - rsId: repair symbol index within the block
118
+ */
119
+ feedRepair(ssStart, ssbLength, rsId, data, ts) {
120
+ if (this.#disposed)
121
+ throw new Error("[FecWorkerClient] feedRepair on a disposed client");
122
+ this.#queueSymbol({ type: "feedRepair", ssStart, ssbLength, rsId, data, ts }, data);
123
+ }
124
+ #queueSymbol(symbol, data, auth) {
125
+ if (!this.#batchSymbols) {
126
+ this.#worker.postMessage(symbol, auth ? [data, auth] : [data]);
127
+ return;
128
+ }
129
+ this.#pendingSymbols.push(symbol);
130
+ this.#pendingTransfer.push(data);
131
+ if (auth)
132
+ this.#pendingTransfer.push(auth);
133
+ if (this.#flushQueued)
134
+ return;
135
+ this.#flushQueued = true;
136
+ queueMicrotask(() => {
137
+ this.#flushQueued = false;
138
+ this.#flushSymbols();
139
+ });
140
+ }
141
+ /**
142
+ * Send the symbols fed so far. Every other command calls this first, so a
143
+ * cleanup barrier, reset or signature still follows all earlier symbols.
144
+ */
145
+ #flushSymbols() {
146
+ if (this.#pendingSymbols.length === 0 || this.#disposed)
147
+ return;
148
+ const symbols = this.#pendingSymbols;
149
+ const transfer = this.#pendingTransfer;
150
+ this.#pendingSymbols = [];
151
+ this.#pendingTransfer = [];
152
+ this.#worker.postMessage({ type: "feedSymbols", symbols }, transfer);
153
+ }
154
+ /**
155
+ * Submit relay block signature for verification. sig and hash are transferred.
156
+ */
157
+ relayBlockSig(sbn, sig, hash) {
158
+ if (this.#disposed)
159
+ throw new Error("[FecWorkerClient] relayBlockSig on a disposed client");
160
+ this.#flushSymbols();
161
+ this.#worker.postMessage({ type: "relayBlockSig", sbn, sig, hash }, [sig, hash]);
162
+ }
163
+ /**
164
+ * Trigger cleanup after a block's inactivity deadline. `currentSbn` is the
165
+ * block key: the SBN under `k-padded-v1`, the SS_Start under `iso-ssbg1-v1`.
166
+ *
167
+ * While one queue-drain barrier is in flight, later SBNs are coalesced into
168
+ * the next command without losing their individual acknowledgement identity.
169
+ */
170
+ cleanup(currentSbn) {
171
+ if (this.#disposed)
172
+ throw new Error("[FecWorkerClient] cleanup on a disposed client");
173
+ if (!Number.isInteger(currentSbn) ||
174
+ currentSbn < 0 ||
175
+ currentSbn > 0xffff_ffff) {
176
+ throw new Error("[FecWorkerClient] cleanup: SBN must be a uint32");
177
+ }
178
+ if (this.#cleanupInFlight) {
179
+ this.#queuedCleanupSbns.add(currentSbn);
180
+ return;
181
+ }
182
+ this.#postCleanup(new Set([currentSbn]));
183
+ }
184
+ /** Reset this track's decoder epoch while preserving Worker configuration. */
185
+ reset() {
186
+ if (this.#disposed)
187
+ throw new Error("[FecWorkerClient] reset on a disposed client");
188
+ this.#flushSymbols();
189
+ this.#pendingResets++;
190
+ this.#cleanupInFlight = null;
191
+ this.#queuedCleanupSbns.clear();
192
+ this.#worker.postMessage({ type: "reset" });
193
+ }
194
+ #postCleanup(sbns) {
195
+ // The cleanup is a queue-drain barrier: every symbol fed before it is
196
+ // posted must reach the Worker first.
197
+ this.#flushSymbols();
198
+ this.#cleanupInFlight = sbns;
199
+ const orderedSbns = [...sbns].sort((a, b) => a - b);
200
+ this.#worker.postMessage({ type: "cleanup", sbns: orderedSbns });
201
+ }
202
+ /** Register callback for decoded/recovered frames (FEC-03). */
203
+ onFrame(cb) {
204
+ this.#onFrame = cb;
205
+ }
206
+ /** Register callback for periodic stats snapshots (FEC-04). */
207
+ onSnapshot(cb) {
208
+ this.#onSnapshot = cb;
209
+ }
210
+ /**
211
+ * Register callback for individual block state changes. The Worker posts
212
+ * them only once asked, so registering subscribes (after the Worker
213
+ * announces `subscribeBlockUpdates`). An older Worker that does not
214
+ * announce it posts them unasked.
215
+ */
216
+ onBlockUpdate(cb) {
217
+ this.#onBlockUpdate = cb;
218
+ this.#subscribeBlockUpdates();
219
+ }
220
+ #subscribeBlockUpdates() {
221
+ if (this.#disposed ||
222
+ this.#blockUpdatesSubscribed ||
223
+ !this.#blockUpdatesAnnounced ||
224
+ !this.#onBlockUpdate)
225
+ return;
226
+ this.#blockUpdatesSubscribed = true;
227
+ this.#worker.postMessage({ type: "subscribeBlockUpdates" });
228
+ }
229
+ /** Register callback fired after the Worker drains all commands queued before cleanup. */
230
+ onCleanupComplete(cb) {
231
+ this.#onCleanupComplete = cb;
232
+ }
233
+ /** Register callback for Worker errors. */
234
+ onError(cb) {
235
+ this.#onError = cb;
236
+ }
237
+ /**
238
+ * True once dispose() ran. A disposed client cannot decode, fill, or
239
+ * acknowledge anything, so routing symbols to it discards them; every
240
+ * command method (feedSource, feedRepair, relayBlockSig, cleanup, reset)
241
+ * throws rather than pretend otherwise. Callers check this first.
242
+ */
243
+ get disposed() {
244
+ return this.#disposed;
245
+ }
246
+ /**
247
+ * Dispose the Worker. Sends dispose command then terminates.
248
+ * Idempotent — safe to call multiple times.
249
+ */
250
+ dispose() {
251
+ if (this.#disposed)
252
+ return;
253
+ this.#disposed = true;
254
+ // A terminated Worker decodes nothing; symbols still batched are dropped.
255
+ this.#pendingSymbols = [];
256
+ this.#pendingTransfer = [];
257
+ this.#cleanupInFlight = null;
258
+ this.#queuedCleanupSbns.clear();
259
+ this.#worker.postMessage({ type: "dispose" });
260
+ this.#worker.terminate();
261
+ }
262
+ #handleEvent(event) {
263
+ if (event.type === "capabilities") {
264
+ if (Array.isArray(event.commands) && event.commands.includes("feedSymbols")) {
265
+ this.#batchSymbols = true;
266
+ }
267
+ if (Array.isArray(event.commands) && event.commands.includes("subscribeBlockUpdates")) {
268
+ this.#blockUpdatesAnnounced = true;
269
+ this.#subscribeBlockUpdates();
270
+ }
271
+ return;
272
+ }
273
+ if (event.type === "resetComplete") {
274
+ this.#pendingResets = Math.max(0, this.#pendingResets - 1);
275
+ this.#resetFailed = false;
276
+ return;
277
+ }
278
+ if (event.type === "error") {
279
+ if (event.code === "reset-failed") {
280
+ this.#pendingResets = Math.max(0, this.#pendingResets - 1);
281
+ this.#resetFailed = true;
282
+ }
283
+ if (event.code)
284
+ this.#onError?.(event.message, event.code);
285
+ else
286
+ this.#onError?.(event.message);
287
+ return;
288
+ }
289
+ if (this.#pendingResets > 0 || this.#resetFailed)
290
+ return;
291
+ switch (event.type) {
292
+ case "frame":
293
+ this.#onFrame?.(event.data, event.meta);
294
+ break;
295
+ case "snapshot":
296
+ this.#onSnapshot?.(event.stats);
297
+ break;
298
+ case "blockUpdate":
299
+ this.#onBlockUpdate?.(event.block);
300
+ break;
301
+ case "cleanupComplete":
302
+ for (const sbn of event.sbns) {
303
+ this.#onCleanupComplete?.(sbn);
304
+ }
305
+ this.#cleanupInFlight = null;
306
+ if (this.#queuedCleanupSbns.size > 0) {
307
+ const next = this.#queuedCleanupSbns;
308
+ this.#queuedCleanupSbns = new Set();
309
+ this.#postCleanup(next);
310
+ }
311
+ break;
312
+ }
313
+ }
314
+ }
315
+ function formatWorkerError(event) {
316
+ const parts = ["Worker error"];
317
+ if (event.message)
318
+ parts.push(event.message);
319
+ if (event.filename) {
320
+ const location = [event.filename];
321
+ if (event.lineno)
322
+ location.push(String(event.lineno));
323
+ if (event.colno)
324
+ location.push(String(event.colno));
325
+ parts.push(`at ${location.join(":")}`);
326
+ }
327
+ if (event.error instanceof Error) {
328
+ if (event.error.message && event.error.message !== event.message) {
329
+ parts.push(event.error.message);
330
+ }
331
+ if (event.error.stack)
332
+ parts.push(event.error.stack);
333
+ }
334
+ else if (event.error != null) {
335
+ parts.push(String(event.error));
336
+ }
337
+ return parts.join(": ");
338
+ }
339
+ function formatWorkerMessageError(event) {
340
+ const data = event.data;
341
+ const detail = data == null ? "" :
342
+ data instanceof Error ? `: ${data.message}` :
343
+ `: ${Object.prototype.toString.call(data)}`;
344
+ return `Worker messageerror: failed to deserialize worker message${detail}`;
345
+ }
346
+ //# sourceMappingURL=fec-worker-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fec-worker-client.js","sourceRoot":"","sources":["../src/fec-worker-client.ts"],"names":[],"mappings":"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"}