Skip to content

fix: bound pending results in ordered worker mapping - #859

Open
Cookie0103 wants to merge 1 commit into
qdrant:mainfrom
Cookie0103:fix/bound-ordered-worker-buffer
Open

Cookie0103 wants to merge 1 commit into
qdrant:mainfrom
Cookie0103:fix/bound-ordered-worker-buffer

Conversation

@Cookie0103

Copy link
Copy Markdown

ordered_map buffers later results while waiting for an earlier batch, but semi_ordered_map counts those buffered results as read and keeps submitting input. If the first embedding batch is slow, the ordered buffer can therefore grow with the corpus despite the bounded multiprocessing queues.

Move ordered buffering into a shared mapping loop and apply backpressure to submitted-but-not-emitted results. At the existing queue window, continue draining outputs until the missing prefix arrives before submitting another input. This bounds pending results without deadlocking on an out-of-order prefix. Public method signatures, worker keyword forwarding, unordered delivery, and existing process/queue cleanup are preserved. One source item may be prefetched by the input loop in addition to the submitted window.

Reproduction and validation

The regression uses a queue window of 4 and holds batch zero while the second real worker processes later batches. On the base revision, all 60 source batches are consumed before an ordered result is returned; after the fix the maximum source lead is 5. Both spawn and forkserver are exercised on macOS/Python 3.12.13. The original 8-case regression suite gives 3 failed / 5 passed on base f91d9168c0291daeafb0a54cebc7c5b4b83f312f.

  • .venv/bin/python -m pytest tests/test_ordered_backpressure.py tests/test_parallel_processor.py tests/test_common.py -q: 21 passed, including input failure, worker failure, early close, empty/non-divisible streams, unordered progress, and a worker's own ordered keyword.
  • The same files plus tests/test_model_management.py tests/test_preprocessor_utils.py tests/test_postprocess.py: 70 passed.
  • CI's mypy fastembed --disallow-incomplete-defs --disallow-untyped-defs --disable-error-code=import-untyped: passed, 69 files.
  • CI's pyright tests/type_stub.py: 0 errors/warnings.
  • Repository-pinned pre-commit Ruff and Ruff-format on both changed files: passed; git diff --check: passed.

A separate real-worker tracemalloc reproduction used 1,000 synthetic 16 KiB results, the same window of 4, and a gated first result. While it was gated:

Base Fixed
Source items pulled 1,000 5
Ordered results delivered 0 0
Current parent Python allocations 16,785,004 bytes 373,117 bytes
Peak parent Python allocations 16,801,417 bytes 388,945 bytes

Both runs then delivered all 1,000 results. The dominant base allocation stack is the multiprocessing result receive/unpickle path retained by ordered_map's buffer. These are synthetic parent-allocation measurements, not total process RSS or model throughput claims. The existing window is not changed; a slow prefix can reduce worker utilization once that window fills, which is the intended memory bound.

The entire model/GPU suite was not run. The deterministic scheduler regression needs no model downloads or API credentials; actual-model throughput and Windows behavior have not been measured.

AI assistance: Codex investigated, implemented, tested, profiled and independently AI-reviewed the change. The account owner has not personally reviewed or tested it.

All Submissions

@Cookie0103
Cookie0103 requested a review from joein as a code owner November 3, 2026 07:38
@coderabbitai

coderabbitai Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review.

Walkthrough

ordered_map and semi_ordered_map now use a shared mapping loop. The loop buffers indexed results for ordered output, emits semi-ordered results as received, and drains output while consuming input to bound the outstanding work. Added tests cover ordering, source lead limits, real-worker behavior, error handling, process cleanup, and forwarding worker options.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix

Possibly related PRs

  • qdrant/fastembed#824: Adds the worker-health-checked output polling used by the updated backpressure loop.
Merge Risk: Minimal · up to 74c82

No actionable merge-blocking issue remains after normal checks.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentat… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Title check Passed The title clearly identifies the main change: bounding pending results in ordered worker mapping.
Description check Passed The description directly explains the ordered-result buffering fix, backpressure behavior, preserved interfaces, tests, and validation results.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 15 functions across 2 files.

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

Finishing Touches
Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Warning

Some tools did not complete. Review the errors below.

ast-grep (0.51.1)

ast-grep could not parse rule config: /ast-grep-rules/ast-grep-essentials/rules/bash/security/wget-pipe-to-shell-bash.yml

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

CodeRabbit Verify

  • Run CodeRabbit Verify to test the changes in this pull request.
Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 14447d13-441e-4a82-b26b-a5f7483aa0a4
Commits

Reviewing files that changed from the base of the PR and between f91d916 and 74c82ad.

Files selected for processing: 2
  • fastembed/parallel_processor.py
  • tests/test_ordered_backpressure.py

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 7 remain after this review.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant