Files
openchamber/packages/ui/src/sync/eviction.ts
T

54 lines
2.0 KiB
TypeScript
Raw Normal View History

import type { DisposeCheck, EvictPlan, State } from "./types"
/**
* Returns true when the directory's child store holds at least one pending
* blocking request — a question awaiting an answer or a permission awaiting
* approval. Such directories must never be evicted, otherwise the SSE-routed
* request data is lost and the user can never satisfy the agent.
*
* Tracks the same `state.question` / `state.permission` shape that
* {@link bootstrapDirectory} re-hydrates on a fresh `ensureChild` call —
* an empty record key (e.g. after a `question.replied` event clears the
* array) is treated as "no pending requests" so a fully resolved directory
* remains a normal eviction candidate.
*/
export function hasPendingBlockingRequests(state: State | undefined): boolean {
if (!state) return false
for (const list of Object.values(state.question ?? {})) {
if (list && list.length > 0) return true
}
for (const list of Object.values(state.permission ?? {})) {
if (list && list.length > 0) return true
}
return false
}
export function pickDirectoriesToEvict(input: EvictPlan) {
const overflow = Math.max(0, input.stores.length - input.max)
let pendingOverflow = overflow
const sorted = input.stores
.filter((dir) => !input.pins.has(dir))
.filter((dir) => !input.hasPendingBlockingRequests?.(dir))
.slice()
.sort((a, b) => (input.state.get(a)?.lastAccessAt ?? 0) - (input.state.get(b)?.lastAccessAt ?? 0))
const output: string[] = []
for (const dir of sorted) {
const last = input.state.get(dir)?.lastAccessAt ?? 0
const idle = input.now - last >= input.ttl
if (!idle && pendingOverflow <= 0) continue
output.push(dir)
if (pendingOverflow > 0) pendingOverflow -= 1
}
return output
}
export function canDisposeDirectory(input: DisposeCheck) {
if (!input.directory) return false
if (!input.hasStore) return false
if (input.pinned) return false
if (input.booting) return false
if (input.loadingSessions) return false
if (input.hasPendingBlockingRequests) return false
return true
}