#!/usr/bin/env bash # hamprint container entrypoint. # # Runs everything inside the single `web` container per plan.md §10: # 1. apply DB migrations (idempotent; runs on every start) # 2. background `process_submissions` (plan.md §7.5, 30 s loop) # 3. background `cleanup_stale` (plan.md §7.6, 5 min loop) # 4. exec Gunicorn so it becomes the foreground process for signal handling # # tini (set as ENTRYPOINT in the Containerfile) reaps zombies and forwards # SIGTERM to all three child processes on container stop. set -euo pipefail python manage.py migrate --noinput # Validation worker. `|| true` keeps the loop alive across a transient # failure (e.g. a flaky external HEAD request); the next tick retries. ( while true; do python manage.py process_submissions || true sleep 30 done ) & # Stale-row reaper. Same pattern, different cadence. ( while true; do python manage.py cleanup_stale || true sleep 300 done ) & exec gunicorn hamprint.wsgi:application \ --bind 0.0.0.0:8000 \ --workers "${GUNICORN_WORKERS:-3}" \ --access-logfile - \ --error-logfile -