Skip to content

Relink dry run: take present paths from the inventory already in memory - #646

Merged
coaxk merged 1 commit into
mainfrom
perf/relink-stale-from-inventory
Oct 31, 2026
Merged

coaxk merged 1 commit into
mainfrom
perf/relink-stale-from-inventory

Conversation

@coaxk

@coaxk coaxk commented Oct 31, 2026

Copy link
Copy Markdown
Owner

Stacked on #645. Retarget to main after #645 merges.

What

The relink dry run no longer stats a known path that an inventory already in memory lists as present. Every other path is still checked, so the inventory can only make a row look present, never missing. Apply (use_no_rules_cache=False) still checks every path.

Why

Measured on the maintainer's install, inside the container: 6,374 known paths on a CIFS share. canonical_to_fs (realpath, which lstats each component) plus exists() took 5.5 s of an 8.0 s dry run, even when the walk came from the #641 cache. The orphans GET pays the same ~5.75 s, but that path deletes data and keeps checking files on disk.

Expected: only the paths the inventory lacks are stat'd (about 1,980 of 6,374 on that install), so roughly 8 s → 2.5 s. This is a projection; measure after deploy.

How

  • relink.peek_inventory(): the newest inventory in memory for the current library key, either the walk cache (INVENTORY_TTL_S, 300 s) or the remembered no-rules answer (NO_RULES_TTL_S), each inside its own TTL. Never walks.
  • _relink_analysis skips the stat for listed paths only when use_no_rules_cache is set.

Trade-off

A file deleted since that walk reads as present until the inventory ages out. This is the same blind spot the #641 cache already accepts, and it is in the safe direction: a stale row is kept, nothing is deleted.

Tests

tests/test_relink_stale_inventory.py (12; 8 red before the change). Covers: no inventory means a full stat; a second dry run stats only unlisted paths, with identical results; a file appearing after the walk is stat'd and is not stale; a file deleted after the walk reads present, then stale once the TTL passes; the no-rules inventory is used after the walk cache expires; apply stats everything; an unresolvable path is stat'd and counts present; peek_inventory returns None when empty, never walks, prefers the newer walk, ignores another library config and ignores an expired entry. All 184 relink and orphan tests pass locally.

🤖 Generated with Claude Code

https://claude.ai/code/session_01ShzWm3urD55AUk5yrSgXsi

Base automatically changed from feat/relink-unoffered-groups to main October 31, 2026 04:22
Every dry run checked every known path with a realpath plus a stat, even when
the walk came from the #641 cache: 5.5 s of an 8.0 s dry run for 6,374 paths
on a CIFS share. A path listed by an in-memory inventory (walk cache, or the
remembered no-rules answer, each inside its TTL) is now present without a
stat; every other path is still checked, so the inventory can only make a row
look present, never missing. Apply keeps checking every path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ShzWm3urD55AUk5yrSgXsi
@coaxk
coaxk force-pushed the perf/relink-stale-from-inventory branch from 27df184 to 8928d33 Compare October 31, 2026 04:23
@coaxk
coaxk merged commit bb9c7c0 into main Oct 31, 2026
19 checks passed
@coaxk
coaxk deleted the perf/relink-stale-from-inventory branch October 31, 2026 04:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant