Skip to content

Commit 30963d5

Browse files
authored
feat: Progress Update on non-interactive runs (#1395) (#1620)
# Progress Update on non-interactive runs (#1395) `feat(cli): add periodic logging for progress in non-interactive terminals` ## PR Description ### Fixes #1395 ### Problem When running `rustic` in headless environments (systemd), the progress bar is hidden, resulting in zero output for long-running operations. This makes it impossible to distinguish between a hang and a working backup. ### Solution This PR modifies `ProgressBars` to detect if `stderr` is a TTY. * **Interactive:** Retains the existing `indicatif` animated progress bars. * **Non-Interactive:** Switches to a `PeriodicLog` mode that prints a plain text status update to stderr at a fixed interval (user-provided, otherwise default to **10s**. ### Changes * Added `PeriodicLog` variant to `ProgressType` enum. * Implemented `IsTerminal` check in `progress_bytes`. * Added logic in `inc()` to check the elapsed time and print a log line if the interval has passed. * **Default Behavior:** If no `--progress-interval` is provided, non-interactive mode defaults to **10s** to avoid flooding logs (unlike the 100ms default for TTYs). ### Testing * Verified interactive mode still renders progress bars correctly. * Verified piped mode (`cargo run ... 2>&1 | cat`) produces heartbeat logs: ``` [INFO] starting to backup /private/tmp/rustic-demo/data ... [INFO] backing up...: 854.0 MiB [INFO] backing up...: 1.7 GiB ... ``` ### Foods for thought **How `set_length` works in rustic_core** During backup operations: rustic_core intentionally runs the size calculation in a **parallel thread** to avoid blocking the actual backup process: This means: inc() is called before `set_length()` during early progress updates. `set_length()` is called later once the size scan completes. self.0.length() returns `None` until `set_length()` is called **Current Fix (Graceful handling)**: Handle the case where length isn't known yet by checking if let Some(len) = self.0.length() instead of using unwrap_or(0), and display progress without total when unknown. ```rs if let Some(len) = self.0.length() { eprintln!("[INFO] {}: {} / {}", prefix, ByteSize(pos), ByteSize(len)); } else { eprintln!("[INFO] {}: {}", prefix, ByteSize(pos)); } ``` **What needs to be tested**: Given my machine's HW limits (tested backup on 5GB), I haven't been able to run backup on files large enough for `set_length` to be called. Can **someone test on a very large backup task** to see if `set_length` is run and the total size is printed correctly?
1 parent b79206f commit 30963d5

File tree

1 file changed

+287
-82
lines changed

1 file changed

+287
-82
lines changed

0 commit comments

Comments
 (0)