feat(v2): persist execution event revisions
This commit is contained in:
@@ -7,7 +7,7 @@ from sqlalchemy import select, update
|
||||
from sqlalchemy.exc import IntegrityError
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from backup_tool.db.models import Execution, Job
|
||||
from backup_tool.db.models import Execution, ExecutionEvent, Job
|
||||
from backup_tool.security.redaction import redact
|
||||
|
||||
ACTIVE_STATES = frozenset({"queued", "preparing", "running", "verifying", "cancelling"})
|
||||
@@ -67,6 +67,8 @@ async def enqueue(db: AsyncSession, job_id: str, trigger: str = "manual") -> Exe
|
||||
"execution_active", "Job already has an active execution.", existing
|
||||
) from error
|
||||
await db.refresh(execution)
|
||||
await record_event(db, execution)
|
||||
await db.commit()
|
||||
return execution
|
||||
|
||||
|
||||
@@ -89,7 +91,11 @@ async def claim(
|
||||
await db.rollback()
|
||||
return None
|
||||
await db.commit()
|
||||
return await db.get(Execution, execution_id)
|
||||
execution = await db.get(Execution, execution_id)
|
||||
if execution is not None:
|
||||
await record_event(db, execution)
|
||||
await db.commit()
|
||||
return execution
|
||||
|
||||
|
||||
async def heartbeat(
|
||||
@@ -128,7 +134,11 @@ async def request_cancellation(db: AsyncSession, execution_id: str) -> Execution
|
||||
await db.rollback()
|
||||
return None
|
||||
await db.commit()
|
||||
return await db.get(Execution, execution_id)
|
||||
execution = await db.get(Execution, execution_id)
|
||||
if execution is not None:
|
||||
await record_event(db, execution)
|
||||
await db.commit()
|
||||
return execution
|
||||
|
||||
|
||||
async def complete_cancellation(db: AsyncSession, execution_id: str, owner: str) -> bool:
|
||||
@@ -177,6 +187,8 @@ async def retry(db: AsyncSession, execution_id: str) -> Execution | None:
|
||||
"execution_active", "Job already has an active execution.", active_id
|
||||
) from error
|
||||
await db.refresh(execution)
|
||||
await record_event(db, execution)
|
||||
await db.commit()
|
||||
return execution
|
||||
|
||||
|
||||
@@ -196,6 +208,19 @@ def _redact_progress(value: object) -> object:
|
||||
return redact(value)
|
||||
|
||||
|
||||
async def record_event(db: AsyncSession, execution: Execution) -> ExecutionEvent:
|
||||
"""Append the public representation as the next durable event revision."""
|
||||
execution.revision += 1
|
||||
event = ExecutionEvent(
|
||||
execution_id=execution.id,
|
||||
revision=execution.revision,
|
||||
payload=public_event(execution),
|
||||
)
|
||||
db.add(event)
|
||||
await db.flush()
|
||||
return event
|
||||
|
||||
|
||||
def public_event(execution: Execution) -> dict[str, object]:
|
||||
"""Return redacted progress suitable for polling or SSE."""
|
||||
progress = _redact_progress(execution.progress)
|
||||
@@ -203,6 +228,7 @@ def public_event(execution: Execution) -> dict[str, object]:
|
||||
"id": execution.id,
|
||||
"state": execution.state,
|
||||
"attempt": execution.attempt,
|
||||
"revision": execution.revision,
|
||||
"reason_code": execution.reason_code,
|
||||
"progress": progress,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user