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
@@ -10,120 +10,152 @@ const SESSION_PREFETCH_CONCURRENCY = 1;
const SESSION_PREFETCH_PENDING_LIMIT = 6;
type Args = {
enabled?: boolean;
currentSessionId: string | null;
sortedSessions: Session[];
recentSessionIds?: string[];
ensureSessionRenderable: (sessionId: string) => Promise<unknown>;
recentSessions?: Session[];
prefetchSession: (sessionId: string, directory: string) => Promise<unknown>;
};
export const useSessionPrefetch = ({ currentSessionId, sortedSessions, recentSessionIds = [], ensureSessionRenderable }: Args): void => {
type PrefetchRequest = {
sessionId: string;
directory: string;
generation: number;
};
const sessionDirectory = (session: Session | null | undefined): string | null => {
const directory = (session as (Session & { directory?: string | null }) | null | undefined)?.directory;
return typeof directory === 'string' && directory.trim() ? directory : null;
};
export const useSessionPrefetch = ({ enabled = true, currentSessionId, sortedSessions, recentSessions = [], prefetchSession }: Args): void => {
const sessionPrefetchTimersRef = React.useRef<Map<string, number>>(new Map());
const sessionPrefetchQueueRef = React.useRef<string[]>([]);
const sessionPrefetchQueueRef = React.useRef<PrefetchRequest[]>([]);
const sessionPrefetchInFlightRef = React.useRef<Set<string>>(new Set());
const generationRef = React.useRef(0);
const prefetchDisabled = React.useMemo(() => isVSCodeRuntime(), []);
const requestKey = React.useCallback((request: Pick<PrefetchRequest, 'directory' | 'sessionId'>) => (
`${request.directory}\n${request.sessionId}`
), []);
const clearPendingPrefetches = React.useCallback(() => {
generationRef.current += 1;
sessionPrefetchQueueRef.current = [];
sessionPrefetchTimersRef.current.forEach((timer) => window.clearTimeout(timer));
sessionPrefetchTimersRef.current.clear();
}, []);
const pumpSessionPrefetchQueue = React.useCallback(() => {
if (prefetchDisabled || typeof window === 'undefined') {
if (!enabled || prefetchDisabled || typeof window === 'undefined') {
return;
}
while (sessionPrefetchInFlightRef.current.size < SESSION_PREFETCH_CONCURRENCY && sessionPrefetchQueueRef.current.length > 0) {
const nextSessionId = sessionPrefetchQueueRef.current.shift();
if (!nextSessionId) {
const request = sessionPrefetchQueueRef.current.shift();
if (!request) {
break;
}
if (request.generation !== generationRef.current) continue;
const state = useSessionUIStore.getState();
if (state.currentSessionId === nextSessionId) {
if (state.currentSessionId === request.sessionId) {
continue;
}
// Check if the session is already renderable in the sync child store.
if (getSyncSessionMaterializationStatus(nextSessionId).renderable) {
if (getSyncSessionMaterializationStatus(request.sessionId, request.directory).renderable) {
continue;
}
sessionPrefetchInFlightRef.current.add(nextSessionId);
void ensureSessionRenderable(nextSessionId)
const key = requestKey(request);
sessionPrefetchInFlightRef.current.add(key);
void prefetchSession(request.sessionId, request.directory)
.catch(() => undefined)
.finally(() => {
sessionPrefetchInFlightRef.current.delete(nextSessionId);
sessionPrefetchInFlightRef.current.delete(key);
pumpSessionPrefetchQueue();
});
}
}, [ensureSessionRenderable, prefetchDisabled]);
}, [enabled, prefetchDisabled, prefetchSession, requestKey]);
const scheduleSessionPrefetch = React.useCallback((sessionId: string | null | undefined) => {
if (prefetchDisabled || !sessionId || sessionId === currentSessionId || typeof window === 'undefined') {
const scheduleSessionPrefetch = React.useCallback((session: Session | null | undefined) => {
const sessionId = session?.id;
const directory = sessionDirectory(session);
if (!enabled || prefetchDisabled || !sessionId || !directory || sessionId === currentSessionId || typeof window === 'undefined') {
return;
}
const request = { sessionId, directory, generation: generationRef.current };
const key = requestKey(request);
// Already renderable in sync
if (getSyncSessionMaterializationStatus(sessionId).renderable) {
if (getSyncSessionMaterializationStatus(sessionId, directory).renderable) {
return;
}
if (sessionPrefetchInFlightRef.current.has(sessionId)) {
if (sessionPrefetchInFlightRef.current.has(key)) {
return;
}
if (sessionPrefetchQueueRef.current.includes(sessionId)) {
if (sessionPrefetchQueueRef.current.some((candidate) => requestKey(candidate) === key)) {
return;
}
if (sessionPrefetchQueueRef.current.length >= SESSION_PREFETCH_PENDING_LIMIT) {
sessionPrefetchQueueRef.current.shift();
}
const existingTimer = sessionPrefetchTimersRef.current.get(sessionId);
const existingTimer = sessionPrefetchTimersRef.current.get(key);
if (existingTimer !== undefined) {
window.clearTimeout(existingTimer);
}
const timer = window.setTimeout(() => {
sessionPrefetchTimersRef.current.delete(sessionId);
sessionPrefetchQueueRef.current.push(sessionId);
sessionPrefetchTimersRef.current.delete(key);
if (request.generation !== generationRef.current) return;
const queue = sessionPrefetchQueueRef.current;
if (queue.length >= SESSION_PREFETCH_PENDING_LIMIT) {
queue.shift();
}
queue.push(request);
pumpSessionPrefetchQueue();
}, SESSION_PREFETCH_HOVER_DELAY_MS);
sessionPrefetchTimersRef.current.set(sessionId, timer);
}, [currentSessionId, prefetchDisabled, pumpSessionPrefetchQueue]);
sessionPrefetchTimersRef.current.set(key, timer);
}, [currentSessionId, enabled, prefetchDisabled, pumpSessionPrefetchQueue, requestKey]);
React.useEffect(() => {
clearPendingPrefetches();
}, [clearPendingPrefetches, currentSessionId, enabled, prefetchDisabled]);
// Wait for the active session to finish loading before prefetching neighbors.
// On rapid session switches the timer resets, so only the final session triggers prefetch.
React.useEffect(() => {
if (prefetchDisabled || !currentSessionId || sortedSessions.length === 0) {
if (!enabled || prefetchDisabled || !currentSessionId || sortedSessions.length === 0) {
return;
}
const timer = window.setTimeout(() => {
const currentIndex = sortedSessions.findIndex((session) => session.id === currentSessionId);
if (currentIndex < 0) return;
scheduleSessionPrefetch(sortedSessions[currentIndex - 1]?.id);
scheduleSessionPrefetch(sortedSessions[currentIndex + 1]?.id);
scheduleSessionPrefetch(sortedSessions[currentIndex - 1]);
scheduleSessionPrefetch(sortedSessions[currentIndex + 1]);
}, SESSION_PREFETCH_SETTLE_MS);
return () => window.clearTimeout(timer);
}, [currentSessionId, prefetchDisabled, scheduleSessionPrefetch, sortedSessions]);
}, [currentSessionId, enabled, prefetchDisabled, scheduleSessionPrefetch, sortedSessions]);
React.useEffect(() => {
if (prefetchDisabled || !currentSessionId || recentSessionIds.length === 0) {
if (!enabled || prefetchDisabled || !currentSessionId || recentSessions.length === 0) {
return;
}
const timer = window.setTimeout(() => {
const currentIndex = recentSessionIds.indexOf(currentSessionId);
const currentIndex = recentSessions.findIndex((session) => session.id === currentSessionId);
if (currentIndex < 0) return;
scheduleSessionPrefetch(recentSessionIds[currentIndex - 1]);
scheduleSessionPrefetch(recentSessionIds[currentIndex + 1]);
scheduleSessionPrefetch(recentSessions[currentIndex - 1]);
scheduleSessionPrefetch(recentSessions[currentIndex + 1]);
}, SESSION_PREFETCH_SETTLE_MS);
return () => window.clearTimeout(timer);
}, [currentSessionId, prefetchDisabled, recentSessionIds, scheduleSessionPrefetch]);
}, [currentSessionId, enabled, prefetchDisabled, recentSessions, scheduleSessionPrefetch]);
React.useEffect(() => {
const prefetchTimers = sessionPrefetchTimersRef.current;
return () => {
prefetchTimers.forEach((timer) => {
clearTimeout(timer);
});
prefetchTimers.clear();
sessionPrefetchQueueRef.current = [];
};
}, []);
React.useEffect(() => clearPendingPrefetches, [clearPendingPrefetches]);
};
export const SessionPrefetchEffect: React.FC<Omit<Args, 'currentSessionId'>> = (args) => {
const currentSessionId = useSessionUIStore((state) => state.currentSessionId);
useSessionPrefetch({ ...args, currentSessionId });
return null;
};