fix: add document_timeout to PdfPipelineOptions (C1)
Docling's native document_timeout is the only mechanism that can interrupt processing inside a blocked thread (OCR, table extraction). Without it, asyncio.wait_for cannot stop a frozen conversion. Configurable via DOCUMENT_TIMEOUT env var (default: 120s). Closes #57 (C1)
This commit is contained in:
parent
5b6f138164
commit
4c76101142
4 changed files with 8 additions and 0 deletions
|
|
@ -42,6 +42,7 @@ from domain.value_objects import (
|
||||||
PageElement,
|
PageElement,
|
||||||
)
|
)
|
||||||
from infra.bbox import to_topleft_list
|
from infra.bbox import to_topleft_list
|
||||||
|
from infra.settings import settings
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
@ -102,6 +103,7 @@ def _build_docling_converter(options: ConversionOptions) -> DoclingConverter:
|
||||||
generate_page_images=options.generate_page_images,
|
generate_page_images=options.generate_page_images,
|
||||||
generate_picture_images=options.generate_picture_images,
|
generate_picture_images=options.generate_picture_images,
|
||||||
images_scale=options.images_scale,
|
images_scale=options.images_scale,
|
||||||
|
document_timeout=settings.document_timeout,
|
||||||
)
|
)
|
||||||
|
|
||||||
return DoclingConverter(
|
return DoclingConverter(
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ class Settings:
|
||||||
docling_serve_url: str = "http://localhost:5001"
|
docling_serve_url: str = "http://localhost:5001"
|
||||||
docling_serve_api_key: str | None = None
|
docling_serve_api_key: str | None = None
|
||||||
conversion_timeout: int = 900
|
conversion_timeout: int = 900
|
||||||
|
document_timeout: float = 120.0 # Docling-level per-document timeout (seconds)
|
||||||
max_concurrent_analyses: int = 3
|
max_concurrent_analyses: int = 3
|
||||||
max_page_count: int = 0 # 0 = unlimited
|
max_page_count: int = 0 # 0 = unlimited
|
||||||
upload_dir: str = "./uploads"
|
upload_dir: str = "./uploads"
|
||||||
|
|
@ -33,6 +34,7 @@ class Settings:
|
||||||
docling_serve_url=os.environ.get("DOCLING_SERVE_URL", "http://localhost:5001"),
|
docling_serve_url=os.environ.get("DOCLING_SERVE_URL", "http://localhost:5001"),
|
||||||
docling_serve_api_key=os.environ.get("DOCLING_SERVE_API_KEY"),
|
docling_serve_api_key=os.environ.get("DOCLING_SERVE_API_KEY"),
|
||||||
conversion_timeout=int(os.environ.get("CONVERSION_TIMEOUT", "900")),
|
conversion_timeout=int(os.environ.get("CONVERSION_TIMEOUT", "900")),
|
||||||
|
document_timeout=float(os.environ.get("DOCUMENT_TIMEOUT", "120.0")),
|
||||||
max_concurrent_analyses=int(os.environ.get("MAX_CONCURRENT_ANALYSES", "3")),
|
max_concurrent_analyses=int(os.environ.get("MAX_CONCURRENT_ANALYSES", "3")),
|
||||||
max_page_count=int(os.environ.get("MAX_PAGE_COUNT", "0")),
|
max_page_count=int(os.environ.get("MAX_PAGE_COUNT", "0")),
|
||||||
upload_dir=os.environ.get("UPLOAD_DIR", "./uploads"),
|
upload_dir=os.environ.get("UPLOAD_DIR", "./uploads"),
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@ class TestBuildConverter:
|
||||||
assert opts.generate_page_images is False
|
assert opts.generate_page_images is False
|
||||||
assert opts.generate_picture_images is False
|
assert opts.generate_picture_images is False
|
||||||
assert opts.images_scale == 1.0
|
assert opts.images_scale == 1.0
|
||||||
|
assert opts.document_timeout is not None
|
||||||
|
|
||||||
def test_ocr_disabled(self):
|
def test_ocr_disabled(self):
|
||||||
conv = build_converter(ConversionOptions(do_ocr=False))
|
conv = build_converter(ConversionOptions(do_ocr=False))
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ class TestSettingsDefaults:
|
||||||
assert s.docling_serve_url == "http://localhost:5001"
|
assert s.docling_serve_url == "http://localhost:5001"
|
||||||
assert s.docling_serve_api_key is None
|
assert s.docling_serve_api_key is None
|
||||||
assert s.conversion_timeout == 900
|
assert s.conversion_timeout == 900
|
||||||
|
assert s.document_timeout == 120.0
|
||||||
assert s.max_page_count == 0
|
assert s.max_page_count == 0
|
||||||
assert s.upload_dir == "./uploads"
|
assert s.upload_dir == "./uploads"
|
||||||
assert s.db_path == "./data/docling_studio.db"
|
assert s.db_path == "./data/docling_studio.db"
|
||||||
|
|
@ -36,6 +37,7 @@ class TestSettingsFromEnv:
|
||||||
monkeypatch.setenv("DOCLING_SERVE_URL", "http://serve:9000")
|
monkeypatch.setenv("DOCLING_SERVE_URL", "http://serve:9000")
|
||||||
monkeypatch.setenv("DOCLING_SERVE_API_KEY", "secret-key")
|
monkeypatch.setenv("DOCLING_SERVE_API_KEY", "secret-key")
|
||||||
monkeypatch.setenv("CONVERSION_TIMEOUT", "120")
|
monkeypatch.setenv("CONVERSION_TIMEOUT", "120")
|
||||||
|
monkeypatch.setenv("DOCUMENT_TIMEOUT", "60.0")
|
||||||
monkeypatch.setenv("MAX_PAGE_COUNT", "20")
|
monkeypatch.setenv("MAX_PAGE_COUNT", "20")
|
||||||
monkeypatch.setenv("UPLOAD_DIR", "/data/uploads")
|
monkeypatch.setenv("UPLOAD_DIR", "/data/uploads")
|
||||||
monkeypatch.setenv("DB_PATH", "/data/test.db")
|
monkeypatch.setenv("DB_PATH", "/data/test.db")
|
||||||
|
|
@ -49,6 +51,7 @@ class TestSettingsFromEnv:
|
||||||
assert s.docling_serve_url == "http://serve:9000"
|
assert s.docling_serve_url == "http://serve:9000"
|
||||||
assert s.docling_serve_api_key == "secret-key"
|
assert s.docling_serve_api_key == "secret-key"
|
||||||
assert s.conversion_timeout == 120
|
assert s.conversion_timeout == 120
|
||||||
|
assert s.document_timeout == 60.0
|
||||||
assert s.max_page_count == 20
|
assert s.max_page_count == 20
|
||||||
assert s.upload_dir == "/data/uploads"
|
assert s.upload_dir == "/data/uploads"
|
||||||
assert s.db_path == "/data/test.db"
|
assert s.db_path == "/data/test.db"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue