75 lines
2.3 KiB
Python
75 lines
2.3 KiB
Python
"""FastAPI application entrypoint.
|
|
|
|
This file is intentionally small:
|
|
- Routes call into a job manager.
|
|
- The job manager calls the pipeline.
|
|
|
|
Keeping the web layer thin makes the business logic easier to test and maintain.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
|
|
from fastapi import BackgroundTasks, Depends, FastAPI, HTTPException
|
|
|
|
from notebook_tools.jobs import JobManager, get_job_manager
|
|
from notebook_tools.logging_utils import configure_logging
|
|
from notebook_tools.models import JobStartRequest, JobStatusResponse
|
|
from notebook_tools.settings import Settings, get_settings
|
|
|
|
app = FastAPI(title="notebook-tools", version="0.1.0")
|
|
logger = logging.getLogger("notebook_tools.api")
|
|
|
|
|
|
@app.on_event("startup")
|
|
async def _startup() -> None:
|
|
# Load settings once at startup so we fail fast if env vars are missing.
|
|
settings = get_settings()
|
|
configure_logging(level=settings.log_level)
|
|
logger.info("Service starting up")
|
|
|
|
|
|
@app.get("/health")
|
|
async def health() -> dict[str, str]:
|
|
return {"status": "ok"}
|
|
|
|
|
|
@app.post("/jobs/paperless/{document_id}", response_model=JobStatusResponse)
|
|
async def start_job_for_paperless_document(
|
|
document_id: int,
|
|
req: JobStartRequest,
|
|
background: BackgroundTasks,
|
|
settings: Settings = Depends(get_settings),
|
|
manager: JobManager = Depends(get_job_manager),
|
|
) -> JobStatusResponse:
|
|
"""Start an OCR job for an existing Paperless document id."""
|
|
|
|
if document_id <= 0:
|
|
raise HTTPException(status_code=422, detail="document_id must be a positive integer")
|
|
|
|
job = manager.create_job(document_id=document_id, notebook_id=req.notebook_id)
|
|
logger.info(
|
|
"Job created job_id=%s paperless_document_id=%s notebook_id=%s",
|
|
job.job_id,
|
|
document_id,
|
|
req.notebook_id,
|
|
)
|
|
background.add_task(
|
|
manager.run_job,
|
|
job_id=job.job_id,
|
|
settings=settings,
|
|
ocr_prompt_override=req.ocr_prompt,
|
|
title_prefix=req.title_prefix,
|
|
)
|
|
return job
|
|
|
|
|
|
@app.get("/jobs/{job_id}", response_model=JobStatusResponse)
|
|
async def get_job(job_id: str, manager: JobManager = Depends(get_job_manager)) -> JobStatusResponse:
|
|
job = manager.get_job(job_id)
|
|
if not job:
|
|
raise HTTPException(status_code=404, detail="job not found")
|
|
return job
|
|
|