Files
simonandClaude Opus 5.5 405c21a8c5 Backups, freshness monitoring, persistent logs, procurement cleanup
- backup service: nightly pg_dump with retention, recorded as a run
- GET /api/v1/status/sources: 503 when a scheduled source or the backup
  missed its last two slots (for Uptime Kuma)
- worker logs to ${DATA_DIR}/logs, so they survive redeploys
- procurement: reject implausible award dates (1900, contract end dates),
  skip placeholder contractors, credit framework agreements to the BBG

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-13 00:46:18 +01:00

34 lines
1.3 KiB
Bash

#!/bin/sh
# Nightly database backup, run by the `backup` service in docker-compose.yml.
# Writes politrack-YYYY-MM-DD.dump (pg_dump custom format) to /backups at 02:30 UTC, deletes dumps older than
# $BACKUP_KEEP_DAYS days, and records each attempt as a run of "backup", so /api/v1/status/sources alerts
# when backups stop. Restore: pg_restore -h <host> -U politrack -d politrack --clean <file>
set -u
KEEP="${BACKUP_KEEP_DAYS:-14}"
export PGHOST=db PGUSER=politrack PGDATABASE=politrack
record() { # record <status> <json stats>
psql -q -c "INSERT INTO run (adapter, mode, status, finished_at, stats) VALUES ('backup', 'backup', '$1', now(), '$2'::jsonb)" \
|| echo "could not record the backup run"
}
while true; do
now=$(date -u +%s)
next=$(date -u -d "today 02:30" +%s)
[ "$next" -le "$now" ] && next=$(date -u -d "tomorrow 02:30" +%s)
echo "next backup at $(date -u -d "@$next")"
sleep $((next - now))
file="/backups/politrack-$(date -u +%F).dump"
if pg_dump -Fc -f "$file.tmp" && mv "$file.tmp" "$file"; then
size=$(stat -c %s "$file")
echo "backup ok: $file ($size bytes)"
record ok "{\"file\": \"$(basename "$file")\", \"bytes\": $size}"
else
rm -f "$file.tmp"
echo "backup FAILED"
record error '{}'
fi
find /backups -name 'politrack-*.dump' -mtime "+$KEEP" -delete
done