Files
Varaverk/Arrs_Stack/arr_cache_prefill.sh
T
Gmer4Lfe 254b400caf Add missing RUNTIME MODES section, document --log
arr_cache_prefill.sh had no RUNTIME MODES section at all; arr_full_rescan.sh
had one but didn't mention --log despite supporting it via parse_args.
Comment-only.
2026-07-17 01:29:06 -04:00

160 lines
7.6 KiB
Bash
Executable File

#!/bin/bash
# ==============================================================================================
# ================================= Arr Cache Prefill ===========================================
# ==============================================================================================
#
# PURPOSE
# ─────────────────────────────────────────────────────────────────────────────
# Populates the shared tracked-data cache (see arr_get_tracked_data() in common.sh) for
# Lidarr, Sonarr, and Radarr. Without this, each arr's cache stays cold until whichever
# script happens to touch that arr first writes through — which could be hours, depending
# on the daily schedule. Originally Lidarr-only (lidarr_cache_prefill.sh, 2026-07-16),
# generalized the same day to cover all three arrs once the cache mechanism itself was
# generalized.
#
# Runs on two schedules (2026-07-17): once at array start (closes the cold-boot gap, 10min
# wait ceiling for slow-starting containers) and again every 30min via
# CRITICAL_MAINTENANCE_SCRIPTS with a 1min wait ceiling (ARR_PREFILL_WAIT_MINUTES=1 override)
# — a live fetch+write takes seconds, so there's no reason to tolerate the boot-time wait on
# a recurring job. This is what keeps the cache-first consumers' data reliably under 30min
# old instead of only refreshing whenever some other script happens to write through.
#
# ==============================================================================================
# OPERATIONAL MODEL
# ==============================================================================================
#
# Each arr's container may still be starting when this fires (array just started) — retries
# reaching that arr's API for up to ARR_PREFILL_WAIT_MINUTES before giving up on it and moving
# to the next. Not fatal if one never comes up in time; that arr's cache just stays cold until
# the next script writes through naturally, exactly as it would without this script existing.
# An arr not configured on this host (e.g. Lidarr is HOST1-only) is skipped cleanly.
#
# ==============================================================================================
# OPERATIONAL SAFEGUARDS
# ==============================================================================================
#
# Root required — chown-free here, but matches convention across Arrs_Stack/
# jq required — skips the whole run cleanly (not fatal) if jq is missing
# acquire_lock — prevents two invocations of this script overlapping (default strict
# mode) — matters if the boot-time run is still waiting on a slow
# container when the first 30min critical-tier tick fires
# Reachability retry — tolerates a slow-starting container up to ARR_PREFILL_WAIT_MINUTES;
# never fatal if one never comes up, that arr's cache just stays cold
# Active-rescan check — skips an arr this cycle if a rescan-type command is running, instead
# of a live fetch arr_cache_write() would refuse to persist anyway
# (2026-07-17) — avoids wasted API calls during a long rescan
# Per-arr isolation — one arr failing or timing out never blocks or fails the others
#
# ==============================================================================================
# CONFIGURATION
# ==============================================================================================
#
# host*.conf
# HOST1_LIDARR_URL / HOST1_LIDARR_API_KEY
# HOST*_SONARR_URL / HOST*_SONARR_API_KEY
# HOST*_RADARR_URL / HOST*_RADARR_API_KEY
# All aliased by detect_hosts()
#
# master.conf
# ARR_PREFILL_WAIT_MINUTES — how long to retry reaching each arr before giving up on it
# (default 10). The CRITICAL_MAINTENANCE_SCRIPTS entry overrides this to 1 via parse_args'
# VAR=VAL mechanism for the 30min recurring run — the 10min default is sized for cold boot,
# not a job that fires every half hour.
#
# ==============================================================================================
# RUNTIME MODES
# ==============================================================================================
#
# arr_cache_prefill.sh
# Normal run — populates all three arr caches, or skips cleanly per-arr as described
# under OPERATIONAL SAFEGUARDS above. No --dry-run/--status mode: this script only ever
# reads and writes cache, there's no destructive action to preview and no separate state
# worth inspecting beyond the cache files themselves (see Tools/arr_rescan_monitor.sh
# --status for cache age/active-rescan inspection).
#
# arr_cache_prefill.sh --log
# Verbose — per-arr detail as each one is checked/fetched/skipped.
#
# arr_cache_prefill.sh ARR_PREFILL_WAIT_MINUTES=1
# Override the reachability-retry ceiling for this run only (parse_args VAR=VAL
# mechanism) — this is how CRITICAL_MAINTENANCE_SCRIPTS invokes it every 30min.
#
# ==============================================================================================
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/../load_config.sh"
parse_args "$@"
if [[ "$EUID" -ne 0 ]]; then
error "Must be run as root"
exit 1
fi
if ! command -v jq >/dev/null 2>&1; then
warn "jq not found — skipping arr cache prefill"
exit 0
fi
acquire_lock
detect_hosts
WAIT_MINUTES="${ARR_PREFILL_WAIT_MINUTES:-10}"
# Args: arr_type, url, api_key, api_version
_prefill_one() {
local arr_type="$1" url="$2" api_key="$3" api_version="$4"
if [[ -z "$url" ]] || [[ -z "$api_key" ]]; then
info "${arr_type^} not configured on $MY_ID ($LOCAL_SERVER_NAME) — nothing to prefill"
return 0
fi
local waited=0
until check_api "$url" "${arr_type^}" 5 >/dev/null 2>&1; do
if [[ "$waited" -ge $(( WAIT_MINUTES * 60 )) ]]; then
warn "${arr_type^} not reachable after ${WAIT_MINUTES}m — leaving cache cold, next script will write through"
return 0
fi
sleep 15
(( waited += 15 ))
done
# Skip cleanly if a rescan-type command is already active — arr_cache_write() below
# would refuse to persist a mid-rescan snapshot anyway (2026-07-17 guard), so fetching
# it live first would just be a wasted API call every time this fires during a long
# rescan. Matches the same check arr_full_rescan.sh and the cleanup scripts already do.
local active_cmd
active_cmd=$(arr_active_rescan_command "$arr_type" "$url" "$api_key" "$api_version")
if [[ -n "$active_cmd" ]]; then
info "${arr_type^} mid-rescan ($active_cmd) — skipping this cycle, cache stays as-is"
return 0
fi
local endpoint="${ARR_LIBRARY_ENDPOINT[$arr_type]:-}"
if [[ -z "$endpoint" ]]; then
warn "No library endpoint known for ${arr_type} — skipping"
return 0
fi
local items
items=$(arr_api "$url" "$api_key" "$api_version" "$endpoint" "${arr_type^}") || {
warn "Could not fetch ${arr_type} library for cache prefill — leaving cache cold"
return 0
}
if arr_cache_write "$arr_type" "$items"; then
log "$ICON_DONE ${arr_type^} cache prefilled ($(echo "$items" | jq 'length') items)"
else
warn "Failed to write ${arr_type} cache prefill"
fi
}
_prefill_one "lidarr" "${LIDARR_URL:-}" "${LIDARR_API_KEY:-}" "v1"
_prefill_one "sonarr" "${SONARR_URL:-}" "${SONARR_API_KEY:-}" "v3"
_prefill_one "radarr" "${RADARR_URL:-}" "${RADARR_API_KEY:-}" "v3"
exit 0