diff --git a/docker-compose.coolify.yml b/docker-compose.coolify.yml index 9c9afc7..3c685a2 100644 --- a/docker-compose.coolify.yml +++ b/docker-compose.coolify.yml @@ -164,8 +164,8 @@ services: test: ["CMD", "curl", "-f", "http://127.0.0.1:8095/health"] interval: 30s timeout: 10s - start_period: 120s - retries: 3 + start_period: 300s + retries: 5 restart: unless-stopped networks: - breakpilot-network diff --git a/paddleocr-service/main.py b/paddleocr-service/main.py index 7c1d581..b025f87 100644 --- a/paddleocr-service/main.py +++ b/paddleocr-service/main.py @@ -1,15 +1,20 @@ """PaddleOCR Remote Service — PP-OCRv5 Latin auf x86_64.""" import io +import logging import os import numpy as np from fastapi import FastAPI, File, Header, HTTPException, UploadFile from PIL import Image +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + app = FastAPI(title="PaddleOCR Service") _engine = None +_ready = False API_KEY = os.environ.get("PADDLEOCR_API_KEY", "") @@ -18,6 +23,7 @@ def get_engine(): if _engine is None: from paddleocr import PaddleOCR + logger.info("Loading PaddleOCR model (first time may download)...") _engine = PaddleOCR( lang="en", text_recognition_model_name="latin_PP-OCRv5_mobile_rec", @@ -25,12 +31,27 @@ def get_engine(): use_doc_unwarping=False, use_textline_orientation=False, ) + logger.info("PaddleOCR model loaded successfully") return _engine +@app.on_event("startup") +def startup_load_model(): + """Pre-load model at startup so health check passes.""" + global _ready + try: + get_engine() + _ready = True + logger.info("PaddleOCR ready to serve requests") + except Exception as e: + logger.error(f"Failed to load PaddleOCR model: {e}") + + @app.get("/health") def health(): - return {"status": "ok", "model": "PP-OCRv5-latin"} + if _ready: + return {"status": "ok", "model": "PP-OCRv5-latin"} + return {"status": "loading"} @app.post("/ocr") @@ -41,6 +62,9 @@ async def ocr( if API_KEY and x_api_key != API_KEY: raise HTTPException(status_code=401, detail="Invalid API key") + if not _ready: + raise HTTPException(status_code=503, detail="Model still loading") + img_bytes = await file.read() img = Image.open(io.BytesIO(img_bytes)).convert("RGB") img_np = np.array(img)