mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-06-02 19:55:18 +02:00
refactor(automations): source runs list from Zero
useAutomationRuns now reads from the zero_publication thin column set and adapts rows to LiveRunSummary (RunSummary + step_results). The detail hook stays on REST for the heavy fields.
This commit is contained in:
parent
c73f7ef03a
commit
69eb64db08
1 changed files with 83 additions and 16 deletions
|
|
@ -1,42 +1,109 @@
|
||||||
"use client";
|
"use client";
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery as useZeroQuery } from "@rocicorp/zero/react";
|
||||||
import type { Run, RunListResponse } from "@/contracts/types/automation.types";
|
import { useQuery as useReactQuery } from "@tanstack/react-query";
|
||||||
|
import { useMemo } from "react";
|
||||||
|
import type { Run, RunStepResult, RunSummary } from "@/contracts/types/automation.types";
|
||||||
import { automationsApiService } from "@/lib/apis/automations-api.service";
|
import { automationsApiService } from "@/lib/apis/automations-api.service";
|
||||||
import { cacheKeys } from "@/lib/query-client/cache-keys";
|
import { cacheKeys } from "@/lib/query-client/cache-keys";
|
||||||
|
import { queries } from "@/zero/queries";
|
||||||
|
|
||||||
const DEFAULT_LIMIT = 50;
|
const DEFAULT_LIMIT = 50;
|
||||||
const DEFAULT_OFFSET = 0;
|
|
||||||
|
/**
|
||||||
|
* Thin live row sourced from Zero. Strict superset of {@link RunSummary} —
|
||||||
|
* existing consumers that only look at the summary fields keep working,
|
||||||
|
* while the run detail panel can read ``step_results`` directly for the
|
||||||
|
* live step ticker without a second REST round-trip.
|
||||||
|
*/
|
||||||
|
export interface LiveRunSummary extends RunSummary {
|
||||||
|
step_results: RunStepResult[];
|
||||||
|
}
|
||||||
|
|
||||||
export interface UseAutomationRunsOptions {
|
export interface UseAutomationRunsOptions {
|
||||||
limit?: number;
|
limit?: number;
|
||||||
offset?: number;
|
|
||||||
enabled?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Paginated run history for one automation. Newest-first per backend. */
|
interface UseAutomationRunsResult {
|
||||||
|
data: { items: LiveRunSummary[]; total: number } | undefined;
|
||||||
|
isLoading: boolean;
|
||||||
|
error: Error | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Live run history for one automation, newest-first. Sourced from Zero's
|
||||||
|
* thin ``automation_runs`` publication so status and per-step progress
|
||||||
|
* tick in real time without polling. Heavy fields (output, artifacts,
|
||||||
|
* inputs, error, definition_snapshot) are still fetched lazily via
|
||||||
|
* {@link useAutomationRun}.
|
||||||
|
*/
|
||||||
export function useAutomationRuns(
|
export function useAutomationRuns(
|
||||||
automationId: number | undefined,
|
automationId: number | undefined,
|
||||||
{ limit = DEFAULT_LIMIT, offset = DEFAULT_OFFSET, enabled = true }: UseAutomationRunsOptions = {}
|
{ limit = DEFAULT_LIMIT }: UseAutomationRunsOptions = {}
|
||||||
) {
|
): UseAutomationRunsResult {
|
||||||
return useQuery<RunListResponse, Error>({
|
const [rows, result] = useZeroQuery(
|
||||||
queryKey: cacheKeys.automations.runs(automationId ?? 0, limit, offset),
|
queries.automationRuns.byAutomation({ automationId: automationId ?? -1 })
|
||||||
queryFn: () => automationsApiService.listRuns(automationId as number, { limit, offset }),
|
);
|
||||||
enabled: enabled && !!automationId,
|
|
||||||
staleTime: 30_000,
|
const items = useMemo<LiveRunSummary[]>(() => {
|
||||||
});
|
if (!automationId) return [];
|
||||||
|
return rows.slice(0, limit).map(toLiveRunSummary);
|
||||||
|
}, [automationId, rows, limit]);
|
||||||
|
|
||||||
|
const total = automationId ? rows.length : 0;
|
||||||
|
|
||||||
|
// Pre-hydration window: nothing visible AND Zero hasn't confirmed
|
||||||
|
// completeness yet. After the first sync (even an empty set) we stop
|
||||||
|
// showing the skeleton so the empty-state copy can take over.
|
||||||
|
const isLoading = !!automationId && result.type !== "complete" && rows.length === 0;
|
||||||
|
|
||||||
|
return {
|
||||||
|
data: automationId ? { items, total } : undefined,
|
||||||
|
isLoading,
|
||||||
|
error: null,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Single run with the full snapshot, step results, output and artifacts. */
|
/**
|
||||||
|
* Full run record (definition snapshot, inputs, output, artifacts, error).
|
||||||
|
* Stays on REST: these fields are large and largely static after the run
|
||||||
|
* finishes, so they're not worth replicating to every connected client.
|
||||||
|
*/
|
||||||
export function useAutomationRun(
|
export function useAutomationRun(
|
||||||
automationId: number | undefined,
|
automationId: number | undefined,
|
||||||
runId: number | undefined,
|
runId: number | undefined,
|
||||||
options: { enabled?: boolean } = {}
|
options: { enabled?: boolean } = {}
|
||||||
) {
|
) {
|
||||||
const { enabled = true } = options;
|
const { enabled = true } = options;
|
||||||
return useQuery<Run, Error>({
|
return useReactQuery<Run, Error>({
|
||||||
queryKey: cacheKeys.automations.run(automationId ?? 0, runId ?? 0),
|
queryKey: cacheKeys.automations.run(automationId ?? 0, runId ?? 0),
|
||||||
queryFn: () => automationsApiService.getRun(automationId as number, runId as number),
|
queryFn: () => automationsApiService.getRun(automationId as number, runId as number),
|
||||||
enabled: enabled && !!automationId && !!runId,
|
enabled: enabled && !!automationId && !!runId,
|
||||||
staleTime: 30_000,
|
staleTime: 30_000,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface ZeroAutomationRunRow {
|
||||||
|
id: number;
|
||||||
|
automationId: number;
|
||||||
|
triggerId?: number | null;
|
||||||
|
status: string;
|
||||||
|
stepResults: unknown;
|
||||||
|
startedAt?: number | null;
|
||||||
|
finishedAt?: number | null;
|
||||||
|
createdAt: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Adapt a Zero camelCase row (epoch ms timestamps) to the snake_case
|
||||||
|
* ISO-string ``RunSummary`` shape the existing UI already consumes. */
|
||||||
|
function toLiveRunSummary(row: ZeroAutomationRunRow): LiveRunSummary {
|
||||||
|
return {
|
||||||
|
id: row.id,
|
||||||
|
automation_id: row.automationId,
|
||||||
|
trigger_id: row.triggerId ?? null,
|
||||||
|
status: row.status as RunSummary["status"],
|
||||||
|
started_at: row.startedAt ? new Date(row.startedAt).toISOString() : null,
|
||||||
|
finished_at: row.finishedAt ? new Date(row.finishedAt).toISOString() : null,
|
||||||
|
created_at: new Date(row.createdAt).toISOString(),
|
||||||
|
step_results: Array.isArray(row.stepResults) ? (row.stepResults as RunStepResult[]) : [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue