import multiprocessing import os # Server socket bind = "127.0.0.1:7433" # nginx will proxy to this backlog = 2048 # Worker processes workers = multiprocessing.cpu_count() * 2 + 1 # Recommended formula worker_class = "uvicorn.workers.UvicornWorker" # Async worker for FastAPI worker_connections = 1000 max_requests = 1000 # Restart workers after this many requests max_requests_jitter = 50 # Add randomness to prevent all workers restarting at once # Timeouts timeout = 30 # Workers silent for more than this are killed keepalive = 2 # Wait this long for requests on Keep-Alive connections # Logging accesslog = "./logs/webhook_access.log" errorlog = "./logs/webhook_error.log" loglevel = "info" access_log_format = '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s" %(D)s' # Process naming proc_name = "studspider" # Server mechanics daemon = False # Run in foreground (systemd will handle daemonization) pidfile = "./logs/studspider.pid" umask = 0 user = None # Run as current user (systemd will set user) group = None tmp_upload_dir = None # SSL (not needed with nginx, but here for reference) # keyfile = None # certfile = None # Security limit_request_line = 4096 limit_request_fields = 100 limit_request_field_size = 8190 # Debugging (disable in production) reload = os.getenv("GUNICORN_RELOAD", "false").lower() == "true" reload_engine = "auto" # Hooks def on_starting(server): """Called just before the master process is initialized.""" print("Studspider WEB starting...") # Load .env file before workers start import dotenv from pathlib import Path env_path = Path(__file__).parent.parent / ".env" print(f"[@DEBUG] Looking for .env at: {env_path.absolute()}") if env_path.exists(): dotenv.load_dotenv(env_path) print(f"✓ Loaded environment from {env_path}") # Verify key was loaded import os key = os.getenv("PROD_SQUARE_WEBHOOK_SIGNATURE_KEY") or os.getenv( "SANDBOX_SQUARE_WEBHOOK_SIGNATURE_KEY" ) if key: print(f"✓ SQUARE_WEBHOOK_SIGNATURE_KEY loaded: {key[:10]}...") else: print(f"⚠ SQUARE_WEBHOOK_SIGNATURE_KEY not found in .env") else: print(f"⚠ No .env file found at {env_path.absolute()}") def on_reload(server): """Called to recycle workers during a reload via SIGHUP.""" print("🔄 Reloading workers...") def when_ready(server): """Called just after the server is started.""" print(f"STUDSPIDER HOOK v0.1 RUNNING ON {bind}") print(f"WORKERS: {workers}") print(f"WORKING CLASS: {worker_class}\n") def worker_int(worker): """Called just after a worker exited on SIGINT or SIGQUIT.""" print(f"⚠️ Worker {worker.pid} received INT or QUIT signal") def worker_abort(worker): """Called when a worker received the SIGABRT signal.""" print(f"❌ Worker {worker.pid} aborted")