diff --git a/plugins/orchestrator/src/components/WorkflowInstancePage.tsx b/plugins/orchestrator/src/components/WorkflowInstancePage.tsx index 3d4632b8e73..2874ec96f53 100644 --- a/plugins/orchestrator/src/components/WorkflowInstancePage.tsx +++ b/plugins/orchestrator/src/components/WorkflowInstancePage.tsx @@ -29,15 +29,17 @@ export const WorkflowInstancePage = ({ workflowInstanceRouteRef, ); + const fetchInstance = React.useCallback(async () => { + if (!instanceId && !queryInstanceId) { + return undefined; + } + return await orchestratorApi.getInstance(instanceId || queryInstanceId); + }, [instanceId, orchestratorApi, queryInstanceId]); + const { loading, error, value, restart } = usePolling< ProcessInstance | undefined >( - async () => { - if (!instanceId && !queryInstanceId) { - return undefined; - } - return await orchestratorApi.getInstance(instanceId || queryInstanceId); - }, + fetchInstance, SHORT_REFRESH_INTERVAL, (curValue: ProcessInstance | undefined) => !!curValue && curValue.state === 'ACTIVE', diff --git a/plugins/orchestrator/src/components/WorkflowRunsTabContent.tsx b/plugins/orchestrator/src/components/WorkflowRunsTabContent.tsx index aefe9644459..99e523ce2a3 100644 --- a/plugins/orchestrator/src/components/WorkflowRunsTabContent.tsx +++ b/plugins/orchestrator/src/components/WorkflowRunsTabContent.tsx @@ -48,14 +48,15 @@ export const WorkflowRunsTabContent = () => { Selector.AllItems, ); - const { loading, error, value } = usePolling(async () => { + const fetchInstances = React.useCallback(async () => { const instances = await orchestratorApi.getInstances(); const clonedData: WorkflowRunDetail[] = instances.map( mapProcessInstanceToDetails, ); - return clonedData; - }); + }, [orchestratorApi]); + + const { loading, error, value } = usePolling(fetchInstances); const columns = React.useMemo( (): TableColumn[] => [ diff --git a/plugins/orchestrator/src/hooks/usePolling.test.ts b/plugins/orchestrator/src/hooks/usePolling.test.ts index 7503d6c237d..69ee2b6198b 100644 --- a/plugins/orchestrator/src/hooks/usePolling.test.ts +++ b/plugins/orchestrator/src/hooks/usePolling.test.ts @@ -162,4 +162,19 @@ describe('usePolling', () => { await act(async () => result.current.restart()); expect(result.current.value).toEqual(ABORTED); }); + + test('should refetch after fn property changed', async () => { + const mockAsyncFn = jest.fn().mockResolvedValue(ACTIVE); + const { result, waitForNextUpdate, rerender } = renderHook( + ({ fn }: { fn: () => Promise }) => + usePolling(fn, SHORT_REFRESH_INTERVAL), + { initialProps: { fn: mockAsyncFn } }, + ); + await waitForNextUpdate(); + const mockAsyncFn2 = jest.fn().mockResolvedValue(COMPLETED); + expect(result.current.value).toEqual(ACTIVE); + rerender({ fn: mockAsyncFn2 }); + await waitForNextUpdate(); + expect(result.current.value).toEqual(COMPLETED); + }); }); diff --git a/plugins/orchestrator/src/hooks/usePolling.ts b/plugins/orchestrator/src/hooks/usePolling.ts index e2f1daf5b71..277ccda25d6 100644 --- a/plugins/orchestrator/src/hooks/usePolling.ts +++ b/plugins/orchestrator/src/hooks/usePolling.ts @@ -13,8 +13,10 @@ const usePolling = ( ) => { const config = useSWRConfig(); + const prevFn = React.useRef(fn); const uniqueKey = React.useMemo(() => { return uuid.v4(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const [error, setError] = React.useState(); @@ -38,6 +40,18 @@ const usePolling = ( }, }); + const restart = React.useCallback( + () => config.mutate(uniqueKey), + [config, uniqueKey], + ); + + React.useEffect(() => { + if (prevFn.current !== fn) { + restart(); + prevFn.current = fn; + } + }, [fn, restart]); + React.useEffect(() => { // clean cache after unmount, no need to store the data globally return () => config.cache.delete(uniqueKey); @@ -48,7 +62,7 @@ const usePolling = ( value: data, error, loading: isLoading, - restart: () => config.mutate(uniqueKey), + restart, }; };