perf: handle large relay status entry lists

This commit is contained in:
Neil
2026-05-30 09:41:52 -07:00
parent 760f5c34ec
commit 1300d404a7
2 changed files with 61 additions and 1 deletions
+56
View File
@@ -0,0 +1,56 @@
import { mkdtempSync } from 'fs'
import * as fs from 'fs/promises'
import { tmpdir } from 'os'
import * as path from 'path'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import type { GitExec } from './git-handler-ops'
import { getStatusOp } from './git-handler-status-ops'
const LARGE_STATUS_ENTRY_COUNT = 150_000
function buildLargeStatusOutput(count: number): string {
const lines: string[] = []
for (let index = 0; index < count; index += 1) {
lines.push(`1 A. N... 100644 100644 100644 000000 111111 generated-${index}.txt`)
}
return lines.join('\n')
}
describe('getStatusOp', () => {
let tmpDir: string
beforeEach(() => {
tmpDir = mkdtempSync(path.join(tmpdir(), 'relay-git-status-'))
})
afterEach(async () => {
await fs.rm(tmpDir, { recursive: true, force: true })
})
it('returns large parsed status entry lists', async () => {
const statusOutput = buildLargeStatusOutput(LARGE_STATUS_ENTRY_COUNT)
const git = vi.fn<GitExec>(async (args) => {
if (args.includes('status')) {
return { stdout: statusOutput, stderr: '' }
}
if (args.includes('diff')) {
return { stdout: '', stderr: '' }
}
throw new Error(`Unexpected git command: ${args.join(' ')}`)
})
const result = await getStatusOp(git, { worktreePath: tmpDir })
expect(result.entries).toHaveLength(LARGE_STATUS_ENTRY_COUNT)
expect(result.entries[0]).toEqual({
path: 'generated-0.txt',
status: 'added',
area: 'staged'
})
expect(result.entries.at(-1)).toEqual({
path: `generated-${LARGE_STATUS_ENTRY_COUNT - 1}.txt`,
status: 'added',
area: 'staged'
})
})
})
+5 -1
View File
@@ -99,7 +99,11 @@ export async function getStatusOp(
disableOptionalLocks: true
})
const parsed = parseStatusOutput(stdout)
entries.push(...parsed.entries)
// Why: huge worktrees can produce enough status rows to exceed JavaScript's
// spread-argument limit during routine source-control polling.
for (const entry of parsed.entries) {
entries.push(entry)
}
head = parsed.head
branch = parsed.branch
upstreamStatus = parsed.upstreamStatus