Skip to content

Commit

Permalink
feat: add refresher hook for long lived processes
Browse files Browse the repository at this point in the history
  • Loading branch information
toniocodo committed Jul 25, 2024
1 parent 1a4affa commit c9f9f67
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 0 deletions.
1 change: 1 addition & 0 deletions libs/shared/providers/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export * from './notifications';
export * from './prices';
export * from './rebaseBanner';
export * from './redeemer';
export * from './refresher';
export * from './settings';
export * from './slippage';
export * from './swapper';
Expand Down
81 changes: 81 additions & 0 deletions libs/shared/providers/src/refresher/hooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { useCallback, useState } from 'react';

import { useIntervalEffect } from '@react-hookz/web';
import { useQueryClient } from '@tanstack/react-query';

import type { QueryFunction, QueryKey } from '@tanstack/react-query';

export type RefreshStatus =
| 'idle'
| 'polling'
| 'processed'
| 'timeout'
| 'error';

export type UseRefresherProps<QueryResult = any> = {
queryKey: QueryKey;
queryFn: QueryFunction<QueryResult>;
isResultProcessed: (prev: QueryResult, next: QueryResult) => boolean;
maxRetries?: number;
interval?: number;
};

export const useRefresher = <QueryResult = any>({
queryKey,
queryFn,
isResultProcessed,
maxRetries = 10,
interval = 2000,
}: UseRefresherProps<QueryResult>) => {
const queryClient = useQueryClient();
const prev = queryClient.getQueryData<QueryResult>(queryKey);
const [retries, setRetries] = useState(0);
const [status, setStatus] = useState<RefreshStatus>('idle');
const [pollInterval, setPollInterval] = useState<number | undefined>(
undefined,
);

const startRefresh = useCallback(() => {
setPollInterval(interval);
setStatus('polling');
}, [interval]);

const stopRefresh = useCallback(() => {
setPollInterval(undefined);
setStatus('idle');
}, []);

useIntervalEffect(() => {
(async () => {
const next = await queryClient.fetchQuery({
queryKey,
queryFn,
staleTime: 0,
});

try {
if (!prev || !next) {
setPollInterval(undefined);
setStatus('error');
} else if (retries > maxRetries) {
setPollInterval(undefined);
setStatus('timeout');
} else if (isResultProcessed(prev, next)) {
setPollInterval(undefined);
setStatus('processed');
}
} catch {
setPollInterval(undefined);
setStatus('error');
}
setRetries((prev) => prev + 1);
})();
}, pollInterval);

return {
status,
startRefresh,
stopRefresh,
};
};
1 change: 1 addition & 0 deletions libs/shared/providers/src/refresher/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './hooks';

0 comments on commit c9f9f67

Please sign in to comment.