Skip to content

perf: bounded concurrent Qdrant setup I/O via buffer_unordered#82

Merged
bashandbone merged 2 commits into
perf/qdrant-setup-concurrency-3772027052885873883from
copilot/sub-pr-78
Mar 13, 2026
Merged

perf: bounded concurrent Qdrant setup I/O via buffer_unordered#82
bashandbone merged 2 commits into
perf/qdrant-setup-concurrency-3772027052885873883from
copilot/sub-pr-78

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 13, 2026

The previous try_join_all refactor achieved concurrency but with unbounded fan-out — N collections meant N simultaneous Qdrant requests, risking connection storms and server overload. Review feedback requested bounded concurrency, race-condition safety documentation, and reduced duplication.

Changes

  • Bounded concurrency: replaced try_join_all with buffer_unordered(MAX_CONCURRENT_SETUP_OPS) (cap: 16). Futures are pre-collected via a for loop + Vec::with_capacity before being streamed — required to satisfy async_trait's HRTB lifetime constraints, which prevent using iter().map() directly with buffer_unordered.

  • Race-condition invariant documented: added a comment confirming CollectionKey uniqueness is enforced by the setup orchestration layer, so intra-phase concurrent ops cannot race on the same collection.

  • Constant for the concurrency limit: MAX_CONCURRENT_SETUP_OPS = 16 makes the bound discoverable and easy to tune.

let mut delete_futures = Vec::with_capacity(setup_change.len());
for change in setup_change.iter() {
    let client_result = self.get_qdrant_client(&change.key.connection, auth_registry);
    delete_futures.push(async move {
        change.setup_change.apply_delete(&change.key.collection_name, &client_result?).await
    });
}
futures::stream::iter(delete_futures)
    .buffer_unordered(MAX_CONCURRENT_SETUP_OPS)
    .try_collect::<Vec<_>>().await.map(|_| ())?;

Phase ordering (all deletes before any creates) is preserved.


🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. Learn more about Advanced Security.

…etup ops

Co-authored-by: bashandbone <89049923+bashandbone@users.noreply.github.com>
@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented Mar 13, 2026

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
recoco-docs 538324f Commit Preview URL

Branch Preview URL
Mar 13 2026, 03:39 AM

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 13, 2026

Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • test
    • Triggering command: /home/REDACTED/work/recoco/recoco/target/debug/deps/recoco_core-cf2701bcf874797c /home/REDACTED/work/recoco/recoco/target/debug/deps/recoco_core-cf2701bcf874797c lib --emit=dep-info,metadata -C opt-level=1 -C embed-bitcode=no .18/src/lib.rs codegen-units=256 -C debuginfo=2 -C s/th�� fccbfb73.dptdgc2--error-format=json s/thiserror_impl--json=diagnostic-rendered-ansi,artifacts,future-incompat bin/rustc lib/rustlib/x86_/home/REDACTED/.rustup/toolchains/stable-x86_64-REDACTED-linux-gnu/bin/clippy-drive-m64 lib/rustlib/x86_/home/REDACTED/.rustup/toolchains/stable-x86_64-REDACTED-linux-gnu/bin/rustc lib/rustlib/x86_--crate-name bin/rustc (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI changed the title [WIP] Refactor Qdrant target setup for concurrent async I/O perf: bounded concurrent Qdrant setup I/O via buffer_unordered Mar 13, 2026
Copilot AI requested a review from bashandbone March 13, 2026 03:39
@bashandbone bashandbone marked this pull request as ready for review March 13, 2026 03:58
Copilot AI review requested due to automatic review settings March 13, 2026 03:58
@bashandbone bashandbone merged commit e2d6086 into perf/qdrant-setup-concurrency-3772027052885873883 Mar 13, 2026
4 checks passed
@bashandbone bashandbone deleted the copilot/sub-pr-78 branch March 13, 2026 03:58
@github-project-automation github-project-automation Bot moved this from Backlog to Done in Recoco v1.0.0 Mar 13, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR bounds concurrent Qdrant collection setup I/O to prevent unbounded request fan-out during delete/create phases while preserving phase ordering.

Changes:

  • Introduces MAX_CONCURRENT_SETUP_OPS and runs setup ops via buffer_unordered to cap concurrency.
  • Adds an invariant comment about CollectionKey uniqueness to justify safe intra-phase concurrency.
  • Reworks delete/create phases to pre-collect futures and then execute them with bounded concurrency.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +589 to 596
for change in setup_change.iter() {
let client_result = self.get_qdrant_client(&change.key.connection, auth_registry);
delete_futures.push(async move {
let client = client_result?;
change
.setup_change
.apply_delete(&change.key.collection_name, &qdrant_client)
.apply_delete(&change.key.collection_name, &client)
.await
Comment on lines +599 to +603
futures::stream::iter(delete_futures)
.buffer_unordered(MAX_CONCURRENT_SETUP_OPS)
.try_collect::<Vec<_>>()
.await
.map(|_| ())?;
Comment on lines +617 to +621
futures::stream::iter(create_futures)
.buffer_unordered(MAX_CONCURRENT_SETUP_OPS)
.try_collect::<Vec<_>>()
.await
.map(|_| ())
Comment on lines +584 to +585
// Each item in setup_change has a unique CollectionKey (enforced by the setup
// orchestration layer), so concurrent operations across items are race-free.
bashandbone added a commit that referenced this pull request Mar 13, 2026
* perf: optimize Qdrant target setup by running async I/O concurrently

Modified `apply_setup_changes` in `qdrant.rs` to group delete and create operations into separate vectors of futures, running them concurrently via `futures::future::try_join_all`. This fixes an O(N) latency inefficiency where N independent collection changes were awaited sequentially.

Co-authored-by: bashandbone <89049923+bashandbone@users.noreply.github.com>

* perf: optimize Qdrant target setup by running async I/O concurrently

Co-authored-by: bashandbone <89049923+bashandbone@users.noreply.github.com>

* perf: bounded concurrent Qdrant setup I/O via buffer_unordered (#82)

* Initial plan

* perf: replace try_join_all with bounded buffer_unordered for Qdrant setup ops

Co-authored-by: bashandbone <89049923+bashandbone@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: bashandbone <89049923+bashandbone@users.noreply.github.com>

---------

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants