fix(plex): a seek during a quiet reclaim is no longer undone

A quiet request leaves `live` alone, so a seek inside the old session's
range went native and the answer then jumped back to where it asked from.
`seek` now also goes by `pending`; the server-away retry had the same hole.

Comments that still named 404 for a lost session say 410, and the hls.js
retry comment now tells a finished playlist from a growing one.
This commit is contained in:
2026-11-03 21:10:51 +01:00
parent 469c8aa481
commit 3f6638bf96
6 changed files with 50 additions and 23 deletions
+26 -1
View File
@@ -374,7 +374,7 @@ describe("a failed session request", () => {
});
});
describe("a session the server no longer has (404)", () => {
describe("something that never arrives (a fatal 404)", () => {
it("is reclaimed where the viewer is", async () => {
const { engine, asks, hlses, state } = setup();
engine.start("A", 600);
@@ -482,6 +482,17 @@ describe("a session the server says is gone (410)", () => {
expect(engine.getSnapshot().error).toBe("generic");
});
it("keeps a seek made while it is out, inside what the old session still reports", async () => {
const { engine, asks, hlses, media } = await playing();
media.seekEnd = 800;
hlses[0]!.gone();
media.currentTime = 42;
engine.seek("A", 1250);
expect(media.currentTime).toBe(42); // the outgoing media stays where it is
await asks[1]!.resolve(hls("A", 1299));
expect(asks.map((a) => a.startAt)).toEqual([600, 1299, 1250]);
});
it("leaves a segment that is merely not there yet to hls.js's retries", async () => {
const { engine, asks, hlses } = await playing();
hlses[0]!.retrying(404);
@@ -493,6 +504,20 @@ describe("a session the server says is gone (410)", () => {
describe("a server that is restarting (a deploy)", () => {
// The gateway answers 502 while the app restarts, and nothing at all may answer (status 0): the
// stream is not broken, the server is away. The buffer keeps playing meanwhile.
it("keeps a seek made while the retry is out", async () => {
const { engine, asks, hlses, state, fire, media } = setup();
engine.start("A", 600);
await asks[0]!.resolve(hls("A", 600));
hlses[0]!.handlers.onManifestParsed();
media.seekEnd = 800;
state.position = 1299;
hlses[0]!.lost(502);
expect(fire()).toBe(true);
engine.seek("A", 1250);
await asks[1]!.resolve(hls("A", 1299));
expect(asks.map((a) => a.startAt)).toEqual([600, 1299, 1250]);
});
it.each([502, 503, 504, 0, null])(
"is waited out on %s: no error, and the stream comes back where the viewer is",
async (status) => {