A cap that aborts cannot drain a backlog bigger than itself, so make it a per-run budget and let the queue clear over consecutive nights
This commit is contained in:
@@ -2734,6 +2734,54 @@ check_delete_size_threshold() {
|
||||
fi
|
||||
}
|
||||
|
||||
# Applies a per-run delete budget instead of refusing the whole run. Reads "<size>\t<ctime>\t<path>"
|
||||
# from $1, writes the paths that fit inside $3 GB to $2 (oldest ctime first), and reports what was
|
||||
# held back in _BUDGET_*.
|
||||
#
|
||||
# A cap that aborts cannot drain a backlog larger than itself. Every run re-finds the same lump,
|
||||
# exceeds the same ceiling and stops, so the queue is stuck permanently and only a human with
|
||||
# --i-know-what-im-doing can clear it. Observed 2026-08-24..26: a partnership merge restored ten
|
||||
# months of superseded Radarr files in one night, 126GB against a 100GB cap, and the daily
|
||||
# orchestrator then failed three nights running on a queue it could never drain. Budgeting keeps
|
||||
# the ceiling meaning exactly what it meant — no single run removes more than max_gb — while the
|
||||
# backlog clears over consecutive runs with nobody touching it.
|
||||
#
|
||||
# Strict oldest-first, stopping at the first file that does not fit rather than skipping it for a
|
||||
# smaller one further down. Skipping would drain more per run but lets a large file be passed over
|
||||
# indefinitely; stopping guarantees every deferred file is newer than everything already removed,
|
||||
# so nothing can starve.
|
||||
#
|
||||
# One case is deliberately left for a human: a single file larger than the entire budget can never
|
||||
# fit, so _BUDGET_STUCK is set and the caller says so rather than looping forever on it.
|
||||
apply_delete_budget() {
|
||||
local src="$1" dst="$2" max_gb="$3"
|
||||
local max_bytes tab
|
||||
tab=$(printf '\t')
|
||||
max_bytes=$(awk "BEGIN {printf \"%d\", $max_gb * 1073741824}")
|
||||
|
||||
_BUDGET_KEPT_BYTES=0; _BUDGET_KEPT_COUNT=0
|
||||
_BUDGET_DEFERRED_BYTES=0; _BUDGET_DEFERRED_COUNT=0
|
||||
_BUDGET_STUCK=""
|
||||
|
||||
: > "$dst"
|
||||
[[ -s "$src" ]] || return 0
|
||||
|
||||
local out
|
||||
out=$(sort -t"$tab" -k2,2n "$src" | awk -F'\t' -v max="$max_bytes" -v dst="$dst" '
|
||||
{
|
||||
if (stop) { defb += $1; defc++; next }
|
||||
if (used + $1 > max) { stop = 1
|
||||
if (kept == 0) stuck = $3
|
||||
defb += $1; defc++; next }
|
||||
used += $1; kept++
|
||||
print $3 > dst
|
||||
}
|
||||
END { printf "%d\t%d\t%d\t%d\t%s", used+0, kept+0, defb+0, defc+0, stuck }
|
||||
')
|
||||
IFS=$'\t' read -r _BUDGET_KEPT_BYTES _BUDGET_KEPT_COUNT \
|
||||
_BUDGET_DEFERRED_BYTES _BUDGET_DEFERRED_COUNT _BUDGET_STUCK <<< "$out"
|
||||
}
|
||||
|
||||
# True if filepath's extension (case-insensitive) matches one of the given extensions.
|
||||
# Usage: has_extension "$filepath" "${LIDARR_EXTENSIONS[@]}"
|
||||
has_extension() {
|
||||
|
||||
Reference in New Issue
Block a user