version: "3.9"

name: fr24-ingest

x-common-env: &common-env
  TZ: ${TZ:-UTC}
  APP_ENV: ${APP_ENV:-dev}
  POSTGRES_HOST: ${POSTGRES_HOST:-postgres}
  POSTGRES_PORT: ${POSTGRES_PORT:-5432}
  POSTGRES_DB: ${POSTGRES_DB:-fr24}
  POSTGRES_USER: ${POSTGRES_USER:-fr24}
  POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-change-me}
  RAW_RETENTION_DAYS: ${RAW_RETENTION_DAYS:-3}
  PARTITION_RETENTION_DAYS: ${PARTITION_RETENTION_DAYS:-3}
  OVERLAP_MINUTES: ${OVERLAP_MINUTES:-10}
  CAPTURE_SOURCE: ${CAPTURE_SOURCE:-rtl-sdr}
  RTLSDR_DEVICE_INDEX: ${RTLSDR_DEVICE_INDEX:-0}
  RTLSDR_SAMPLE_RATE: ${RTLSDR_SAMPLE_RATE:-2000000}
  RTLSDR_CENTER_FREQUENCY: ${RTLSDR_CENTER_FREQUENCY:-1090000000}
  RTLSDR_GAIN: ${RTLSDR_GAIN:-auto}
  RTLSDR_BIAS_T: ${RTLSDR_BIAS_T:-0}

services:
  postgres:
    image: postgis/postgis:16-3.4
    container_name: fr24-postgres
    environment:
      POSTGRES_DB: ${POSTGRES_DB:-fr24}
      POSTGRES_USER: ${POSTGRES_USER:-fr24}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-change-me}
      TZ: ${TZ:-UTC}
    ports:
      - "${POSTGRES_PUBLISHED_PORT:-5432}:5432"
    volumes:
      - ../db/postgres:/var/lib/postgresql/data
      - ../db/init:/docker-entrypoint-initdb.d:ro
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-fr24} -d ${POSTGRES_DB:-fr24}"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 20s
    restart: unless-stopped
    networks:
      - fr24-net

  capture:
    build:
      context: ../ingest/capture
      dockerfile: Dockerfile
    image: fr24-capture
    container_name: fr24-capture
    environment:
      <<: *common-env
      SERVICE_ROLE: capture
    privileged: true
    devices:
      - "/dev/bus/usb:/dev/bus/usb"
    volumes:
      - ../logs/capture:/var/log/fr24
      - ../backup:/backup
    depends_on:
      postgres:
        condition: service_healthy
    healthcheck:
      test: ["CMD-SHELL", "test -f /tmp/capture-ready && python -c 'import psycopg2' 2>/dev/null || exit 1"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 10s
    restart: unless-stopped
    networks:
      - fr24-net

  preprocess:
    build:
      context: ../ingest/preprocess
      dockerfile: Dockerfile
    image: fr24-preprocess
    container_name: fr24-preprocess
    environment:
      <<: *common-env
      SERVICE_ROLE: preprocess
      BATCH_SIZE: "500"
    volumes:
      - ../logs/preprocess:/var/log/fr24
      - ../backup:/backup
    depends_on:
      postgres:
        condition: service_healthy
      capture:
        condition: service_started
    healthcheck:
      test: ["CMD-SHELL", "test -f /tmp/preprocess-ready && python -c 'import psycopg2' 2>/dev/null || exit 1"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 10s
    restart: unless-stopped
    networks:
      - fr24-net

  api:
    build:
      context: ../frontend
      dockerfile: Dockerfile
    image: fr24-api
    container_name: fr24-api
    environment:
      <<: *common-env
      SERVICE_ROLE: api
      API_PORT: ${API_PORT:-8080}
    ports:
      - "${API_PUBLISHED_PORT:-8080}:8080"
    volumes:
      - ../logs/api:/var/log/fr24
    depends_on:
      postgres:
        condition: service_healthy
      preprocess:
        condition: service_started
    healthcheck:
      test: ["CMD-SHELL", "python -c 'import urllib.request; urllib.request.urlopen(\"http://localhost:8080/health\")' || exit 1"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 10s
    restart: unless-stopped
    networks:
      - fr24-net

  monitoring:
    build:
      context: ../monitoring
      dockerfile: Dockerfile
    image: fr24-monitoring
    container_name: fr24-monitoring
    environment:
      <<: *common-env
      SERVICE_ROLE: monitoring
      MONITORING_INTERVAL_SECONDS: ${MONITORING_INTERVAL_SECONDS:-60}
    volumes:
      - ../logs/monitoring:/var/log/fr24
    depends_on:
      postgres:
        condition: service_healthy
      capture:
        condition: service_started
      preprocess:
        condition: service_started
      api:
        condition: service_started
    healthcheck:
      test: ["CMD-SHELL", "test -f /tmp/monitoring-ready || exit 1"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 15s
    restart: unless-stopped
    networks:
      - fr24-net

  backup:
    image: postgres:16-alpine
    container_name: fr24-backup
    environment:
      PGPASSWORD: ${POSTGRES_PASSWORD:-change-me}
      PGHOST: ${POSTGRES_HOST:-postgres}
      PGUSER: ${POSTGRES_USER:-fr24}
      PGDATABASE: ${POSTGRES_DB:-fr24}
      TZ: ${TZ:-UTC}
    volumes:
      - ../backup:/backup
      - ../backup/backup.sh:/usr/local/bin/backup.sh:ro
    depends_on:
      postgres:
        condition: service_healthy
    command: >
      sh -c 'echo "[backup] service started, interval=6h" &&
             while true; do
               /usr/local/bin/backup.sh;
               sleep 21600;
             done'
    restart: unless-stopped
    networks:
      - fr24-net

  fr24-schedule:
    build:
      context: ../ingest/schedule
      dockerfile: Dockerfile
    image: fr24-schedule
    container_name: fr24-schedule
    environment:
      POSTGRES_HOST: ${POSTGRES_HOST:-postgres}
      POSTGRES_PORT: ${POSTGRES_PORT:-5432}
      POSTGRES_DB: ${POSTGRES_DB:-fr24}
      POSTGRES_USER: ${POSTGRES_USER:-fr24}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-change-me}
      YANDEX_RASP_API_KEY: ${YANDEX_RASP_API_KEY:-}
      OPENSKY_USERNAME: ${OPENSKY_USERNAME:-}
      OPENSKY_PASSWORD: ${OPENSKY_PASSWORD:-}
      SCHEDULE_RETENTION_DAYS: ${SCHEDULE_RETENTION_DAYS:-1095}
      TZ: ${TZ:-UTC}
    depends_on:
      postgres:
        condition: service_healthy
    healthcheck:
      test: ["CMD-SHELL", "python -c 'import urllib.request; urllib.request.urlopen(\"http://localhost:8000/health\", timeout=3)' || exit 1"]
      interval: 60s
      timeout: 10s
      retries: 3
      start_period: 20s
    restart: unless-stopped
    networks:
      - fr24-net

  fr24-tracks-fr24:
    build:
      context: ../ingest/tracks_fr24
      dockerfile: Dockerfile
    image: fr24-tracks-fr24
    container_name: fr24-tracks-fr24
    environment:
      POSTGRES_HOST: ${POSTGRES_HOST:-postgres}
      POSTGRES_PORT: ${POSTGRES_PORT:-5432}
      POSTGRES_DB: ${POSTGRES_DB:-fr24}
      POSTGRES_USER: ${POSTGRES_USER:-fr24}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-change-me}
      FR24_API_KEY: ${FR24_API_KEY:-}
      FR24_RATE_LIMIT_SEC: ${FR24_RATE_LIMIT_SEC:-6.0}
      TZ: ${TZ:-UTC}
    ports:
      - "${FR24_TRACKS_PORT:-8001}:8001"
    depends_on:
      postgres:
        condition: service_healthy
    healthcheck:
      test: ["CMD-SHELL", "python -c 'import urllib.request; urllib.request.urlopen(\"http://localhost:8001/health\", timeout=3)' || exit 1"]
      interval: 60s
      timeout: 10s
      retries: 3
      start_period: 20s
    restart: unless-stopped
    networks:
      - fr24-net

  fr24-tracks-fa:
    build:
      context: ../ingest/tracks_fa
      dockerfile: Dockerfile
    image: fr24-tracks-fa
    container_name: fr24-tracks-fa
    environment:
      POSTGRES_HOST: ${POSTGRES_HOST:-postgres}
      POSTGRES_PORT: ${POSTGRES_PORT:-5432}
      POSTGRES_DB: ${POSTGRES_DB:-fr24}
      POSTGRES_USER: ${POSTGRES_USER:-fr24}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-change-me}
      FLIGHTAWARE_API_KEY: ${FLIGHTAWARE_API_KEY:-}
      FA_RATE_LIMIT_SEC: ${FA_RATE_LIMIT_SEC:-2.0}
      TZ: ${TZ:-UTC}
    ports:
      - "${FA_TRACKS_PORT:-8002}:8002"
    depends_on:
      postgres:
        condition: service_healthy
    healthcheck:
      test: ["CMD-SHELL", "python -c 'import urllib.request; urllib.request.urlopen(\"http://localhost:8002/health\", timeout=3)' || exit 1"]
      interval: 60s
      timeout: 10s
      retries: 3
      start_period: 20s
    restart: unless-stopped
    networks:
      - fr24-net

  fr24-mart:
    build:
      context: ../ingest/mart
      dockerfile: Dockerfile
    image: fr24-mart
    container_name: fr24-mart
    environment:
      POSTGRES_HOST: ${POSTGRES_HOST:-postgres}
      POSTGRES_PORT: ${POSTGRES_PORT:-5432}
      POSTGRES_DB: ${POSTGRES_DB:-fr24}
      POSTGRES_USER: ${POSTGRES_USER:-fr24}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-change-me}
      MART_BUILD_INTERVAL_MINUTES: ${MART_BUILD_INTERVAL_MINUTES:-60}
      TZ: ${TZ:-UTC}
    depends_on:
      postgres:
        condition: service_healthy
    healthcheck:
      test: ["CMD-SHELL", "test -f /tmp/ready || exit 1"]
      interval: 60s
      timeout: 10s
      retries: 3
      start_period: 30s
    restart: unless-stopped
    networks:
      - fr24-net

networks:
  fr24-net:
    name: fr24-net
    driver: bridge
