feat(presence): add presence channel handling in real-time updates
This commit is contained in:
parent
6d9b0ed8d8
commit
0eba54b8b8
3 changed files with 18 additions and 0 deletions
|
|
@ -29,6 +29,7 @@ export async function GET(req: NextRequest) {
|
||||||
send: (data) => controller.enqueue(encoder.encode(data)),
|
send: (data) => controller.enqueue(encoder.encode(data)),
|
||||||
userId: user ? Number(user.id) : undefined,
|
userId: user ? Number(user.id) : undefined,
|
||||||
events: channel ? new Set(["presence"]) : undefined,
|
events: channel ? new Set(["presence"]) : undefined,
|
||||||
|
presenceChannel: channel ?? undefined,
|
||||||
};
|
};
|
||||||
subscribe(client);
|
subscribe(client);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ export function useRealtimePresence(channel: string, active: boolean, observe =
|
||||||
} catch {
|
} catch {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (detail.channel !== channel) return;
|
||||||
if (detail.action === "snapshot") setParticipants(detail.participants ?? []);
|
if (detail.action === "snapshot") setParticipants(detail.participants ?? []);
|
||||||
if ((detail.action === "join" || detail.action === "update") && detail.participant) {
|
if ((detail.action === "join" || detail.action === "update") && detail.participant) {
|
||||||
setParticipants((current) => [
|
setParticipants((current) => [
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ export interface SSEEventClient {
|
||||||
send: (data: string) => void;
|
send: (data: string) => void;
|
||||||
events?: Set<string>;
|
events?: Set<string>;
|
||||||
userId?: number;
|
userId?: number;
|
||||||
|
presenceChannel?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const clients = new Set<SSEEventClient>();
|
const clients = new Set<SSEEventClient>();
|
||||||
|
|
@ -21,8 +22,23 @@ export function clientCount(): number {
|
||||||
|
|
||||||
export function broadcast(event: string, data: unknown): number {
|
export function broadcast(event: string, data: unknown): number {
|
||||||
const payload = `event: ${event}\ndata: ${JSON.stringify(data)}\n\n`;
|
const payload = `event: ${event}\ndata: ${JSON.stringify(data)}\n\n`;
|
||||||
|
const presenceChannel =
|
||||||
|
event === "presence" &&
|
||||||
|
typeof data === "object" &&
|
||||||
|
data !== null &&
|
||||||
|
"channel" in data &&
|
||||||
|
typeof data.channel === "string"
|
||||||
|
? data.channel
|
||||||
|
: undefined;
|
||||||
for (const client of clients) {
|
for (const client of clients) {
|
||||||
if (client.events && !client.events.has(event)) continue;
|
if (client.events && !client.events.has(event)) continue;
|
||||||
|
if (
|
||||||
|
event === "presence" &&
|
||||||
|
client.presenceChannel !== undefined &&
|
||||||
|
client.presenceChannel !== presenceChannel
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
client.send(payload);
|
client.send(payload);
|
||||||
} catch {
|
} catch {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue