{ "cells": [ { "cell_type": "code", "execution_count": 1, "id": "c2b3a63a", "metadata": {}, "outputs": [], "source": [ "%load_ext autoreload\n", "%autoreload 2" ] }, { "cell_type": "code", "execution_count": null, "id": "a84d3520", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2026-06-27 22:09:01 DEBUG | Logging configured\n", "2026-06-27 22:09:01 DEBUG | Initialized async database runtime for database_url=sqlite+aiosqlite:///./transcription.db\n", "2026-06-27 22:09:01 DEBUG | Database schema bootstrap complete for database_url=sqlite+aiosqlite:///./transcription.db\n" ] } ], "source": [ "from pathlib import Path\n", "from uuid import UUID\n", "\n", "import rich\n", "\n", "from transcription.config import configure_logging\n", "from transcription.config import get_settings\n", "from transcription.db.operations import create_all\n", "from transcription.db.runtime import get_engine\n", "from transcription.db.runtime import get_session\n", "from transcription.models import Document\n", "from transcription.models import Job\n", "from transcription.models import JobStatus\n", "from transcription.services import ServiceBundle\n", "from transcription.services.documents import DocumentService\n", "from transcription.services.documents import create_upload_job\n", "from transcription.services.jobs import JobService\n", "from transcription.services.store import store_file\n", "from transcription.worker import process_queued_job\n", "\n", "configure_logging()\n", "settings = get_settings(worker_max_retries=2)\n", "engine = get_engine(settings=settings)\n", "await create_all(engine=engine)\n", "services = ServiceBundle()" ] }, { "cell_type": "code", "execution_count": 3, "id": "b3b2c783", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
[\n", " Job(\n", " id=UUID('c79d20d1-ab5c-4b3b-a898-13eac7d2c71a'),\n", " retry_count=0,\n", " updated_at=datetime.datetime(2026, 6, 28, 2, 55, 13, 69063),\n", " document_id=UUID('105e84b2-d773-4abb-bd49-8dc26b966046'),\n", " status=<JobStatus.TRANSCRIBED: 'transcribed'>,\n", " created_at=datetime.datetime(2026, 6, 28, 2, 55, 13, 69054)\n", " ),\n", " Job(\n", " id=UUID('271b688e-63c7-4652-9ccf-5c1dd3f61058'),\n", " retry_count=0,\n", " updated_at=datetime.datetime(2026, 6, 28, 2, 55, 17, 189346),\n", " document_id=UUID('06f49121-9b98-4b0e-b879-7a3b959fe984'),\n", " status=<JobStatus.TRANSCRIBED: 'transcribed'>,\n", " created_at=datetime.datetime(2026, 6, 28, 2, 55, 17, 189338)\n", " ),\n", " Job(\n", " id=UUID('4386391c-3ce9-412a-9bd4-46b3860d0ef7'),\n", " retry_count=0,\n", " updated_at=datetime.datetime(2026, 6, 28, 2, 55, 19, 161570),\n", " document_id=UUID('ac04c024-25ca-4707-8cd8-641606976344'),\n", " status=<JobStatus.TRANSCRIBED: 'transcribed'>,\n", " created_at=datetime.datetime(2026, 6, 28, 2, 55, 19, 161560)\n", " ),\n", " Job(\n", " id=UUID('6637b36d-82e1-41e1-8776-037183851d30'),\n", " retry_count=0,\n", " updated_at=datetime.datetime(2026, 6, 28, 2, 55, 26, 921982),\n", " document_id=UUID('9c6d8632-fe6b-4f70-bb9b-5e8d762b4b3e'),\n", " status=<JobStatus.TRANSCRIBED: 'transcribed'>,\n", " created_at=datetime.datetime(2026, 6, 28, 2, 55, 26, 921974)\n", " ),\n", " Job(\n", " id=UUID('758f457a-343c-4b4a-98af-278875303803'),\n", " retry_count=0,\n", " updated_at=datetime.datetime(2026, 6, 28, 3, 4, 40, 999438),\n", " document_id=UUID('0fb70d21-6409-40cc-83df-abce2917f367'),\n", " status=<JobStatus.TRANSCRIBED: 'transcribed'>,\n", " created_at=datetime.datetime(2026, 6, 28, 3, 4, 40, 999427)\n", " ),\n", " Job(\n", " id=UUID('01060a33-464d-48c9-b4bb-f1f6acd91820'),\n", " retry_count=0,\n", " updated_at=datetime.datetime(2026, 6, 28, 3, 7, 6, 284063),\n", " document_id=UUID('c8d0eacb-87dd-4d88-a576-ce810436dc45'),\n", " status=<JobStatus.TRANSCRIBED: 'transcribed'>,\n", " created_at=datetime.datetime(2026, 6, 28, 3, 7, 6, 284053)\n", " ),\n", " Job(\n", " id=UUID('50800d67-fece-452e-b3ff-b7045fb1838f'),\n", " retry_count=0,\n", " updated_at=datetime.datetime(2026, 6, 28, 3, 8, 2, 737235),\n", " document_id=UUID('273a58fd-4c4d-4e3a-93dd-4f391650e646'),\n", " status=<JobStatus.TRANSCRIBED: 'transcribed'>,\n", " created_at=datetime.datetime(2026, 6, 28, 3, 8, 2, 737226)\n", " )\n", "]\n", "\n" ], "text/plain": [ "\u001b[1m[\u001b[0m\n", " \u001b[1;35mJob\u001b[0m\u001b[1m(\u001b[0m\n", " \u001b[33mid\u001b[0m=\u001b[1;35mUUID\u001b[0m\u001b[1m(\u001b[0m\u001b[32m'c79d20d1-ab5c-4b3b-a898-13eac7d2c71a'\u001b[0m\u001b[1m)\u001b[0m,\n", " \u001b[33mretry_count\u001b[0m=\u001b[1;36m0\u001b[0m,\n", " \u001b[33mupdated_at\u001b[0m=\u001b[1;35mdatetime\u001b[0m\u001b[1;35m.datetime\u001b[0m\u001b[1m(\u001b[0m\u001b[1;36m2026\u001b[0m, \u001b[1;36m6\u001b[0m, \u001b[1;36m28\u001b[0m, \u001b[1;36m2\u001b[0m, \u001b[1;36m55\u001b[0m, \u001b[1;36m13\u001b[0m, \u001b[1;36m69063\u001b[0m\u001b[1m)\u001b[0m,\n", " \u001b[33mdocument_id\u001b[0m=\u001b[1;35mUUID\u001b[0m\u001b[1m(\u001b[0m\u001b[32m'105e84b2-d773-4abb-bd49-8dc26b966046'\u001b[0m\u001b[1m)\u001b[0m,\n", " \u001b[33mstatus\u001b[0m=\u001b[1m<\u001b[0m\u001b[1;95mJobStatus.TRANSCRIBED:\u001b[0m\u001b[39m \u001b[0m\u001b[32m'transcribed'\u001b[0m\u001b[39m>,\u001b[0m\n", "\u001b[39m \u001b[0m\u001b[33mcreated_at\u001b[0m\u001b[39m=\u001b[0m\u001b[1;35mdatetime\u001b[0m\u001b[1;35m.datetime\u001b[0m\u001b[1;39m(\u001b[0m\u001b[1;36m2026\u001b[0m\u001b[39m, \u001b[0m\u001b[1;36m6\u001b[0m\u001b[39m, \u001b[0m\u001b[1;36m28\u001b[0m\u001b[39m, \u001b[0m\u001b[1;36m2\u001b[0m\u001b[39m, \u001b[0m\u001b[1;36m55\u001b[0m\u001b[39m, \u001b[0m\u001b[1;36m13\u001b[0m\u001b[39m, \u001b[0m\u001b[1;36m69054\u001b[0m\u001b[1;39m)\u001b[0m\n", "\u001b[39m \u001b[0m\u001b[1;39m)\u001b[0m\u001b[39m,\u001b[0m\n", "\u001b[39m \u001b[0m\u001b[1;35mJob\u001b[0m\u001b[1;39m(\u001b[0m\n", "\u001b[39m \u001b[0m\u001b[33mid\u001b[0m\u001b[39m=\u001b[0m\u001b[1;35mUUID\u001b[0m\u001b[1;39m(\u001b[0m\u001b[32m'271b688e-63c7-4652-9ccf-5c1dd3f61058'\u001b[0m\u001b[1;39m)\u001b[0m\u001b[39m,\u001b[0m\n", "\u001b[39m \u001b[0m\u001b[33mretry_count\u001b[0m\u001b[39m=\u001b[0m\u001b[1;36m0\u001b[0m\u001b[39m,\u001b[0m\n", "\u001b[39m \u001b[0m\u001b[33mupdated_at\u001b[0m\u001b[39m=\u001b[0m\u001b[1;35mdatetime\u001b[0m\u001b[1;35m.datetime\u001b[0m\u001b[1;39m(\u001b[0m\u001b[1;36m2026\u001b[0m\u001b[39m, \u001b[0m\u001b[1;36m6\u001b[0m\u001b[39m, \u001b[0m\u001b[1;36m28\u001b[0m\u001b[39m, \u001b[0m\u001b[1;36m2\u001b[0m\u001b[39m, \u001b[0m\u001b[1;36m55\u001b[0m\u001b[39m, \u001b[0m\u001b[1;36m17\u001b[0m\u001b[39m, \u001b[0m\u001b[1;36m189346\u001b[0m\u001b[1;39m)\u001b[0m\u001b[39m,\u001b[0m\n", "\u001b[39m \u001b[0m\u001b[33mdocument_id\u001b[0m\u001b[39m=\u001b[0m\u001b[1;35mUUID\u001b[0m\u001b[1;39m(\u001b[0m\u001b[32m'06f49121-9b98-4b0e-b879-7a3b959fe984'\u001b[0m\u001b[1;39m)\u001b[0m\u001b[39m,\u001b[0m\n", "\u001b[39m \u001b[0m\u001b[33mstatus\u001b[0m\u001b[39m=
UploadJobResult(\n", " document_id=UUID('7102ad0c-dcc3-4164-a86f-4e601fe31e70'),\n", " job_id=UUID('5bb45fc1-6b3b-4e92-9942-f8f059baaaaf'),\n", " stored_path=PosixPath('uploads/9d3ce411-e027-4e97-9c11-786783926ce4_Time Rolls On - page 013.jpg'),\n", " original_filename='Time Rolls On - page 013.jpg'\n", ")\n", "\n" ], "text/plain": [ "\u001b[1;35mUploadJobResult\u001b[0m\u001b[1m(\u001b[0m\n", " \u001b[33mdocument_id\u001b[0m=\u001b[1;35mUUID\u001b[0m\u001b[1m(\u001b[0m\u001b[32m'7102ad0c-dcc3-4164-a86f-4e601fe31e70'\u001b[0m\u001b[1m)\u001b[0m,\n", " \u001b[33mjob_id\u001b[0m=\u001b[1;35mUUID\u001b[0m\u001b[1m(\u001b[0m\u001b[32m'5bb45fc1-6b3b-4e92-9942-f8f059baaaaf'\u001b[0m\u001b[1m)\u001b[0m,\n", " \u001b[33mstored_path\u001b[0m=\u001b[1;35mPosixPath\u001b[0m\u001b[1m(\u001b[0m\u001b[32m'uploads/9d3ce411-e027-4e97-9c11-786783926ce4_Time Rolls On - page 013.jpg'\u001b[0m\u001b[1m)\u001b[0m,\n", " \u001b[33moriginal_filename\u001b[0m=\u001b[32m'Time Rolls On - page 013.jpg'\u001b[0m\n", "\u001b[1m)\u001b[0m\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "async with get_session(settings=settings) as session:\n", " result = await create_upload_job(\n", " session=session,\n", " filename=doc_path.name.rpartition(\"_\")[2],\n", " file_bytes=doc_path.read_bytes(),\n", " settings=settings,\n", " )\n", "\n", "rich.print(result)" ] }, { "cell_type": "code", "execution_count": 6, "id": "c3d92127", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
Job(\n", " id=UUID('5bb45fc1-6b3b-4e92-9942-f8f059baaaaf'),\n", " retry_count=0,\n", " updated_at=datetime.datetime(2026, 6, 28, 3, 9, 1, 351464),\n", " document_id=UUID('7102ad0c-dcc3-4164-a86f-4e601fe31e70'),\n", " status=<JobStatus.QUEUED: 'queued'>,\n", " created_at=datetime.datetime(2026, 6, 28, 3, 9, 1, 351451)\n", ")\n", "\n" ], "text/plain": [ "\u001b[1;35mJob\u001b[0m\u001b[1m(\u001b[0m\n", " \u001b[33mid\u001b[0m=\u001b[1;35mUUID\u001b[0m\u001b[1m(\u001b[0m\u001b[32m'5bb45fc1-6b3b-4e92-9942-f8f059baaaaf'\u001b[0m\u001b[1m)\u001b[0m,\n", " \u001b[33mretry_count\u001b[0m=\u001b[1;36m0\u001b[0m,\n", " \u001b[33mupdated_at\u001b[0m=\u001b[1;35mdatetime\u001b[0m\u001b[1;35m.datetime\u001b[0m\u001b[1m(\u001b[0m\u001b[1;36m2026\u001b[0m, \u001b[1;36m6\u001b[0m, \u001b[1;36m28\u001b[0m, \u001b[1;36m3\u001b[0m, \u001b[1;36m9\u001b[0m, \u001b[1;36m1\u001b[0m, \u001b[1;36m351464\u001b[0m\u001b[1m)\u001b[0m,\n", " \u001b[33mdocument_id\u001b[0m=\u001b[1;35mUUID\u001b[0m\u001b[1m(\u001b[0m\u001b[32m'7102ad0c-dcc3-4164-a86f-4e601fe31e70'\u001b[0m\u001b[1m)\u001b[0m,\n", " \u001b[33mstatus\u001b[0m=\u001b[1m<\u001b[0m\u001b[1;95mJobStatus.QUEUED:\u001b[0m\u001b[39m \u001b[0m\u001b[32m'queued'\u001b[0m\u001b[1m>\u001b[0m,\n", " \u001b[33mcreated_at\u001b[0m=\u001b[1;35mdatetime\u001b[0m\u001b[1;35m.datetime\u001b[0m\u001b[1m(\u001b[0m\u001b[1;36m2026\u001b[0m, \u001b[1;36m6\u001b[0m, \u001b[1;36m28\u001b[0m, \u001b[1;36m3\u001b[0m, \u001b[1;36m9\u001b[0m, \u001b[1;36m1\u001b[0m, \u001b[1;36m351451\u001b[0m\u001b[1m)\u001b[0m\n", "\u001b[1m)\u001b[0m\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import random\n", "\n", "job = random.choice(await services.jobs.query_jobs(status=JobStatus.QUEUED))\n", "rich.print(job)" ] }, { "cell_type": "code", "execution_count": 7, "id": "5209430c", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2026-06-27 22:09:01 DEBUG | Initialized async database runtime for database_url=sqlite+aiosqlite:///./transcription.db\n" ] }, { "data": { "text/html": [ "
Job(\n", " id=UUID('5bb45fc1-6b3b-4e92-9942-f8f059baaaaf'),\n", " retry_count=0,\n", " updated_at=datetime.datetime(2026, 6, 28, 3, 9, 1, 351464),\n", " document_id=UUID('7102ad0c-dcc3-4164-a86f-4e601fe31e70'),\n", " status=<JobStatus.QUEUED: 'queued'>,\n", " created_at=datetime.datetime(2026, 6, 28, 3, 9, 1, 351451)\n", ")\n", "\n" ], "text/plain": [ "\u001b[1;35mJob\u001b[0m\u001b[1m(\u001b[0m\n", " \u001b[33mid\u001b[0m=\u001b[1;35mUUID\u001b[0m\u001b[1m(\u001b[0m\u001b[32m'5bb45fc1-6b3b-4e92-9942-f8f059baaaaf'\u001b[0m\u001b[1m)\u001b[0m,\n", " \u001b[33mretry_count\u001b[0m=\u001b[1;36m0\u001b[0m,\n", " \u001b[33mupdated_at\u001b[0m=\u001b[1;35mdatetime\u001b[0m\u001b[1;35m.datetime\u001b[0m\u001b[1m(\u001b[0m\u001b[1;36m2026\u001b[0m, \u001b[1;36m6\u001b[0m, \u001b[1;36m28\u001b[0m, \u001b[1;36m3\u001b[0m, \u001b[1;36m9\u001b[0m, \u001b[1;36m1\u001b[0m, \u001b[1;36m351464\u001b[0m\u001b[1m)\u001b[0m,\n", " \u001b[33mdocument_id\u001b[0m=\u001b[1;35mUUID\u001b[0m\u001b[1m(\u001b[0m\u001b[32m'7102ad0c-dcc3-4164-a86f-4e601fe31e70'\u001b[0m\u001b[1m)\u001b[0m,\n", " \u001b[33mstatus\u001b[0m=\u001b[1m<\u001b[0m\u001b[1;95mJobStatus.QUEUED:\u001b[0m\u001b[39m \u001b[0m\u001b[32m'queued'\u001b[0m\u001b[1m>\u001b[0m,\n", " \u001b[33mcreated_at\u001b[0m=\u001b[1;35mdatetime\u001b[0m\u001b[1;35m.datetime\u001b[0m\u001b[1m(\u001b[0m\u001b[1;36m2026\u001b[0m, \u001b[1;36m6\u001b[0m, \u001b[1;36m28\u001b[0m, \u001b[1;36m3\u001b[0m, \u001b[1;36m9\u001b[0m, \u001b[1;36m1\u001b[0m, \u001b[1;36m351451\u001b[0m\u001b[1m)\u001b[0m\n", "\u001b[1m)\u001b[0m\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "async with get_session(settings=settings) as session:\n", " jobs = await services.jobs.query_jobs(\n", " status=JobStatus.QUEUED,\n", " session=session,\n", " )\n", "\n", " job = random.choice(jobs)\n", " job = Job.model_copy(job)\n", "\n", "rich.print(job)" ] }, { "cell_type": "code", "execution_count": null, "id": "569e5d9f", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2026-06-27 22:09:06 DEBUG | Initialized async database runtime for database_url=sqlite+aiosqlite:///./transcription.db\n" ] }, { "ename": "InvalidRequestError", "evalue": "Instance '