// [TSM.ID].[11031972] -- All Rights Reserved. Proprietary & Confidential. import { NextRequest, NextResponse } from "next/server"; import Redis from "ioredis"; // Klien Redis khusus untuk Subscriber (Mendengarkan event OmniBrain) // Karena ini adalah endpoint streaming, kita membutuhkan instance Redis tersendiri per koneksi (opsional), // namun karena SSE bersifat long-lived, kita instansiasi dalam blok handler. const redisUrl = process.env.REDIS_URL || "redis://localhost:6379"; export async function GET(req: NextRequest) { const searchParams = req.nextUrl.searchParams; const channel = searchParams.get("channel"); // Misalnya: "room_alpha_events" if (!channel) { return NextResponse.json({ error: "Missing channel" }, { status: 400 }); } const redis = new Redis(redisUrl); const stream = new ReadableStream({ async start(controller) { // 1. Subscribe ke channel spesifik di Redis await redis.subscribe(channel, (err) => { if (err) { console.error("[SSE] Gagal subscribe ke Redis:", err); controller.error(err); } else { console.log(`[SSE] OmniBrain terhubung ke saluran: ${channel}`); } }); // 2. Dengarkan pesan yang dipancarkan oleh API /emit redis.on("message", (subChannel, message) => { if (subChannel === channel) { // Format SSE: "data: {JSON}\n\n" controller.enqueue(`data: ${message}\n\n`); } }); // 3. Keep-Alive (Mencegah koneksi HTTP ditutup oleh Proxy/Nginx) const keepAlive = setInterval(() => { controller.enqueue(":\n\n"); // Komentar SSE untuk keep-alive }, 15000); // 4. Deteksi klien putus req.signal.addEventListener("abort", () => { clearInterval(keepAlive); redis.disconnect(); console.log(`[SSE] Klien terputus dari saluran: ${channel}`); }); }, cancel() { redis.disconnect(); } }); return new NextResponse(stream, { headers: { "Content-Type": "text/event-stream", "Cache-Control": "no-cache, no-transform", "Connection": "keep-alive", "Access-Control-Allow-Origin": "*", }, }); }