From bf1a866f2f7b3747ce3a09cf1001a5e2da47d68b Mon Sep 17 00:00:00 2001 From: sudacode Date: Sat, 14 Feb 2026 15:13:07 -0800 Subject: [PATCH] refactor mpv reconnect scheduling into transport layer --- src/core/services/mpv-service.ts | 26 +++++++------ src/core/services/mpv-transport.test.ts | 50 ++++++++++++++++++++++++- src/core/services/mpv-transport.ts | 26 +++++++++++++ 3 files changed, 89 insertions(+), 13 deletions(-) diff --git a/src/core/services/mpv-service.ts b/src/core/services/mpv-service.ts index fcde05d..ce9532a 100644 --- a/src/core/services/mpv-service.ts +++ b/src/core/services/mpv-service.ts @@ -14,7 +14,9 @@ import { splitMpvMessagesFromBuffer, } from "./mpv-protocol"; import { requestMpvInitialState, subscribeToMpvProperties } from "./mpv-properties"; -import { getMpvReconnectDelay } from "./mpv-transport"; +import { + scheduleMpvReconnect, +} from "./mpv-transport"; export { MPV_REQUEST_ID_SECONDARY_SUB_VISIBILITY, @@ -192,20 +194,20 @@ export class MpvIpcClient implements MpvClient { } private scheduleReconnect(): void { - const reconnectTimer = this.deps.getReconnectTimer(); - if (reconnectTimer) { - clearTimeout(reconnectTimer); - } - const attempt = this.reconnectAttempt++; - const delay = getMpvReconnectDelay(attempt, this.hasConnectedOnce); - this.deps.setReconnectTimer( - setTimeout(() => { + this.reconnectAttempt = scheduleMpvReconnect({ + attempt: this.reconnectAttempt, + hasConnectedOnce: this.hasConnectedOnce, + getReconnectTimer: () => this.deps.getReconnectTimer(), + setReconnectTimer: (timer) => this.deps.setReconnectTimer(timer), + onReconnectAttempt: (attempt, delay) => { console.log( - `Attempting to reconnect to MPV (attempt ${attempt + 1}, delay ${delay}ms)...`, + `Attempting to reconnect to MPV (attempt ${attempt}, delay ${delay}ms)...`, ); + }, + connect: () => { this.connect(); - }, delay), - ); + }, + }); } private processBuffer(): void { diff --git a/src/core/services/mpv-transport.test.ts b/src/core/services/mpv-transport.test.ts index f14cacb..e2aba10 100644 --- a/src/core/services/mpv-transport.test.ts +++ b/src/core/services/mpv-transport.test.ts @@ -1,6 +1,9 @@ import test from "node:test"; import assert from "node:assert/strict"; -import { getMpvReconnectDelay } from "./mpv-transport"; +import { + getMpvReconnectDelay, + scheduleMpvReconnect, +} from "./mpv-transport"; test("getMpvReconnectDelay follows existing reconnect ramp", () => { assert.equal(getMpvReconnectDelay(0, true), 1000); @@ -14,3 +17,48 @@ test("getMpvReconnectDelay follows existing reconnect ramp", () => { assert.equal(getMpvReconnectDelay(4, false), 1000); assert.equal(getMpvReconnectDelay(6, false), 2000); }); + +test("scheduleMpvReconnect clears existing timer and increments attempt", () => { + const existing = {} as ReturnType; + const cleared: Array | null> = []; + const setTimers: Array | null> = []; + const calls: Array<{ attempt: number; delay: number }> = []; + let connected = 0; + + const originalSetTimeout = globalThis.setTimeout; + const originalClearTimeout = globalThis.clearTimeout; + (globalThis as any).setTimeout = (handler: () => void, _delay: number) => { + handler(); + return 1 as unknown as ReturnType; + }; + (globalThis as any).clearTimeout = (timer: ReturnType | null) => { + cleared.push(timer); + }; + + const nextAttempt = scheduleMpvReconnect({ + attempt: 3, + hasConnectedOnce: true, + getReconnectTimer: () => existing, + setReconnectTimer: (timer) => { + setTimers.push(timer); + }, + onReconnectAttempt: (attempt, delay) => { + calls.push({ attempt, delay }); + }, + connect: () => { + connected += 1; + }, + }); + + (globalThis as any).setTimeout = originalSetTimeout; + (globalThis as any).clearTimeout = originalClearTimeout; + + assert.equal(nextAttempt, 4); + assert.equal(cleared.length, 1); + assert.equal(cleared[0], existing); + assert.equal(setTimers.length, 1); + assert.equal(calls.length, 1); + assert.equal(calls[0].attempt, 4); + assert.equal(calls[0].delay, getMpvReconnectDelay(3, true)); + assert.equal(connected, 1); +}); diff --git a/src/core/services/mpv-transport.ts b/src/core/services/mpv-transport.ts index 8bf64ac..90b8843 100644 --- a/src/core/services/mpv-transport.ts +++ b/src/core/services/mpv-transport.ts @@ -26,3 +26,29 @@ export function getMpvReconnectDelay( } return 2000; } + +export interface MpvReconnectSchedulerDeps { + attempt: number; + hasConnectedOnce: boolean; + getReconnectTimer: () => ReturnType | null; + setReconnectTimer: (timer: ReturnType | null) => void; + onReconnectAttempt: (attempt: number, delay: number) => void; + connect: () => void; +} + +export function scheduleMpvReconnect( + deps: MpvReconnectSchedulerDeps, +): number { + const reconnectTimer = deps.getReconnectTimer(); + if (reconnectTimer) { + clearTimeout(reconnectTimer); + } + const delay = getMpvReconnectDelay(deps.attempt, deps.hasConnectedOnce); + deps.setReconnectTimer( + setTimeout(() => { + deps.onReconnectAttempt(deps.attempt + 1, delay); + deps.connect(); + }, delay), + ); + return deps.attempt + 1; +}