mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 07:52:24 +00:00
fix(webtorrent): ensure webseed-only streams are marked healthy
Previously, `probePeers` would mark a stream as unhealthy (healthy: false) if no P2P peers were found, even if a valid webseed was present. This caused the UI to potentially disable playback or show error states for webseed-only content. This fix ensures that if `peers === 0` but `hasWebSeed` is true, the probe result returns `healthy: true` with reason `"webseed"`. Added `tests/webtorrent-regression.test.mjs` to verify this behavior and prevent future regressions. Co-authored-by: PR0M3TH3AN <[email protected]>
This commit is contained in:
1 parent
1dd379577f
commit
9aaf8aa4d5
2 files changed
+98
-6
No files matched your search
+8
-6
@@ -346,23 +346,25 @@ export class TorrentClient {
|
||||
|
||||
torrent.once("error", (err) => {
|
||||
const peers = Math.max(0, Math.floor(normalizeNumber(torrent?.numPeers, 0)));
|
||||
const webseedOnly = peers === 0 && hasWebSeed;
|
||||
finalize({
|
||||
healthy: false,
|
||||
reason: "error",
|
||||
healthy: webseedOnly,
|
||||
reason: webseedOnly ? "webseed" : "error",
|
||||
error: toError(err),
|
||||
peers,
|
||||
webseedOnly: peers === 0 && hasWebSeed,
|
||||
webseedOnly,
|
||||
});
|
||||
});
|
||||
|
||||
if (safeTimeout > 0) {
|
||||
timeoutId = setTimeout(() => {
|
||||
const peers = Math.max(0, Math.floor(normalizeNumber(torrent?.numPeers, 0)));
|
||||
const webseedOnly = peers === 0 && hasWebSeed;
|
||||
finalize({
|
||||
healthy: false,
|
||||
healthy: webseedOnly,
|
||||
peers,
|
||||
reason: "timeout",
|
||||
webseedOnly: peers === 0 && hasWebSeed,
|
||||
reason: webseedOnly ? "webseed" : "timeout",
|
||||
webseedOnly,
|
||||
});
|
||||
}, safeTimeout);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
|
||||
import { test, describe, it, after, before } from "node:test";
|
||||
import assert from "node:assert";
|
||||
import EventEmitter from "events";
|
||||
import { TorrentClient } from "../js/webtorrent.js";
|
||||
|
||||
// Mock WebTorrent class
|
||||
class MockWebTorrent extends EventEmitter {
|
||||
constructor() {
|
||||
super();
|
||||
this.torrents = [];
|
||||
this.setMaxListeners = () => {};
|
||||
}
|
||||
|
||||
add(magnet, opts, cb) {
|
||||
const torrent = new MockTorrent(magnet, opts);
|
||||
this.torrents.push(torrent);
|
||||
|
||||
setTimeout(() => {
|
||||
if (typeof cb === 'function') cb(torrent);
|
||||
this.emit('torrent', torrent);
|
||||
}, 10);
|
||||
|
||||
return torrent;
|
||||
}
|
||||
|
||||
destroy(cb) {
|
||||
if (typeof cb === 'function') cb();
|
||||
}
|
||||
}
|
||||
|
||||
class MockTorrent extends EventEmitter {
|
||||
constructor(magnet, opts) {
|
||||
super();
|
||||
this.magnet = magnet;
|
||||
this.opts = opts;
|
||||
this.numPeers = 0;
|
||||
this.files = [];
|
||||
}
|
||||
|
||||
destroy(opts, cb) {
|
||||
if (typeof cb === 'function') cb();
|
||||
}
|
||||
}
|
||||
|
||||
describe("WebTorrent Regression Tests", () => {
|
||||
before(() => {
|
||||
if (typeof global.window === "undefined") {
|
||||
global.window = {};
|
||||
}
|
||||
if (typeof global.window.location === "undefined") {
|
||||
global.window.location = { hostname: "localhost" };
|
||||
}
|
||||
if (typeof global.navigator === "undefined") {
|
||||
global.navigator = { userAgent: "node" };
|
||||
}
|
||||
});
|
||||
|
||||
it("probePeers should report healthy if webseed is present even with 0 peers", async () => {
|
||||
const client = new TorrentClient({ webTorrentClass: MockWebTorrent });
|
||||
const magnet = "magnet:?xt=urn:btih:0123456789abcdef0123456789abcdef01234567";
|
||||
const webSeedUrl = "http://localhost:8080/video.mp4";
|
||||
|
||||
const result = await client.probePeers(magnet, {
|
||||
timeoutMs: 50, // Short timeout
|
||||
urlList: [webSeedUrl]
|
||||
});
|
||||
|
||||
assert.strictEqual(result.webseedOnly, true, "Should detect webseed only scenario");
|
||||
assert.strictEqual(result.healthy, true, "Should be healthy due to webseed");
|
||||
assert.strictEqual(result.reason, "webseed", "Reason should be 'webseed'");
|
||||
});
|
||||
|
||||
it("probePeers should report unhealthy if no webseed and 0 peers", async () => {
|
||||
const client = new TorrentClient({ webTorrentClass: MockWebTorrent });
|
||||
const magnet = "magnet:?xt=urn:btih:0123456789abcdef0123456789abcdef01234567";
|
||||
|
||||
// Adding tracker to avoid "no-trackers" immediate return
|
||||
const magnetWithTr = magnet + "&tr=wss://tracker.example.com";
|
||||
|
||||
const result = await client.probePeers(magnetWithTr, {
|
||||
timeoutMs: 50,
|
||||
urlList: []
|
||||
});
|
||||
|
||||
assert.strictEqual(result.webseedOnly, false, "Should not be webseed only");
|
||||
assert.strictEqual(result.healthy, false, "Should be unhealthy");
|
||||
assert.strictEqual(result.reason, "timeout", "Reason should be 'timeout'");
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user