Skip to content

cache: unify record/energy-WAL/users-CSV paths via platform-aware dirs::cache_dir() (Scope B from #223) #229

Description

@inureyes

Background

Follow-up tracking issue for Scope B of #223, intentionally deferred when #227 landed Scope A (the doc/resolution-consistency fix for all-smi record's default output path). #227 deliberately left the cache-path code untouched so this platform-aware work could be decided and shipped on its own — it relocates files on macOS and Windows and needs a migration/changelog note.

Decision (from review on this issue): adopt B1 — resolve every cache path (record output, energy WAL, users CSV) through a single platform-aware helper built on dirs::cache_dir(), and retire the hard-coded ~/.cache/... strings. Rationale below.

Why B1 (it's more than "platform correctness")

A code audit shows the cache base is currently resolved three different ways, so the locations already diverge per platform today:

Consumer Source Linux ($XDG_CACHE_HOME set) macOS Windows
users CSV export cache_dir_for_all_smi()src/view/event_handler.rs:671 $XDG_CACHE_HOME/all-smi ~/.cache/all-smi %LOCALAPPDATA%\all-smi\cache
record output (default) record.output_dir = "~/.cache/all-smi/records"src/common/config_file.rs:256 ~/.cache/all-smi/records (ignores $XDG_CACHE_HOME) ~/.cache/all-smi/records …\.cache\all-smi\records (Unix-style dotdir in the profile)
energy WAL wal_path = "~/.cache/all-smi/energy-wal.bin"src/common/config.rs:197 ~/.cache/all-smi/energy-wal.bin (ignores $XDG_CACHE_HOME) ~/.cache/all-smi/energy-wal.bin …\.cache\all-smi\energy-wal.bin (dotdir)
  • Windows is already split: the users CSV lands under %LOCALAPPDATA%\all-smi\cache, but record output and the energy WAL land in a Unix-style .cache dotdir inside the user profile.
  • Linux is split when $XDG_CACHE_HOME is set: the users CSV honors it; record output and the WAL ignore it.
  • macOS puts all three under ~/.cache/... (none use the Apple-correct ~/Library/Caches/...).
  • cache_dir_for_all_smi() is a hand-rolled reimplementation of dirs::cache_dir(), with a comment that it avoids pulling in the dirs crate "for a single lookup." That rationale no longer holds: dirs is already a direct dependency (used by src/common/paths.rs for config_dir()/home_dir()), and there are now three lookups, not one.
  • The config path is already platform-aware via dirs::config_dir() (src/common/paths.rs:95), so the cache path being hard-coded is an internal inconsistency.

B1 collapses these three paths into one helper, deletes cache_dir_for_all_smi(), and aligns the cache layer with the config layer.

Target layout

Resolve a single cache root via dirs::cache_dir().join("all-smi"):

Platform dirs::cache_dir() all-smi cache root
Linux $XDG_CACHE_HOME or ~/.cache …/all-smi
macOS ~/Library/Caches ~/Library/Caches/all-smi
Windows %LOCALAPPDATA% %LOCALAPPDATA%\all-smi

Then: record output → <cache-root>/records/, energy WAL → <cache-root>/energy-wal.bin, users CSV → <cache-root>/users-<ts>.csv.

Recordings also live under cache_dir() (decided)

dirs::cache_dir() maps to OS-purgeable locations (macOS may reclaim ~/Library/Caches under storage pressure; cleanup tools target cache dirs). The energy WAL (crash-recovery scratch) and users CSV (on-demand export) are unambiguously cache-like.

record outputs are user-created artifacts, so dirs::data_local_dir() was considered for them specifically. Decision: keep all three — record output included — under dirs::cache_dir(). The default output path is a convenience fallback; operators who want durability already pass -o <path>, and a single cache root keeps the resolver and the docs simple and consistent. (data_dir() was explicitly rejected: on Windows it is Roaming %APPDATA%, which would sync potentially-large recordings across machines.)

Migration

  • Linux without $XDG_CACHE_HOME (the common case): dirs::cache_dir() == ~/.cache, so nothing moves — no migration needed.
  • macOS, Windows, and Linux with $XDG_CACHE_HOME set: the cache root relocates. The affected data is low-stakes — recordings remain replayable via an explicit view --replay <path>, the WAL is recoverable scratch, and the users CSV is an on-demand export whose path is printed to the user.
  • Ship a release/changelog note documenting the new per-platform locations, plus an optional one-time best-effort migration that moves an existing ~/.cache/all-smi/{records,energy-wal.bin} to the new root only when the new root is empty (never overwrite).

Implementation notes

  • Add a cache_dir() helper in src/common/paths.rs mirroring the existing config_dir(): dirs::cache_dir().map(|d| d.join(APP_DIR_NAME)).
  • Route all three consumers through it; delete the hand-rolled cache_dir_for_all_smi() in src/view/event_handler.rs (≈ lines 667–695) and its bespoke XDG_CACHE_HOME/LOCALAPPDATA/HOME probing.
  • Reconcile the Windows users-CSV subpath: today it is %LOCALAPPDATA%\all-smi\cache; under the shared helper it becomes %LOCALAPPDATA%\all-smi.
  • Keep expand_tilde for user-supplied values only (explicit -o <path>, and config-file record.output_dir / energy wal_path overrides); the compiled default should come from the platform helper, not a ~/.cache/... string literal.
  • Update the defaults in src/common/config_file.rs (output_dir) and src/common/config.rs (wal_path) so they derive from the helper rather than hard-coded ~/.cache/... literals.
  • Preserve the existing symlink / O_NOFOLLOW / 0o600 defenses around the users-CSV and any new cache writes.

Affected files

  • src/common/paths.rs — new cache_dir() helper.
  • src/common/config_file.rsrecord.output_dir default.
  • src/common/config.rs — energy wal_path default.
  • src/view/event_handler.rs — delete cache_dir_for_all_smi(), use the helper.
  • src/metrics/energy_wal.rs — consume the resolved WAL path (no hard-coded literal).
  • Docs: src/cli.rs (--output long_help, ALL_SMI_ENERGY_WAL_PATH text), README.md, docs/man/all-smi.1 if applicable.

Acceptance criteria

  • A single platform-aware cache_dir() helper exists in src/common/paths.rs (built on dirs::cache_dir()), mirroring config_dir().
  • record output, energy WAL, and users CSV all default under <cache_dir()>/all-smi/... through that one helper; cache_dir_for_all_smi() is removed and records are not split out to data_local_dir.
  • Hard-coded ~/.cache/all-smi/... default literals are gone from config_file.rs and config.rs; expand_tilde is used only for user-supplied overrides.
  • A one-time best-effort migration (or an explicit decision not to migrate) is implemented, with a changelog/release note describing the new per-platform locations.
  • --help, source docs, README, and the manpage agree on the new defaults.
  • Existing symlink / O_NOFOLLOW / 0o600 write protections are preserved.

References

Metadata

Metadata

Assignees

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions