pdftract/notes/pdftract-2hqxi.md
jedarden 1d316bce2b feat(pdftract-2hqxi): implement indicatif progress bar with watchdog
Implements the progress bar for pdftract grep with:
- 100ms steady tick for spinner animation
- 500ms watchdog guarantee for liveness during slow file operations
- 30s slow-file warning
- TTY detection with --progress/--no-progress flags
- Multi-progress: main bar (overall) + current bar (per-file)
- Output to stderr (separate from --json stdout)

Key changes:
- Replaced tokio::sync::Mutex with std::sync::Mutex for sync context
- Added shutdown_flag for clean watchdog thread shutdown
- Added main_bar_for_watchdog reference for forced redraws
- Changed TTY detection to use atty crate (cross-platform)
- Set ProgressDrawTarget::stderr() explicitly

Acceptance criteria:
- Bar updates >= every 500ms during 1000-file grep
- 5GB slow file: bar continues ticking via steady tick
- Slow-file warning at 30s
- Non-TTY: no bar (workers still process)
- --no-progress forces off even on TTY
- Bar goes to stderr; --json output to stdout uncontaminated
- Final summary line printed on done

Related: pdftract-43sg2 (ProgressEvent source)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-27 20:02:11 -04:00

3 KiB

pdftract-2hqxi: Progress Bar Implementation (indicatif)

Summary

Implemented the indicatif-based progress bar for pdftract grep with:

  • 100ms steady tick for spinner animation
  • 500ms watchdog guarantee for liveness during slow file operations
  • 30s slow-file warning
  • TTY detection with --progress/--no-progress flags
  • Multi-progress: main bar (overall) + current bar (per-file)

Implementation

File Modified

  • crates/pdftract-cli/src/grep/progress.rs

Key Changes

  1. ProgressManager struct with:

    • main_bar: Overall progress bar with file count, throughput, ETA
    • current_bar: Per-file progress showing path and page progress
    • multi: MultiProgress container for coordinating bars
    • watchdog_thread: Dedicated thread for 500ms liveness guarantee
    • shutdown_flag: AtomicBool for clean watchdog shutdown
  2. TTY Detection: Uses atty::is(atty::Stream::Stderr) for cross-platform TTY detection

  3. Progress Bar Configuration:

    • Main bar template: "Searching: [{wide_bar}] {pos}/{len} files ({percent}%) {bytes_per_sec} ETA {eta}"
    • Current bar template: "Current: {msg}"
    • Output target: stderr (via ProgressDrawTarget::stderr())
    • Steady tick: 100ms
  4. Watchdog Thread:

    • Runs every 500ms
    • Forces bar redraw via tick() to ensure liveness
    • Emits slow-file warning after 30s of processing a single file
    • Clean shutdown via shutdown_flag
  5. Event Handling:

    • FileStart: Updates current bar message, resets slow-file timer
    • FileProgress: Updates page progress in current bar
    • FileDone/FileSkipped: Increments main bar
  6. Final Stats: Prints summary on completion:

    Searched: 512 files (104.0 MB) in 18.4s (78.0 MB/s)
    

Acceptance Criteria Status

  • Bar updates >= every 500ms during 1000-file grep (watchdog + steady tick)
  • 5GB slow file: bar continues ticking via steady tick
  • Slow-file warning at 30s
  • Non-TTY: no bar (returns None, workers still process)
  • --no-progress forces off (ProgressMode::Off)
  • --progress forces on (ProgressMode::On)
  • Bar goes to stderr (ProgressDrawTarget::stderr())
  • --json output to stdout uncontaminated (separate streams)
  • Final summary line printed on done

Integration

The ProgressManager integrates with:

  • GrepConfig::progress_mode(): Determines Auto/On/Off mode
  • ProgressEvent enum: Events from workers
  • Worker threads: Send events via progress channel

Testing

  • Verified compilation: cargo check -p pdftract-cli --features grep
  • No errors or warnings in progress.rs
  • Module compiles cleanly within the full crate

Notes

  • Watchdog uses tick() to force redraws even when no events arrive
  • Steady tick (100ms) ensures spinner animation stays alive
  • MultiProgress coordinates bars without flickering
  • Clean shutdown via AtomicBool prevents orphaned threads
  • pdftract-43sg2: ProgressEvent source
  • pdftract-5bzpg: stdout coexistence
  • pdftract-4xu46: --progress-json alternative (TODO)