Count runs per flow, and page the run list by offset

This commit is contained in:
2026-08-25 11:34:07 +02:00
parent 60757fa7fa
commit 7e422c0047
5 changed files with 139 additions and 3 deletions
+42 -1
View File
@@ -10,6 +10,8 @@ from typing import Any
from fastapi import APIRouter, Depends, HTTPException, Request
from fastapi.concurrency import run_in_threadpool
from pydantic import BaseModel, Field
from sqlalchemy import func
from sqlalchemy import select as sa_select
from sqlmodel import col, select
from fluksio.api.deps import CurrentUser, SessionDep, get_current_user
@@ -98,6 +100,16 @@ class RunDetail(RunRow):
artifacts: list[ArtifactRow] = Field(default_factory=list)
class FlowRunsRow(BaseModel):
"""How much a flow has been run, for the screen's list of flows."""
flow: str
runs: int
running: int
queued: int
last_created_at: Any = None
class MetricPoint(BaseModel):
step: int
ts: float
@@ -197,6 +209,7 @@ def read_runs(
group: str | None = None,
digest: str | None = None,
limit: int = 50,
offset: int = 0,
) -> Any:
"""Runs, newest first. The queryable table an experiment log needs."""
statement = select(Run).order_by(col(Run.created_at).desc())
@@ -208,7 +221,35 @@ def read_runs(
statement = statement.where(col(Run.group_id) == group)
if digest:
statement = statement.where(col(Run.params_digest) == digest)
return list(session.exec(statement.limit(min(limit, 500))))
statement = statement.offset(max(0, offset)).limit(min(limit, 500))
return list(session.exec(statement))
@router.get("/overview", response_model=list[FlowRunsRow])
def read_overview(session: SessionDep) -> Any:
"""One row per flow that has ever run, busiest-recent first.
The list caps at 500 newest runs, so counting flows on the client goes
wrong the moment a history outgrows one page. The database counts instead.
"""
statement = sa_select(
col(Run.flow),
col(Run.status),
func.count(col(Run.id)),
func.max(col(Run.created_at)),
).group_by(col(Run.flow), col(Run.status))
rows: dict[str, FlowRunsRow] = {}
for flow, status, count, latest in session.execute(statement):
row = rows.setdefault(flow, FlowRunsRow(flow=flow, runs=0, running=0, queued=0))
row.runs += count
if status == "running":
row.running += count
elif status == "queued":
row.queued += count
if row.last_created_at is None or latest > row.last_created_at:
row.last_created_at = latest
return sorted(rows.values(), key=lambda row: row.last_created_at, reverse=True)
@router.get("/{run_id}", response_model=RunDetail)