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.
This commit is contained in:
schroda
2023-11-25 15:35:36 +01:00
committed by GitHub
parent a4bd44de9e
commit 7c69a4a5a1
3 changed files with 27 additions and 20 deletions

View File

@@ -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');
}
};

View File

@@ -1987,15 +1987,7 @@ export class RequestManager {
public useGetLastGlobalUpdateTimestamp(
options?: QueryHookOptions<GetLastUpdateTimestampQuery, GetLastUpdateTimestampQueryVariables>,
): AbortableApolloUseQueryResponse<GetLastUpdateTimestampQuery, GetLastUpdateTimestampQueryVariables> {
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);
}
}

View File

@@ -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() : '-',
})}
</Typography>
<UpdateChecker handleFinishedUpdate={() => refetchlastTimestamp()} />
<UpdateChecker />
</>,
);
}, [t, lastUpdateTimestamp]);