SSE reconnect, task switcher state/inbox/new task, stream throttle

This commit is contained in:
Ian Gulliver
2026-10-14 22:28:25 -07:00
parent 8e4c40eb5f
commit 33e682a9d5
27 changed files with 418 additions and 182 deletions
+49 -5
View File
@@ -46,11 +46,55 @@ export const get = (path, opts) => request("get", path, opts);
export const post = (path, opts) => request("post", path, opts);
export const put = (path, opts) => request("put", path, opts);
export const del = (path, opts) => request("delete", path, opts);
const staleAfterMs = 40_000;
const retryAfterMs = 2_000;
export function subscribe(after, onEvent, onState) {
const source = new EventSource(`/api/events?after=${after}`);
source.onopen = () => onState(true);
source.onerror = () => onState(false);
source.onmessage = (msg) => onEvent(JSON.parse(msg.data));
return source;
let last = after;
let heard = Date.now();
let source;
let retry = 0;
const connect = () => {
clearTimeout(retry);
source?.close();
heard = Date.now();
const s = new EventSource(`/api/events?after=${last}`);
source = s;
s.onopen = () => {
heard = Date.now();
onState(true);
};
s.onerror = () => {
onState(false);
if (s.readyState === EventSource.CLOSED) {
retry = setTimeout(connect, retryAfterMs);
}
};
s.addEventListener("ping", () => {
heard = Date.now();
});
s.onmessage = (msg) => {
heard = Date.now();
const ev = JSON.parse(msg.data);
if (ev.seq > last) {
last = ev.seq;
}
onEvent(ev);
};
};
const check = () => {
if (Date.now() - heard < staleAfterMs) {
return;
}
onState(false);
connect();
};
setInterval(check, 5_000);
addEventListener("online", connect);
document.addEventListener("visibilitychange", () => {
if (document.visibilityState === "visible") {
check();
}
});
connect();
}
//# sourceMappingURL=api.js.map