tracking: one ledger, one authority — prune protection and replace-vs-add answered from the same records, fail-safe on unreadable state

This commit is contained in:
2026-07-30 19:44:11 -04:00
parent 7bd911d58b
commit 7f70d94228
40 changed files with 1546 additions and 633 deletions
+20 -5
View File
@@ -147,16 +147,31 @@ std::vector<std::string> usageHeldPaths(
const std::unordered_set<std::string>& liveTrackGuids,
bool anyInstanceLive);
// The prune-side entry fold over raw read/decode results, one element per
// enumerated rsusage_* key: nullopt = present but unreadable/undecodable. ANY
// nullopt sets abortPrune (halt, delete nothing); otherwise delegates to
// usageHeldPaths (including its protect-all net).
// One enumerated rsusage_* key and what came back from it: nullopt = present but
// unreadable/undecodable.
struct DecodedUsage {
std::string key; // "rsusage_<guid>"
std::optional<UsageRecord> record;
};
// A record that counted toward heldPaths, still attributed to its key. Lets a
// consumer ask "who holds this path" — the flattened path list cannot.
struct CountedUsage {
std::string key;
UsageRecord record;
};
// The prune-side entry fold. ANY unreadable record sets abortPrune (halt, delete
// nothing) and names its key; otherwise delegates to usageHeldPaths (including its
// protect-all net) and reports which records counted.
struct UsageFoldResult {
bool abortPrune = false;
std::vector<std::string> offendingKeys; // non-empty iff abortPrune
std::vector<std::string> heldPaths;
std::vector<CountedUsage> counted; // empty on abort
};
UsageFoldResult foldUsageRecords(
const std::vector<std::optional<UsageRecord>>& decoded,
const std::vector<DecodedUsage>& decoded,
const std::unordered_set<std::string>& liveTrackGuids,
bool anyInstanceLive);