techdj/gunicorn.conf.py

46 lines
2.0 KiB
Python

# gunicorn.conf.py — Gunicorn configuration for TechDJ
# Used by production.py. Do not run gunicorn directly without this file.
#
# Architecture:
# - Gunicorn (eventlet worker, 1 worker) serves the DJ panel app on DJ_PORT.
# - post_worker_init spawns the listener app on LISTENER_PORT and starts
# background greenlets — all within the same worker process so they share
# in-process state (SRT state, pre-roll buffer, queue, etc.).
import os
import json
# ── Load ports from config.json ──────────────────────────────────────────────
def _load_cfg():
try:
with open(os.path.join(os.path.dirname(__file__), 'config.json')) as f:
return json.load(f)
except Exception:
return {}
_cfg = _load_cfg()
# ── Gunicorn settings ─────────────────────────────────────────────────────────
worker_class = 'eventlet'
workers = 1 # Must be 1 — eventlet handles concurrency via greenlets
# and both apps share in-process state.
bind = f"{_cfg.get('host', '0.0.0.0')}:{_cfg.get('dj_port', 5000)}"
timeout = 0 # Disable worker timeout — long-lived SSE/WS connections.
keepalive = 5
# Log format
accesslog = '-' # stdout — production.py redirects to techdj.log
errorlog = '-'
loglevel = 'info'
# ── Hooks ─────────────────────────────────────────────────────────────────────
def post_worker_init(worker):
"""Called after the eventlet worker is fully initialised.
Starts the listener server + background greenlets in the same process
as the DJ panel so they share all in-process state.
"""
from server import _start_background_tasks
_start_background_tasks()