fix(anime): cap outcome polling and upstream stalls by wall clock

- watchPlaybackOutcome now tracks a real deadline so slow property reads eat the timeout budget instead of extending it, and a zero probe interval still terminates
- stream strip proxy aborts upstream GETs that go silent for 15s instead of hanging mpv on that segment forever
- anime browser runtime drops a stream proxy that finishes starting after its bridge already died, instead of leaking a listener pointed at nothing
This commit is contained in:
2026-08-01 03:13:48 -07:00
parent dec7851a17
commit 336e9fb8a5
5 changed files with 120 additions and 58 deletions
+11 -2
View File
@@ -26,6 +26,8 @@ export interface WatchPlaybackOutcomeDeps {
/** One-shot mpv property read; may reject while the file is still loading. */
readProperty: (name: string) => Promise<unknown>;
wait: (ms: number) => Promise<void>;
/** Injectable clock; the timeout is wall-clock, not a probe count. */
now?: () => number;
timeoutMs?: number;
probeIntervalMs?: number;
}
@@ -58,7 +60,11 @@ export function watchPlaybackOutcome(deps: WatchPlaybackOutcomeDeps): PlaybackOu
});
async function wait(): Promise<PlaybackOutcome> {
for (let elapsed = 0; elapsed < timeoutMs; elapsed += probeIntervalMs) {
// Wall-clock, not a probe count: a slow `readProperty` must eat into the
// budget rather than stretch it, and a zero probe interval must still end.
const now = deps.now ?? Date.now;
const deadline = now() + timeoutMs;
while (now() < deadline) {
if (failure) return failure;
try {
if ((await deps.readProperty('vo-configured')) === true) return { ok: true };
@@ -66,7 +72,10 @@ export function watchPlaybackOutcome(deps: WatchPlaybackOutcomeDeps): PlaybackOu
// The property is unreadable while mpv is between files; keep polling.
}
if (failure) return failure;
await deps.wait(probeIntervalMs);
// Sleeping past the deadline would only delay the timeout report.
const remaining = deadline - now();
if (remaining <= 0) break;
await deps.wait(Math.min(probeIntervalMs, remaining));
}
return (
failure ?? {