Files
orca/src/main/git/command-runner/git-spawn-admission-lifetime.test.ts
T
Brennan Benson 6a71077316 perf(git): bound git subprocess execution with an atomic admission scheduler
Field traces (#16038, #11363) show Windows freeze storms driven by unbounded
concurrent git children (12+ at once, 50-65s status convoys for 25+ minutes).
Admit every main-process git child against atomic per-budget base+headroom
counters (general / network / per-route), with reserved interactive capacity,
ordering-only aging, close-bound permit release, a 120s fail-safe read timeout
that feeds scheduler backoff, tier plumbing through every option carrier, and
coalesced+jittered visibility pollers. Killswitch: ORCA_GIT_ADMISSION_DISABLED=1.

Storm harness A/B: max concurrent children 65 -> 6, interactive p95 791ms -> 88ms;
output-parity battery byte-identical with admission on vs off.
2026-08-27 14:53:31 -07:00

80 lines
3.0 KiB
TypeScript

import { EventEmitter } from 'node:events'
import type { ChildProcess } from 'node:child_process'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { withGitAdmission } from './git-spawn'
import {
GitAdmissionScheduler,
_gitAdmissionSnapshotForTests,
_resetGitAdmissionForTests
} from './git-subprocess-admission'
function mockChild(pid: number | undefined = 1234): ChildProcess {
const child = new EventEmitter() as EventEmitter & Record<string, unknown>
child.pid = pid
child.kill = vi.fn(() => true)
return child as unknown as ChildProcess
}
describe('git spawn admission lifetime', () => {
beforeEach(() => {
_resetGitAdmissionForTests(new GitAdmissionScheduler({ generalCap: 1, generalHeadroom: 1 }))
})
afterEach(() => _resetGitAdmissionForTests())
it('releases a normally closed child exactly once', async () => {
const child = mockChild()
await withGitAdmission(['status'], { cwd: '/repo' }, () => child)
child.emit('close', 0, null)
child.emit('close', 0, null)
expect(_gitAdmissionSnapshotForTests().budgets.general?.baseUsed).toBe(0)
})
it('retains an early-killed child until eventual close', async () => {
const child = mockChild()
await withGitAdmission(['status'], { cwd: '/repo' }, () => child)
child.kill()
expect(_gitAdmissionSnapshotForTests().budgets.general?.baseUsed).toBe(1)
child.emit('close', null, 'SIGTERM')
expect(_gitAdmissionSnapshotForTests().budgets.general?.baseUsed).toBe(0)
})
it('retains a live child error until eventual close and releases once', async () => {
const child = mockChild()
await withGitAdmission(['status'], { cwd: '/repo' }, () => child)
expect(_gitAdmissionSnapshotForTests().budgets.general?.baseUsed).toBe(1)
child.emit('error', new Error('kill delivery failed'))
expect(_gitAdmissionSnapshotForTests().budgets.general?.baseUsed).toBe(1)
child.emit('close', null, 'SIGKILL')
child.emit('close', null, 'SIGKILL')
expect(_gitAdmissionSnapshotForTests().budgets.general?.baseUsed).toBe(0)
})
it('releases a no-PID spawn error without waiting for close', async () => {
const child = mockChild(0)
await withGitAdmission(['status'], { cwd: '/repo' }, () => child)
child.emit('error', new Error('ENOENT'))
expect(_gitAdmissionSnapshotForTests().budgets.general?.baseUsed).toBe(0)
})
it('aborts while queued without releasing the running child', async () => {
const scheduler = new GitAdmissionScheduler({ generalCap: 1, generalHeadroom: 0 })
_resetGitAdmissionForTests(scheduler)
const running = await scheduler.acquire({ args: ['status'], cwd: '/repo' })
const controller = new AbortController()
const pending = withGitAdmission(['status'], { cwd: '/repo', signal: controller.signal }, () =>
mockChild()
)
controller.abort()
await expect(pending).rejects.toMatchObject({ name: 'AbortError' })
expect(_gitAdmissionSnapshotForTests().budgets.general?.baseUsed).toBe(1)
running.release()
})
})