Repository navigation
feat(sort): distribute spill files across multiple temp dirs - #284
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #284 +/- ##
==========================================
+ Coverage 90.02% 90.07% +0.04%
==========================================
Files 122 123 +1
Lines 61791 62144 +353
==========================================
+ Hits 55629 55974 +345
- Misses 6162 6170 +8 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
📝 WalkthroughWalkthroughAdds support for multiple temporary directories for sorting. 🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 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 |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/lib/sort/tmp_dir_alloc.rs`:
- Around line 60-68: The startup filtering in TmpDirAllocator::with_probe
currently hard-codes DEFAULT_MIN_FREE_BYTES when populating active, so calling
TmpDirAllocator::with_probe(...).with_min_free_bytes(0) can't re-include
directories; change with_probe to use a configurable threshold value (store
min_free_bytes on the TmpDirAllocator or accept it as a parameter) when deciding
which dirs to push into active, and/or defer the initial filtering (populate
with all dirs and apply the min_free_bytes filter later in with_min_free_bytes).
Specifically update the logic in with_probe that calls probe(&dir) and compares
to DEFAULT_MIN_FREE_BYTES so it references the allocator's min_free_bytes field
or the passed-in parameter, and ensure the duplicate code path at the other
occurrence (lines 94-99) is updated the same way.
- Around line 141-145: Removing an active dir can shift the rotation cursor and
break round-robin order: update the cursor in mark_full (and other pruning sites
around the same block) after removing at position pos by adjusting cursor =
(cursor - 1) if pos < cursor (or wrapping appropriately) and ensure cursor is
clamped modulo active.len() (or set to 0 when active becomes empty) so the next
allocation still returns the expected next element in the round-robin sequence;
locate the logic in the mark_full method and the other pruning functions that
remove from self.active and apply the same cursor rebase rule.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 31f05e46-deb6-46b0-a581-e5655b5c1e7e
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (5)
Cargo.tomlsrc/lib/commands/sort.rssrc/lib/sort/mod.rssrc/lib/sort/raw.rssrc/lib/sort/tmp_dir_alloc.rs
`fgumi sort -T/--tmp-dir` is now repeatable; pass more than one path to spread spill chunks across multiple filesystems in free-space-aware round-robin order. `FGUMI_TMP_DIRS` (PATH-style list) is honoured as a fallback when no `-T` flags are passed on the command line; CLI flags take precedence. A new `TmpDirAllocator` owns the rotation and a periodic free-space recheck (every 8 spills). Directories whose free space drops below 1 GiB are dropped from the rotation automatically; `mark_full()` is in place for future `ENOSPC` handling. The sort fails cleanly once all candidate directories are exhausted. With zero or one `-T` flag the behaviour is unchanged. The new `fs4` dependency (default-features off) provides a cross-platform `available_space` query on top of rustix. Known limitation: mid-write `ENOSPC` is not auto-recovered; the startup filter and periodic recheck catch most cases before a write begins.
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/lib/commands/sort.rs (1)
33-33:⚠️ Potential issue | 🟡 MinorUse
var_osto preserve non-UTF-8 temp-dir values.
std::env::varsilently ignoresFGUMI_TMP_DIRSwhen it contains non-UTF-8 bytes. Switch tovar_osand updateresolve_tmp_dirsto acceptOption<&OsStr>so Unix paths with non-UTF-8 sequences aren't lost.Proposed fix
+use std::ffi::OsStr; use std::path::PathBuf; @@ -pub(crate) fn resolve_tmp_dirs(cli: &[PathBuf], env_value: Option<&str>) -> Vec<PathBuf> { +pub(crate) fn resolve_tmp_dirs(cli: &[PathBuf], env_value: Option<&OsStr>) -> Vec<PathBuf> { if !cli.is_empty() { return cli.to_vec(); } let Some(value) = env_value else { return Vec::new() }; - if value.is_empty() { - return Vec::new(); - } std::env::split_paths(value) .filter(|p| !p.as_os_str().is_empty()) .filter(|p| !p.to_string_lossy().trim().is_empty()) .collect() } @@ - let env_value = std::env::var(TMP_DIRS_ENV).ok(); + let env_value = std::env::var_os(TMP_DIRS_ENV); let resolved_tmp_dirs = resolve_tmp_dirs(&self.tmp_dirs, env_value.as_deref());Update resolver tests to pass
Some(OsStr::new(env)).Also applies to: 335-348, 596-597
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/lib/commands/sort.rs` at line 33, The code currently uses std::env::var which drops FGUMI_TMP_DIRS values containing non-UTF-8 bytes; change calls to std::env::var to std::env::var_os and update the signature of resolve_tmp_dirs to accept Option<&OsStr> (instead of Option<&str> or String) so non-UTF-8 temp-dir values are preserved, then adapt all callers (including places referenced by resolve_tmp_dirs and the other similar spots around the sort logic) to pass the Option<&OsStr> returned by var_os; update the resolver tests to call resolve_tmp_dirs with Some(OsStr::new(env)) where needed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@src/lib/commands/sort.rs`:
- Line 33: The code currently uses std::env::var which drops FGUMI_TMP_DIRS
values containing non-UTF-8 bytes; change calls to std::env::var to
std::env::var_os and update the signature of resolve_tmp_dirs to accept
Option<&OsStr> (instead of Option<&str> or String) so non-UTF-8 temp-dir values
are preserved, then adapt all callers (including places referenced by
resolve_tmp_dirs and the other similar spots around the sort logic) to pass the
Option<&OsStr> returned by var_os; update the resolver tests to call
resolve_tmp_dirs with Some(OsStr::new(env)) where needed.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 9849cd64-e2f3-4f88-9a1d-f54d734bfe59
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (5)
Cargo.tomlsrc/lib/commands/sort.rssrc/lib/sort/mod.rssrc/lib/sort/raw.rssrc/lib/sort/tmp_dir_alloc.rs
✅ Files skipped from review due to trivial changes (2)
- Cargo.toml
- src/lib/sort/mod.rs
🚧 Files skipped from review as they are similar to previous changes (2)
- src/lib/sort/raw.rs
- src/lib/sort/tmp_dir_alloc.rs
Summary
fgumi sort -T/--tmp-diris now repeatable; pass more than one path to spread spill chunks across multiple filesystems in free-space-aware round-robin order.FGUMI_TMP_DIRS(PATH-style list) is honoured as a fallback when no-Tflags are passed on the command line. CLI flags take precedence.TmpDirAllocatorowns the rotation and re-checks free space every 8 spills; dirs below 1 GiB free are dropped from rotation automatically.-Tflag is unchanged.Usage
Design notes
sort_*fns are untouched.fgumi sortspills today, so the option lives insrc/lib/commands/sort.rsrather than inCompressionOptions-style shared common-options.Known limitation
Mid-write
ENOSPCis not auto-recovered — the startup filter and periodic recheck catch most cases before a write begins, but if a pooled spill writer hitsENOSPCmid-flight the sort fails with a clean error.TmpDirAllocator::mark_full()is wired and ready for a follow-up that intercepts the asyncPendingSpillerror path.New dependency
fs4 = "0.13"(default-features off) — cross-platformavailable_space()query. Pulls in rustix + libc + errno + bitflags only; no async runtime.Test plan
cargo ci-fmtcleancargo ci-lintcleancargo ci-testall green (2559/2559)TmpDirAllocatorunit tests (round-robin,mark_full, startup filter, periodic recheck, exhaustion), 4 env-var resolver tests, 1 rstest-parameterized clap parse test (4 cases), 1 e2e multi-tmpdir sort test (byte-equal to single-dir)fgumi sort --helprenders new-Tdoc andEXAMPLESentries cleanly