From 5b3787f19f6116a48ae4de057f64220954564d7a Mon Sep 17 00:00:00 2001 From: James Magahern Date: Wed, 18 Feb 2026 17:57:42 -0800 Subject: [PATCH] retry logic for when mpv doesnt start right away --- web/backend/src/MediaPlayer.ts | 62 +++++++++++++++++++++++++++------- 1 file changed, 50 insertions(+), 12 deletions(-) diff --git a/web/backend/src/MediaPlayer.ts b/web/backend/src/MediaPlayer.ts index 5018d61..7d9a242 100644 --- a/web/backend/src/MediaPlayer.ts +++ b/web/backend/src/MediaPlayer.ts @@ -129,21 +129,27 @@ export class MediaPlayer { let socketReady!: (s: Socket) => void; - let socketPromise = new Promise(resolve => { + let socketFailed!: (reason?: unknown) => void; + let socketPromise = new Promise((resolve, reject) => { socketReady = resolve; + socketFailed = reject; }); this.playerProcess.on("spawn", () => { console.log(`Player process spawned, opening socket @ ${socketPath}`); - setTimeout(() => { - let socket = this.connectToSocket(socketPath); - socketReady(socket); - }, 500); + this.connectToSocket(socketPath) + .then(socket => socketReady(socket)) + .catch((error: unknown) => { + console.error(`Failed to connect to mpv socket @ ${socketPath}:`, error); + console.log("Continuing without mpv player..."); + socketFailed(error); + }); }); - this.playerProcess.on("error", (error) => { + this.playerProcess.on("error", (error: unknown) => { console.error("Player process error:", error); console.log("Continuing without mpv player..."); + socketFailed(error); }); return socketPromise; @@ -397,7 +403,7 @@ export class MediaPlayer { socket.write(commandObject + '\n'); } catch (e: any) { console.error(`Error writing to socket: ${e}. Trying to respawn.`) - this.tryRespawnPlayerProcess(); + this.socket = this.tryRespawnPlayerProcess(); } // Add timeout to prevent hanging promises @@ -436,12 +442,44 @@ export class MediaPlayer { } } - private connectToSocket(path: string): Socket { - let socket = new Socket(); - socket.connect(path); - socket.on("data", data => this.receiveData(data.toString())); + private connectToSocket(path: string): Promise { + const retryDelayMs = 100; + const maxAttempts = 50; - return socket; + return new Promise((resolve, reject) => { + type SocketError = Error & { code?: string }; + + const attemptConnection = (attempt: number) => { + const socket = new Socket(); + + const onError = (error: SocketError) => { + socket.removeAllListeners(); + socket.destroy(); + + const shouldRetry = (error.code === "ENOENT" || error.code === "ECONNREFUSED") && attempt < maxAttempts; + if (shouldRetry) { + setTimeout(() => attemptConnection(attempt + 1), retryDelayMs); + return; + } + + reject(error); + }; + + socket.once("connect", () => { + socket.removeListener("error", onError); + socket.on("data", (data: unknown) => this.receiveData(String(data))); + socket.on("error", (error: unknown) => { + console.error("MPV socket error:", error); + }); + resolve(socket); + }); + + socket.once("error", onError); + socket.connect(path); + }; + + attemptConnection(1); + }); } private handleEvent(event: string, data: any) {