perf: overhaul session loading, caching, and runtime isolation (#2360)

Improve OpenChamber responsiveness under large session workloads while fixing
cache, synchronization, and persistence correctness across runtimes, projects,
directories, and worktrees.

- prioritize selected and visible sessions during bootstrap and defer
  non-critical enrichment work
- reduce redundant message loading, event processing, store publication, and
  hidden sidebar work
- prevent stale session and message requests from overwriting newer
  authoritative state
- preserve existing data when authoritative fetches fail instead of treating
  failures as successful empty responses
- scope session materialization, messages, drafts, queues, todos, pins,
  permissions, folders, tabs, Git state, and pull request data by runtime and
  directory identity
- harden runtime switching, reconnect, cleanup, mutation reconciliation, and
  persisted-state ordering
- preserve live subagent Task linkage when metadata arrives after an older
  message request or while streaming parts are suspended
- coalesce overlapping tail refreshes without losing newer refresh demand
- improve cold-session loading by moving deferrable work out of the critical
  bootstrap path
- isolate URL authentication, mobile credentials, native secrets, and other
  runtime-owned state across endpoint changes
- bound long-lived caches and remove avoidable allocations from event and
  rendering hot paths
- limit virtualization to archive collections where it improves rendering
  without disrupting active sidebar layout
- stabilize session folders, pin ordering, expanded state, and persisted
  sidebar behavior
- open skill files through the same secure editor and outside-workspace grant
  flow used by file navigation, including worktree sessions
- expand regression coverage for stale completions, runtime collisions,
  reconnect behavior, persistence races, authoritative empty results, and
  subagent refresh ordering
- document the updated synchronization, cache ownership, performance, and
  runtime-isolation invariants
This commit is contained in:
Bohdan Triapitsyn
2026-07-21 20:52:20 +03:00
committed by GitHub
parent 485efc7117
commit 85400459e9
197 changed files with 10835 additions and 3400 deletions
@@ -1,6 +1,7 @@
const SESSION_COOLDOWN_DURATION_MS = 2000;
const SESSION_STATE_MAX_AGE_MS = 24 * 60 * 60 * 1000;
const SESSION_ATTENTION_MAX_AGE_MS = 24 * 60 * 60 * 1000;
const SESSION_ACTIVITY_MAX_AGE_MS = 24 * 60 * 60 * 1000;
const SESSION_STATE_CLEANUP_INTERVAL_MS = 60 * 60 * 1000;
const extractSessionStatusUpdate = (payload) => {
@@ -37,26 +38,12 @@ const extractSessionStatusUpdate = (payload) => {
};
};
const deriveSessionActivityTransitions = (payload) => {
const update = extractSessionStatusUpdate(payload);
if (!update) {
return [];
}
if (update.type === 'busy' || update.type === 'retry') {
return [{ sessionId: update.sessionId, phase: 'busy' }];
}
if (update.type === 'idle') {
return [{ sessionId: update.sessionId, phase: 'cooldown' }];
}
return [];
};
export const createSessionRuntime = ({ writeSseEvent, getNotificationClients, broadcastEvent }) => {
const sessionActivityPhases = new Map();
const sessionActivityCooldowns = new Map();
const sessionStates = new Map();
const sessionAttentionStates = new Map();
let activeSessionCount = 0;
const getOrCreateAttentionState = (sessionId) => {
if (!sessionId || typeof sessionId !== 'string') return null;
@@ -90,6 +77,11 @@ export const createSessionRuntime = ({ writeSseEvent, getNotificationClients, br
sessionActivityCooldowns.delete(sessionId);
}
const wasActive = current?.phase === 'busy';
const isActive = phase === 'busy';
if (wasActive !== isActive) {
activeSessionCount = Math.max(0, activeSessionCount + (isActive ? 1 : -1));
}
sessionActivityPhases.set(sessionId, { phase, updatedAt: Date.now() });
if (phase === 'cooldown') {
@@ -287,11 +279,14 @@ export const createSessionRuntime = ({ writeSseEvent, getNotificationClients, br
return result;
};
const getActiveSessionCount = () => activeSessionCount;
const resetAllSessionActivityToIdle = () => {
for (const timer of sessionActivityCooldowns.values()) {
clearTimeout(timer);
}
sessionActivityCooldowns.clear();
activeSessionCount = 0;
const now = Date.now();
for (const [sessionId] of sessionActivityPhases) {
sessionActivityPhases.set(sessionId, { phase: 'idle', updatedAt: now });
@@ -310,26 +305,33 @@ export const createSessionRuntime = ({ writeSseEvent, getNotificationClients, br
sessionAttentionStates.delete(sessionId);
}
}
for (const [sessionId, data] of sessionActivityPhases) {
if (now - data.updatedAt <= SESSION_ACTIVITY_MAX_AGE_MS) continue;
const timer = sessionActivityCooldowns.get(sessionId);
if (timer) clearTimeout(timer);
sessionActivityCooldowns.delete(sessionId);
sessionActivityPhases.delete(sessionId);
if (data.phase === 'busy') activeSessionCount = Math.max(0, activeSessionCount - 1);
}
};
const cleanupInterval = setInterval(cleanupOldSessionStates, SESSION_STATE_CLEANUP_INTERVAL_MS);
const processOpenCodeSsePayload = (payload) => {
const transitions = deriveSessionActivityTransitions(payload);
for (const activity of transitions) {
setSessionActivityPhase(activity.sessionId, activity.phase);
const update = extractSessionStatusUpdate(payload);
if (!update) return;
if (update.type === 'busy' || update.type === 'retry') {
setSessionActivityPhase(update.sessionId, 'busy');
} else if (update.type === 'idle') {
setSessionActivityPhase(update.sessionId, 'cooldown');
}
if (payload && payload.type === 'session.status') {
const update = extractSessionStatusUpdate(payload);
if (update) {
updateSessionState(update.sessionId, update.type, update.eventId || `sse-${Date.now()}`, {
attempt: update.attempt,
message: update.message,
next: update.next,
});
}
}
updateSessionState(update.sessionId, update.type, update.eventId || `sse-${Date.now()}`, {
attempt: update.attempt,
message: update.message,
next: update.next,
});
};
const dispose = () => {
@@ -338,11 +340,16 @@ export const createSessionRuntime = ({ writeSseEvent, getNotificationClients, br
clearTimeout(timer);
}
sessionActivityCooldowns.clear();
sessionActivityPhases.clear();
sessionStates.clear();
sessionAttentionStates.clear();
activeSessionCount = 0;
};
return {
processOpenCodeSsePayload,
getSessionActivitySnapshot,
getActiveSessionCount,
getSessionStateSnapshot,
getSessionAttentionSnapshot,
getSessionState,