Skip to content

refactor(code-index): route chunk fan-outs through one yielding helper - #1491

Closed
ScriptedAlchemy wants to merge 2 commits into
codex/tracedecay-total-redesign-plan-reopenedfrom
cursor/background-cpu-yield-guard-d94a
Closed

ScriptedAlchemy wants to merge 2 commits into
codex/tracedecay-total-redesign-plan-reopenedfrom
cursor/background-cpu-yield-guard-d94a

Conversation

@ScriptedAlchemy

Copy link
Copy Markdown
Owner

Summary

  • Move both chunk fan-outs in chunks.rs (try_for_each_chunk_ordered, admit_all) behind one private fan_out::map_yielding that performs the with_yielded_background_cpu_permits wrap internally.
  • rayon is now imported only inside mod fan_out, so a bare par_iter anywhere else in chunks.rs fails to compile.
  • Add a source-scan test that pins every pool token in chunks.rs to mod fan_out and pins the yield to that module.
  • Isolated tip leaf forked once from 9fbf169fe; not re-rebased as the tip moves.

Motivation

The nested-admission deadlock fix from #1449 (f81df3b34) was two call-site wraps around two par_iters. The merge resolution in d039bee89 (#1435) kept both par_iters and dropped both wraps; the base stayed wedge-prone for sixteen merges (#1435 through #1383, including 630702adb where the hang was re-observed) until 76a8e7838 (#1460) restored them. A fix that a conflict resolution can silently detach from the code it protects is not durable. Welding the yield to the fan-out inside one helper, and making that helper the only route to the pool in the module, means the yield cannot be kept out while the fan-out stays in.

Changes

  • crates/tracedecay-code-index/src/chunks.rs
    • New private mod fan_out with pub(super) fn map_yielding<I, R>(items, map) -> Vec<R> for any IntoParallelIterator whose iterator is indexed. It yields the caller's admitted units around the join and collects outputs in input order.
    • try_for_each_chunk_ordered: map_yielding(chunks, |chunk| admit(&mut || operation(chunk)).err()) then the first Some in input order. This equals the previous filter_map + min_by_key(index) because indexed collect preserves order.
    • admit_all: map_yielding(chunks, |chunk| with_background_cpu_permit(|| self.admit(chunk))).into_iter().collect().
    • Top-level use rayon::prelude::* removed; the import lives inside mod fan_out.
    • Test every_pool_fan_out_in_chunks_goes_through_the_yielding_helper: include_str!("chunks.rs"), skip comment lines, assert no rayon / par_iter( (also matches into_par_iter() / par_chunks / par_bridge token outside mod fan_out, and assert the module contains with_yielded_background_cpu_permits(. Token literals are built with concat! so the test's own source is not an occurrence. It caught itself on the first run (identifiers named rayon_tokens), which is the evidence it scans what it claims to.
  • Sequential path (< PARALLEL_CHUNK_THRESHOLD) untouched. No behaviour change on the parallel path beyond collecting Option<ChunkingFailureV1> per chunk instead of filter_map.

Test plan

All on the fork point 9fbf169fe, --profile perf, CARGO_INCREMENTAL=0, own target.

Check Result
cargo test -p tracedecay-code-index --lib whole binary ×3 246/246 ok ×3 (7.8 s, 7.0 s, 7.5 s); nested-admission pin and the new guard green in each; one more 246/246 after commit split
Guard self-check first run FAILED on the test's own rayon_tokens identifiers before the rename; passes after — the scan sees real code lines
cargo fmt --check no diffs in chunks.rs
cargo clippy -p tracedecay-code-index --profile perf --no-deps --all-targets --keep-going -- -D warnings lib, lib unittests and every other target clean; the only diagnostics are two pre-existing E0425 in tests/code_index_suite/chunk_incremental.rs:362,366 (base red, reproduced identically with this diff stashed)
npm run lint:commit -- --from origin/codex/... --to HEAD pass
cargo test -p tracedecay-code-index-runtime --lib -- reconcile not runnable on this tip: the runtime crate does not compile at 9fbf169fe (publication_store.rs:2640 .reused), identically with this diff stashed; being fixed separately. The same filter completed 2/2 (168 tests) on d1586e4ae earlier today with identical wrappers in place.
  • cargo nextest run --workspace --no-fail-fast — CI (expected red until the base compile fixes land; merge only on real SUCCESS)

Checklist

  • CHANGELOG.md — internal refactor + test, no user-facing change
  • No secrets, credentials, or .env files included
  • No breaking changes

Base reds seen while verifying (not fixed here)

  1. crates/tracedecay-code-index-runtime/src/code_index_scheduler/publication_store.rs:2640 — .reused on ChangedCodeChunkSetV1; the runtime crate does not build at 9fbf169fe.
  2. crates/tracedecay-code-index/tests/code_index_suite/chunk_incremental.rs:362,366 — parallelism::force_install_failure_for_test is no longer exported from the lib to integration tests.
  3. code_index_scheduler::tests::reconcile::concurrent_query_admissions_claim_one_pending_wake_before_worker_coalescing fails alone 2/3 on d1586e4ae (admitted == 0); present since d62bf238d, unrelated to background-CPU admission.
Open in Web Open in Cursor 

cursoragent and others added 2 commits September 17, 2026 00:22
`try_for_each_chunk_ordered` and `admit_all` each wrapped their own
`par_iter` in `with_yielded_background_cpu_permits`. That wrap is the
nested-admission fix from #1449, and the merge resolution in d039bee
kept both `par_iter`s while dropping both wraps, leaving the base
wedge-prone for sixteen merges until 76a8e78 restored it. Move the
fan-out into a private `fan_out` module whose single `map_yielding`
performs the yield internally and is the only place in `chunks` that
imports `rayon`, so a bare `par_iter` elsewhere in the file no longer
compiles and the yield cannot be separated from the join. Outputs are
collected in input order, so the ordered sweep's lowest-index failure
is the first `Some`. No behaviour change.

Co-authored-by: Zack Jackson <ScriptedAlchemy@users.noreply.github.com>
Scan `chunks.rs` and assert that every pool token (`rayon`, `par_iter`,
`par_chunks`, `par_bridge`) outside comments sits inside `mod fan_out`,
and that `fan_out` itself carries the yield. Token literals are built
with `concat!` so the test's own source does not count.

Co-authored-by: Zack Jackson <ScriptedAlchemy@users.noreply.github.com>
@changeset-bot

changeset-bot Bot commented Sep 17, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: e88be5e

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

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.

2 participants