#!/usr/bin/env bash
# diariz-nightly-restart — restart Diariz's two workers about 0300 so they drop their cached models (Prime 2026-10-19:
# GPU 3 is OK for Diariz as an exception to the "no always-resident tenant" rule, with a nightly restart). The workers
# load Whisper/pyannote/ECAPA lazily on their first job and keep them for later jobs; a restart is the only unload
# (except the live worker, which unloads itself when live transcription is switched off in the app).
#
# IDLE GATE (it gates, it does not just print): GPU 3 is sampled every 2 s for 20 s; any sample above 10% means work is
# running there (a Diariz job, or a Scriberr job on the same card), so wait 15 min and try again, until 0500. Then skip
# tonight and say so in the journal.
set -uo pipefail
GPU=3; DEADLINE=$(date -d '05:00' +%s); WORKERS=(diariz-worker-1 diariz-live-worker-1)
busy() { local s; for _ in $(seq 10); do s=$(nvidia-smi -i $GPU --query-gpu=utilization.gpu --format=csv,noheader,nounits | tr -d ' '); [ "${s:-100}" -gt 10 ] && return 0; sleep 2; done; return 1; }
while busy; do
  if [ "$(date +%s)" -ge "$DEADLINE" ]; then echo "GPU $GPU still busy at $(date +%H%M); skipping tonight's restart"; exit 0; fi
  echo "GPU $GPU busy at $(date +%H%M); retrying in 15 min"; sleep 900
done
before=$(nvidia-smi -i $GPU --query-gpu=memory.used --format=csv,noheader,nounits | tr -d ' ')
present=(); for c in "${WORKERS[@]}"; do docker inspect "$c" >/dev/null 2>&1 && present+=("$c"); done
[ ${#present[@]} -gt 0 ] || { echo "no Diariz worker containers found; nothing to restart"; exit 0; }
docker restart "${present[@]}" >/dev/null
sleep 20
after=$(nvidia-smi -i $GPU --query-gpu=memory.used --format=csv,noheader,nounits | tr -d ' ')
echo "restarted ${present[*]}; GPU $GPU memory ${before} MiB -> ${after} MiB"
