@blockcast/mmt-container 0.5.0-main.6f3380bce0c1 → 0.5.0-main.8fbc25eb9deb

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.
@@ -13502,6 +13502,9 @@ var FECManager = class _FECManager {
13502
13502
  // Receiver-local first-accepted-symbol time per block, bounded like
13503
13503
  // #blockPathCounts (see blockAnchorAtMs).
13504
13504
  this.#blockAnchorsMs = /* @__PURE__ */ new Map();
13505
+ // The receipt time of the packet being fed, when it is not now: a datagram
13506
+ // held on a miss and admitted later (withReceiptTime).
13507
+ this.#receiptAtMs = void 0;
13505
13508
  // Exact catalog identity observed on accepted symbols for each FEC block.
13506
13509
  // Conflicting identities collapse to null so recovery fails closed.
13507
13510
  this.#blockCatalogTrackNames = /* @__PURE__ */ new Map();
@@ -13747,6 +13750,7 @@ var FECManager = class _FECManager {
13747
13750
  #seenSymbols;
13748
13751
  #blockPathCounts;
13749
13752
  #blockAnchorsMs;
13753
+ #receiptAtMs;
13750
13754
  #blockCatalogTrackNames;
13751
13755
  #startupAlignedPackets;
13752
13756
  #startupPartialBlocks;
@@ -14238,7 +14242,7 @@ var FECManager = class _FECManager {
14238
14242
  * remainder, so repeated source progress costs no timer operation.
14239
14243
  */
14240
14244
  #armRepairDeadline(key, sbn, packetId, catalogTrackName, delayMs) {
14241
- const deadlineMs = performance.now() + delayMs;
14245
+ const deadlineMs = this.#notEarlierUnderReceipt(this.#receiptNow() + delayMs, this.#repairDeadlineAtMs.get(key));
14242
14246
  this.#repairDeadlineAtMs.set(key, deadlineMs);
14243
14247
  const armed = this.#repairDeadlines.get(key);
14244
14248
  if (armed?.handle != null) {
@@ -14258,7 +14262,7 @@ var FECManager = class _FECManager {
14258
14262
  timer.handle = null;
14259
14263
  this.#requestRepair(sbn, packetId, catalogTrackName);
14260
14264
  };
14261
- timer.handle = setTimeout(onFire, delayMs);
14265
+ timer.handle = setTimeout(onFire, Math.max(0, deadlineMs - performance.now()));
14262
14266
  this.#repairDeadlines.set(key, timer);
14263
14267
  }
14264
14268
  #requestRepair(sbn, packetId, catalogTrackName, settledByOrder = false) {
@@ -14662,7 +14666,10 @@ var FECManager = class _FECManager {
14662
14666
  }
14663
14667
  #armBlockTimeout(sbn, packetId, catalogTrackName, delayMs) {
14664
14668
  const key = this.#blockKey(sbn, packetId, catalogTrackName);
14665
- const waitAtMs = performance.now() + Math.max(1, Math.ceil(delayMs));
14669
+ const waitAtMs = this.#notEarlierUnderReceipt(
14670
+ this.#receiptNow() + Math.max(1, Math.ceil(delayMs)),
14671
+ this.#blockWaitDeadlinesMs.get(key)
14672
+ );
14666
14673
  const holdAtMs = this.#repairHoldUntilMs.get(key);
14667
14674
  this.#blockWaitDeadlinesMs.set(key, holdAtMs === void 0 ? waitAtMs : Math.min(waitAtMs, holdAtMs));
14668
14675
  this.#applyBlockDeadline(key, sbn, packetId, catalogTrackName);
@@ -15292,7 +15299,9 @@ var FECManager = class _FECManager {
15292
15299
  moqSymbols: 0,
15293
15300
  complete: false
15294
15301
  };
15295
- if (!this.#blockAnchorsMs.has(blockKey)) this.#blockAnchorsMs.set(blockKey, performance.now());
15302
+ const receivedAtMs = this.#receiptNow();
15303
+ const anchorMs = this.#blockAnchorsMs.get(blockKey);
15304
+ if (anchorMs === void 0 || receivedAtMs < anchorMs) this.#blockAnchorsMs.set(blockKey, receivedAtMs);
15296
15305
  if (source === "multicast") counts.multicastSymbols++;
15297
15306
  else counts.moqSymbols++;
15298
15307
  this.#blockPathCounts.set(blockKey, counts);
@@ -16567,6 +16576,33 @@ var FECManager = class _FECManager {
16567
16576
  }
16568
16577
  queueMicrotask(() => this.#syncDecoderBlockOwners.delete(key));
16569
16578
  }
16579
+ /**
16580
+ * Run `fn` with `receivedAtMs` (performance.now() clock) as the receipt
16581
+ * time of what it feeds. Within a consumer the bc-provenance profile
16582
+ * governs, a datagram held on a miss and admitted later keeps its receipt
16583
+ * time (fec-01 9): it anchors its block's ts and arms the block's
16584
+ * deadlines from then, never later than they are already armed.
16585
+ */
16586
+ withReceiptTime(receivedAtMs, fn) {
16587
+ const outer = this.#receiptAtMs;
16588
+ this.#receiptAtMs = receivedAtMs;
16589
+ try {
16590
+ fn();
16591
+ } finally {
16592
+ this.#receiptAtMs = outer;
16593
+ }
16594
+ }
16595
+ #receiptNow() {
16596
+ return this.#receiptAtMs ?? performance.now();
16597
+ }
16598
+ /**
16599
+ * A held packet admitted late arms from its (earlier) receipt time; that
16600
+ * never pulls in a deadline later activity already armed. Outside a
16601
+ * receipt scope a re-arm replaces the deadline, as a narrower bound may.
16602
+ */
16603
+ #notEarlierUnderReceipt(deadlineMs, armedMs) {
16604
+ return this.#receiptAtMs === void 0 || armedMs === void 0 ? deadlineMs : Math.max(deadlineMs, armedMs);
16605
+ }
16570
16606
  /** Refresh deadlines after accepted block activity. */
16571
16607
  noteBlockActivity(sbn, packetId, catalogTrackName, sourceProgress = false) {
16572
16608
  if (!this.#trackConfigs.has(packetId)) return;
@@ -19452,6 +19488,8 @@ var MmtpRouter = class {
19452
19488
  #unicastRepair = false;
19453
19489
  /** How to route a held unicast (MoQ) datagram once a record admits it. */
19454
19490
  #heldReplay = /* @__PURE__ */ new WeakMap();
19491
+ /** When a held datagram was received: admitted later, it keeps that receipt time (fec-01 9). */
19492
+ #heldAt = /* @__PURE__ */ new WeakMap();
19455
19493
  /** The flow whose receiver admitted a stream's source datagrams, by packetId then catalog track name: recovered packets answer to it. */
19456
19494
  #provenanceStreamFlow = /* @__PURE__ */ new Map();
19457
19495
  #unregisteredFlowDrops = 0;
@@ -20237,6 +20275,7 @@ var MmtpRouter = class {
20237
20275
  if (verdict === "admitted") return "admitted";
20238
20276
  if (verdict === "held") {
20239
20277
  this.#heldReplay.set(packet, replay);
20278
+ this.#heldAt.set(packet, performance.now());
20240
20279
  return "held";
20241
20280
  }
20242
20281
  this.#unadmittedListedDrops++;
@@ -20255,9 +20294,14 @@ var MmtpRouter = class {
20255
20294
  this.#noteFlowAdmitted(flow);
20256
20295
  this.#withDeferredFecPokes(() => {
20257
20296
  for (const datagram of result.admitted) {
20258
- const replay = this.#heldReplay.get(datagram);
20259
- if (replay) replay();
20260
- else this.#processMMTP(datagram, "multicast", true, this.#heldIngress.get(datagram) ?? entry.ingress, false, true);
20297
+ const route = () => {
20298
+ const replay = this.#heldReplay.get(datagram);
20299
+ if (replay) replay();
20300
+ else this.#processMMTP(datagram, "multicast", true, this.#heldIngress.get(datagram) ?? entry.ingress, false, true);
20301
+ };
20302
+ const heldAt = this.#heldAt.get(datagram);
20303
+ if (heldAt !== void 0 && this.#fecManager?.withReceiptTime) this.#fecManager.withReceiptTime(heldAt, route);
20304
+ else route();
20261
20305
  }
20262
20306
  });
20263
20307
  }
@@ -21263,7 +21307,10 @@ var MmtpRouter = class {
21263
21307
  if (verdict === "admitted") {
21264
21308
  this.#noteFlowAdmitted(ingress.flow);
21265
21309
  this.#processMMTP(packet, source, true, ingress, overlapCopy);
21266
- } else if (verdict === "held") this.#heldIngress.set(packet, ingress);
21310
+ } else if (verdict === "held") {
21311
+ this.#heldIngress.set(packet, ingress);
21312
+ this.#heldAt.set(packet, performance.now());
21313
+ }
21267
21314
  return;
21268
21315
  }
21269
21316
  if (source === "moq" && !manifestAdmitted) {