All checks were successful
Deploy / deploy (push) Successful in 22s
app.py's dev server and gunicorn both hardcoded 5000, which is awkward
locally — macOS ControlCenter already holds that port, so the app can't
bind on the dev laptop without editing source.
Both now read PORT, defaulting to 5000 so EXPOSE, the compose
`${HOST_PORT}:5000` mapping and the deployed container are unchanged.
Read at run time rather than import time so a dev harness can assign a
free port.
Also tracks .claude/launch.json with autoPort set. It doesn't actually
launch on this machine — the preview sandbox can't read files under
~/Desktop — so CLAUDE.md notes that running from a shell with an
explicit PORT is the working local path.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
26 lines
893 B
Python
26 lines
893 B
Python
# Gunicorn configuration
|
||
import os
|
||
|
||
workers = 2 # 2 workers × 4 threads = 8 concurrent requests; fewer cold-cache workers
|
||
threads = 4
|
||
worker_class = "gthread"
|
||
# Defaults to 5000 to match EXPOSE, the `${HOST_PORT}:5000` mapping in
|
||
# docker-compose.yml, and app.py's own dev-server default.
|
||
bind = "0.0.0.0:" + os.environ.get("PORT", "5000")
|
||
timeout = 30 # fail fast — app has its own 5s internal deadline
|
||
keepalive = 5
|
||
|
||
def post_fork(server, worker):
|
||
"""Pre-warm the slow caches in each worker right after fork.
|
||
This runs in the background so the worker is ready instantly."""
|
||
import threading
|
||
def _warm():
|
||
try:
|
||
import app as a
|
||
a.get_radarr_summary()
|
||
a.get_sonarr_summary()
|
||
a.get_tautulli_summary()
|
||
except Exception:
|
||
pass
|
||
t = threading.Thread(target=_warm, daemon=True)
|
||
t.start()
|