Skip to content

Warn when a replayed hashfile config has no -d (timer that never dedupes) #149

Description

@martinus

What problem would this solve?

A [email protected] job can run every week forever, exit 0 every time, and never deduplicate anything — because the run that seeded its hashfile was missing -d.

The self-describing hashfile stores -d as opt_run_dedupe (src/dbfile.c:1161, replayed at :1249), so a bare oans --hashfile=FILE correctly replays whatever the seeding run did. That's working as designed. But it also means the seeding run's -d is load-bearing for every future scheduled run, and the setup flow makes it easy to get wrong: docs/nas-quickstart.md and systemd/README.md walk the user through a first run to establish the hashfile, then systemctl enable --now [email protected]. If that first run was a deliberate read-only preview — which the man page actively encourages, "Without -d, oans reads, hashes, and prints the duplicate extents it found — useful for previewing what a dedupe run would do" — then the timer inherits run_dedupe = 0.

The resulting job is indistinguishable from a healthy one: it walks the tree, updates hashes, records a run in run_history, exits 0, and reclaims nothing. --history shows a growing list of runs with 0 B reclaimed, which also looks exactly like a healthy job on an already-deduped tree.

This is not a bug in the replay mechanism — it's a missing guard rail on a footgun the docs lead users toward.

Proposed solution

Warn when a replayed configuration is a no-op, at the point where it's replayed.

In apply_scan_config() (src/oans.c), when the run is a replay (no file arguments given) and the loaded sc->run_dedupe is 0:

WARNING: the stored configuration for /var/cache/oans/media.hash has no -d,
         so this run will hash but not deduplicate.
         Re-run once with -d and the paths to update it:
           oans -rd --hashfile=/var/cache/oans/media.hash /srv/media

The message should print the concrete fix-up command, including the stored roots, since the whole point of a replay is that the user no longer remembers the arguments.

Complementary, cheaper documentation fixes worth doing regardless:

  • docs/nas-quickstart.md and systemd/README.md: state explicitly that the seeding run must include -d, and that a preview run without it will be the thing that gets replayed.
  • systemd/[email protected]: the comment above ExecStart explains that the hashfile is self-describing but doesn't warn that -d-ness comes from the seeding run. One added line.

Considered and rejected: having the systemd unit pass -d explicitly. It would fix this case but break the replay contract in a worse way — the unit would then silently override a user who deliberately configured a hash-only job, and -d on the command line would diverge from what the hashfile says it does. The warning keeps one source of truth.

Related: if #145 lands, a replayed no-op run is also a natural thing to reflect in --json (e.g. surfacing run_dedupe in the metrics), so a monitoring dashboard can show that a job is configured read-only rather than merely finding nothing.

Alternatives considered

  • Documentation only. Helps the next user, does nothing for the person whose timer has been idling since they set it up. The warning is what reaches them.
  • Refuse to run a replay without -d. Too strong: a hash-only scheduled job is a legitimate configuration (keeping a hashfile warm so a later -d run is fast), and failing it would break working setups.
  • Warn only when run_history shows N runs with 0 reclaimed. More targeted in principle, but "0 reclaimed" is also what a correctly-working job on a clean tree looks like, so it would cry wolf. The run_dedupe flag is the unambiguous signal.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions