From 8a533d028d56347201a5e3312ca93050d7305efa Mon Sep 17 00:00:00 2001 From: Alejandro Lembke Barrientos Date: Mon, 1 Jun 2026 20:24:19 +0000 Subject: [PATCH] fix: remove worker mutex and increase collab timeout to 120s - Remove workerBusy promise chain (mutex) in src/index.ts: each StreamableHTTPServerTransport is stateless and per-request, so concurrent handling within a worker is safe. Eliminates request starvation when long page writes are in flight. - Raise the Hocuspocus safety timeout in collaboration.ts from 25 s to 120 s, giving large documents enough time to complete the Yjs sync phase before the hard abort fires. Co-Authored-By: Claude Sonnet 4.5 --- src/index.ts | 22 ++++++++++------------ src/lib/collaboration.ts | 2 +- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/index.ts b/src/index.ts index 0bbc931..8f609d4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -873,8 +873,8 @@ if (cluster.isPrimary) { }); } else { // ── Worker: cada uno tiene su propio McpServer singleton ── - // El mutex serializa las requests dentro de este worker (stateless, 1 request a la vez por worker) - let workerBusy: Promise = Promise.resolve(); + // Sin mutex: cada request se atiende concurrentemente dentro del worker. + // StreamableHTTPServerTransport es stateless (uno por request), sin estado compartido. async function handleMcpRequest(req: IncomingMessage, res: ServerResponse): Promise { const transport = new StreamableHTTPServerTransport({ @@ -893,16 +893,14 @@ if (cluster.isPrimary) { res.writeHead(404).end("Not found"); return; } - workerBusy = workerBusy - .then(() => handleMcpRequest(req, res)) - .catch((err) => { - console.error(`[docmost-mcp] Worker PID=${process.pid} error:`, err); - if (!res.headersSent) { - res.writeHead(500, { "Content-Type": "application/json" }).end( - JSON.stringify({ jsonrpc: "2.0", error: { code: -32603, message: String(err) }, id: null }) - ); - } - }); + handleMcpRequest(req, res).catch((err) => { + console.error(`[docmost-mcp] Worker PID=${process.pid} error:`, err); + if (!res.headersSent) { + res.writeHead(500, { "Content-Type": "application/json" }).end( + JSON.stringify({ jsonrpc: "2.0", error: { code: -32603, message: String(err) }, id: null }) + ); + } + }); }); httpServer.listen(8080, () => { diff --git a/src/lib/collaboration.ts b/src/lib/collaboration.ts index c767127..452e340 100644 --- a/src/lib/collaboration.ts +++ b/src/lib/collaboration.ts @@ -67,7 +67,7 @@ export async function updatePageContentRealtime( const timer = setTimeout(() => { if (provider) provider.destroy(); reject(new Error("Connection timeout to collaboration server")); - }, 25000); + }, 120000); const provider = new HocuspocusProvider({ url: wsUrl, -- 2.49.1