From 7c69a4a5a1b2d49d23a00b17c6624f49222664fb Mon Sep 17 00:00:00 2001 From: schroda <50052685+schroda@users.noreply.github.com> Date: Sat, 25 Nov 2023 15:35:36 +0100 Subject: [PATCH] Feature/global update last timestamp use stale data while fetching (#473) * Cache last update timestamp * Correctly detect update as finished The update status on server side does not get reset, thus, in case a previous update was finished, it would get detected as finished and handled once on the initial render. --- src/components/library/UpdateChecker.tsx | 27 +++++++++++++++++------- src/lib/requests/RequestManager.ts | 10 +-------- src/screens/Updates.tsx | 10 ++++++--- 3 files changed, 27 insertions(+), 20 deletions(-) diff --git a/src/components/library/UpdateChecker.tsx b/src/components/library/UpdateChecker.tsx index 5e33bf09..7363333b 100644 --- a/src/components/library/UpdateChecker.tsx +++ b/src/components/library/UpdateChecker.tsx @@ -6,7 +6,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -import { useMemo } from 'react'; +import { useEffect, useMemo } from 'react'; import IconButton from '@mui/material/IconButton'; import RefreshIcon from '@mui/icons-material/Refresh'; import { useTranslation } from 'react-i18next'; @@ -29,10 +29,12 @@ const calcProgress = (status: UpdaterSubscription['updateStatusChanged'] | undef return Number.isNaN(progress) ? 0 : progress; }; -export function UpdateChecker({ handleFinishedUpdate }: { handleFinishedUpdate: () => void }) { +let lastRunningState = false; + +export function UpdateChecker({ handleFinishedUpdate }: { handleFinishedUpdate?: () => void }) { const { t } = useTranslation(); - const { data: lastUpdateTimestampData, refetch: refetchlastTimestamp } = + const { data: lastUpdateTimestampData, refetch: reFetchLastTimestamp } = requestManager.useGetLastGlobalUpdateTimestamp(); const lastUpdateTimestamp = lastUpdateTimestampData?.lastUpdateTimestamp.timestamp; const { data: updaterData } = requestManager.useUpdaterSubscription(); @@ -49,16 +51,25 @@ export function UpdateChecker({ handleFinishedUpdate }: { handleFinishedUpdate: ], ); - const isUpdateFinished = progress === 100; - if (isUpdateFinished) { - refetchlastTimestamp(); - handleFinishedUpdate(); - } + useEffect(() => { + const isUpdateFinished = lastRunningState && progress === 100; + if (!isUpdateFinished) { + return; + } + + lastRunningState = false; + handleFinishedUpdate?.(); + // this re-fetch is necessary since a running update could have been triggered by the server or another client + reFetchLastTimestamp().catch(() => {}); + }, [status?.isRunning]); const onClick = async () => { try { + lastRunningState = true; await requestManager.startGlobalUpdate().response; + reFetchLastTimestamp().catch(() => {}); } catch (e) { + lastRunningState = false; makeToast(t('global.error.label.update_failed'), 'error'); } }; diff --git a/src/lib/requests/RequestManager.ts b/src/lib/requests/RequestManager.ts index 70c2937e..86efec84 100644 --- a/src/lib/requests/RequestManager.ts +++ b/src/lib/requests/RequestManager.ts @@ -1987,15 +1987,7 @@ export class RequestManager { public useGetLastGlobalUpdateTimestamp( options?: QueryHookOptions, ): AbortableApolloUseQueryResponse { - return this.doRequest( - GQLMethod.USE_QUERY, - GET_LAST_UPDATE_TIMESTAMP, - {}, - { - fetchPolicy: 'network-only', - ...options, - }, - ); + return this.doRequest(GQLMethod.USE_QUERY, GET_LAST_UPDATE_TIMESTAMP, {}, options); } } diff --git a/src/screens/Updates.tsx b/src/screens/Updates.tsx index 12b8029e..b16638a7 100644 --- a/src/screens/Updates.tsx +++ b/src/screens/Updates.tsx @@ -118,8 +118,12 @@ export const Updates: React.FC = () => { const { data: downloaderData } = requestManager.useDownloadSubscription(); const queue = (downloaderData?.downloadChanged.queue as DownloadType[]) ?? []; - const { data: lastUpdateTimestampData, refetch: refetchlastTimestamp } = - requestManager.useGetLastGlobalUpdateTimestamp(); + const { data: lastUpdateTimestampData } = requestManager.useGetLastGlobalUpdateTimestamp({ + /** + * The {@link UpdateChecker} is responsible for updating the timestamp + */ + fetchPolicy: 'cache-only', + }); const lastUpdateTimestamp = lastUpdateTimestampData?.lastUpdateTimestamp.timestamp; useEffect(() => { @@ -132,7 +136,7 @@ export const Updates: React.FC = () => { date: lastUpdateTimestamp ? new Date(+lastUpdateTimestamp).toLocaleString() : '-', })} - refetchlastTimestamp()} /> + , ); }, [t, lastUpdateTimestamp]);