perf: fix database query performance bottlenecks (#1982)

* perf: fix database query performance bottlenecks

- Add composite index on workspace_repos(workspace_id, repo_id) to optimize lookup queries that were taking up to 5 seconds
- Add composite index on merges(merge_type, pr_status) to optimize status filtering queries that were taking 2+ seconds
- Fix N+1 query pattern in workspace_repos.create_many by wrapping inserts in a transaction
- Fix N+1 query pattern in get_task_attempt_branch_status by batch fetching all merges upfront instead of querying per repo

These changes address significant performance bottlenecks identified in production logs where simple lookup queries were experiencing multi-second latencies.

* cargo fmt

* run sqlx prepare

---------

Co-authored-by: Solomon <abcpro11051@disroot.org>
This commit is contained in:
William Reed
2026-01-14 06:04:22 -05:00
committed by GitHub
parent cd579ca791
commit 4a48233cff
4 changed files with 40 additions and 3 deletions

View File

@@ -728,6 +728,20 @@ pub async fn get_task_attempt_branch_status(
.await?;
let workspace_dir = PathBuf::from(&container_ref);
// Batch fetch all merges for the workspace to avoid N+1 queries
let all_merges = Merge::find_by_workspace_id(pool, workspace.id).await?;
let merges_by_repo: HashMap<Uuid, Vec<Merge>> =
all_merges
.into_iter()
.fold(HashMap::new(), |mut acc, merge| {
let repo_id = match &merge {
Merge::Direct(dm) => dm.repo_id,
Merge::Pr(pm) => pm.repo_id,
};
acc.entry(repo_id).or_insert_with(Vec::new).push(merge);
acc
});
let mut results = Vec::with_capacity(repositories.len());
for repo in repositories {
@@ -735,7 +749,7 @@ pub async fn get_task_attempt_branch_status(
continue;
};
let repo_merges = Merge::find_by_workspace_and_repo_id(pool, workspace.id, repo.id).await?;
let repo_merges = merges_by_repo.get(&repo.id).cloned().unwrap_or_default();
let worktree_path = workspace_dir.join(&repo.name);