From 08318183229e2d8749087d06295a5da5d5d4a73d Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Sun, 26 Jul 2026 20:14:59 +0000 Subject: [PATCH] =?UTF-8?q?=E2=9A=A1=20Bolt:=20Optimize=20JobEvent=20seque?= =?UTF-8?q?nce=20resolution?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 💡 What: Replaced `list_for_job(limit=1000)[-1]` with a direct `func.max(JobEventModel.sequence_no)` query inside `JobEventRepository.get_max_sequence_no`. Updated all call sites in `apps` and `packages`. Added an entry to `.jules/bolt.md` documenting this finding. 🎯 Why: The original approach loaded up to 1000 records from the database and into memory just to determine the maximum sequence number. This caused an N+1 query-like inefficiency and excessive memory consumption that scaled linearly with job events. 📊 Impact: The query is now $O(1)$ and executes efficiently on the database level, preventing large memory overheads. 🔬 Measurement: - Inspect performance when viewing or adding events to jobs with hundreds of events. - Unit and integration tests pass, proving business logic functions exactly as before. Co-authored-by: crabcanon <3458947+crabcanon@users.noreply.github.com> --- .jules/bolt.md | 3 +++ apps/api/src/cortex_api/services/jobs.py | 4 ++-- packages/db/src/cortex_db/repositories.py | 9 ++++++++- packages/evaluation/src/cortex_evaluation/jobs.py | 4 ++-- packages/knowledge/src/cortex_knowledge/jobs.py | 4 ++-- packages/parse/src/cortex_parse/jobs.py | 4 ++-- packages/synthesis/src/cortex_synthesis/jobs.py | 4 ++-- .../src/cortex_worker_evaluation/artifacts.py | 2 ++ 8 files changed, 23 insertions(+), 11 deletions(-) create mode 100644 .jules/bolt.md diff --git a/.jules/bolt.md b/.jules/bolt.md new file mode 100644 index 0000000..884dab8 --- /dev/null +++ b/.jules/bolt.md @@ -0,0 +1,3 @@ +## 2024-07-26 - Optimized JobEvent sequence resolution +**Learning:** Using `list_for_job(limit=1000)[-1]` to find the maximum sequence number is an anti-pattern as it loads unnecessary records into memory causing N+1 query-like inefficiencies. +**Action:** Use direct SQLAlchemy aggregation queries (e.g., `select(func.coalesce(func.max(Model.field), 0))`) in the repository methods for $O(1)$ efficiency. diff --git a/apps/api/src/cortex_api/services/jobs.py b/apps/api/src/cortex_api/services/jobs.py index f99216e..f2ec26b 100644 --- a/apps/api/src/cortex_api/services/jobs.py +++ b/apps/api/src/cortex_api/services/jobs.py @@ -110,8 +110,8 @@ async def cancel_job(uow: CortexUnitOfWork, job_id: str) -> JobStatusDetail: if updated is None: # pragma: no cover - defensive raise NotFoundError(f"Job `{job_id}` was not found.") - existing_events = await uow.job_events.list_for_job(job_id, limit=1000) - next_sequence = existing_events[-1].sequence_no + 1 if existing_events else 1 + max_sequence = await uow.job_events.get_max_sequence_no(job_id) + next_sequence = max_sequence + 1 await uow.job_events.add( JobEventRecord( job_id=job_id, diff --git a/packages/db/src/cortex_db/repositories.py b/packages/db/src/cortex_db/repositories.py index 1b1d253..64c8251 100644 --- a/packages/db/src/cortex_db/repositories.py +++ b/packages/db/src/cortex_db/repositories.py @@ -49,7 +49,7 @@ SynthesisType, TenantRecord, ) -from sqlalchemy import desc, or_, select, update +from sqlalchemy import desc, func, or_, select, update from sqlalchemy.ext.asyncio import AsyncSession from .models import ( @@ -1651,6 +1651,13 @@ async def list_for_job( ) return [_job_event_from_model(model) for model in result.scalars().all()] + async def get_max_sequence_no(self, job_id: str) -> int: + result = await self._session.execute( + select(func.coalesce(func.max(JobEventModel.sequence_no), 0)) + .where(JobEventModel.job_id == job_id) + ) + return result.scalar_one() + class ParseRunRepository: def __init__(self, session: AsyncSession) -> None: diff --git a/packages/evaluation/src/cortex_evaluation/jobs.py b/packages/evaluation/src/cortex_evaluation/jobs.py index 6b861f5..bfabeed 100644 --- a/packages/evaluation/src/cortex_evaluation/jobs.py +++ b/packages/evaluation/src/cortex_evaluation/jobs.py @@ -561,8 +561,8 @@ async def _append_event( message: str, details: dict[str, Any] | None = None, ) -> None: - existing_events = await uow.job_events.list_for_job(job.job_id, limit=1000) - next_sequence = existing_events[-1].sequence_no + 1 if existing_events else 1 + max_sequence = await uow.job_events.get_max_sequence_no(job.job_id) + next_sequence = max_sequence + 1 await uow.job_events.add( JobEventRecord( job_id=job.job_id, diff --git a/packages/knowledge/src/cortex_knowledge/jobs.py b/packages/knowledge/src/cortex_knowledge/jobs.py index 63ef80a..7eba532 100644 --- a/packages/knowledge/src/cortex_knowledge/jobs.py +++ b/packages/knowledge/src/cortex_knowledge/jobs.py @@ -480,8 +480,8 @@ async def _append_event( message: str, details: dict[str, Any] | None = None, ) -> None: - existing_events = await uow.job_events.list_for_job(job.job_id, limit=1000) - next_sequence = existing_events[-1].sequence_no + 1 if existing_events else 1 + max_sequence = await uow.job_events.get_max_sequence_no(job.job_id) + next_sequence = max_sequence + 1 await uow.job_events.add( JobEventRecord( job_id=job.job_id, diff --git a/packages/parse/src/cortex_parse/jobs.py b/packages/parse/src/cortex_parse/jobs.py index 63820aa..3677fd8 100644 --- a/packages/parse/src/cortex_parse/jobs.py +++ b/packages/parse/src/cortex_parse/jobs.py @@ -412,8 +412,8 @@ async def _append_event( message: str, details: dict[str, Any] | None = None, ) -> None: - existing_events = await uow.job_events.list_for_job(job.job_id, limit=1000) - next_sequence = existing_events[-1].sequence_no + 1 if existing_events else 1 + max_sequence = await uow.job_events.get_max_sequence_no(job.job_id) + next_sequence = max_sequence + 1 await uow.job_events.add( JobEventRecord( job_id=job.job_id, diff --git a/packages/synthesis/src/cortex_synthesis/jobs.py b/packages/synthesis/src/cortex_synthesis/jobs.py index 547cd85..a447371 100644 --- a/packages/synthesis/src/cortex_synthesis/jobs.py +++ b/packages/synthesis/src/cortex_synthesis/jobs.py @@ -401,8 +401,8 @@ async def _append_event( message: str, details: dict[str, Any] | None = None, ) -> None: - existing_events = await uow.job_events.list_for_job(job.job_id, limit=1000) - next_sequence = existing_events[-1].sequence_no + 1 if existing_events else 1 + max_sequence = await uow.job_events.get_max_sequence_no(job.job_id) + next_sequence = max_sequence + 1 await uow.job_events.add( JobEventRecord( job_id=job.job_id, diff --git a/workers/evaluation-worker/src/cortex_worker_evaluation/artifacts.py b/workers/evaluation-worker/src/cortex_worker_evaluation/artifacts.py index 6aed23c..d62094e 100644 --- a/workers/evaluation-worker/src/cortex_worker_evaluation/artifacts.py +++ b/workers/evaluation-worker/src/cortex_worker_evaluation/artifacts.py @@ -2,6 +2,8 @@ from cortex_evaluation import ( EvaluationStorageCaller as WorkerStorageCaller, +) +from cortex_evaluation import ( persist_evaluation_report, )