ignore: refactoring and tests (#12460)

This commit is contained in:
Adam
2026-02-06 05:51:01 -06:00
committed by GitHub
parent 5d92219812
commit 4afec6731d
11 changed files with 899 additions and 292 deletions

View File

@@ -27,6 +27,7 @@ import type { InitError } from "../pages/error"
import {
batch,
createContext,
createRoot,
createEffect,
untrack,
getOwner,
@@ -131,6 +132,96 @@ function normalizeProviderList(input: ProviderListResponse): ProviderListRespons
}
}
const MAX_DIR_STORES = 30
const DIR_IDLE_TTL_MS = 20 * 60 * 1000
type DirState = {
lastAccessAt: number
}
type EvictPlan = {
stores: string[]
state: Map<string, DirState>
pins: Set<string>
max: number
ttl: number
now: number
}
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))
.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
}
type RootLoadArgs = {
directory: string
limit: number
list: (query: { directory: string; roots: true; limit?: number }) => Promise<{ data?: Session[] }>
onFallback: () => void
}
type RootLoadResult = {
data?: Session[]
limit: number
limited: boolean
}
export async function loadRootSessionsWithFallback(input: RootLoadArgs) {
try {
const result = await input.list({ directory: input.directory, roots: true, limit: input.limit })
return {
data: result.data,
limit: input.limit,
limited: true,
} satisfies RootLoadResult
} catch {
input.onFallback()
const result = await input.list({ directory: input.directory, roots: true })
return {
data: result.data,
limit: input.limit,
limited: false,
} satisfies RootLoadResult
}
}
export function estimateRootSessionTotal(input: { count: number; limit: number; limited: boolean }) {
if (!input.limited) return input.count
if (input.count < input.limit) return input.count
return input.count + 1
}
type DisposeCheck = {
directory: string
hasStore: boolean
pinned: boolean
booting: boolean
loadingSessions: boolean
}
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
return true
}
function createGlobalSync() {
const globalSDK = useGlobalSDK()
const platform = usePlatform()
@@ -140,8 +231,133 @@ function createGlobalSync() {
const vcsCache = new Map<string, VcsCache>()
const metaCache = new Map<string, MetaCache>()
const iconCache = new Map<string, IconCache>()
const lifecycle = new Map<string, DirState>()
const pins = new Map<string, number>()
const ownerPins = new WeakMap<object, Set<string>>()
const disposers = new Map<string, () => void>()
const stats = {
evictions: 0,
loadSessionsFallback: 0,
}
const sdkCache = new Map<string, ReturnType<typeof createOpencodeClient>>()
const updateStats = () => {
if (!import.meta.env.DEV) return
;(
globalThis as {
__OPENCODE_GLOBAL_SYNC_STATS?: {
activeDirectoryStores: number
evictions: number
loadSessionsFullFetchFallback: number
}
}
).__OPENCODE_GLOBAL_SYNC_STATS = {
activeDirectoryStores: Object.keys(children).length,
evictions: stats.evictions,
loadSessionsFullFetchFallback: stats.loadSessionsFallback,
}
}
const mark = (directory: string) => {
if (!directory) return
lifecycle.set(directory, { lastAccessAt: Date.now() })
runEviction()
}
const pin = (directory: string) => {
if (!directory) return
pins.set(directory, (pins.get(directory) ?? 0) + 1)
mark(directory)
}
const unpin = (directory: string) => {
if (!directory) return
const next = (pins.get(directory) ?? 0) - 1
if (next > 0) {
pins.set(directory, next)
return
}
pins.delete(directory)
runEviction()
}
const pinned = (directory: string) => (pins.get(directory) ?? 0) > 0
const pinForOwner = (directory: string) => {
const current = getOwner()
if (!current) return
if (current === owner) return
const key = current as object
const set = ownerPins.get(key)
if (set?.has(directory)) return
if (set) set.add(directory)
else ownerPins.set(key, new Set([directory]))
pin(directory)
onCleanup(() => {
const set = ownerPins.get(key)
if (set) {
set.delete(directory)
if (set.size === 0) ownerPins.delete(key)
}
unpin(directory)
})
}
function disposeDirectory(directory: string) {
if (
!canDisposeDirectory({
directory,
hasStore: !!children[directory],
pinned: pinned(directory),
booting: booting.has(directory),
loadingSessions: sessionLoads.has(directory),
})
) {
return false
}
queued.delete(directory)
sessionMeta.delete(directory)
sdkCache.delete(directory)
vcsCache.delete(directory)
metaCache.delete(directory)
iconCache.delete(directory)
lifecycle.delete(directory)
const dispose = disposers.get(directory)
if (dispose) {
dispose()
disposers.delete(directory)
}
delete children[directory]
updateStats()
return true
}
function runEviction() {
const stores = Object.keys(children)
if (stores.length === 0) return
const list = pickDirectoriesToEvict({
stores,
state: lifecycle,
pins: new Set(stores.filter(pinned)),
max: MAX_DIR_STORES,
ttl: DIR_IDLE_TTL_MS,
now: Date.now(),
})
if (list.length === 0) return
let changed = false
for (const directory of list) {
if (!disposeDirectory(directory)) continue
stats.evictions += 1
changed = true
}
if (changed) updateStats()
}
const sdkFor = (directory: string) => {
const cached = sdkCache.get(directory)
if (cached) return cached
@@ -379,52 +595,56 @@ function createGlobalSync() {
if (!icon) throw new Error("Failed to create persisted project icon")
iconCache.set(directory, { store: icon[0], setStore: icon[1], ready: icon[3] })
const init = () => {
const child = createStore<State>({
project: "",
projectMeta: meta[0].value,
icon: icon[0].value,
provider: { all: [], connected: [], default: {} },
config: {},
path: { state: "", config: "", worktree: "", directory: "", home: "" },
status: "loading" as const,
agent: [],
command: [],
session: [],
sessionTotal: 0,
session_status: {},
session_diff: {},
todo: {},
permission: {},
question: {},
mcp: {},
lsp: [],
vcs: vcsStore.value,
limit: 5,
message: {},
part: {},
})
const init = () =>
createRoot((dispose) => {
const child = createStore<State>({
project: "",
projectMeta: meta[0].value,
icon: icon[0].value,
provider: { all: [], connected: [], default: {} },
config: {},
path: { state: "", config: "", worktree: "", directory: "", home: "" },
status: "loading" as const,
agent: [],
command: [],
session: [],
sessionTotal: 0,
session_status: {},
session_diff: {},
todo: {},
permission: {},
question: {},
mcp: {},
lsp: [],
vcs: vcsStore.value,
limit: 5,
message: {},
part: {},
})
children[directory] = child
children[directory] = child
disposers.set(directory, dispose)
createEffect(() => {
if (!vcsReady()) return
const cached = vcsStore.value
if (!cached?.branch) return
child[1]("vcs", (value) => value ?? cached)
})
createEffect(() => {
if (!vcsReady()) return
const cached = vcsStore.value
if (!cached?.branch) return
child[1]("vcs", (value) => value ?? cached)
})
createEffect(() => {
child[1]("projectMeta", meta[0].value)
})
createEffect(() => {
child[1]("projectMeta", meta[0].value)
})
createEffect(() => {
child[1]("icon", icon[0].value)
createEffect(() => {
child[1]("icon", icon[0].value)
})
})
}
runWithOwner(owner, init)
updateStats()
}
mark(directory)
const childStore = children[directory]
if (!childStore) throw new Error("Failed to create store")
return childStore
@@ -432,6 +652,7 @@ function createGlobalSync() {
function child(directory: string, options: ChildOptions = {}) {
const childStore = ensureChild(directory)
pinForOwner(directory)
const shouldBootstrap = options.bootstrap ?? true
if (shouldBootstrap && childStore[0].status === "loading") {
void bootstrapInstance(directory)
@@ -443,6 +664,7 @@ function createGlobalSync() {
const pending = sessionLoads.get(directory)
if (pending) return pending
pin(directory)
const [store, setStore] = child(directory, { bootstrap: false })
const meta = sessionMeta.get(directory)
if (meta && meta.limit >= store.limit) {
@@ -450,11 +672,20 @@ function createGlobalSync() {
if (next.length !== store.session.length) {
setStore("session", reconcile(next, { key: "id" }))
}
unpin(directory)
return
}
const promise = globalSDK.client.session
.list({ directory, roots: true })
const limit = Math.max(store.limit + sessionRecentLimit, sessionRecentLimit)
const promise = loadRootSessionsWithFallback({
directory,
limit,
list: (query) => globalSDK.client.session.list(query),
onFallback: () => {
stats.loadSessionsFallback += 1
updateStats()
},
})
.then((x) => {
const nonArchived = (x.data ?? [])
.filter((s) => !!s?.id)
@@ -468,8 +699,13 @@ function createGlobalSync() {
const children = store.session.filter((s) => !!s.parentID)
const sessions = trimSessions([...nonArchived, ...children], { limit, permission: store.permission })
// Store total session count (used for "load more" pagination)
setStore("sessionTotal", nonArchived.length)
// Store root session total for "load more" pagination.
// For limited root queries, preserve has-more behavior by treating
// full-limit responses as "potentially more".
setStore(
"sessionTotal",
estimateRootSessionTotal({ count: nonArchived.length, limit: x.limit, limited: x.limited }),
)
setStore("session", reconcile(sessions, { key: "id" }))
sessionMeta.set(directory, { limit })
})
@@ -482,6 +718,7 @@ function createGlobalSync() {
sessionLoads.set(directory, promise)
promise.finally(() => {
sessionLoads.delete(directory)
unpin(directory)
})
return promise
}
@@ -491,6 +728,7 @@ function createGlobalSync() {
const pending = booting.get(directory)
if (pending) return pending
pin(directory)
const promise = (async () => {
const [store, setStore] = ensureChild(directory)
const cache = vcsCache.get(directory)
@@ -605,6 +843,7 @@ function createGlobalSync() {
booting.set(directory, promise)
promise.finally(() => {
booting.delete(directory)
unpin(directory)
})
return promise
}
@@ -670,6 +909,7 @@ function createGlobalSync() {
const existing = children[directory]
if (!existing) return
mark(directory)
const [store, setStore] = existing
@@ -955,6 +1195,11 @@ function createGlobalSync() {
if (!timer) return
clearTimeout(timer)
})
onCleanup(() => {
for (const directory of Object.keys(children)) {
disposeDirectory(directory)
}
})
async function bootstrap() {
const health = await globalSDK.client.global