Files
openclaw-market/app/api/v1/stream/route.ts
richarjiang fa4c458eda init
2026-03-13 11:00:01 +08:00

61 lines
1.6 KiB
TypeScript

import { NextRequest } from "next/server";
import Redis from "ioredis";
export const dynamic = "force-dynamic";
export const runtime = "nodejs";
export async function GET(req: NextRequest) {
const encoder = new TextEncoder();
const stream = new ReadableStream({
start(controller) {
const subscriber = new Redis(process.env.REDIS_URL!);
subscriber.subscribe("channel:realtime");
subscriber.on("message", (_channel: string, message: string) => {
try {
const data = JSON.parse(message);
controller.enqueue(
encoder.encode(
`event: ${data.type}\ndata: ${JSON.stringify(data)}\n\n`
)
);
} catch {
// skip malformed messages
}
});
// Send keepalive every 30 seconds
const keepalive = setInterval(() => {
try {
controller.enqueue(encoder.encode(": keepalive\n\n"));
} catch {
clearInterval(keepalive);
}
}, 30000);
// Send initial connection event
controller.enqueue(
encoder.encode(`event: connected\ndata: {"status":"connected"}\n\n`)
);
// Cleanup on close
req.signal.addEventListener("abort", () => {
clearInterval(keepalive);
subscriber.unsubscribe("channel:realtime");
subscriber.quit();
});
},
});
return new Response(stream, {
headers: {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache, no-transform",
Connection: "keep-alive",
"X-Accel-Buffering": "no",
},
});
}