fix: handle SSE controller errors gracefully

- Add isActive checks before writing to SSE controller
- Wrap controller operations in try/catch to prevent 'already closed' errors
- Fix race condition when client disconnects during SSE streaming
This commit is contained in:
2026-03-06 22:40:57 +01:00
parent f0a967515b
commit 9141edfaa9
2 changed files with 32 additions and 13 deletions

View File

@@ -33,27 +33,39 @@ export async function GET(
},
});
if (response.ok) {
if (response.ok && isActive) {
const data = await response.json();
const dataStr = JSON.stringify(data);
// Only send if data changed
if (dataStr !== lastData) {
if (dataStr !== lastData && isActive) {
lastData = dataStr;
try {
controller.enqueue(
new TextEncoder().encode(`data: ${dataStr}\n\n`)
);
} catch (err) {
// Controller closed, ignore
isActive = false;
return;
}
// Stop polling if job is complete
if (data.status === "success" || data.status === "failed" || data.status === "cancelled") {
isActive = false;
try {
controller.close();
} catch (err) {
// Already closed, ignore
}
}
}
}
} catch (error) {
if (isActive) {
console.error("SSE fetch error:", error);
}
}
};
// Initial fetch

View File

@@ -28,21 +28,28 @@ export async function GET(request: NextRequest) {
},
});
if (response.ok) {
if (response.ok && isActive) {
const data = await response.json();
const dataStr = JSON.stringify(data);
// Send if data changed
if (dataStr !== lastData) {
if (dataStr !== lastData && isActive) {
lastData = dataStr;
try {
controller.enqueue(
new TextEncoder().encode(`data: ${dataStr}\n\n`)
);
} catch (err) {
// Controller closed, ignore
isActive = false;
}
}
}
} catch (error) {
if (isActive) {
console.error("SSE fetch error:", error);
}
}
};
// Initial fetch