movetdarr v4: flock-Serialisierung gegen n8n-staticData-Race bei parallelen SAB-Auftraegen
This commit is contained in:
parent
71247af6b6
commit
e8a36502e9
1 changed files with 81 additions and 60 deletions
|
|
@ -1,7 +1,9 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# movetdarr.sh v3 — SABnzbd -> FileFlows with durable n8n handoff lease
|
# movetdarr.sh v4 — SABnzbd -> FileFlows with durable n8n handoff lease
|
||||||
# Categories: serien4k->Sonarr UHD, serien->Sonarr FHD,
|
# Categories: serien4k->Sonarr UHD, serien->Sonarr FHD,
|
||||||
# video4k->Radarr UHD, video->Radarr FHD.
|
# video4k->Radarr UHD, video->Radarr FHD.
|
||||||
|
# v4: flock-Serialisierung des Lease-Blocks gegen n8n-staticData-Race
|
||||||
|
# bei parallelen SAB-Aufträgen (Last-Writer-Wins verschluckt Jobs).
|
||||||
|
|
||||||
DIR="$1"
|
DIR="$1"
|
||||||
NZB_NAME="$2"
|
NZB_NAME="$2"
|
||||||
|
|
@ -15,6 +17,7 @@ SOURCE_ROOT="${SOURCE_ROOT:-/usenet/complete}"
|
||||||
DEST_ROOT="${DEST_ROOT:-/tdarr/complete}"
|
DEST_ROOT="${DEST_ROOT:-/tdarr/complete}"
|
||||||
POLL_SECONDS="${POLL_SECONDS:-60}"
|
POLL_SECONDS="${POLL_SECONDS:-60}"
|
||||||
MAX_POLLS="${MAX_POLLS:-1440}" # 24 hours
|
MAX_POLLS="${MAX_POLLS:-1440}" # 24 hours
|
||||||
|
LEASE_LOCK="${LEASE_LOCK:-/usenet/scripts/.movetdarr.lease.lock}"
|
||||||
|
|
||||||
log() { echo "$(date '+%d.%m.%Y %H:%M:%S'): $1" >> "$LOGFILE"; }
|
log() { echo "$(date '+%d.%m.%Y %H:%M:%S'): $1" >> "$LOGFILE"; }
|
||||||
|
|
||||||
|
|
@ -39,7 +42,7 @@ notify_failure() {
|
||||||
handoff "$payload" >/dev/null 2>&1 || true
|
handoff "$payload" >/dev/null 2>&1 || true
|
||||||
}
|
}
|
||||||
|
|
||||||
log "Start v3 - Kategorie=$CATEGORY Status=$STATUS Dir=$DIR"
|
log "Start v4 - Kategorie=$CATEGORY Status=$STATUS Dir=$DIR"
|
||||||
|
|
||||||
if [ "$STATUS" != "0" ]; then
|
if [ "$STATUS" != "0" ]; then
|
||||||
log "Download fehlgeschlagen, ueberspringe"
|
log "Download fehlgeschlagen, ueberspringe"
|
||||||
|
|
@ -74,7 +77,9 @@ if [ -z "$EXPECTED_FILES" ] || [ "$EXPECTED_FILES" -lt 1 ] || [ "$EXPECTED_FILES
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Lease registrieren, solange der SAB-Job und sein Quellpfad noch sichtbar sind.
|
# Lease registrieren und Move+Bestaetigung unter exclusivem Lock, damit parallele
|
||||||
|
# SAB-Auftraege sich nicht gegenseitig den n8n-staticData-Job zerstoeren (v4).
|
||||||
|
register_lease() {
|
||||||
START_PAYLOAD="$(json_payload action start category "$CATEGORY" directory "$DIR" release "$NZB_NAME" cleanName "$CLEAN_NAME" expectedFiles "$EXPECTED_FILES")"
|
START_PAYLOAD="$(json_payload action start category "$CATEGORY" directory "$DIR" release "$NZB_NAME" cleanName "$CLEAN_NAME" expectedFiles "$EXPECTED_FILES")"
|
||||||
START_RESPONSE="$(handoff "$START_PAYLOAD" 2>>"$LOGFILE")" || {
|
START_RESPONSE="$(handoff "$START_PAYLOAD" 2>>"$LOGFILE")" || {
|
||||||
log "FEHLER: n8n-Handoff konnte nicht registriert werden - kein Move"
|
log "FEHLER: n8n-Handoff konnte nicht registriert werden - kein Move"
|
||||||
|
|
@ -87,8 +92,9 @@ if [ "$START_OK" != "True" ] && [ "$START_OK" != "true" ] || [ -z "$JOB_ID" ]; t
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
log "Handoff registriert: Job=$JOB_ID"
|
log "Handoff registriert: Job=$JOB_ID"
|
||||||
|
export JOB_ID
|
||||||
|
|
||||||
DEST="${DEST_ROOT}/${CATEGORY}"
|
DEST="${DEST_ROOT:?DEST_ROOT muss gesetzt sein}/${CATEGORY}"
|
||||||
BASENAME="$(basename "$DIR")"
|
BASENAME="$(basename "$DIR")"
|
||||||
TARGET="$DEST/$BASENAME"
|
TARGET="$DEST/$BASENAME"
|
||||||
mkdir -p "$DEST" || {
|
mkdir -p "$DEST" || {
|
||||||
|
|
@ -136,7 +142,22 @@ if [ "$MOVED_OK" != "true" ]; then
|
||||||
notify_failure "move_confirmation_failed"
|
notify_failure "move_confirmation_failed"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
if command -v flock >/dev/null 2>&1; then
|
||||||
|
flock -w 900 "$LEASE_LOCK" -c 'set -e' || true # Lock-Datei anlegen
|
||||||
|
exec 9>"$LEASE_LOCK"
|
||||||
|
if ! flock -w 900 9; then
|
||||||
|
log "WARNUNG: Lease-Lock nach 15 Minuten nicht erhalten; fahre ohne Lock fort"
|
||||||
|
register_lease
|
||||||
|
else
|
||||||
|
register_lease
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
register_lease
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Ab hier: Status-Polling ohne Lock (lang laufend, stoert keine andere Registrierung).
|
||||||
STATUS_PAYLOAD="$(json_payload action status jobId "$JOB_ID")"
|
STATUS_PAYLOAD="$(json_payload action status jobId "$JOB_ID")"
|
||||||
for poll in $(seq 1 "$MAX_POLLS"); do
|
for poll in $(seq 1 "$MAX_POLLS"); do
|
||||||
if RESPONSE="$(handoff "$STATUS_PAYLOAD" 2>>"$LOGFILE")"; then
|
if RESPONSE="$(handoff "$STATUS_PAYLOAD" 2>>"$LOGFILE")"; then
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue