Fix SSE streaming by hijacking Fastify response

Fastify was buffering the SSE response, causing store progress
to appear stuck. Using reply.hijack() hands off the raw response
so events flush immediately to the client.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
mariosemes
2026-03-26 22:22:45 +01:00
parent 37425812e0
commit b243e06175

View File

@@ -66,12 +66,28 @@ export const searchRoutes: FastifyPluginAsync = async (app) => {
? stores.split(',').map(Number).filter((n) => !isNaN(n))
: undefined;
reply.raw.writeHead(200, {
// Hijack the response from Fastify so we can stream SSE directly
reply.hijack();
const res = reply.raw;
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Cache-Control': 'no-cache, no-transform',
'Connection': 'keep-alive',
'X-Accel-Buffering': 'no',
});
// Send initial comment to establish connection
res.write(':ok\n\n');
const sendEvent = (event: any) => {
if (!res.closed) {
res.write(`data: ${JSON.stringify(event)}\n\n`);
}
};
try {
await searchStreaming(
{
query: q,
@@ -79,11 +95,12 @@ export const searchRoutes: FastifyPluginAsync = async (app) => {
categoryId: category ? Number(category) : undefined,
groupId: group ? Number(group) : undefined,
},
(event) => {
reply.raw.write(`data: ${JSON.stringify(event)}\n\n`);
},
sendEvent,
);
} catch (err) {
sendEvent({ type: 'done', meta: { query: q, duration: 0, storeCount: 0, totalResults: 0, errors: [{ storeId: 0, storeName: 'System', error: String(err) }] } });
}
reply.raw.end();
res.end();
});
};