Count runs per flow, and page the run list by offset
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user