Skip to content

Commit 7303d7d

Browse files
committed
fix(backend): Limit concurrent git operations to prevent resource exhaustion (#590)
When syncing generic-git-host connections with thousands of repositories, unbounded Promise.all caused resource exhaustion (EAGAIN errors) by spawning too many concurrent git processes. This resulted in valid repositories being incorrectly skipped during sync. - Add p-limit to control concurrent git operations (max 100) - Follow existing pattern from github.ts for consistency - Prevents file descriptor and process limit exhaustion - Uses rolling concurrency to avoid head-of-line blocking Fixes #590
1 parent d1655d4 commit 7303d7d

File tree

1 file changed

+8
-2
lines changed

1 file changed

+8
-2
lines changed

packages/backend/src/repoCompileUtils.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,17 @@ import assert from 'assert';
2020
import GitUrlParse from 'git-url-parse';
2121
import { RepoMetadata } from '@sourcebot/shared';
2222
import { SINGLE_TENANT_ORG_ID } from './constants.js';
23+
import pLimit from 'p-limit';
2324

2425
export type RepoData = WithRequired<Prisma.RepoCreateInput, 'connections'>;
2526

2627
const logger = createLogger('repo-compile-utils');
2728

29+
// Limit concurrent git operations to prevent resource exhaustion (EAGAIN errors)
30+
// when processing thousands of repositories simultaneously
31+
const MAX_CONCURRENT_GIT_OPERATIONS = 100;
32+
const gitOperationLimit = pLimit(MAX_CONCURRENT_GIT_OPERATIONS);
33+
2834
type CompileResult = {
2935
repoData: RepoData[],
3036
warnings: string[],
@@ -472,7 +478,7 @@ export const compileGenericGitHostConfig_file = async (
472478
const repos: RepoData[] = [];
473479
const warnings: string[] = [];
474480

475-
await Promise.all(repoPaths.map(async (repoPath) => {
481+
await Promise.all(repoPaths.map((repoPath) => gitOperationLimit(async () => {
476482
const isGitRepo = await isPathAValidGitRepoRoot({
477483
path: repoPath,
478484
});
@@ -526,7 +532,7 @@ export const compileGenericGitHostConfig_file = async (
526532
}
527533

528534
repos.push(repo);
529-
}));
535+
})));
530536

531537
return {
532538
repoData: repos,

0 commit comments

Comments
 (0)