diff --git a/src/components/operation-details/OperationDetailsComponent.tsx b/src/components/operation-details/OperationDetailsComponent.tsx index 345f910b..3ec749ba 100644 --- a/src/components/operation-details/OperationDetailsComponent.tsx +++ b/src/components/operation-details/OperationDetailsComponent.tsx @@ -42,7 +42,7 @@ const OperationDetailsComponent: React.FC = ({ operationI const [zoomedInView, setZoomedInView] = useState(false); const { - operationDetails: { data: operationDetails, isLoading }, + operationDetails: { data: operationDetails, isLoading, status }, } = useOperationDetails(operationId); const { data: previousOperationDetails, isLoading: isPrevLoading } = @@ -61,10 +61,13 @@ const OperationDetailsComponent: React.FC = ({ operationI if (isLoading || isPrevLoading || !operationDetails || !previousOperationDetails) { return ( - + <> + + {status === 'error' &&

Operation {operationId} not found

} + ); } diff --git a/src/hooks/useAPI.tsx b/src/hooks/useAPI.tsx index a618354e..9fb71a10 100644 --- a/src/hooks/useAPI.tsx +++ b/src/hooks/useAPI.tsx @@ -4,11 +4,35 @@ import axios, { AxiosError } from 'axios'; import { useQuery } from 'react-query'; -import { MicroOperation, OperationDescription, OperationDetailsData, ReportMetaData } from '../model/APIData'; - -const fetchOperationDetails = async (id: number): Promise => { - const { data: operationDetails } = await axios.get(`/api/operations/${id}`); - return operationDetails; +import { + MicroOperation, + OperationDescription, + OperationDetailsData, + ReportMetaData, + defaultOperationDetailsData, +} from '../model/APIData'; + +const fetchOperationDetails = async (id: number | null): Promise => { + if (id === null) { + return defaultOperationDetailsData; + } + try { + const { data: operationDetails } = await axios.get(`/api/operations/${id}`, { + maxRedirects: 1, + }); + return operationDetails; + } catch (error: unknown) { + if (axios.isAxiosError(error)) { + if (error.response && error.response.status >= 400 && error.response.status < 500) { + // we may want to handle this differently + throw error; + } + if (error.response && error.response.status >= 500) { + throw error; + } + } + } + return defaultOperationDetailsData; }; const fetchOperations = async (): Promise => { const [{ data: operationList }, { data: microOperations }] = await Promise.all([ @@ -46,18 +70,20 @@ export const useAllBuffers = () => { return useQuery<{ operation_id: number; buffers: [] }[], AxiosError>('get-operation-buffers', fetchAllBuffers); }; -export const useOperationDetails = (operationId: number) => { +export const useOperationDetails = (operationId: number | null) => { const { data: operations } = useOperationsList(); const operation = operations?.filter((_operation) => { return _operation.id === operationId; })[0]; - const operationDetails = useQuery(['get-operation-detail', operationId], () => - fetchOperationDetails(operationId), + const operationDetails = useQuery( + ['get-operation-detail', operationId], + () => fetchOperationDetails(operationId), + { + retry: 2, + retryDelay: (retryAttempt) => Math.min(retryAttempt * 100, 500), + }, ); - - // TODO: consider useQueries or include operation data on BE - return { operation, operationDetails, @@ -72,7 +98,7 @@ export const usePreviousOperationDetails = (operationId: number) => { return operationList[index + 1]?.id === operationId; }); - return useOperationDetails(operation ? operation.id : -1); + return useOperationDetails(operation ? operation.id : null); }; export const usePreviousOperation = (operationId: number) => { diff --git a/src/model/APIData.ts b/src/model/APIData.ts index 342337e4..8cd9b00d 100644 --- a/src/model/APIData.ts +++ b/src/model/APIData.ts @@ -35,6 +35,17 @@ export interface OperationDetailsData extends Operation { stack_trace: string; } +// TODO: we may want to revisit the 'default' portion fo the variable name +export const defaultOperationDetailsData: OperationDetailsData = { + id: 0, + name: '', + inputs: [], + outputs: [], + buffers: [], + l1_sizes: [], + stack_trace: '', +}; + export interface Chunk { address: number; size: number;