← back to Dw Rotation Activator
drain.sh
42 lines
#!/bin/zsh
# Hourly rotation-activator drip. Activates the next per-slot batch of gate-passing
# DRAFTs in the canonical textures-first + vendor-round-robin order, capped by the
# activator's OWN daily activation ledger (~500/day). Idempotent, resumable,
# singleton-guarded. Activation is NOT a variant-create, so it never touches the
# budget.cjs variant ledger — the field-fix drain and this run in independent lanes.
set -u
export PATH="/opt/homebrew/opt/postgresql@14/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin"
SK="$HOME/Projects/dw-rotation-activator"
LOG="$SK/drain.log"
LOCKDIR="$SK/.drain.lock"
EXE="$SK/rotate-activate.js"
ts(){ date '+%Y-%m-%d %H:%M:%S'; }
# singleton (atomic mkdir lock, stale after 2h)
if ! mkdir "$LOCKDIR" 2>/dev/null; then
if [ -d "$LOCKDIR" ] && [ "$(find "$LOCKDIR" -maxdepth 0 -mmin +120 2>/dev/null)" ]; then
rmdir "$LOCKDIR" 2>/dev/null; mkdir "$LOCKDIR" 2>/dev/null || { echo "[$(ts)] locked, skip" >>"$LOG"; exit 0; }
else
echo "[$(ts)] already running, skip" >>"$LOG"; exit 0
fi
fi
trap 'rmdir "$LOCKDIR" 2>/dev/null' EXIT
# ~21/slot spreads the 500/day activation cap across the 24 hourly slots; the
# activator's daily ledger hard-caps the day's total regardless of per-slot ask.
SLOT_MAX="${DW_ROTATION_SLOT_MAX:-21}"
echo "[$(ts)] rotation-activate start slot_max=$SLOT_MAX" >>"$LOG"
/opt/homebrew/bin/node "$EXE" --max "$SLOT_MAX" --commit >>"$LOG" 2>&1
RC=$?
echo "[$(ts)] rotation-activate end rc=$RC" >>"$LOG"
# Keep the activation-calendar cadence to STAGED (DRAFT) items only: this run just
# flipped a batch DRAFT->ACTIVE, so drop any now-active SKU from the projected
# schedule (Steve's rule — the daily cadence must never list already-live items).
# Local, reversible, idempotent; a no-op when the snapshot is already clean.
PRUNE="$HOME/Projects/dw-activation-calendar/scripts/prune-active.js"
if [ -f "$PRUNE" ]; then
/opt/homebrew/bin/node "$PRUNE" >>"$LOG" 2>&1
echo "[$(ts)] cadence prune-active rc=$?" >>"$LOG"
fi