feat: add Redis-backed SSE updates

This commit is contained in:
2026-07-24 21:31:47 +07:00 Unverified
parent 5cc7edaa13
commit 29df784aeb
22 changed files with 912 additions and 96 deletions
+56 -8
View File
@@ -1,15 +1,63 @@
// @ts-expect-error Bun exposes RedisClient at runtime.
import { RedisClient } from "bun";
import type { RedisClient } from "bun";
const globalForRedis = global as unknown as { redis: RedisClient };
type RedisConnections = {
client: RedisClient;
publisher?: Promise<RedisClient>;
subscriber?: Promise<RedisClient>;
};
export const getRedisClient = async () => {
if (!globalForRedis.redis) {
globalForRedis.redis = new RedisClient(process.env.REDIS_URL || "");
const globalForRedis = globalThis as typeof globalThis & {
erikaRedis?: RedisConnections;
};
function getRedisConnections() {
if (typeof Bun === "undefined") {
throw new Error("Redis is only available on the Bun server runtime.");
}
const client = globalForRedis.redis;
if (!globalForRedis.erikaRedis) {
globalForRedis.erikaRedis = { client: Bun.redis };
}
return globalForRedis.erikaRedis;
}
async function connect(client: RedisClient) {
if (!client.connected) {
await client.connect();
}
return client;
};
}
function duplicateConnection(kind: "publisher" | "subscriber") {
const connections = getRedisConnections();
const existing = connections[kind];
if (existing) {
return existing;
}
const pending = connect(connections.client)
.then((client) => client.duplicate())
.then(connect);
connections[kind] = pending;
void pending.catch(() => {
if (connections[kind] === pending) {
connections[kind] = undefined;
}
});
return pending;
}
export async function getRedisClient() {
return connect(getRedisConnections().client);
}
export function getRedisPublisher() {
return duplicateConnection("publisher");
}
export function getRedisSubscriber() {
return duplicateConnection("subscriber");
}