feat: slskd reconnect guard in downloaders_reset, mass v2 sync
- downloaders_reset: connection check block before slskd API sections; triggers PUT /api/v0/server reconnect if disconnected, polls 60s, gates Stuck Searches and Dead Transfer Records on SLSKD_CONNECTED - Sync all modified/new/deleted files from v2 refactor across Docker_Essentials, Media, Monitors, Partnership, Rsync, Tools, Transcodes, unRAID_Essentials, common.sh, master confs, and new Manual/README docs
This commit is contained in:
+92
-54
@@ -1,78 +1,116 @@
|
||||
#!/bin/bash
|
||||
# ==============================================================================================
|
||||
# ================================= ARR SYNC ===================================================
|
||||
# ================================= ARR Sync ===================================================
|
||||
# ==============================================================================================
|
||||
# Bidirectional arr library sync across all nodes in the ecosystem.
|
||||
# Syncs Lidarr, Sonarr, and Radarr libraries so every node tracks the same content.
|
||||
# Run before rsync — once arrs agree on library, rsync spreads the files.
|
||||
#
|
||||
# ── DESIGN ────────────────────────────────────────────────────────────────────────────────────
|
||||
# Full mesh: every node syncs with every other node — no primary, no hierarchy.
|
||||
# PURPOSE
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# Full-mesh arr library sync across all nodes — Lidarr, Sonarr, and Radarr.
|
||||
# Every node syncs with every other, union model, no hierarchy. Run before
|
||||
# rsync in the weekly sync window: once arrs agree on what to track, rsync
|
||||
# spreads the actual files.
|
||||
#
|
||||
# ==============================================================================================
|
||||
# OPERATIONAL MODEL
|
||||
# ==============================================================================================
|
||||
#
|
||||
# Full mesh: every node syncs with every other — no primary, no hierarchy.
|
||||
# Union model: if any node tracks an item, all nodes get it (unless blocklisted).
|
||||
# Convergence: any node can add content; after one full cycle all nodes agree.
|
||||
# Upgrade-aware: server1 upgrades a file → arr tracks new path → rsync spreads it →
|
||||
# arr_cleanup removes old file on all nodes because arr no longer tracks it.
|
||||
# Upgrade-aware: a file upgrade on one node → arr tracks new path → rsync spreads
|
||||
# it → arr_cleanup removes old path on all nodes (arr no longer tracks it).
|
||||
#
|
||||
# ── NODE DISCOVERY ────────────────────────────────────────────────────────────────────────────
|
||||
# Reads HOST* vars from master.conf. Add HOST3= and it joins the sync automatically.
|
||||
# No scripts change when adding a new node.
|
||||
# Node discovery: reads HOST* vars from master.conf. Add HOST3= and it joins the
|
||||
# sync automatically — no script changes needed for a new node.
|
||||
#
|
||||
# ── REMOTE API KEY ACCESS ─────────────────────────────────────────────────────────────────────
|
||||
# Remote API keys are not stored anywhere. Script SSHes to each remote node and reads
|
||||
# the key directly from that arr's config.xml in its appdata directory.
|
||||
# Only the API response (JSON) is returned — key never leaves the remote node.
|
||||
# Self-maintaining: remote key regeneration is picked up automatically.
|
||||
# Graceful skip: arr not configured locally → skip cleanly. Arr not reachable on
|
||||
# a remote → skip that node for that arr type, continue with others.
|
||||
#
|
||||
# ── BLOCKLIST ─────────────────────────────────────────────────────────────────────────────────
|
||||
# ARR_SYNC_BLOCKLIST in DATA_DIR tombstones IDs that must never be re-added anywhere.
|
||||
# Read from ALL nodes via SSH at start of each run — immediate effect across all nodes.
|
||||
# (Each node reads every other node's blocklist file via SSH — no rsync delay.)
|
||||
# Manage via --blocklist-add / --blocklist-remove / --blocklist-list.
|
||||
#
|
||||
# --blocklist-add does three things atomically:
|
||||
# 1. Writes the TSV tombstone entry (prevents future re-adds by arr_sync)
|
||||
# 2. Deletes the item from the local arr API (deleteFiles=false)
|
||||
# 3. SSHes each remote node and deletes from their arr API (deleteFiles=false)
|
||||
# Files become orphans on all nodes — arr_cleanup.sh removes them on next run.
|
||||
#
|
||||
# ── GRACEFUL SKIP ─────────────────────────────────────────────────────────────────────────────
|
||||
# Arr not configured locally → skip cleanly, no error.
|
||||
# Arr not reachable on a remote → skip that node for that arr type, continue with others.
|
||||
# Partial mesh works — nodes that share an arr type sync with each other.
|
||||
#
|
||||
# ── WHAT GETS SYNCED ──────────────────────────────────────────────────────────────────────────
|
||||
# Library items (tracked artists/series/movies) keyed on stable IDs:
|
||||
# What gets synced — library items keyed on stable external IDs:
|
||||
# Lidarr — MusicBrainz artist ID (foreignArtistId)
|
||||
# Sonarr — TVDB series ID (tvdbId)
|
||||
# Radarr — TMDB movie ID (tmdbId)
|
||||
# When adding to a remote node, that node's own quality profile, metadata profile,
|
||||
# and root folder path are used — settings are never copied from the source node.
|
||||
# When adding to a remote, that node's own quality profile, metadata profile,
|
||||
# and root folder path are used — settings are never copied from source.
|
||||
#
|
||||
# ==============================================================================================
|
||||
# DESIGN PRINCIPLES
|
||||
# ==============================================================================================
|
||||
#
|
||||
# Remote API Keys Never Stored
|
||||
# SSHes to each remote node and reads the key directly from that arr's
|
||||
# config.xml in its appdata directory. Only the API response (JSON) is
|
||||
# returned — the key never leaves the remote node. Self-maintaining: key
|
||||
# regeneration on the remote is picked up automatically next run.
|
||||
#
|
||||
# Blocklist TSV
|
||||
# ARR_SYNC_BLOCKLIST in DATA_DIR tombstones IDs that must never be re-added
|
||||
# anywhere. Read from ALL nodes via SSH at run start — immediate effect with
|
||||
# no rsync delay.
|
||||
#
|
||||
# --blocklist-add does three things atomically:
|
||||
# 1. Writes the TSV tombstone entry (prevents future re-adds by arr_sync)
|
||||
# 2. Deletes the item from the local arr API (deleteFiles=false)
|
||||
# 3. SSHes each remote node and deletes from their arr API (deleteFiles=false)
|
||||
# Files become orphans on all nodes — arr_cleanup removes them on next run.
|
||||
#
|
||||
# ==============================================================================================
|
||||
# OPERATIONAL SAFEGUARDS
|
||||
# ==============================================================================================
|
||||
#
|
||||
# acquire_lock — prevents two sync instances running simultaneously
|
||||
# ARR_SYNC_ENABLED — global gate, exits cleanly when false
|
||||
# SSH connect timeout — ARR_SYNC_CONNECT_TIMEOUT — does not hang on unreachable node
|
||||
# API call timeout — ARR_SYNC_API_TIMEOUT — does not hang on slow arr
|
||||
# Graceful skip — unreachable node/arr → skip and continue, never abort
|
||||
# Blocklist gate — item in blocklist → never added to any node
|
||||
# Silent by default — only additions produce output, clean runs stay silent
|
||||
#
|
||||
# ==============================================================================================
|
||||
# STATE FILES
|
||||
# ==============================================================================================
|
||||
#
|
||||
# ARR_SYNC_BLOCKLIST — TSV file in DATA_DIR (default: DATA_DIR/arr_sync_blocklist.tsv)
|
||||
# Columns: arr_type, id, reason, date_added
|
||||
# Read from all nodes via SSH at the start of each run.
|
||||
#
|
||||
# ==============================================================================================
|
||||
# CONFIGURATION
|
||||
# ==============================================================================================
|
||||
#
|
||||
# master_host*.conf
|
||||
#
|
||||
# HOST*_LIDARR_URL / HOST*_LIDARR_API_KEY — local Lidarr (aliased by detect_hosts)
|
||||
# HOST*_SONARR_URL / HOST*_SONARR_API_KEY — local Sonarr
|
||||
# HOST*_RADARR_URL / HOST*_RADARR_API_KEY — local Radarr
|
||||
#
|
||||
# master.conf
|
||||
#
|
||||
# ARR_SYNC_ENABLED — global on/off toggle (default: true)
|
||||
# ARR_SYNC_BLOCKLIST — path to TSV blocklist file
|
||||
# ARR_SYNC_CONNECT_TIMEOUT — SSH connect timeout in seconds (default: 10)
|
||||
# ARR_SYNC_API_TIMEOUT — curl API call timeout in seconds (default: 60)
|
||||
# DOCKER_APPDATA_BASE — base path for arr appdata dirs (default: /mnt/user/appdata)
|
||||
# ARR_SYNC_LIDARR_PORT — Lidarr port on all nodes (default: 8686)
|
||||
# ARR_SYNC_SONARR_PORT — Sonarr port on all nodes (default: 8989)
|
||||
# ARR_SYNC_RADARR_PORT — Radarr port on all nodes (default: 7878)
|
||||
#
|
||||
# ==============================================================================================
|
||||
# RUNTIME MODES
|
||||
# ==============================================================================================
|
||||
#
|
||||
# ── USAGE ─────────────────────────────────────────────────────────────────────────────────────
|
||||
# arr_sync.sh — sync all arr types, all nodes
|
||||
# arr_sync.sh --dry-run — preview only, no changes
|
||||
# arr_sync.sh --log — verbose output
|
||||
# arr_sync.sh --status — show config and exit
|
||||
# arr_sync.sh --blocklist-add lidarr <mbid> "reason" — remove from all arrs + tombstone
|
||||
#
|
||||
# Blocklist management:
|
||||
# arr_sync.sh --blocklist-add lidarr <mbid> "reason" — remove from all arrs + tombstone
|
||||
# arr_sync.sh --blocklist-add sonarr <tvdbId> "reason" — remove from all arrs + tombstone
|
||||
# arr_sync.sh --blocklist-add radarr <tmdbId> "reason" — remove from all arrs + tombstone
|
||||
# arr_sync.sh --blocklist-remove lidarr <id> — un-tombstone (does NOT re-add)
|
||||
# arr_sync.sh --blocklist-list — show all blocklisted IDs
|
||||
# arr_sync.sh --blocklist-list — show all blocklisted IDs
|
||||
#
|
||||
# ── CONFIGURATION (master.conf) ───────────────────────────────────────────────────────────────
|
||||
# ARR_SYNC_ENABLED — global on/off toggle (default true)
|
||||
# ARR_SYNC_BLOCKLIST — path to TSV blocklist (default: DATA_DIR/arr_sync_blocklist.tsv)
|
||||
# ARR_SYNC_CONNECT_TIMEOUT — SSH connect timeout in seconds (default 10)
|
||||
# ARR_SYNC_API_TIMEOUT — curl API call timeout in seconds (default 60)
|
||||
# DOCKER_APPDATA_BASE — base path for arr appdata dirs (default /mnt/user/appdata)
|
||||
# ARR_SYNC_LIDARR_PORT — Lidarr port on all nodes (default 8686)
|
||||
# ARR_SYNC_SONARR_PORT — Sonarr port on all nodes (default 8989)
|
||||
# ARR_SYNC_RADARR_PORT — Radarr port on all nodes (default 7878)
|
||||
#
|
||||
# ── CONFIGURATION (master_host*.conf) ─────────────────────────────────────────────────────────
|
||||
# HOST*_LIDARR_URL / HOST*_LIDARR_API_KEY — local Lidarr (aliased by detect_hosts)
|
||||
# HOST*_SONARR_URL / HOST*_SONARR_API_KEY — local Sonarr
|
||||
# HOST*_RADARR_URL / HOST*_RADARR_API_KEY — local Radarr
|
||||
# ==============================================================================================
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
Reference in New Issue
Block a user