initial
This commit is contained in:
38
apps/server/src/services/broker.ts
Normal file
38
apps/server/src/services/broker.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
export type Frame = Record<string, unknown> & { type: string };
|
||||
export type Listener = (frame: Frame) => void;
|
||||
|
||||
export interface Broker {
|
||||
publish(sessionId: string, frame: Frame): void;
|
||||
subscribe(sessionId: string, listener: Listener): () => void;
|
||||
}
|
||||
|
||||
export function createBroker(): Broker {
|
||||
const topics = new Map<string, Set<Listener>>();
|
||||
return {
|
||||
publish(sessionId, frame) {
|
||||
const set = topics.get(sessionId);
|
||||
if (!set) return;
|
||||
for (const listener of set) {
|
||||
try {
|
||||
listener(frame);
|
||||
} catch {
|
||||
// ignore listener errors so one bad subscriber doesn't break the rest
|
||||
}
|
||||
}
|
||||
},
|
||||
subscribe(sessionId, listener) {
|
||||
let set = topics.get(sessionId);
|
||||
if (!set) {
|
||||
set = new Set();
|
||||
topics.set(sessionId, set);
|
||||
}
|
||||
set.add(listener);
|
||||
return () => {
|
||||
const s = topics.get(sessionId);
|
||||
if (!s) return;
|
||||
s.delete(listener);
|
||||
if (s.size === 0) topics.delete(sessionId);
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user