fix(chat): allow AI to finish and save responses even if client disconnects

This commit is contained in:
mstfyldz
2026-08-12 13:02:40 +03:00
parent d10ea1b0fd
commit f1457b02ca
+14
View File
@@ -41,10 +41,16 @@ function startSse(res: Response) {
} }
function sseWrite(res: Response, payload: Record<string, unknown>) { function sseWrite(res: Response, payload: Record<string, unknown>) {
if (res.destroyed || res.writableEnded) return;
try {
res.write(`data: ${JSON.stringify(payload)}\n\n`); res.write(`data: ${JSON.stringify(payload)}\n\n`);
if (typeof (res as any).flush === 'function') { if (typeof (res as any).flush === 'function') {
(res as any).flush(); (res as any).flush();
} }
} catch (err) {
// Client disconnect olduysa yazma hatasını yoksay, arka planda AI'ın
// yanıt üretmeyi bitirip veritabanına kaydetmesine izin ver.
}
} }
interface ChatAttachment { filename: string; text: string; } interface ChatAttachment { filename: string; text: string; }
@@ -198,10 +204,13 @@ export const chatMessage = async (req: AuthenticatedRequest, res: Response) => {
} }
} }
if (!res.destroyed && !res.writableEnded) {
sseWrite(res, { done: true, newTitle, messageId: aiMessage?.id || null }); sseWrite(res, { done: true, newTitle, messageId: aiMessage?.id || null });
res.end(); res.end();
}
} catch (error: any) { } catch (error: any) {
console.error('Chat Error:', error); console.error('Chat Error:', error);
if (!res.destroyed && !res.writableEnded) {
if (!res.headersSent) { if (!res.headersSent) {
res.status(500).json({ error: error.message || 'Internal Server Error' }); res.status(500).json({ error: error.message || 'Internal Server Error' });
} else { } else {
@@ -209,6 +218,7 @@ export const chatMessage = async (req: AuthenticatedRequest, res: Response) => {
res.end(); res.end();
} }
} }
}
}; };
// Genel (dosyasız) Sohbet/Asistan sayfası için — chat_threads/thread_messages // Genel (dosyasız) Sohbet/Asistan sayfası için — chat_threads/thread_messages
@@ -281,10 +291,13 @@ export const sendThreadMessage = async (req: AuthenticatedRequest, res: Response
} }
} }
if (!res.destroyed && !res.writableEnded) {
sseWrite(res, { done: true, newTitle, messageId: aiMessage?.id || null }); sseWrite(res, { done: true, newTitle, messageId: aiMessage?.id || null });
res.end(); res.end();
}
} catch (error: any) { } catch (error: any) {
console.error('Send Thread Message Error:', error); console.error('Send Thread Message Error:', error);
if (!res.destroyed && !res.writableEnded) {
if (!res.headersSent) { if (!res.headersSent) {
res.status(500).json({ error: error.message || 'Internal Server Error' }); res.status(500).json({ error: error.message || 'Internal Server Error' });
} else { } else {
@@ -292,4 +305,5 @@ export const sendThreadMessage = async (req: AuthenticatedRequest, res: Response
res.end(); res.end();
} }
} }
}
}; };