@torrent-tv/proxy 2.102.3 → 2.103.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/package.json
CHANGED
|
@@ -38,6 +38,7 @@ export class PieceTimings {
|
|
|
38
38
|
*/
|
|
39
39
|
asked(piece, offset, peer, now) {
|
|
40
40
|
let record = this.#pieces.get(piece);
|
|
41
|
+
const firstAsk = !record;
|
|
41
42
|
if (!record) {
|
|
42
43
|
record = { firstAskAt: now, asks: 0, peers: new Set(), blocks: new Map(), arrived: new Set(), askedAgain: 0, arrivedTwice: 0,
|
|
43
44
|
slowestMs: 0, slowestPeer: null, lastInFlightMs: 0, lastPeer: null };
|
|
@@ -47,6 +48,7 @@ export class PieceTimings {
|
|
|
47
48
|
record.peers.add(peer);
|
|
48
49
|
if (!record.blocks.has(offset)) record.blocks.set(offset, now);
|
|
49
50
|
else record.askedAgain += 1;
|
|
51
|
+
return firstAsk;
|
|
50
52
|
}
|
|
51
53
|
|
|
52
54
|
/**
|
|
@@ -26,6 +26,7 @@ import { deriveSourceKey } from "../../utils/torrent-source-key.js";
|
|
|
26
26
|
import { noteTorrentDestroyed } from "./destroyed-torrents.js";
|
|
27
27
|
import { PieceTimings, describePieceTiming } from "./piece-timing.js";
|
|
28
28
|
import { TailRepeat } from "./worker/tail-repeat.js";
|
|
29
|
+
import { tracePieceStorePut } from "./worker/trace-piece-store-put.js";
|
|
29
30
|
|
|
30
31
|
/**
|
|
31
32
|
* The second-peer requests for the last blocks of a piece somebody waits for,
|
|
@@ -1544,6 +1545,7 @@ export class TorrentPool {
|
|
|
1544
1545
|
wrap("_onListening", "W1");
|
|
1545
1546
|
wrap("_startDiscovery", "W2");
|
|
1546
1547
|
wrap("_onStore", "W6");
|
|
1548
|
+
tracePieceStorePut(pieceStoreOf(torrent), trace);
|
|
1547
1549
|
const verify = torrent._verifyPieces;
|
|
1548
1550
|
if (typeof verify === "function") {
|
|
1549
1551
|
torrent._verifyPieces = function (callback, ...args) {
|
|
@@ -1603,6 +1605,7 @@ export class TorrentPool {
|
|
|
1603
1605
|
// its blocks were in flight, and from whom (`piece-timing.js`). One line
|
|
1604
1606
|
// per piece: a 2.3 GB film is 563.
|
|
1605
1607
|
const timings = new PieceTimings();
|
|
1608
|
+
const waitTracePieceStarts = new Map();
|
|
1606
1609
|
tailRepeats.set(torrent, new TailRepeat({ torrent, requiredPieces: () => demandFor(torrent).selection.requiredPieces(),
|
|
1607
1610
|
log: (line) => logger.info(`download ${label()} ${line}`) }));
|
|
1608
1611
|
torrent.on("wire", (wire) => {
|
|
@@ -1616,9 +1619,13 @@ export class TorrentPool {
|
|
|
1616
1619
|
const queued = this.requests.length;
|
|
1617
1620
|
const answer = request.call(this, index, offset, length, callback);
|
|
1618
1621
|
if (this.requests.length > queued) {
|
|
1619
|
-
trace("W8", "event", { moment: "block-requested", piece: index, offset, length, peer });
|
|
1620
1622
|
const now = Date.now();
|
|
1621
|
-
timings.asked(index, offset, peer, now);
|
|
1623
|
+
const firstAsk = timings.asked(index, offset, peer, now);
|
|
1624
|
+
if (firstAsk) {
|
|
1625
|
+
const startedAt = performance.now();
|
|
1626
|
+
waitTracePieceStarts.set(index, startedAt);
|
|
1627
|
+
trace("W8", "begin", { piece: index, startedAt, firstOffset: offset, blockLength: length });
|
|
1628
|
+
}
|
|
1622
1629
|
// When this wire was asked for the block: how long it has held it is
|
|
1623
1630
|
// what decides whether a second peer is asked (`duplicateTailFor`).
|
|
1624
1631
|
this.requests.at(-1).askedAt = now;
|
|
@@ -1627,11 +1634,19 @@ export class TorrentPool {
|
|
|
1627
1634
|
};
|
|
1628
1635
|
wire.on("piece", (index, offset) => {
|
|
1629
1636
|
timings.arrived(index, offset, peer, Date.now());
|
|
1630
|
-
trace("W8", "event", { moment: "block-received", piece: index, offset, peer });
|
|
1631
1637
|
});
|
|
1632
1638
|
});
|
|
1633
1639
|
torrent.on("verified", (piece) => {
|
|
1634
|
-
|
|
1640
|
+
const pieceTiming = timings.verified(piece, Date.now());
|
|
1641
|
+
const startedAt = waitTracePieceStarts.get(piece);
|
|
1642
|
+
if (startedAt !== undefined) {
|
|
1643
|
+
waitTracePieceStarts.delete(piece);
|
|
1644
|
+
const endedAt = performance.now();
|
|
1645
|
+
trace("W8", "end", { piece, startedAt, endedAt, durationMs: endedAt - startedAt,
|
|
1646
|
+
outcome: "verified", asks: pieceTiming?.asks ?? null, peers: pieceTiming?.peers ?? null,
|
|
1647
|
+
askedAgain: pieceTiming?.askedAgain ?? null, slowestBlockMs: pieceTiming?.slowestMs ?? null });
|
|
1648
|
+
}
|
|
1649
|
+
logger.info(`download ${label()} verified piece=${piece}${describePieceTiming(pieceTiming)}`);
|
|
1635
1650
|
});
|
|
1636
1651
|
|
|
1637
1652
|
// The first connected peer, said once, because the wait for it can BE the
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** Record the torrent worker's verified-piece storage write without changing its callback API. */
|
|
2
|
+
export function tracePieceStorePut(store, trace, now = () => performance.now()) {
|
|
3
|
+
const put = store?.put;
|
|
4
|
+
if (typeof put !== "function") return false;
|
|
5
|
+
|
|
6
|
+
store.put = function (index, bytes, callback) {
|
|
7
|
+
const startedAt = now();
|
|
8
|
+
const fields = { piece: index, bytes: bytes?.byteLength ?? bytes?.length ?? null, startedAt };
|
|
9
|
+
trace("W9", "begin", fields);
|
|
10
|
+
let finished = false;
|
|
11
|
+
const finish = error => {
|
|
12
|
+
if (finished) return;
|
|
13
|
+
finished = true;
|
|
14
|
+
const endedAt = now();
|
|
15
|
+
trace("W9", "end", { ...fields, endedAt, durationMs: endedAt - startedAt,
|
|
16
|
+
outcome: error ? "error" : "stored", ...(error ? { error: String(error?.message ?? error) } : {}) });
|
|
17
|
+
callback?.(error);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
return put.call(this, index, bytes, finish);
|
|
22
|
+
} catch (error) {
|
|
23
|
+
finish(error);
|
|
24
|
+
throw error;
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
return true;
|
|
28
|
+
}
|