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 import APIRouter, Depends, HTTPException, Request
|
||||||
from fastapi.concurrency import run_in_threadpool
|
from fastapi.concurrency import run_in_threadpool
|
||||||
from pydantic import BaseModel, Field
|
from pydantic import BaseModel, Field
|
||||||
|
from sqlalchemy import func
|
||||||
|
from sqlalchemy import select as sa_select
|
||||||
from sqlmodel import col, select
|
from sqlmodel import col, select
|
||||||
|
|
||||||
from fluksio.api.deps import CurrentUser, SessionDep, get_current_user
|
from fluksio.api.deps import CurrentUser, SessionDep, get_current_user
|
||||||
@@ -98,6 +100,16 @@ class RunDetail(RunRow):
|
|||||||
artifacts: list[ArtifactRow] = Field(default_factory=list)
|
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):
|
class MetricPoint(BaseModel):
|
||||||
step: int
|
step: int
|
||||||
ts: float
|
ts: float
|
||||||
@@ -197,6 +209,7 @@ def read_runs(
|
|||||||
group: str | None = None,
|
group: str | None = None,
|
||||||
digest: str | None = None,
|
digest: str | None = None,
|
||||||
limit: int = 50,
|
limit: int = 50,
|
||||||
|
offset: int = 0,
|
||||||
) -> Any:
|
) -> Any:
|
||||||
"""Runs, newest first. The queryable table an experiment log needs."""
|
"""Runs, newest first. The queryable table an experiment log needs."""
|
||||||
statement = select(Run).order_by(col(Run.created_at).desc())
|
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)
|
statement = statement.where(col(Run.group_id) == group)
|
||||||
if digest:
|
if digest:
|
||||||
statement = statement.where(col(Run.params_digest) == 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)
|
@router.get("/{run_id}", response_model=RunDetail)
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ from datetime import UTC, datetime
|
|||||||
import pytest
|
import pytest
|
||||||
from sqlmodel import Session
|
from sqlmodel import Session
|
||||||
|
|
||||||
|
from fluksio.core.config import settings
|
||||||
from fluksio.core.db import engine as db_engine
|
from fluksio.core.db import engine as db_engine
|
||||||
from fluksio.flow.artifacts import ArtifactStore
|
from fluksio.flow.artifacts import ArtifactStore
|
||||||
from fluksio.flow.messages import DType, MessageSpec
|
from fluksio.flow.messages import DType, MessageSpec
|
||||||
@@ -196,3 +197,37 @@ def test_a_reference_passed_whole_is_left_alone(made_artifact):
|
|||||||
assert resolve_references(artifact_flow(), {"dataset": reference}) == {
|
assert resolve_references(artifact_flow(), {"dataset": reference}) == {
|
||||||
"dataset": reference
|
"dataset": reference
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_the_overview_counts_a_flow_the_list_page_would_not_reach(
|
||||||
|
client, superuser_token_headers
|
||||||
|
):
|
||||||
|
"""The list caps at 500 newest; the flow rail needs whole counts."""
|
||||||
|
with Session(db_engine) as session:
|
||||||
|
for index in range(3):
|
||||||
|
session.add(
|
||||||
|
Run(
|
||||||
|
id=f"ov-{index}",
|
||||||
|
flow="overviewed",
|
||||||
|
status="ok" if index else "running",
|
||||||
|
created_at=datetime(2026, 1, 1 + index, tzinfo=UTC),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
rows = client.get(
|
||||||
|
f"{settings.API_V1_STR}/runs/overview", headers=superuser_token_headers
|
||||||
|
).json()
|
||||||
|
row = next(r for r in rows if r["flow"] == "overviewed")
|
||||||
|
|
||||||
|
assert (row["runs"], row["running"], row["queued"]) == (3, 1, 0)
|
||||||
|
|
||||||
|
|
||||||
|
def test_overview_is_not_read_as_a_run_id(client, superuser_token_headers):
|
||||||
|
"""`/overview` is declared before `/{run_id}`, which would swallow it."""
|
||||||
|
answer = client.get(
|
||||||
|
f"{settings.API_V1_STR}/runs/overview", headers=superuser_token_headers
|
||||||
|
)
|
||||||
|
|
||||||
|
assert answer.status_code == 200
|
||||||
|
assert isinstance(answer.json(), list)
|
||||||
|
|||||||
@@ -1033,6 +1033,34 @@ export const FlowRollupSchema = {
|
|||||||
title: 'FlowRollup'
|
title: 'FlowRollup'
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
export const FlowRunsRowSchema = {
|
||||||
|
properties: {
|
||||||
|
flow: {
|
||||||
|
type: 'string',
|
||||||
|
title: 'Flow'
|
||||||
|
},
|
||||||
|
runs: {
|
||||||
|
type: 'integer',
|
||||||
|
title: 'Runs'
|
||||||
|
},
|
||||||
|
running: {
|
||||||
|
type: 'integer',
|
||||||
|
title: 'Running'
|
||||||
|
},
|
||||||
|
queued: {
|
||||||
|
type: 'integer',
|
||||||
|
title: 'Queued'
|
||||||
|
},
|
||||||
|
last_created_at: {
|
||||||
|
title: 'Last Created At'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
type: 'object',
|
||||||
|
required: ['flow', 'runs', 'running', 'queued'],
|
||||||
|
title: 'FlowRunsRow',
|
||||||
|
description: "How much a flow has been run, for the screen's list of flows."
|
||||||
|
} as const;
|
||||||
|
|
||||||
export const FlowStatePublicSchema = {
|
export const FlowStatePublicSchema = {
|
||||||
properties: {
|
properties: {
|
||||||
values: {
|
values: {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
import type { CancelablePromise } from './core/CancelablePromise';
|
import type { CancelablePromise } from './core/CancelablePromise';
|
||||||
import { OpenAPI } from './core/OpenAPI';
|
import { OpenAPI } from './core/OpenAPI';
|
||||||
import { request as __request } from './core/request';
|
import { request as __request } from './core/request';
|
||||||
import type { AlertsReadAlertsConfigResponse, AlertsSaveAlertsConfigData, AlertsSaveAlertsConfigResponse, AlertsTestChannelData, AlertsTestChannelResponse, ArtifactsPutArtifactData, ArtifactsPutArtifactResponse, ArtifactsGetArtifactData, ArtifactsGetArtifactResponse, CloudReadStatusResponse, CloudEnrollData, CloudEnrollResponse, CloudAddRemoteUserData, CloudAddRemoteUserResponse, CloudDisconnectResponse, DashboardsReadDashboardsResponse, DashboardsReadDashboardData, DashboardsReadDashboardResponse, DashboardsCreateDashboardData, DashboardsCreateDashboardResponse, DashboardsSaveDashboardData, DashboardsSaveDashboardResponse, DashboardsDeleteDashboardData, DashboardsDeleteDashboardResponse, DashboardsPublishDashboardData, DashboardsPublishDashboardResponse, DashboardsDiscardDashboardDraftData, DashboardsDiscardDashboardDraftResponse, DashboardsRenameDashboardData, DashboardsRenameDashboardResponse, FlowsReadFlowsResponse, FlowsReadNodeTypesResponse, FlowsReadGraphResponse, FlowsReadLibraryResponse, FlowsDeleteSharedNodeData, FlowsDeleteSharedNodeResponse, FlowsReadFlowData, FlowsReadFlowResponse, FlowsSaveFlowData, FlowsSaveFlowResponse, FlowsDeleteFlowData, FlowsDeleteFlowResponse, FlowsPublishFlowData, FlowsPublishFlowResponse, FlowsDiscardDraftData, FlowsDiscardDraftResponse, FlowsRenameFlowData, FlowsRenameFlowResponse, FlowsReadNodeSourceData, FlowsReadNodeSourceResponse, FlowsSaveNodeSourceData, FlowsSaveNodeSourceResponse, FlowsShareNodeData, FlowsShareNodeResponse, FlowsUnshareNodeData, FlowsUnshareNodeResponse, FlowsStartFlowData, FlowsStartFlowResponse, FlowsStopFlowData, FlowsStopFlowResponse, FlowsPauseFlowData, FlowsPauseFlowResponse, FlowsResumeFlowData, FlowsResumeFlowResponse, FlowsStepFlowData, FlowsStepFlowResponse, FlowsValidateFlowData, FlowsValidateFlowResponse, FlowsRunFlowData, FlowsRunFlowResponse, FlowsTriggerNodeData, FlowsTriggerNodeResponse, FlowsCancelNodeData, FlowsCancelNodeResponse, FlowsAcknowledgeNodeErrorData, FlowsAcknowledgeNodeErrorResponse, FlowsReadFlowStateData, FlowsReadFlowStateResponse, FlowsReadMessageHistoryData, FlowsReadMessageHistoryResponse, LoginLoginAccessTokenData, LoginLoginAccessTokenResponse, LoginTestTokenResponse, LoginRecoverPasswordData, LoginRecoverPasswordResponse, LoginResetPasswordData, LoginResetPasswordResponse, LoginRecoverPasswordHtmlContentData, LoginRecoverPasswordHtmlContentResponse, MessagesReadMessagesResponse, MessagesPublishMessageData, MessagesPublishMessageResponse, MessagesReadMessageHistoryData, MessagesReadMessageHistoryResponse, ModulesReadModulesResponse, ModulesApplyModulesData, ModulesApplyModulesResponse, ModulesRefreshModulesResponse, OauthRegisterClientData, OauthRegisterClientResponse, OauthAuthorizeValidateData, OauthAuthorizeValidateResponse, OauthAuthorizeData, OauthAuthorizeResponse, OauthTokenData, OauthTokenResponse, OauthReadClientsResponse, OauthRevokeClientData, OauthRevokeClientResponse, ObservabilityReadSummaryResponse, ObservabilityReadTimeseriesData, ObservabilityReadTimeseriesResponse, ObservabilityReadFlowRollupsData, ObservabilityReadFlowRollupsResponse, ObservabilityReadRunsData, ObservabilityReadRunsResponse, ObservabilityReadEventsData, ObservabilityReadEventsResponse, ObservabilityReadDeadLettersData, ObservabilityReadDeadLettersResponse, PanelsReadPanelsResponse, PanelsSavePanelsData, PanelsSavePanelsResponse, PanelsStartPairingResponse, PanelsPollPairingData, PanelsPollPairingResponse, PanelsPendingDeviceData, PanelsPendingDeviceResponse, PanelsApprovePairingData, PanelsApprovePairingResponse, PanelsUnpairPanelData, PanelsUnpairPanelResponse, PanelsReadPanelData, PanelsReadPanelResponse, PrivateCreateUserData, PrivateCreateUserResponse, RunsCreateRunData, RunsCreateRunResponse, RunsCreateSweepData, RunsCreateSweepResponse, RunsReadRunsData, RunsReadRunsResponse, RunsReadRunData, RunsReadRunResponse, RunsCancelRunData, RunsCancelRunResponse, RunsReadMetricsData, RunsReadMetricsResponse, RunsCompareMetricData, RunsCompareMetricResponse, SecretsReadSecretsResponse, SecretsSaveSecretData, SecretsSaveSecretResponse, SecretsDeleteSecretData, SecretsDeleteSecretResponse, UsersReadUsersData, UsersReadUsersResponse, UsersCreateUserData, UsersCreateUserResponse, UsersReadUserMeResponse, UsersDeleteUserMeResponse, UsersUpdateUserMeData, UsersUpdateUserMeResponse, UsersUpdatePasswordMeData, UsersUpdatePasswordMeResponse, UsersRegisterUserData, UsersRegisterUserResponse, UsersReadUserByIdData, UsersReadUserByIdResponse, UsersUpdateUserData, UsersUpdateUserResponse, UsersDeleteUserData, UsersDeleteUserResponse, UtilsTestEmailData, UtilsTestEmailResponse, UtilsHealthCheckResponse, UtilsHealthResponse, WorkersReadWorkersResponse, WorkersIssueTokenData, WorkersIssueTokenResponse, WorkersReadRuntimeResponse } from './types.gen';
|
import type { AlertsReadAlertsConfigResponse, AlertsSaveAlertsConfigData, AlertsSaveAlertsConfigResponse, AlertsTestChannelData, AlertsTestChannelResponse, ArtifactsPutArtifactData, ArtifactsPutArtifactResponse, ArtifactsGetArtifactData, ArtifactsGetArtifactResponse, CloudReadStatusResponse, CloudEnrollData, CloudEnrollResponse, CloudAddRemoteUserData, CloudAddRemoteUserResponse, CloudDisconnectResponse, DashboardsReadDashboardsResponse, DashboardsReadDashboardData, DashboardsReadDashboardResponse, DashboardsCreateDashboardData, DashboardsCreateDashboardResponse, DashboardsSaveDashboardData, DashboardsSaveDashboardResponse, DashboardsDeleteDashboardData, DashboardsDeleteDashboardResponse, DashboardsPublishDashboardData, DashboardsPublishDashboardResponse, DashboardsDiscardDashboardDraftData, DashboardsDiscardDashboardDraftResponse, DashboardsRenameDashboardData, DashboardsRenameDashboardResponse, FlowsReadFlowsResponse, FlowsReadNodeTypesResponse, FlowsReadGraphResponse, FlowsReadLibraryResponse, FlowsDeleteSharedNodeData, FlowsDeleteSharedNodeResponse, FlowsReadFlowData, FlowsReadFlowResponse, FlowsSaveFlowData, FlowsSaveFlowResponse, FlowsDeleteFlowData, FlowsDeleteFlowResponse, FlowsPublishFlowData, FlowsPublishFlowResponse, FlowsDiscardDraftData, FlowsDiscardDraftResponse, FlowsRenameFlowData, FlowsRenameFlowResponse, FlowsReadNodeSourceData, FlowsReadNodeSourceResponse, FlowsSaveNodeSourceData, FlowsSaveNodeSourceResponse, FlowsShareNodeData, FlowsShareNodeResponse, FlowsUnshareNodeData, FlowsUnshareNodeResponse, FlowsStartFlowData, FlowsStartFlowResponse, FlowsStopFlowData, FlowsStopFlowResponse, FlowsPauseFlowData, FlowsPauseFlowResponse, FlowsResumeFlowData, FlowsResumeFlowResponse, FlowsStepFlowData, FlowsStepFlowResponse, FlowsValidateFlowData, FlowsValidateFlowResponse, FlowsRunFlowData, FlowsRunFlowResponse, FlowsTriggerNodeData, FlowsTriggerNodeResponse, FlowsCancelNodeData, FlowsCancelNodeResponse, FlowsAcknowledgeNodeErrorData, FlowsAcknowledgeNodeErrorResponse, FlowsReadFlowStateData, FlowsReadFlowStateResponse, FlowsReadMessageHistoryData, FlowsReadMessageHistoryResponse, LoginLoginAccessTokenData, LoginLoginAccessTokenResponse, LoginTestTokenResponse, LoginRecoverPasswordData, LoginRecoverPasswordResponse, LoginResetPasswordData, LoginResetPasswordResponse, LoginRecoverPasswordHtmlContentData, LoginRecoverPasswordHtmlContentResponse, MessagesReadMessagesResponse, MessagesPublishMessageData, MessagesPublishMessageResponse, MessagesReadMessageHistoryData, MessagesReadMessageHistoryResponse, ModulesReadModulesResponse, ModulesApplyModulesData, ModulesApplyModulesResponse, ModulesRefreshModulesResponse, OauthRegisterClientData, OauthRegisterClientResponse, OauthAuthorizeValidateData, OauthAuthorizeValidateResponse, OauthAuthorizeData, OauthAuthorizeResponse, OauthTokenData, OauthTokenResponse, OauthReadClientsResponse, OauthRevokeClientData, OauthRevokeClientResponse, ObservabilityReadSummaryResponse, ObservabilityReadTimeseriesData, ObservabilityReadTimeseriesResponse, ObservabilityReadFlowRollupsData, ObservabilityReadFlowRollupsResponse, ObservabilityReadRunsData, ObservabilityReadRunsResponse, ObservabilityReadEventsData, ObservabilityReadEventsResponse, ObservabilityReadDeadLettersData, ObservabilityReadDeadLettersResponse, PanelsReadPanelsResponse, PanelsSavePanelsData, PanelsSavePanelsResponse, PanelsStartPairingResponse, PanelsPollPairingData, PanelsPollPairingResponse, PanelsPendingDeviceData, PanelsPendingDeviceResponse, PanelsApprovePairingData, PanelsApprovePairingResponse, PanelsUnpairPanelData, PanelsUnpairPanelResponse, PanelsReadPanelData, PanelsReadPanelResponse, PrivateCreateUserData, PrivateCreateUserResponse, RunsCreateRunData, RunsCreateRunResponse, RunsCreateSweepData, RunsCreateSweepResponse, RunsReadRunsData, RunsReadRunsResponse, RunsReadOverviewResponse, RunsReadRunData, RunsReadRunResponse, RunsCancelRunData, RunsCancelRunResponse, RunsReadMetricsData, RunsReadMetricsResponse, RunsCompareMetricData, RunsCompareMetricResponse, SecretsReadSecretsResponse, SecretsSaveSecretData, SecretsSaveSecretResponse, SecretsDeleteSecretData, SecretsDeleteSecretResponse, UsersReadUsersData, UsersReadUsersResponse, UsersCreateUserData, UsersCreateUserResponse, UsersReadUserMeResponse, UsersDeleteUserMeResponse, UsersUpdateUserMeData, UsersUpdateUserMeResponse, UsersUpdatePasswordMeData, UsersUpdatePasswordMeResponse, UsersRegisterUserData, UsersRegisterUserResponse, UsersReadUserByIdData, UsersReadUserByIdResponse, UsersUpdateUserData, UsersUpdateUserResponse, UsersDeleteUserData, UsersDeleteUserResponse, UtilsTestEmailData, UtilsTestEmailResponse, UtilsHealthCheckResponse, UtilsHealthResponse, WorkersReadWorkersResponse, WorkersIssueTokenData, WorkersIssueTokenResponse, WorkersReadRuntimeResponse } from './types.gen';
|
||||||
|
|
||||||
export class AlertsService {
|
export class AlertsService {
|
||||||
/**
|
/**
|
||||||
@@ -1756,6 +1756,7 @@ export class RunsService {
|
|||||||
* @param data.group
|
* @param data.group
|
||||||
* @param data.digest
|
* @param data.digest
|
||||||
* @param data.limit
|
* @param data.limit
|
||||||
|
* @param data.offset
|
||||||
* @returns fluksio__api__routes__runs__RunRow Successful Response
|
* @returns fluksio__api__routes__runs__RunRow Successful Response
|
||||||
* @throws ApiError
|
* @throws ApiError
|
||||||
*/
|
*/
|
||||||
@@ -1768,7 +1769,8 @@ export class RunsService {
|
|||||||
status: data.status,
|
status: data.status,
|
||||||
group: data.group,
|
group: data.group,
|
||||||
digest: data.digest,
|
digest: data.digest,
|
||||||
limit: data.limit
|
limit: data.limit,
|
||||||
|
offset: data.offset
|
||||||
},
|
},
|
||||||
errors: {
|
errors: {
|
||||||
422: 'Validation Error'
|
422: 'Validation Error'
|
||||||
@@ -1776,6 +1778,22 @@ export class RunsService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read Overview
|
||||||
|
* 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.
|
||||||
|
* @returns FlowRunsRow Successful Response
|
||||||
|
* @throws ApiError
|
||||||
|
*/
|
||||||
|
public static readOverview(): CancelablePromise<RunsReadOverviewResponse> {
|
||||||
|
return __request(OpenAPI, {
|
||||||
|
method: 'GET',
|
||||||
|
url: '/api/v1/runs/overview'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read Run
|
* Read Run
|
||||||
* One run in full: what it was asked, what each node did, what it made.
|
* One run in full: what it was asked, what each node did, what it made.
|
||||||
|
|||||||
@@ -334,6 +334,17 @@ export type FlowRollup = {
|
|||||||
last_error_ts?: (number | null);
|
last_error_ts?: (number | null);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How much a flow has been run, for the screen's list of flows.
|
||||||
|
*/
|
||||||
|
export type FlowRunsRow = {
|
||||||
|
flow: string;
|
||||||
|
runs: number;
|
||||||
|
running: number;
|
||||||
|
queued: number;
|
||||||
|
last_created_at?: unknown;
|
||||||
|
};
|
||||||
|
|
||||||
export type FlowsPublic = {
|
export type FlowsPublic = {
|
||||||
data: Array<FlowSummary>;
|
data: Array<FlowSummary>;
|
||||||
count: number;
|
count: number;
|
||||||
@@ -1600,11 +1611,14 @@ export type RunsReadRunsData = {
|
|||||||
flow?: (string | null);
|
flow?: (string | null);
|
||||||
group?: (string | null);
|
group?: (string | null);
|
||||||
limit?: number;
|
limit?: number;
|
||||||
|
offset?: number;
|
||||||
status?: (string | null);
|
status?: (string | null);
|
||||||
};
|
};
|
||||||
|
|
||||||
export type RunsReadRunsResponse = (Array<fluksio__api__routes__runs__RunRow>);
|
export type RunsReadRunsResponse = (Array<fluksio__api__routes__runs__RunRow>);
|
||||||
|
|
||||||
|
export type RunsReadOverviewResponse = (Array<FlowRunsRow>);
|
||||||
|
|
||||||
export type RunsReadRunData = {
|
export type RunsReadRunData = {
|
||||||
runId: string;
|
runId: string;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user