@torrent-tv/proxy 2.104.1 → 2.104.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@torrent-tv/proxy",
3
- "version": "2.104.1",
3
+ "version": "2.104.2",
4
4
  "description": "Torrent proxy client that exposes webseed-like HTTP stream endpoint.",
5
5
  "license": "GPL-3.0-or-later",
6
6
  "repository": {
@@ -1520,6 +1520,11 @@ export class TorrentPool {
1520
1520
  const context = this.#waitTraceByTorrent.get(torrent);
1521
1521
  if (context?.trace === true) context.emitWaitTrace?.(context.sourceKey, process, phase, fields);
1522
1522
  };
1523
+ if (waitTrace?.trace === true) {
1524
+ // WebTorrent assigns the store during _onStore, after client.add first
1525
+ // returns. Revisit this hook when its ready callback calls us.
1526
+ tracePieceStorePut(pieceStoreOf(torrent), trace);
1527
+ }
1523
1528
  const pool = this;
1524
1529
  const wrap = (method, process) => {
1525
1530
  const original = torrent[method];
@@ -1564,16 +1569,28 @@ export class TorrentPool {
1564
1569
  this.#waitTraceHooks.add(torrent);
1565
1570
  wrap("_startDiscovery", "W2");
1566
1571
  wrap("_onStore", "W6");
1567
- tracePieceStorePut(pieceStoreOf(torrent), trace);
1568
1572
  const verify = torrent._verifyPieces;
1569
1573
  if (typeof verify === "function") {
1570
1574
  torrent._verifyPieces = function (callback, ...args) {
1571
1575
  const startedAt = performance.now();
1572
1576
  trace("W5", "begin", { startedAt });
1573
- return verify.call(this, (...results) => {
1574
- trace("W5", "end", { startedAt, endedAt: performance.now(), outcome: "verified" });
1575
- callback?.(...results);
1576
- }, ...args);
1577
+ let finished = false;
1578
+ const finish = (outcome, fields = {}) => {
1579
+ if (finished) return;
1580
+ finished = true;
1581
+ const endedAt = performance.now();
1582
+ trace("W5", "end", { startedAt, endedAt, durationMs: endedAt - startedAt, outcome, ...fields });
1583
+ };
1584
+ try {
1585
+ return verify.call(this, (...results) => {
1586
+ const error = results[0];
1587
+ finish(error ? "error" : "verified", error ? { error: String(error?.message ?? error) } : {});
1588
+ callback?.(...results);
1589
+ }, ...args);
1590
+ } catch (error) {
1591
+ finish("error", { error: String(error?.message ?? error) });
1592
+ throw error;
1593
+ }
1577
1594
  };
1578
1595
  }
1579
1596
  const timing = this.#swarmTimingByTorrent.get(torrent);
@@ -1,7 +1,9 @@
1
1
  /** Record the torrent worker's verified-piece storage write without changing its callback API. */
2
+ const tracedStores = new WeakSet();
3
+
2
4
  export function tracePieceStorePut(store, trace, now = () => performance.now()) {
3
5
  const put = store?.put;
4
- if (typeof put !== "function") return false;
6
+ if (!store || tracedStores.has(store) || typeof put !== "function") return false;
5
7
 
6
8
  store.put = function (index, bytes, callback) {
7
9
  const startedAt = now();
@@ -24,5 +26,6 @@ export function tracePieceStorePut(store, trace, now = () => performance.now())
24
26
  throw error;
25
27
  }
26
28
  };
29
+ tracedStores.add(store);
27
30
  return true;
28
31
  }
@@ -541,6 +541,16 @@ async function runCommand(command, params, id) {
541
541
  }
542
542
 
543
543
  case Command.PRIORITY_MAP: {
544
+ const startedAt = performance.now();
545
+ emitWaitTrace(params.sourceKey, "W7", "begin", { startedAt, fileIndex: params.fileIndex });
546
+ let traceFinished = false;
547
+ const finishPriorityTrace = (outcome, fields = {}) => {
548
+ if (traceFinished) return;
549
+ traceFinished = true;
550
+ const endedAt = performance.now();
551
+ emitWaitTrace(params.sourceKey, "W7", "end", { startedAt, endedAt,
552
+ durationMs: endedAt - startedAt, outcome, fileIndex: params.fileIndex, ...fields });
553
+ };
544
554
  // When this handler began, on the clock the main thread posted by: the
545
555
  // post to here holds the transfer and this thread's queue together
546
556
  // (torrent-tv/meta#177).
@@ -549,27 +559,21 @@ async function runCommand(command, params, id) {
549
559
  // only update an existing source, never revive one after its viewer left.
550
560
  const zones = Array.isArray(params.zones) ? params.zones : [];
551
561
  // Nor may one for a file held whole, which has nothing left to fetch.
552
- const torrent = await knownTorrent(params.sourceKey);
553
- if (!torrent) {
554
- emitWaitTrace(params.sourceKey, "W7", "event", { outcome: "source-not-ready", fileIndex: params.fileIndex });
555
- return { appliedMs: null, receivedAt, repliedAt: performance.timeOrigin + performance.now() };
556
- }
557
- // What applying a map costs this thread, told to whoever sent it: every
558
- // zone becomes a window of the register and the swarm is told again
559
- // (torrent-tv/meta#166).
560
- const startedAt = performance.now();
561
- emitWaitTrace(params.sourceKey, "W7", "begin", { startedAt, fileIndex: params.fileIndex });
562
562
  try {
563
+ const torrent = await knownTorrent(params.sourceKey);
564
+ if (!torrent) {
565
+ finishPriorityTrace("source-not-ready");
566
+ return { appliedMs: null, receivedAt, repliedAt: performance.timeOrigin + performance.now() };
567
+ }
568
+ // What applying a map costs this thread, told to whoever sent it: every
569
+ // zone becomes a window of the register and the swarm is told again
570
+ // (torrent-tv/meta#166).
563
571
  ensureArrivalsWired(params.sourceKey, torrent);
564
572
  pool.applyPriorityMap(torrent, params.fileIndex, zones, params.durationSeconds);
565
573
  torrent.emit("priority-map-changed", params.fileIndex);
566
- const endedAt = performance.now();
567
- emitWaitTrace(params.sourceKey, "W7", "end", { startedAt, endedAt, durationMs: endedAt - startedAt,
568
- outcome: "applied", fileIndex: params.fileIndex });
574
+ finishPriorityTrace("applied");
569
575
  } catch (error) {
570
- const endedAt = performance.now();
571
- emitWaitTrace(params.sourceKey, "W7", "end", { startedAt, endedAt, durationMs: endedAt - startedAt,
572
- outcome: "error", error: String(error?.message ?? error), fileIndex: params.fileIndex });
576
+ finishPriorityTrace("error", { error: String(error?.message ?? error) });
573
577
  throw error;
574
578
  }
575
579
  return { appliedMs: performance.now() - startedAt, receivedAt, repliedAt: performance.timeOrigin + performance.now() };