← Back to PRs

#21978: perf: parallelize QMD multi-collection queries

by maximalmargin open 2026-02-20 16:01 View on GitHub →
size: S
Fixes #21974 ## Summary Converts `runQueryAcrossCollections` from sequential to parallel execution using `Promise.allSettled`. ## Problem With 8 collections and a 30s per-query timeout, worst-case latency was **240 seconds** (sum of all collection query times), often causing the outer timeout to kill the search and fall back to local embeddings. ## Solution Use `Promise.allSettled` to query all collections in parallel. **Before (sequential):** ```typescript for (const collectionName of collectionNames) { const result = await this.runQmd(args, { timeoutMs: this.qmd.limits.timeoutMs }); // ... } ``` **After (parallel):** ```typescript const results = await Promise.allSettled( collectionNames.map(async (collectionName) => { const args = this.buildSearchArgs("query", query, limit); args.push("-c", collectionName); const result = await this.runQmd(args, { timeoutMs: this.qmd.limits.timeoutMs }); return parseQmdQueryJson(result.stdout, result.stderr); }) ); ``` ## Benefits - ✅ **Total latency = max(collection times)** instead of sum - ✅ **Failed collections gracefully skipped** via `allSettled` - ✅ **No behavior change** for the happy path - ✅ **Worst-case improvement:** 240s → 30s with 8 collections ## Testing - Existing tests pass (linting clean) - Logic unchanged: still merges results by `docid`, keeping highest score - Error handling improved: individual collection failures don't block others ## Environment Tested on OpenClaw 2026.2.19-2, 8 QMD collections, searchMode: "query". <!-- greptile_comment --> <h3>Greptile Summary</h3> Converts sequential multi-collection QMD queries to parallel execution using `Promise.allSettled`, reducing worst-case latency from 240s (sum of 8×30s timeouts) to 30s (max timeout). The change maintains identical result-merging logic (keeping highest-scoring result per `docid`) while gracefully skipping failed collections. The implementation correctly uses `Promise.allSettled` to prevent individual collection failures from blocking the entire search operation. <h3>Confidence Score: 5/5</h3> - Safe to merge - straightforward performance optimization with no behavior changes - The parallelization is correctly implemented with `Promise.allSettled` to handle failures gracefully. The result-merging logic remains identical to the sequential version. The change is well-tested (per PR description) and addresses a clear performance issue without introducing new edge cases or changing the API contract. - No files require special attention <sub>Last reviewed commit: f0df321</sub> <!-- greptile_other_comments_section --> <!-- /greptile_comment -->

Most Similar PRs