perf(editor): keep the fs-watcher delete path O(deletes) when no move is in flight

Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
Neil
2026-07-21 00:59:46 -07:00
co-authored by Orca
parent f51d258803
commit efea87d2c0
2 changed files with 40 additions and 19 deletions
@@ -48,12 +48,22 @@ export function settleEditorPathMove(operationId: string): void {
operations.delete(operationId)
}
/** Cheap gate so watcher hot paths can skip per-file work when no move is live. */
export function hasActiveEditorPathMoves(): boolean {
return operations.size > 0
}
/** True when this delete is the source side of a live Orca-owned move. */
export function isActiveMoveSourcePath(
worktreeId: string,
runtimeEnvironmentId: string | null | undefined,
absolutePath: string
): boolean {
// Fast path: this runs per deleted open-editor in the fs-watcher hot path, but a
// move is in flight only briefly and rarely. Skip the normalize regex when idle.
if (operations.size === 0) {
return false
}
const normalizedPath = normalize(absolutePath)
const scopedOwner = owner(runtimeEnvironmentId)
for (const operation of operations.values()) {
@@ -16,7 +16,10 @@ import {
getRecentSelfWrite,
type RecentSelfWrite
} from '@/components/editor/editor-self-write-registry'
import { isActiveMoveSourcePath } from '@/components/editor/editor-path-move-inflight'
import {
hasActiveEditorPathMoves,
isActiveMoveSourcePath
} from '@/components/editor/editor-path-move-inflight'
import type { FsChangedPayload } from '../../../shared/types'
import { findWorktreeById } from '@/store/slices/worktree-helpers'
import type { OpenFile } from '@/store/slices/editor'
@@ -418,20 +421,23 @@ export function createExternalWatchEventHandler(
// Why: mark editor tabs deleted/renamed instead of closing them so the user keeps in-memory content; a paired create means rename, a lone delete is hard.
// Why: snapshot openFiles once so the delete/rename helpers share a consistent view without N store reads per payload.
const openFilesAtStart = useAppStore.getState().openFiles
const deletedOpenEditorIds = collectDeletedOpenEditorIds(
const deletedOpenEditorIdsRaw = collectDeletedOpenEditorIds(
payload,
target.worktreeId,
target.runtimeEnvironmentId,
openFilesAtStart
).filter((fileId) => {
// Don't tombstone the source side of an in-flight Orca move (the tab is
// being re-homed, not deleted).
const file = openFilesAtStart.find((f) => f.id === fileId)
return (
!file ||
!isActiveMoveSourcePath(target.worktreeId, target.runtimeEnvironmentId, file.filePath)
)
})
)
// Only pay the per-id lookup to suppress a move's own source-delete when a move
// is actually in flight; otherwise the whole delete batch stays O(deletes).
const deletedOpenEditorIds = hasActiveEditorPathMoves()
? deletedOpenEditorIdsRaw.filter((fileId) => {
const file = openFilesAtStart.find((f) => f.id === fileId)
return (
!file ||
!isActiveMoveSourcePath(target.worktreeId, target.runtimeEnvironmentId, file.filePath)
)
})
: deletedOpenEditorIdsRaw
// Why: correlate creates to deletes by basename to avoid mislabelling unrelated create+delete pairs as "renamed"; default to 'deleted' when we can't correlate.
const hasPairedCreate =
deletedOpenEditorIds.length > 0 &&
@@ -559,14 +565,19 @@ export function createExternalWatchEventHandler(
const dirtyIds = dirtyMatches.filter((f) => canAutoSaveOpenFile(f)).map((f) => f.id)
// A tab carrying move-echo provenance for this path may be seeing the
// move's own echo — settle it by disk identity: an echo leaves disk ==
// the tab's baseline, a real external write does not.
const normalizedAbsolutePath = normalizeRuntimePathForComparison(absolutePath)
const isSelfMoveEcho = dirtyMatches.some(
(f) =>
f.pendingSelfMoveEcho &&
normalizeRuntimePathForComparison(f.pendingSelfMoveEcho.targetPath) ===
normalizedAbsolutePath
)
// the tab's baseline, a real external write does not. Only a tab WITH
// provenance can match, so skip the path normalize in the common
// external-write-to-dirty case where none carries it.
let isSelfMoveEcho = false
if (dirtyMatches.some((f) => f.pendingSelfMoveEcho)) {
const normalizedAbsolutePath = normalizeRuntimePathForComparison(absolutePath)
isSelfMoveEcho = dirtyMatches.some(
(f) =>
f.pendingSelfMoveEcho &&
normalizeRuntimePathForComparison(f.pendingSelfMoveEcho.targetPath) ===
normalizedAbsolutePath
)
}
if (isSelfMoveEcho) {
// A real destination fs event confirms the echo — consume the
// provenance so a later genuine write takes the normal path.