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:
committed by
GitHub
parent
485efc7117
commit
85400459e9
@@ -567,9 +567,9 @@ const FileRow: React.FC<FileRowProps> = ({
|
||||
onOpenChange={(open) => setContextMenuPath(open ? node.path : null)}
|
||||
>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="size-6"
|
||||
onClick={handleMenuButtonClick}
|
||||
>
|
||||
@@ -810,7 +810,6 @@ export const FilesView: React.FC<FilesViewProps> = ({ mode = 'full' }) => {
|
||||
const openPaths = useFilesViewTabsStore((state) => (root ? (state.byRoot[root]?.openPaths ?? EMPTY_PATHS) : EMPTY_PATHS));
|
||||
const selectedPath = useFilesViewTabsStore((state) => (root ? (state.byRoot[root]?.selectedPath ?? null) : null));
|
||||
const expandedPaths = useFilesViewTabsStore((state) => (root ? (state.byRoot[root]?.expandedPaths ?? EMPTY_PATHS) : EMPTY_PATHS));
|
||||
const addOpenPath = useFilesViewTabsStore((state) => state.addOpenPath);
|
||||
const removeOpenPath = useFilesViewTabsStore((state) => state.removeOpenPath);
|
||||
const removeOpenPathsByPrefix = useFilesViewTabsStore((state) => state.removeOpenPathsByPrefix);
|
||||
const removeExpandedPathsByPrefix = useFilesViewTabsStore((state) => state.removeExpandedPathsByPrefix);
|
||||
@@ -922,6 +921,7 @@ export const FilesView: React.FC<FilesViewProps> = ({ mode = 'full' }) => {
|
||||
const diagramEditorRef = React.useRef<React.ComponentRef<typeof DiagramEditor>>(null);
|
||||
const lastLoadedFileStatRef = React.useRef<FileStatSnapshot | null>(null);
|
||||
const activeFileLoadIdRef = React.useRef(0);
|
||||
const loadingFilePathRef = React.useRef<string | null>(null);
|
||||
const [autoSaveStatus, setAutoSaveStatus] = React.useState<'idle' | 'saved'>('idle');
|
||||
const [diagramSaved, setDiagramSaved] = React.useState(false);
|
||||
const [autoSaveEnabled, setAutoSaveEnabled] = React.useState(getInitialAutoSaveEnabled);
|
||||
@@ -1952,7 +1952,6 @@ export const FilesView: React.FC<FilesViewProps> = ({ mode = 'full' }) => {
|
||||
|
||||
if (root) {
|
||||
setSelectedPath(root, node.path);
|
||||
addOpenPath(root, node.path);
|
||||
void ensurePathVisible(node.path, false);
|
||||
}
|
||||
|
||||
@@ -1966,7 +1965,7 @@ export const FilesView: React.FC<FilesViewProps> = ({ mode = 'full' }) => {
|
||||
if (isMobile) {
|
||||
setShowMobilePageContent(true);
|
||||
}
|
||||
}, [addOpenPath, ensurePathVisible, isDirty, isMobile, root, setSelectedPath]);
|
||||
}, [ensurePathVisible, isDirty, isMobile, root, setSelectedPath]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!selectedFile?.path) {
|
||||
@@ -1979,16 +1978,23 @@ export const FilesView: React.FC<FilesViewProps> = ({ mode = 'full' }) => {
|
||||
React.useEffect(() => {
|
||||
if (!selectedFile) {
|
||||
activeFileLoadIdRef.current += 1;
|
||||
loadingFilePathRef.current = null;
|
||||
setFileLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (loadedFilePath === selectedFile.path) {
|
||||
if (loadedFilePath === selectedFile.path || loadingFilePathRef.current === selectedFile.path) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Selection changes are guarded; this effect is also what restores persisted tabs on mount.
|
||||
void loadSelectedFile(selectedFile);
|
||||
const loadingPath = selectedFile.path;
|
||||
loadingFilePathRef.current = loadingPath;
|
||||
void loadSelectedFile(selectedFile).finally(() => {
|
||||
if (loadingFilePathRef.current === loadingPath) {
|
||||
loadingFilePathRef.current = null;
|
||||
}
|
||||
});
|
||||
}, [loadSelectedFile, loadedFilePath, selectedFile]);
|
||||
|
||||
// Sync isDirty to a ref so the polling interval can read the latest value
|
||||
@@ -2192,7 +2198,7 @@ export const FilesView: React.FC<FilesViewProps> = ({ mode = 'full' }) => {
|
||||
const getFileStatus = React.useCallback((path: string): FileStatus | null => {
|
||||
// Check open status
|
||||
if (openPaths.includes(path)) return 'open';
|
||||
|
||||
|
||||
// Check git status
|
||||
if (gitStatus?.files) {
|
||||
const relative = path.startsWith(root + '/') ? path.slice(root.length + 1) : path;
|
||||
@@ -2210,7 +2216,7 @@ export const FilesView: React.FC<FilesViewProps> = ({ mode = 'full' }) => {
|
||||
if (!gitStatus?.files) return null;
|
||||
const relativeDir = dirPath.startsWith(root + '/') ? dirPath.slice(root.length + 1) : dirPath;
|
||||
const prefix = relativeDir ? `${relativeDir}/` : '';
|
||||
|
||||
|
||||
let modified = 0, added = 0;
|
||||
for (const f of gitStatus.files) {
|
||||
if (f.path.startsWith(prefix)) {
|
||||
|
||||
Reference in New Issue
Block a user