perf(client): cut needless polling for local users
- ConversationView: an ended session (SessionDetail, SessionReplay pass `ended`) polls its transcript every 60 s instead of 3 s and stops rescanning sub-agents; new_event, reconnect and show still fetch at once. - Workspace: GET /api/run follows run-moving WS messages (lane run columns, session created/status change, runs_interrupted) with a 30 s fallback, instead of a blind 5 s poll. - StatusBar: session counts re-read only when a session's status/waiting/archived state changes (60 s fallback); costs re-read at most every 30 s while work is happening and every 2 min otherwise. - Dashboard recent activity: 60 s safety poll (was 10 s) plus remote import messages; WS still prepends new events. - New lib/sessionChange.ts matcher with tests.
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* @file sessionChange.ts
|
||||
* @description `session_created` / `session_updated` matcher for live-refresh
|
||||
* callers that care about only a few session columns. A session row is
|
||||
* re-broadcast on nearly every hook (last activity, name, tokens…), so
|
||||
* matching the bare message types made every such frame refetch; this one
|
||||
* fires on a new session, or when the chosen key of a session actually
|
||||
* changed. Each call keeps its own memory of the keys it has seen.
|
||||
* @author Nguyễn Ngọc Trí Vĩ <vinnt@smartgift.vn>
|
||||
*/
|
||||
|
||||
import type { Session, WSMessage } from "./types";
|
||||
|
||||
/** The columns that move a session between the active / waiting / archived counts. */
|
||||
export const sessionStateKeyOf = (s: Partial<Session>): string =>
|
||||
`${s.status}:${s.awaiting_input_since ? 1 : 0}:${s.archived_at ? 1 : 0}`;
|
||||
|
||||
export function sessionChangeMatcher(
|
||||
keyOf: (s: Partial<Session>) => string = sessionStateKeyOf
|
||||
): (msg: WSMessage) => boolean {
|
||||
const seen = new Map<string, string>();
|
||||
return (msg) => {
|
||||
if (msg.type !== "session_created" && msg.type !== "session_updated") return false;
|
||||
const s = msg.data as Partial<Session> | undefined;
|
||||
// A frame we cannot key is taken as a change: refetching is the safe side.
|
||||
if (!s || typeof s.id !== "string") return true;
|
||||
const key = keyOf(s);
|
||||
if (msg.type === "session_updated" && seen.get(s.id) === key) return false;
|
||||
seen.set(s.id, key);
|
||||
return true;
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user