From e75ca4c79a3056791c514a212c75e781c3145a42 Mon Sep 17 00:00:00 2001 From: John Lancaster <32917998+jsl12@users.noreply.github.com> Date: Sat, 27 Jun 2026 10:38:17 -0500 Subject: [PATCH] service base --- src/transcription/services/base.py | 26 +++++++++++++++++++++++++ src/transcription/services/documents.py | 21 +++++++++++--------- src/transcription/services/jobs.py | 11 ++--------- 3 files changed, 40 insertions(+), 18 deletions(-) create mode 100644 src/transcription/services/base.py diff --git a/src/transcription/services/base.py b/src/transcription/services/base.py new file mode 100644 index 0000000..1d6522a --- /dev/null +++ b/src/transcription/services/base.py @@ -0,0 +1,26 @@ +import asyncio +from abc import ABC + +from sqlalchemy.ext.asyncio import async_sessionmaker +from sqlmodel.ext.asyncio.session import AsyncSession + +from ..config import Settings +from ..config import get_settings +from ..db.runtime import get_session_factory + + +class ServiceBase(ABC): + """Thin service class for managing documents in the database.""" + + settings: Settings + session_factory: async_sessionmaker[AsyncSession] + queue: asyncio.Queue + + def __init__( + self, + session_factory: async_sessionmaker[AsyncSession] | None = None, + queue: asyncio.Queue | None = None, + ): + self.settings = get_settings() + self.session_factory = session_factory or get_session_factory() + self.queue = queue or asyncio.Queue() diff --git a/src/transcription/services/documents.py b/src/transcription/services/documents.py index 9d15d63..3f5320a 100644 --- a/src/transcription/services/documents.py +++ b/src/transcription/services/documents.py @@ -1,23 +1,22 @@ from collections.abc import Sequence +from pathlib import Path from uuid import UUID -from sqlalchemy.ext.asyncio import async_sessionmaker from sqlalchemy.orm import selectinload from sqlmodel import select -from sqlmodel.ext.asyncio.session import AsyncSession -from ..db.runtime import get_session_factory +from ..errors import AppError from ..models import Document +from .base import ServiceBase -class DocumentService: +class MissingImageError(AppError): + """Raised when a required image is missing.""" + + +class DocumentService(ServiceBase): """Thin service class for managing documents in the database.""" - session_factory: async_sessionmaker[AsyncSession] - - def __init__(self, session_factory: async_sessionmaker[AsyncSession] | None = None): - self.session_factory = session_factory or get_session_factory() - async def create_document(self, document: Document) -> Document: """Create a new document in the database.""" async with self.session_factory() as session: @@ -39,6 +38,10 @@ class DocumentService: ) if document is None: raise ValueError(f"Document with id {document_id} not found") + elif not Path(document.file_path).exists(): + raise MissingImageError( + f"Document with id {document_id} is missing its image file in {self.settings.upload_dir:!s}" + ) return document async def update_document(self, document: Document) -> Document: diff --git a/src/transcription/services/jobs.py b/src/transcription/services/jobs.py index 9dfac87..5963cd5 100644 --- a/src/transcription/services/jobs.py +++ b/src/transcription/services/jobs.py @@ -1,24 +1,17 @@ from collections.abc import Sequence from uuid import UUID -from sqlalchemy.ext.asyncio import async_sessionmaker from sqlalchemy.orm import selectinload from sqlmodel import select -from sqlmodel.ext.asyncio.session import AsyncSession -from ..db.runtime import get_session_factory from ..models import Job from ..models import JobStatus +from .base import ServiceBase -class JobService: +class JobService(ServiceBase): """Thin service class for managing jobs in the database.""" - session_factory: async_sessionmaker[AsyncSession] - - def __init__(self, session_factory: async_sessionmaker[AsyncSession] | None = None): - self.session_factory = session_factory or get_session_factory() - async def create_job(self, job: Job) -> Job: """Create a new job in the database.""" async with self.session_factory() as session: