Resolve Resource Manager Space scan ready state before commit (#3200)

* Resolve resource space scan ready state before commit

* Avoid render-time ref writes for space scan ready state

Co-authored-by: Orca <help@stably.ai>

---------

Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
Neil
2026-05-30 15:19:33 -04:00
committed by GitHub
co-authored by Orca Jinwoo-H
parent c4e931e806
commit 824f4dbdde
3 changed files with 236 additions and 33 deletions
@@ -61,6 +61,10 @@ import {
getResourceUsageRuntimePaneTitlesByTabId,
getResourceUsageTabsByWorktree
} from './resource-usage-open-slices'
import {
resolveResourceUsageSpaceScanReady,
type ResourceUsageSpaceScanSnapshot
} from './resource-usage-space-scan-ready'
const POLL_MS = 2_000
const SESSIONS_POLL_MS = 10_000
@@ -670,7 +674,13 @@ export function ResourceUsageStatusSegment({
const [sessionsError, setSessionsError] = useState(false)
const [killConfirm, setKillConfirm] = useState<UnifiedSessionRow | null>(null)
const [killing, setKilling] = useState(false)
const [spaceScanReady, setSpaceScanReady] = useState(false)
const [spaceScanSnapshot, setSpaceScanSnapshot] = useState<ResourceUsageSpaceScanSnapshot>(
() => ({
ready: false,
previousScanning: workspaceSpaceScanning,
lastSeenScannedAt: workspaceSpaceScannedAt
})
)
// Why: tab titles can update on terminal keystrokes. The resource popover's
// merged tree needs them only while open, so closed status-bar badges should
// not subscribe to those high-churn maps.
@@ -684,8 +694,6 @@ export function ResourceUsageStatusSegment({
const tabsByWorktree = useAppStore((s) =>
getResourceUsageTabsByWorktree(s, open, runtimeEnvironmentActive)
)
const previousSpaceScanningRef = useRef(workspaceSpaceScanning)
const lastSeenSpaceScanAtRef = useRef<number | null>(workspaceSpaceScannedAt)
// Why: this segment only understands the local Electron PTY/resource daemon.
// While a runtime server is active, hiding local samples avoids showing or
// killing sessions from the wrong machine.
@@ -754,37 +762,24 @@ export function ResourceUsageStatusSegment({
// Why: Space scans can finish after the user backs out of the full page or
// closes this popover; the status-bar trigger becomes the handoff point.
useEffect(() => {
if (runtimeEnvironmentActive) {
setSpaceScanReady(false)
previousSpaceScanningRef.current = false
return
}
const scannedAt = workspaceSpaceScannedAt
const wasScanning = previousSpaceScanningRef.current
const scanCompleted =
wasScanning &&
!workspaceSpaceScanning &&
scannedAt !== null &&
scannedAt !== lastSeenSpaceScanAtRef.current
if (scanCompleted) {
lastSeenSpaceScanAtRef.current = scannedAt
setSpaceScanReady(!open && activeView !== 'space')
} else if (spaceScanReady && (open || activeView === 'space')) {
setSpaceScanReady(false)
lastSeenSpaceScanAtRef.current = scannedAt
}
previousSpaceScanningRef.current = workspaceSpaceScanning
}, [
activeView,
open,
const nextSpaceScanSnapshot = resolveResourceUsageSpaceScanReady({
snapshot: spaceScanSnapshot,
runtimeEnvironmentActive,
spaceScanReady,
workspaceSpaceScannedAt,
workspaceSpaceScanning
])
open,
activeView,
scannedAt: workspaceSpaceScannedAt,
scanning: workspaceSpaceScanning
})
if (
nextSpaceScanSnapshot.ready !== spaceScanSnapshot.ready ||
nextSpaceScanSnapshot.previousScanning !== spaceScanSnapshot.previousScanning ||
nextSpaceScanSnapshot.lastSeenScannedAt !== spaceScanSnapshot.lastSeenScannedAt
) {
// Why: keep the scan transition render-time without mutating refs during
// render; React can safely retry this guarded state update before commit.
setSpaceScanSnapshot(nextSpaceScanSnapshot)
}
const spaceScanReady = nextSpaceScanSnapshot.ready
// Poll memory + sessions when popover is open. Sessions also poll in the
// background at a slower rate so the badge count stays reasonably fresh
@@ -0,0 +1,148 @@
import { describe, expect, it } from 'vitest'
import {
resolveResourceUsageSpaceScanReady,
type ResourceUsageSpaceScanSnapshot
} from './resource-usage-space-scan-ready'
const baseSnapshot: ResourceUsageSpaceScanSnapshot = {
ready: false,
previousScanning: false,
lastSeenScannedAt: null
}
describe('resolveResourceUsageSpaceScanReady', () => {
it('marks Space results ready when a scan finishes away from the resource popover and Space page', () => {
expect(
resolveResourceUsageSpaceScanReady({
snapshot: { ...baseSnapshot, previousScanning: true },
runtimeEnvironmentActive: false,
open: false,
activeView: 'terminal',
scannedAt: 100,
scanning: false
})
).toEqual({
ready: true,
previousScanning: false,
lastSeenScannedAt: 100
})
})
it('does not show the ready handoff when results finish while already visible', () => {
expect(
resolveResourceUsageSpaceScanReady({
snapshot: { ...baseSnapshot, previousScanning: true },
runtimeEnvironmentActive: false,
open: true,
activeView: 'terminal',
scannedAt: 100,
scanning: false
})
).toEqual({
ready: false,
previousScanning: false,
lastSeenScannedAt: 100
})
expect(
resolveResourceUsageSpaceScanReady({
snapshot: { ...baseSnapshot, previousScanning: true },
runtimeEnvironmentActive: false,
open: false,
activeView: 'space',
scannedAt: 100,
scanning: false
}).ready
).toBe(false)
})
it('clears the handoff once the popover or Space page is opened', () => {
const readySnapshot = {
ready: true,
previousScanning: false,
lastSeenScannedAt: 100
}
expect(
resolveResourceUsageSpaceScanReady({
snapshot: readySnapshot,
runtimeEnvironmentActive: false,
open: true,
activeView: 'terminal',
scannedAt: 100,
scanning: false
})
).toEqual({
ready: false,
previousScanning: false,
lastSeenScannedAt: 100
})
expect(
resolveResourceUsageSpaceScanReady({
snapshot: readySnapshot,
runtimeEnvironmentActive: false,
open: false,
activeView: 'space',
scannedAt: 100,
scanning: false
}).ready
).toBe(false)
})
it('does not announce the same scan completion twice', () => {
const result = resolveResourceUsageSpaceScanReady({
snapshot: {
ready: false,
previousScanning: true,
lastSeenScannedAt: 100
},
runtimeEnvironmentActive: false,
open: false,
activeView: 'terminal',
scannedAt: 100,
scanning: false
})
expect(result.ready).toBe(false)
expect(result.lastSeenScannedAt).toBe(100)
})
it('hides local Space scan handoffs while a remote runtime is active', () => {
expect(
resolveResourceUsageSpaceScanReady({
snapshot: {
ready: true,
previousScanning: true,
lastSeenScannedAt: 100
},
runtimeEnvironmentActive: true,
open: false,
activeView: 'terminal',
scannedAt: 200,
scanning: true
})
).toEqual({
ready: false,
previousScanning: false,
lastSeenScannedAt: 100
})
})
it('tracks scanning starts without changing readiness', () => {
expect(
resolveResourceUsageSpaceScanReady({
snapshot: baseSnapshot,
runtimeEnvironmentActive: false,
open: false,
activeView: 'terminal',
scannedAt: null,
scanning: true
})
).toEqual({
ready: false,
previousScanning: true,
lastSeenScannedAt: null
})
})
})
@@ -0,0 +1,60 @@
export type ResourceUsageSpaceScanSnapshot = {
ready: boolean
previousScanning: boolean
lastSeenScannedAt: number | null
}
export function resolveResourceUsageSpaceScanReady({
snapshot,
runtimeEnvironmentActive,
open,
activeView,
scannedAt,
scanning
}: {
snapshot: ResourceUsageSpaceScanSnapshot
runtimeEnvironmentActive: boolean
open: boolean
activeView: string
scannedAt: number | null
scanning: boolean
}): ResourceUsageSpaceScanSnapshot {
if (runtimeEnvironmentActive) {
return {
ready: false,
previousScanning: false,
lastSeenScannedAt: snapshot.lastSeenScannedAt
}
}
const scanCompleted =
snapshot.previousScanning &&
!scanning &&
scannedAt !== null &&
scannedAt !== snapshot.lastSeenScannedAt
if (scanCompleted) {
return {
ready: !open && activeView !== 'space',
previousScanning: scanning,
lastSeenScannedAt: scannedAt
}
}
if (snapshot.ready && (open || activeView === 'space')) {
return {
ready: false,
previousScanning: scanning,
lastSeenScannedAt: scannedAt
}
}
if (snapshot.previousScanning !== scanning) {
return {
...snapshot,
previousScanning: scanning
}
}
return snapshot
}