79 lines
2.0 KiB
TypeScript
79 lines
2.0 KiB
TypeScript
import { getPool } from "@/lib/db-postgres";
|
|
import { authSession } from "@/lib/auth/session-server";
|
|
|
|
export const dynamic = "force-dynamic";
|
|
|
|
export async function GET(
|
|
req: Request,
|
|
ctx: { params: Promise<{ projectId: string }> },
|
|
) {
|
|
const { projectId } = await ctx.params;
|
|
const session = await authSession();
|
|
|
|
if (!session?.user?.email) {
|
|
return new Response("Unauthorized", { status: 401 });
|
|
}
|
|
|
|
const encoder = new TextEncoder();
|
|
|
|
const stream = new ReadableStream({
|
|
async start(controller) {
|
|
const pool = getPool();
|
|
let client: import("pg").PoolClient;
|
|
|
|
try {
|
|
client = await pool.connect();
|
|
} catch (err) {
|
|
console.error("[SSE] Failed to connect to pg pool:", err);
|
|
controller.close();
|
|
return;
|
|
}
|
|
|
|
const notifyHandler = (msg: import("pg").Notification) => {
|
|
if (msg.payload === projectId) {
|
|
try {
|
|
controller.enqueue(encoder.encode(`data: {"event":"updated"}\n\n`));
|
|
} catch {
|
|
// controller might be closed
|
|
}
|
|
}
|
|
};
|
|
|
|
client.on("notification", notifyHandler);
|
|
await client.query("LISTEN project_updates");
|
|
|
|
// Keep alive ping every 15s to prevent browser/proxy from dropping the connection
|
|
const keepAlive = setInterval(() => {
|
|
try {
|
|
controller.enqueue(encoder.encode(`: ping\n\n`));
|
|
} catch {
|
|
cleanup();
|
|
}
|
|
}, 15000);
|
|
|
|
const cleanup = () => {
|
|
clearInterval(keepAlive);
|
|
if (client) {
|
|
client.removeListener("notification", notifyHandler);
|
|
client.release();
|
|
}
|
|
};
|
|
|
|
// When the client disconnects, clean up the DB connection
|
|
req.signal.addEventListener("abort", cleanup);
|
|
},
|
|
cancel() {
|
|
// Handled by abort listener
|
|
},
|
|
});
|
|
|
|
return new Response(stream, {
|
|
headers: {
|
|
"Content-Type": "text/event-stream",
|
|
"Cache-Control": "no-cache, no-transform",
|
|
Connection: "keep-alive",
|
|
"X-Accel-Buffering": "no",
|
|
},
|
|
});
|
|
}
|