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:
@@ -6,7 +6,7 @@
|
|||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
* 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 IconButton from '@mui/material/IconButton';
|
||||||
import RefreshIcon from '@mui/icons-material/Refresh';
|
import RefreshIcon from '@mui/icons-material/Refresh';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
@@ -29,10 +29,12 @@ const calcProgress = (status: UpdaterSubscription['updateStatusChanged'] | undef
|
|||||||
return Number.isNaN(progress) ? 0 : progress;
|
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 { t } = useTranslation();
|
||||||
|
|
||||||
const { data: lastUpdateTimestampData, refetch: refetchlastTimestamp } =
|
const { data: lastUpdateTimestampData, refetch: reFetchLastTimestamp } =
|
||||||
requestManager.useGetLastGlobalUpdateTimestamp();
|
requestManager.useGetLastGlobalUpdateTimestamp();
|
||||||
const lastUpdateTimestamp = lastUpdateTimestampData?.lastUpdateTimestamp.timestamp;
|
const lastUpdateTimestamp = lastUpdateTimestampData?.lastUpdateTimestamp.timestamp;
|
||||||
const { data: updaterData } = requestManager.useUpdaterSubscription();
|
const { data: updaterData } = requestManager.useUpdaterSubscription();
|
||||||
@@ -49,16 +51,25 @@ export function UpdateChecker({ handleFinishedUpdate }: { handleFinishedUpdate:
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
const isUpdateFinished = progress === 100;
|
useEffect(() => {
|
||||||
if (isUpdateFinished) {
|
const isUpdateFinished = lastRunningState && progress === 100;
|
||||||
refetchlastTimestamp();
|
if (!isUpdateFinished) {
|
||||||
handleFinishedUpdate();
|
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 () => {
|
const onClick = async () => {
|
||||||
try {
|
try {
|
||||||
|
lastRunningState = true;
|
||||||
await requestManager.startGlobalUpdate().response;
|
await requestManager.startGlobalUpdate().response;
|
||||||
|
reFetchLastTimestamp().catch(() => {});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
lastRunningState = false;
|
||||||
makeToast(t('global.error.label.update_failed'), 'error');
|
makeToast(t('global.error.label.update_failed'), 'error');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1987,15 +1987,7 @@ export class RequestManager {
|
|||||||
public useGetLastGlobalUpdateTimestamp(
|
public useGetLastGlobalUpdateTimestamp(
|
||||||
options?: QueryHookOptions<GetLastUpdateTimestampQuery, GetLastUpdateTimestampQueryVariables>,
|
options?: QueryHookOptions<GetLastUpdateTimestampQuery, GetLastUpdateTimestampQueryVariables>,
|
||||||
): AbortableApolloUseQueryResponse<GetLastUpdateTimestampQuery, GetLastUpdateTimestampQueryVariables> {
|
): AbortableApolloUseQueryResponse<GetLastUpdateTimestampQuery, GetLastUpdateTimestampQueryVariables> {
|
||||||
return this.doRequest(
|
return this.doRequest(GQLMethod.USE_QUERY, GET_LAST_UPDATE_TIMESTAMP, {}, options);
|
||||||
GQLMethod.USE_QUERY,
|
|
||||||
GET_LAST_UPDATE_TIMESTAMP,
|
|
||||||
{},
|
|
||||||
{
|
|
||||||
fetchPolicy: 'network-only',
|
|
||||||
...options,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -118,8 +118,12 @@ export const Updates: React.FC = () => {
|
|||||||
const { data: downloaderData } = requestManager.useDownloadSubscription();
|
const { data: downloaderData } = requestManager.useDownloadSubscription();
|
||||||
const queue = (downloaderData?.downloadChanged.queue as DownloadType[]) ?? [];
|
const queue = (downloaderData?.downloadChanged.queue as DownloadType[]) ?? [];
|
||||||
|
|
||||||
const { data: lastUpdateTimestampData, refetch: refetchlastTimestamp } =
|
const { data: lastUpdateTimestampData } = requestManager.useGetLastGlobalUpdateTimestamp({
|
||||||
requestManager.useGetLastGlobalUpdateTimestamp();
|
/**
|
||||||
|
* The {@link UpdateChecker} is responsible for updating the timestamp
|
||||||
|
*/
|
||||||
|
fetchPolicy: 'cache-only',
|
||||||
|
});
|
||||||
const lastUpdateTimestamp = lastUpdateTimestampData?.lastUpdateTimestamp.timestamp;
|
const lastUpdateTimestamp = lastUpdateTimestampData?.lastUpdateTimestamp.timestamp;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -132,7 +136,7 @@ export const Updates: React.FC = () => {
|
|||||||
date: lastUpdateTimestamp ? new Date(+lastUpdateTimestamp).toLocaleString() : '-',
|
date: lastUpdateTimestamp ? new Date(+lastUpdateTimestamp).toLocaleString() : '-',
|
||||||
})}
|
})}
|
||||||
</Typography>
|
</Typography>
|
||||||
<UpdateChecker handleFinishedUpdate={() => refetchlastTimestamp()} />
|
<UpdateChecker />
|
||||||
</>,
|
</>,
|
||||||
);
|
);
|
||||||
}, [t, lastUpdateTimestamp]);
|
}, [t, lastUpdateTimestamp]);
|
||||||
|
|||||||
Reference in New Issue
Block a user