name: islandflow-vps

x-build-contexts: &build-contexts
  context: .
  additional_contexts:
    workspace: ./workspace-root
    apps: ../../apps
    services: ../../services
    packages: ../../packages

x-service-common: &service-common
  build:
    <<: *build-contexts
    dockerfile: Dockerfile.service
  env_file:
    - ./.env
  environment:
    LOG_LEVEL: ${LOG_LEVEL:-warn}
  restart: unless-stopped
  init: true
  extra_hosts:
    - "host.docker.internal:host-gateway"
  depends_on:
    nats:
      condition: service_started
    clickhouse:
      condition: service_healthy
    redis:
      condition: service_healthy

services:
  web:
    build:
      <<: *build-contexts
      dockerfile: Dockerfile.web
      args:
        NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL:-}
        NEXT_PUBLIC_NBBO_MAX_AGE_MS: ${NEXT_PUBLIC_NBBO_MAX_AGE_MS:-1000}
    env_file:
      - ./.env
    restart: unless-stopped
    init: true
    expose:
      - "3000"
    ports:
      - "${WEB_BIND_IP:-127.0.0.1}:${WEB_HOST_PORT:-3000}:3000"
    networks:
      - default
      - shared
    depends_on:
      api:
        condition: service_healthy
    healthcheck:
      test:
        [
          "CMD",
          "bun",
          "-e",
          "const r=await fetch('http://127.0.0.1:3000/'); if(!r.ok) throw new Error('web healthcheck failed: '+r.status);"
        ]
      interval: 30s
      timeout: 10s
      retries: 5
      start_period: 45s

  api:
    <<: *service-common
    command: ["services/api/src/index.ts"]
    environment:
      LOG_LEVEL: ${LOG_LEVEL:-warn}
      API_HOST: 0.0.0.0
    expose:
      - "4000"
    ports:
      - "${API_BIND_IP:-127.0.0.1}:${API_HOST_PORT:-4000}:4000"
    networks:
      - default
      - shared
    healthcheck:
      test:
        [
          "CMD",
          "bun",
          "-e",
          "const r=await fetch('http://127.0.0.1:4000/health'); if(!r.ok) throw new Error('api healthcheck failed: '+r.status);"
        ]
      interval: 30s
      timeout: 10s
      retries: 5
      start_period: 20s

  compute:
    <<: *service-common
    command: ["services/compute/src/index.ts"]

  candles:
    <<: *service-common
    command: ["services/candles/src/index.ts"]

  ingest-options:
    build:
      <<: *build-contexts
      dockerfile: Dockerfile.ingest-options
    env_file:
      - ./.env
    environment:
      LOG_LEVEL: ${LOG_LEVEL:-warn}
    restart: unless-stopped
    init: true
    extra_hosts:
      - "host.docker.internal:host-gateway"
    depends_on:
      nats:
        condition: service_started
      clickhouse:
        condition: service_healthy
      redis:
        condition: service_healthy
    command: ["services/ingest-options/src/index.ts"]

  ingest-equities:
    <<: *service-common
    command: ["services/ingest-equities/src/index.ts"]

  ingest-news:
    <<: *service-common
    command: ["services/ingest-news/src/index.ts"]

  replay:
    <<: *service-common
    profiles: ["replay"]
    command: ["services/replay/src/index.ts"]

  clickhouse:
    image: clickhouse/clickhouse-server:23.8
    restart: unless-stopped
    ulimits:
      nofile:
        soft: 262144
        hard: 262144
    volumes:
      - ${ISLANDFLOW_DATA_ROOT:-/var/lib/islandflow}/clickhouse:/var/lib/clickhouse
      - ./clickhouse/listen.xml:/etc/clickhouse-server/config.d/listen.xml:ro
    healthcheck:
      test:
        [
          "CMD-SHELL",
          "wget -qO- http://127.0.0.1:8123/ping | grep -q Ok."
        ]
      interval: 10s
      timeout: 5s
      retries: 12
      start_period: 20s

  redis:
    image: redis:7.2
    restart: unless-stopped
    command: ["redis-server", "--appendonly", "yes"]
    volumes:
      - ${ISLANDFLOW_DATA_ROOT:-/var/lib/islandflow}/redis:/data
    healthcheck:
      test:
        [
          "CMD",
          "redis-cli",
          "ping"
        ]
      interval: 10s
      timeout: 5s
      retries: 10
      start_period: 5s

  nats:
    image: nats:2.10
    restart: unless-stopped
    command: ["-js", "-sd", "/data"]
    volumes:
      - ${ISLANDFLOW_DATA_ROOT:-/var/lib/islandflow}/nats:/data

networks:
  shared:
    external: true
    name: ${NPM_SHARED_NETWORK:-npm-shared}
