backend, web: support for resuming streams

This commit is contained in:
2026-05-04 09:12:31 -07:00
parent 70a60edf1c
commit f514c42de6
7 changed files with 1186 additions and 406 deletions

View File

@@ -0,0 +1,59 @@
export type SseStreamEvent = {
event: string;
data: unknown;
};
type SseStreamListener = (event: SseStreamEvent) => void;
export class ActiveSseStream {
private readonly events: SseStreamEvent[] = [];
private readonly listeners = new Set<SseStreamListener>();
private completed = false;
private resolveDone!: () => void;
readonly done: Promise<void>;
constructor() {
this.done = new Promise((resolve) => {
this.resolveDone = resolve;
});
}
get isCompleted() {
return this.completed;
}
emit(event: string, data: unknown) {
if (this.completed) return;
const entry = { event, data };
this.events.push(entry);
for (const listener of this.listeners) {
listener(entry);
}
}
complete(finalEvent?: SseStreamEvent) {
if (this.completed) return;
if (finalEvent) {
this.emit(finalEvent.event, finalEvent.data);
}
this.completed = true;
this.listeners.clear();
this.resolveDone();
}
subscribe(listener: SseStreamListener) {
for (const event of this.events) {
listener(event);
}
if (this.completed) {
return () => {};
}
this.listeners.add(listener);
return () => {
this.listeners.delete(listener);
};
}
}