Repository navigation
feat(server): spill oversized TUIndex results to a store tmp file - #593
orionsutton wants to merge 2 commits into
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughThe change adds configurable TUIndex spilling for oversized worker results. Workers write results to temporary files and return size and hash metadata. The indexer verifies and loads spilled data, handles failures, logs transfer mode, and removes temporary files. Unit and integration tests cover these paths. ChangesTUIndex spill transfer
Estimated code review effort: 3 (Moderate) | ~25 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
|
Hi — thanks for spending time on this. Our workflow asks contributors to open an issue first so we can discuss the problem and agree on a direction before any code is written. Jumping straight to a PR skips that conversation, and we're unlikely to merge unsolicited PRs that haven't gone through that process — how a fix should look is ultimately a maintainer decision, and the approach may differ from what's proposed here. If you've hit a real problem, please file an issue describing the scenario and we'll figure out the right fix together. |
Problem
A stateless worker returns the serialized TUIndex inline in the IPC response (
BuildResult::tu_index_data). On large TUs this frame is enormous — on a 4795-TU field workspace the largest observed result is 283.5MB — and an inline frame that size costs several transient copies along the pipe (worker serialize → frame → 64KB ring-buffer chunks → master reassembly → codec decode) and head-of-line blocks every other message on that worker link while it streams. It is also what made the transport's frame cap reachable in the first place: results past the cap could never be delivered at all.Change
Results above a threshold travel out-of-line:
begin_store) and passes it in the existingBuildParams::index_output_path(the same pattern BuildPCH already uses for its PreambleState blob). ThePendingEntryis held across the request, so the file is removed on every master-side exit path — completion, error, and coroutine cancellation; tmp files orphaned by a crashed master are swept by the next instance'sopen().{tu_index_file_size, tu_index_hash}(xxh3_64) instead of the bytes; results at or under the threshold stay inline, so the common case has zero extra filesystem traffic. A failed spill write falls back to inline delivery.llvm::MemoryBuffer::getFile), verifies size and hash before parsing — the worker may have died mid-write, and a torn blob must not poison the merge — and on verification failure requeues the file like a crash (note_dispatch_failure) instead of serving the stale shard as fresh. The[perf:index]line gainstransfer=file|inline.project.index_inline_limit(default 8MB, undocumented liketest_hooks): its default only matters for results too large for CI to produce, and the knob is what makes the spill path testable at all.fs::writenow surfaces mid-write failures (disk full, EIO) as ordinary errors — previously an unchecked stream error flag turned into a fatal error in theraw_fd_ostreamdestructor, which for a worker meant dying instead of reporting.Master and workers are the same binary on the same machine, so a shared filesystem path is a given for this transport.
Tests
IndexSpillToFilepins the wire contract (empty inline bytes, on-disk size and xxh3 match the reply);SpillFailureFallsInlinepins the fallback; the existingIndexRequestnow also asserts a small index stays inline when a spill path is offered.index_spill.test.tsreproduces the manual validation deterministically —index_inline_limit: 1makes every background-index result spill; a cross-file reference proves the master verified and merged spilled bytes;transfer=filein the master log proves the file path actually ran; the tmp dir is empty after settling (PendingEntry cleanup end-to-end).npm run check.