diff --git a/components/PerformanceList/index.tsx b/components/PerformanceList/index.tsx
index 6ba1c98a..8f1a87fc 100644
--- a/components/PerformanceList/index.tsx
+++ b/components/PerformanceList/index.tsx
@@ -6,31 +6,35 @@ import { ExplorerTooltip } from "@components/ExplorerTooltip";
import Link from "next/link";
import { useMemo } from "react";
import QRCode from "qrcode.react";
-import { useAllScoreData, useEnsData } from "hooks";
+import { useEnsData } from "hooks";
import { OrchestratorsQueryResult } from "apollo";
import numeral from "numeral";
import { Pipeline } from "@lib/api/types/get-available-pipelines";
import { Region } from "@lib/api/types/get-regions";
+import { AllPerformanceMetrics } from "@lib/api/types/get-performance";
const EmptyData = () => ;
const PerformanceList = ({
- data,
+ orchestratorIds,
pageSize = 20,
region,
pipeline,
model,
+ performanceMetrics = null,
+ isLoadingMetrics = false,
}: {
pageSize: number;
region: Region["id"];
pipeline: Pipeline["id"] | null;
model: string | null;
- data: Pick<
+ performanceMetrics?: AllPerformanceMetrics | null;
+ isLoadingMetrics?: boolean;
+ orchestratorIds: Pick<
NonNullable["transcoders"][number],
"id"
>[];
}) => {
- const {isValidating, data: allScores} = useAllScoreData(pipeline, model);
const isAIData = pipeline !== null && model !== null;
const scoreAccessor = `scores.${region}`;//total score
const successRateAccessor = `successRates.${region}`;//success rate
@@ -53,8 +57,8 @@ const PerformanceList = ({
};
const mergedData = useMemo(
- () => data.map((o) => ({ ...o, ...allScores?.[o?.id] })),
- [allScores, data]
+ () => orchestratorIds.map((o) => ({ ...o, ...performanceMetrics?.[o?.id] })),
+ [performanceMetrics, orchestratorIds]
);
//tanstack v7's numberic sorting function incorrectly treats 0, null, and undefined as 0 (the same value).
@@ -215,11 +219,8 @@ const PerformanceList = ({
defaultCanSort: true,
sortType: sortTypeFn,
Cell: ({ value }) => {
- if (
- isValidating
- ) {
- return ;
- }
+ if (isLoadingMetrics) return ;
+
return (
{typeof value === "undefined" || value === null ?
@@ -251,9 +252,8 @@ const PerformanceList = ({
accessor: `${successRateAccessor}`,
sortType: sortTypeFn,
Cell: ({ value }) => {
- if (isValidating) {
- return ;
- }
+ if (isLoadingMetrics) return ;
+
return (
{typeof value === "undefined" || value === null ?
@@ -286,9 +286,8 @@ const PerformanceList = ({
accessor: `${roundTripScoreAccessor}`,
sortType: sortTypeFn,
Cell: ({ value }) => {
- if (isValidating) {
- return ;
- }
+ if (isLoadingMetrics) return ;
+
return (
{typeof value === "undefined" || value === null ?
@@ -302,7 +301,7 @@ const PerformanceList = ({
},
},
],
- [region, isValidating]
+ [region, isLoadingMetrics]
);
return (
diff --git a/pages/leaderboard.tsx b/pages/leaderboard.tsx
index 4985563f..e5c4edd6 100644
--- a/pages/leaderboard.tsx
+++ b/pages/leaderboard.tsx
@@ -6,10 +6,10 @@ import { EnsIdentity } from "@lib/api/types/get-ens";
import { Box, Container, Flex, Heading } from "@livepeer/design-system";
import { ChevronDownIcon } from "@modulz/radix-icons";
import Head from "next/head";
-import { useState } from "react";
+import { useState, useMemo } from "react";
import { getApollo, OrchestratorsQueryResult } from "../apollo";
import { Pipeline } from "@lib/api/types/get-available-pipelines";
-import { useRegionsData } from "hooks/useSwr";
+import { useRegionsData, useAllScoreData } from "hooks/useSwr";
import { Region } from "@lib/api/types/get-regions";
type PageProps = {
@@ -25,6 +25,36 @@ const LeaderboardPage = ({ orchestratorIds }: PageProps) => {
const [selectedModel, setSelectedModel] = useState(null);
const knownRegions = useRegionsData();
const [region, setRegion] = useState("GLOBAL");
+ const { data: allScores, isValidating } = useAllScoreData(selectedPipeline, selectedModel);
+
+ // Filter regions to only show those with data.
+ const availableRegions = useMemo(() => {
+ if (!knownRegions?.regions) return [];
+
+ const pipelineType = selectedPipeline ? "ai" : "transcoding";
+
+ // If no scores loaded yet, just filter by pipeline type.
+ if (!allScores) {
+ return knownRegions.regions.filter((r) => r.type === pipelineType);
+ }
+
+ // Collect regions that have score data.
+ const regionsWithData = new Set();
+ Object.values(allScores).forEach((orchestratorData) => {
+ if (orchestratorData?.scores) {
+ Object.entries(orchestratorData.scores).forEach(([regionKey, value]) => {
+ if (value != null) {
+ regionsWithData.add(regionKey);
+ }
+ });
+ }
+ });
+
+ // Filter regions based on pipeline type and data availability.
+ return knownRegions.regions.filter(
+ (r) => r.type === pipelineType && regionsWithData.has(r.id)
+ );
+ }, [knownRegions?.regions, allScores, selectedPipeline]);
return (
<>
@@ -99,9 +129,7 @@ const LeaderboardPage = ({ orchestratorIds }: PageProps) => {
appearance: "none",
}}
>
- {knownRegions?.regions
- .filter((r) => r.type === (selectedPipeline?"ai":"transcoding"))
- .map((region) => {
+ {availableRegions.map((region) => {
return (
{region.name}
)
@@ -137,11 +165,13 @@ const LeaderboardPage = ({ orchestratorIds }: PageProps) => {