@torrent-tv/proxy 2.9.80 → 2.9.81
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/CHANGELOG.md +4 -0
- package/package.json +1 -1
- package/routes/stream/get.js +11 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
## 2.9.81
|
|
2
|
+
|
|
3
|
+
- **New**: The stream route says why a read failed. A body that failed mid-flight was dropped silently — the connection closed with no status and no log line, which from the client looks like the proxy died and from the log like nothing happened; found while probing the route by hand, where every ranged read closed the socket without a word. It now reports the file, the range, how many bytes had been sent, and the error.
|
|
4
|
+
|
|
1
5
|
## 2.9.80
|
|
2
6
|
|
|
3
7
|
- **Fix**: A seek backward could hang forever. `prioritizeByteRange` demotes the pieces behind the playhead with `deselect`, which removes them from the download set — and `critical`, which runs right after, only flags pieces that are already selected, so it never puts them back. A seek forward followed by a seek backward therefore left the target pieces wanted by nobody: the encoder waited on data the torrent had been told to stop fetching, while the swarm ran at full speed on pieces nobody needed. The read position is now re-selected whenever it moves back behind what an earlier seek deselected, tracked per file because WebTorrent does not report its own selection back.
|
package/package.json
CHANGED
package/routes/stream/get.js
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { parseRange } from "../../utils/parse-range.js";
|
|
10
|
+
import { logger } from "../../utils/logger.js";
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Resolve source parameters from the query string.
|
|
@@ -121,6 +122,7 @@ export async function handleStreamGet(req, reply, { sourceRegistry, torrentPool
|
|
|
121
122
|
// being fetched for nobody.
|
|
122
123
|
reply.raw.once("close", () => fragments.cancel());
|
|
123
124
|
|
|
125
|
+
let sent = 0;
|
|
124
126
|
try {
|
|
125
127
|
for await (const fragment of fragments) {
|
|
126
128
|
if (reply.raw.writableEnded || reply.raw.destroyed) {
|
|
@@ -130,15 +132,23 @@ export async function handleStreamGet(req, reply, { sourceRegistry, torrentPool
|
|
|
130
132
|
await new Promise((resolve, reject) => {
|
|
131
133
|
reply.raw.write(fragment.bytes, (error) => (error ? reject(error) : resolve()));
|
|
132
134
|
});
|
|
135
|
+
sent += fragment.bytes.length;
|
|
133
136
|
// Only now are these bytes gone: the piece can be unpinned, and the
|
|
134
137
|
// slot it occupies reused. Releasing before this point corrupts the
|
|
135
138
|
// response silently.
|
|
136
139
|
fragment.release();
|
|
137
140
|
}
|
|
138
141
|
reply.raw.end();
|
|
139
|
-
} catch {
|
|
142
|
+
} catch (error) {
|
|
140
143
|
// The body is already committed by its headers, so there is nothing
|
|
141
144
|
// useful to send instead — drop the connection and let the client retry.
|
|
145
|
+
// But say why: swallowing this made the route close connections with no
|
|
146
|
+
// status and no trace, which from the client looks like the proxy died
|
|
147
|
+
// and from the log looks like nothing happened at all.
|
|
148
|
+
logger.warn(
|
|
149
|
+
`stream: read of "${file.name}" bytes ${start}-${end} failed after ` +
|
|
150
|
+
`${sent} of ${contentLength} bytes: ${error instanceof Error ? error.message : String(error)}`
|
|
151
|
+
);
|
|
142
152
|
reply.raw.destroy();
|
|
143
153
|
} finally {
|
|
144
154
|
releaseFile();
|