Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions js/packages/ui/src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,15 @@ export type {
export { submitRowCountDiff } from "./rowcount";
// Runs API (core run operations and aggregation)
export type {
AggregatedRunResult,
ColumnValidationSummary,
NodeRunsAggregated,
ProfileDiffValidationSummary,
RunsAggregated,
SubmitOptions,
SubmitRunTrackProps,
ValidationSummary,
ValueDiffValidationSummary,
} from "./runs";
export {
aggregateRuns,
Expand Down
57 changes: 46 additions & 11 deletions js/packages/ui/src/api/runs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,53 @@ import { isQueryRun, type Run, type RunType } from "./types";
// ============================================================================

/**
* Aggregated run results by model and run type
* A full result retained for legacy row-count lineage decorations.
*/
export type RunsAggregated = Record<
string,
Record<
"row_count_diff" | "value_diff" | "row_count",
{
run_id: string;
result: unknown;
}
>
>;
export interface AggregatedRunResult {
run_id: string;
result: unknown;
}

interface AvailableValidationResult {
result_available: true;
}

export interface ValueDiffValidationSummary extends AvailableValidationResult {
latest_run_id: string;
difference_count: number;
}

export interface ProfileDiffValidationSummary
extends AvailableValidationResult {
latest_run_id: string;
result_count: number;
}

export interface ColumnValidationSummary extends AvailableValidationResult {
latest_run_ids_by_column: Record<string, string>;
column_count: number;
}

export interface ValidationSummary {
result_count: number;
difference_count: number;
types: {
value_diff?: ValueDiffValidationSummary;
profile_diff?: ProfileDiffValidationSummary;
top_k_diff?: ColumnValidationSummary;
histogram_diff?: ColumnValidationSummary;
};
}

export interface NodeRunsAggregated {
row_count_diff?: AggregatedRunResult;
value_diff?: AggregatedRunResult;
row_count?: AggregatedRunResult;
validation_summary?: ValidationSummary;
}

/** Aggregated run results by resolved lineage node ID. */
export type RunsAggregated = Record<string, NodeRunsAggregated>;

/**
* Properties for tracking run submissions (analytics)
Expand Down
4 changes: 2 additions & 2 deletions js/packages/ui/src/components/lineage/NodeTag.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ export function RowCountDiffTag({
const { featureToggles } = useRecceInstanceContext();
const { runsAggregated } = useLineageGraphContext();
const lastRowCount: RowCountDiff | undefined = runsAggregated?.[node.id]
?.row_count_diff.result as RowCountDiff | undefined;
?.row_count_diff?.result as RowCountDiff | undefined;
const RunTypeIcon = findByRunType("row_count_diff").icon;

// Calculate during render instead of effect
Expand Down Expand Up @@ -302,7 +302,7 @@ export function RowCountTag({
const isDark = useIsDark();
const { runsAggregated } = useLineageGraphContext();
const lastRowCount: RowCountDiff | undefined = runsAggregated?.[node.id]
?.row_count.result as RowCountDiff | undefined;
?.row_count?.result as RowCountDiff | undefined;

const RunTypeIcon = findByRunType("row_count").icon;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,35 @@ function createMockRunsAggregated(): RunsAggregated {
run_id: "run-3",
result: 100,
},
validation_summary: {
result_count: 5,
difference_count: 2,
types: {
value_diff: {
latest_run_id: "run-4",
difference_count: 2,
result_available: true,
},
profile_diff: {
latest_run_id: "run-5",
result_count: 1,
result_available: true,
},
top_k_diff: {
latest_run_ids_by_column: {
status: "run-6",
region: "run-7",
},
column_count: 2,
result_available: true,
},
histogram_diff: {
latest_run_ids_by_column: { amount: "run-8" },
column_count: 1,
result_available: true,
},
},
},
},
};
}
Expand Down
32 changes: 26 additions & 6 deletions js/packages/ui/src/hooks/__tests__/useRun.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
* - New run submission (resets isRunning and completedRunIdRef)
* - RunResultView component resolution
* - Cancel functionality
* - Aggregated runs refetch for row_count types
* - Aggregated runs refetch for lineage aggregate run types
*/

import { vi } from "vitest";
Expand Down Expand Up @@ -596,13 +596,33 @@ describe("useRun", () => {
});
});

it("does not refetch aggregated runs for other run types", async () => {
const valueDiffRun = createMockRun({
type: "value_diff",
result: { diff: [] },
it.each(["value_diff", "profile_diff", "top_k_diff", "histogram_diff"])(
"refetches aggregated runs when %s completes",
async (runType) => {
const validationRun = createMockRun({
type: runType,
result: { available: true },
status: "Finished",
});
mockWaitRun.mockResolvedValue(validationRun);

renderHook(() => useRun("test-run-id"), {
wrapper: createWrapper(),
});

await waitFor(() => {
expect(mockRefetchRunsAggregated).toHaveBeenCalled();
});
},
);

it("does not refetch aggregated runs for an unrelated run type", async () => {
const queryRun = createMockRun({
type: "query",
result: { data: [] },
status: "Finished",
});
mockWaitRun.mockResolvedValue(valueDiffRun);
mockWaitRun.mockResolvedValue(queryRun);

const { result } = renderHook(() => useRun("test-run-id"), {
wrapper: createWrapper(),
Expand Down
12 changes: 11 additions & 1 deletion js/packages/ui/src/hooks/useRun.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ import { useRunsAggregated } from "../contexts";
import { useApiConfig } from "./useApiConfig";
import { useCanceledRuns } from "./useCanceledRuns";

const AGGREGATED_RUN_TYPES = new Set<Run["type"]>([
"row_count_diff",
"row_count",
"value_diff",
"profile_diff",
"top_k_diff",
"histogram_diff",
]);

export interface UseRunResult {
run?: Run;
isRunning: boolean;
Expand Down Expand Up @@ -68,7 +77,8 @@ export const useRun = (runId?: string): UseRunResult => {
useEffect(() => {
if (
(error || run?.result || run?.error) &&
(run?.type === "row_count_diff" || run?.type === "row_count")
run &&
AGGREGATED_RUN_TYPES.has(run.type)
) {
refetchRunsAggregated?.();
}
Expand Down
Loading
Loading