#!/bin/bash
# Window W1 (19 Sep 2026): admits the three new collectors one at a time, only while the app
# container has room. Adapted from sweep-2026-09-19b/admit-queue.sh; that copy is the record of
# its own window and is not edited.
#
# Collectors share the app container's cgroup with uvicorn. The cap is 4 GB now (docker-compose.yml,
# raised on 18 Sep after eight collectors OOMed a 1 GB cap in six minutes). The sweep's trace of
# 19 Sep (sweep-2026-09-19b/memory-trace.tsv) is the measurement: ten collectors sat at 1472 to
# 1577 MiB, about 150 MiB each once settled, and a lone one ended at 240 MiB; a collector GROWS as
# its run accumulates. guard.sh sheds the heaviest collector above 3400 MiB, so the queue admits
# only while one more collector (up to about 300 MiB with growth) still fits under that line:
# CEILING_MIB is 3000, not the 620 the 1 GB window used. Three collectors are expected to sit at
# 700 to 900 MiB in all, so the ceiling binds only if the container is already carrying something
# it should not be (a leftover run: the deploy gate says none may exist when this starts).
set -u
D="$(cd "$(dirname "$0")" && pwd)"
CEILING_MIB=3000
LOG="$D/admit-queue.log"

mem_mib() {
  # docker stats prints "1.08GiB / 4GiB" once the container passes a gibibyte; the sweep's copy
  # read that as 1 MiB (int of "1.08") and would have admitted into a full container. Scaled here.
  docker stats --no-stream --format '{{.MemUsage}}' dutyfreeprofessor-app 2>/dev/null \
    | awk '{v=$1; if (v ~ /GiB/) {sub(/GiB.*/,"",v); printf "%d\n", v*1024}
            else if (v ~ /MiB/) {sub(/MiB.*/,"",v); printf "%d\n", v}
            else if (v ~ /KiB/) {print 0} else {print 9999}}'
}
running_for() {  # a source already collecting? never start a second run of one
  docker exec dutyfreeprofessor-db psql -U dfp -d dfp -tAc \
    "SELECT count(*) FROM collection_runs r JOIN sources s ON s.id=r.source_id
     WHERE r.status='running' AND s.slug='$1';" 2>/dev/null | tr -d '[:space:]'
}

echo "$(date '+%F %T') queue starts: $*" >> "$LOG"
for s in "$@"; do
  # This window is for exactly these three sources; anything else is refused here rather than
  # collected under a window that never announced it.
  case "$s" in
    avolta-las|avolta-lgw|avolta-hel) ;;
    *) echo "$(date '+%F %T') REFUSED $s: not one of this window's three sources" >> "$LOG"; continue ;;
  esac
  while :; do
    m=$(mem_mib)
    [ -z "$m" ] && m=9999
    if [ "$m" -lt "$CEILING_MIB" ] && [ "$(running_for "$s")" = "0" ]; then
      echo "$(date '+%F %T') admitting $s (app at ${m}MiB)" >> "$LOG"
      setsid nohup docker exec dutyfreeprofessor-app python -m app.cli collect --source "$s" \
        > "$D/$s.log" 2>&1 < /dev/null &
      sleep 90   # let it settle before judging headroom again
      break
    fi
    sleep 120
  done
done
echo "$(date '+%F %T') queue done" >> "$LOG"
