fix: bound runtime fetch caches (#4068)

Cap runtime remote-fetch cache maps while preserving freshness and in-flight coalescing behavior.
This commit is contained in:
Neil
2026-05-31 03:15:31 -07:00
committed by GitHub
parent 255bb24c37
commit bbb7a9d25f
2 changed files with 45 additions and 7 deletions
@@ -118,6 +118,24 @@ describe('OrcaRuntimeService.fetchRemoteWithCache', () => {
expect(fetchCallCount()).toBe(1)
})
it('bounds process-lifetime fetch cache maps for churned repo paths', async () => {
mockFetchResults(Array.from({ length: 520 }, () => ({ stdout: '', stderr: '' })))
const runtime = new OrcaRuntimeService(null)
const caches = runtime as unknown as {
canonicalFetchKeyCache: Map<string, string>
fetchLastCompletedAt: Map<string, number>
}
for (let i = 0; i < 520; i += 1) {
await runtime.fetchRemoteWithCache(`/repo/cache-${i}`, 'origin')
}
expect(caches.canonicalFetchKeyCache.size).toBeLessThanOrEqual(512)
expect(caches.fetchLastCompletedAt.size).toBeLessThanOrEqual(512)
expect(caches.canonicalFetchKeyCache.has('/repo/cache-0::origin')).toBe(false)
expect(caches.fetchLastCompletedAt.has('/repo/cache-0::origin')).toBe(false)
})
it('resolves remote-tracking bases with longest configured remote matching', async () => {
gitExecFileAsyncMock.mockResolvedValue({ stdout: 'foo\nfoo/bar\norigin\n', stderr: '' })
const runtime = new OrcaRuntimeService(null)
+27 -7
View File
@@ -8270,6 +8270,7 @@ export class OrcaRuntimeService {
const cacheKey = `${repoPath}::${remote}`
const cached = this.canonicalFetchKeyCache.get(cacheKey)
if (cached !== undefined) {
setBoundedMapEntry(this.canonicalFetchKeyCache, cacheKey, cached, REMOTE_FETCH_CACHE_MAX)
return cached
}
let resolved = cacheKey
@@ -8286,7 +8287,7 @@ export class OrcaRuntimeService {
// Fall through to the caller-provided path. The fetch still runs from
// repoPath; this key only controls cache sharing.
}
this.canonicalFetchKeyCache.set(cacheKey, resolved)
setBoundedMapEntry(this.canonicalFetchKeyCache, cacheKey, resolved, REMOTE_FETCH_CACHE_MAX)
return resolved
}
@@ -8308,11 +8309,15 @@ export class OrcaRuntimeService {
async getOrStartRemoteFetch(repoPath: string, remote: string): Promise<RemoteFetchResult> {
const key = await this.getCanonicalFetchKey(repoPath, remote)
const lastAt = this.fetchLastCompletedAt.get(key)
if (lastAt !== undefined && Date.now() - lastAt < FETCH_FRESHNESS_MS) {
// Why: freshness window hit — skip the fetch entirely. Do NOT reuse any
// in-flight promise here; the timestamp is only written on success, so
// hitting this branch means a previous fetch did succeed recently.
return { ok: true }
if (lastAt !== undefined) {
if (Date.now() - lastAt < FETCH_FRESHNESS_MS) {
// Why: freshness window hit — skip the fetch entirely. Do NOT reuse any
// in-flight promise here; the timestamp is only written on success, so
// hitting this branch means a previous fetch did succeed recently.
setBoundedMapEntry(this.fetchLastCompletedAt, key, lastAt, REMOTE_FETCH_CACHE_MAX)
return { ok: true }
}
this.fetchLastCompletedAt.delete(key)
}
const existing = this.fetchInflight.get(key)
@@ -8327,7 +8332,7 @@ export class OrcaRuntimeService {
.then((): RemoteFetchResult => {
// Why (§3.3 Lifecycle): timestamp on success ONLY. Writing on rejection
// would make the freshness cache lie about the last known remote state.
this.fetchLastCompletedAt.set(key, Date.now())
setBoundedMapEntry(this.fetchLastCompletedAt, key, Date.now(), REMOTE_FETCH_CACHE_MAX)
return { ok: true }
})
.catch((err): RemoteFetchResult => {
@@ -12773,8 +12778,23 @@ const PTY_CONTROLLER_LIST_TIMEOUT_MS = 3000
// clicks and successive coordinator dispatches feel snappy, while still being
// short enough that a genuinely-changed remote is observed on the next action.
const FETCH_FRESHNESS_MS = 30_000
const REMOTE_FETCH_CACHE_MAX = 512
const DRIFT_PROBE_SUBJECT_LIMIT = 5
function setBoundedMapEntry<K, V>(map: Map<K, V>, key: K, value: V, maxEntries: number): void {
if (map.has(key)) {
map.delete(key)
}
map.set(key, value)
while (map.size > maxEntries) {
const oldest = map.keys().next()
if (oldest.done) {
return
}
map.delete(oldest.value)
}
}
function getExplicitWorktreeIdSelector(selector: string | undefined): string | null {
if (!selector?.startsWith('id:')) {
return null