US02-04: Expose Job APIs and Activity Events (#57)
This commit was merged in pull request #57.
This commit is contained in:
@@ -23,7 +23,7 @@ from collections import Counter
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from collections.abc import Iterable, Sequence
|
||||
|
||||
from sqlalchemy import select, update
|
||||
from sqlalchemy import select, text, update
|
||||
from sqlalchemy.exc import IntegrityError
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
|
||||
@@ -357,6 +357,20 @@ class JobService:
|
||||
).scalars()
|
||||
return [{"type": e.event_type, "message": e.message} for e in rows]
|
||||
|
||||
def events_after(self, job_id: str, after: int = 0) -> list[dict]:
|
||||
"""Durable events with ``seq`` > ``after``, ordered — the resumable cursor for
|
||||
SSE and polling. SQLite's monotonic rowid is the sequence (job_events is a
|
||||
rowid table), so no extra column is needed."""
|
||||
with self._session_factory() as session:
|
||||
rows = session.execute(
|
||||
text(
|
||||
"SELECT rowid AS seq, event_type, message FROM job_events "
|
||||
"WHERE job_id = :jid AND rowid > :after ORDER BY rowid"
|
||||
),
|
||||
{"jid": job_id, "after": after},
|
||||
).mappings().all()
|
||||
return [{"seq": r["seq"], "type": r["event_type"], "message": r["message"]} for r in rows]
|
||||
|
||||
# ── helpers ──────────────────────────────────────────────────────────────────
|
||||
@staticmethod
|
||||
def _event(session, job_id: str, event_type: str, message: str | None = None) -> None:
|
||||
|
||||
Reference in New Issue
Block a user