From f71a02db2f27fe56467794a0f53a6d331414a273 Mon Sep 17 00:00:00 2001 From: CREDO23 Date: Wed, 27 May 2026 15:02:36 +0200 Subject: [PATCH] feat(automation): add automation run repository --- .../app/automations/runtime/repository.py | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 surfsense_backend/app/automations/runtime/repository.py diff --git a/surfsense_backend/app/automations/runtime/repository.py b/surfsense_backend/app/automations/runtime/repository.py new file mode 100644 index 000000000..a8bdbc55a --- /dev/null +++ b/surfsense_backend/app/automations/runtime/repository.py @@ -0,0 +1,62 @@ +"""Persistence operations on ``AutomationRun``. Pure SQL, no business logic.""" + +from __future__ import annotations + +from datetime import UTC, datetime +from typing import Any + +from sqlalchemy import select +from sqlalchemy.ext.asyncio import AsyncSession +from sqlalchemy.orm import selectinload + +from app.automations.persistence.enums.run_status import RunStatus +from app.automations.persistence.models.run import AutomationRun + + +async def load_run(session: AsyncSession, run_id: int) -> AutomationRun | None: + """Load a run with its automation and trigger eagerly loaded.""" + stmt = ( + select(AutomationRun) + .where(AutomationRun.id == run_id) + .options( + selectinload(AutomationRun.automation), + selectinload(AutomationRun.trigger), + ) + ) + result = await session.execute(stmt) + return result.scalar_one_or_none() + + +async def mark_running(session: AsyncSession, run: AutomationRun) -> None: + run.status = RunStatus.RUNNING + run.started_at = datetime.now(UTC) + await session.flush() + + +async def mark_succeeded(session: AsyncSession, run: AutomationRun) -> None: + run.status = RunStatus.SUCCEEDED + run.finished_at = datetime.now(UTC) + await session.flush() + + +async def mark_failed( + session: AsyncSession, + run: AutomationRun, + error: dict[str, Any] | None, +) -> None: + run.status = RunStatus.FAILED + run.finished_at = datetime.now(UTC) + run.error = error + await session.flush() + + +async def append_step_result( + session: AsyncSession, + run: AutomationRun, + step_result: dict[str, Any], +) -> None: + """Append one step result. Reassigns the list so SQLAlchemy detects the change.""" + current = list(run.step_results or []) + current.append(step_result) + run.step_results = current + await session.flush()