import os import multiprocessing import threading port = int(os.environ.get("PORT", "8001")) workers = int(os.environ.get("GUNICORN_WORKERS", "3")) threads = int(os.environ.get("GUNICORN_THREADS", "4")) timeout = int(os.environ.get("GUNICORN_TIMEOUT", "600")) bind = f"0.0.0.0:{port}" workers = min(workers, 8) worker_class = "gthread" graceful_timeout = 60 accesslog = "-" errorlog = "-" loglevel = os.environ.get("GUNICORN_LOGLEVEL", "info") # Do NOT preload — each worker starts its own background thread and loads models preload_app = False max_requests = 1000 max_requests_jitter = 100 tempdir = "/app/uploads" def post_fork(server, worker): """Start background worker thread after fork (filesystem-based store works across workers).""" t = threading.Thread(target=_bg_worker, daemon=True) t.start() def _bg_worker(): import app as marker_api from request_store import _job_queue, _job_cond, get_request, complete_request, fail_request, get_result while True: import time import traceback with _job_cond: while not _job_queue: _job_cond.wait() job = _job_queue.pop(0) request_id, endpoint, raw_bytes, filename, opts = job try: if endpoint == "convert": result = marker_api.convert_with_ocr_backend(raw_bytes, filename, **opts) elif endpoint == "ocr": from deepseek_ocr import ocr_pdf result = ocr_pdf(raw_bytes, max_pages=opts.get("max_pages"), page_range=opts.get("page_range")) elif endpoint == "extract": conv_result = marker_api.convert_with_ocr_backend(raw_bytes, filename, **opts) if conv_result["success"]: import json schema_json = opts.get("page_schema") or "{}" try: schema = json.loads(schema_json) if isinstance(schema_json, str) else schema_json except json.JSONDecodeError: schema = {} extraction = marker_api._apply_extraction_schema(conv_result["output"], schema) result = {**conv_result, "extraction": extraction} else: result = conv_result elif endpoint == "segment": conv_result = marker_api.convert_with_ocr_backend(raw_bytes, filename, **opts) if conv_result["success"]: import json schema_json = opts.get("segmentation_schema") or "{}" try: schema = json.loads(schema_json) if isinstance(schema_json, str) else schema_json except json.JSONDecodeError: schema = {} segments = marker_api._apply_segmentation_schema(conv_result["output"], schema) result = {**conv_result, "segments": segments} else: result = conv_result elif endpoint == "table_rec": conv_result = marker_api.convert_with_ocr_backend(raw_bytes, filename, **opts, output_format="json") tables = marker_api._extract_tables(conv_result) result = {**conv_result, "tables": tables} else: result = {"success": False, "error": f"Unknown endpoint: {endpoint}"} if result["success"]: complete_request(request_id, result) else: fail_request(request_id, result.get("error", "Unknown error")) except Exception as exc: traceback.print_exc() fail_request(request_id, str(exc))