Log promise failures instead of ignoring them (#531)

In case the failure does not get handled, it should at least get logged, to prevent silently ignoring it
This commit is contained in:
schroda
2023-12-31 01:42:54 +01:00
committed by GitHub
parent 37d6b84cf4
commit 37ce494fda
10 changed files with 44 additions and 13 deletions

View File

@@ -16,6 +16,7 @@ import { Box } from '@mui/material';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { PartialExtension, TranslationKey } from '@/typings'; import { PartialExtension, TranslationKey } from '@/typings';
import { requestManager } from '@/lib/requests/RequestManager.ts'; import { requestManager } from '@/lib/requests/RequestManager.ts';
import { defaultPromiseErrorHandler } from '@/util/defaultPromiseErrorHandler.ts';
interface IProps { interface IProps {
extension: PartialExtension; extension: PartialExtension;
@@ -108,10 +109,14 @@ export function ExtensionCard(props: IProps) {
case ExtensionAction.INSTALL: case ExtensionAction.INSTALL:
case ExtensionAction.UPDATE: case ExtensionAction.UPDATE:
case ExtensionAction.UNINSTALL: case ExtensionAction.UNINSTALL:
requestExtensionAction(installedState).catch(() => {}); requestExtensionAction(installedState).catch(
defaultPromiseErrorHandler(`ExtensionCard:handleButtonClick(${installedState})`),
);
break; break;
case ExtensionState.OBSOLETE: case ExtensionState.OBSOLETE:
requestExtensionAction(ExtensionAction.UNINSTALL).catch(() => {}); requestExtensionAction(ExtensionAction.UNINSTALL).catch(
defaultPromiseErrorHandler(`ExtensionCard:handleButtonClick(${installedState})`),
);
break; break;
default: default:
break; break;

View File

@@ -15,6 +15,7 @@ import { requestManager } from '@/lib/requests/RequestManager.ts';
import { makeToast } from '@/components/util/Toast'; import { makeToast } from '@/components/util/Toast';
import { UpdaterSubscription } from '@/lib/graphql/generated/graphql.ts'; import { UpdaterSubscription } from '@/lib/graphql/generated/graphql.ts';
import { Progress } from '@/components/util/Progress'; import { Progress } from '@/components/util/Progress';
import { defaultPromiseErrorHandler } from '@/util/defaultPromiseErrorHandler.ts';
const calcProgress = (status: UpdaterSubscription['updateStatusChanged'] | undefined) => { const calcProgress = (status: UpdaterSubscription['updateStatusChanged'] | undefined) => {
if (!status) { if (!status) {
@@ -64,14 +65,14 @@ export function UpdateChecker({ handleFinishedUpdate }: { handleFinishedUpdate?:
lastRunningState = false; lastRunningState = false;
handleFinishedUpdate?.(); handleFinishedUpdate?.();
// this re-fetch is necessary since a running update could have been triggered by the server or another client // this re-fetch is necessary since a running update could have been triggered by the server or another client
reFetchLastTimestamp().catch(() => {}); reFetchLastTimestamp().catch(defaultPromiseErrorHandler('UpdateChecker::reFetchLastTimestamp'));
}, [status?.isRunning]); }, [status?.isRunning]);
const onClick = async () => { const onClick = async () => {
try { try {
lastRunningState = true; lastRunningState = true;
await requestManager.startGlobalUpdate().response; await requestManager.startGlobalUpdate().response;
reFetchLastTimestamp().catch(() => {}); reFetchLastTimestamp().catch(defaultPromiseErrorHandler('UpdateChecker::reFetchLastTimestamp'));
} catch (e) { } catch (e) {
lastRunningState = false; lastRunningState = false;
makeToast(t('global.error.label.update_failed'), 'error'); makeToast(t('global.error.label.update_failed'), 'error');

View File

@@ -21,6 +21,7 @@ import { SelectableCollectionReturnType } from '@/components/collection/useSelec
import { CategorySelect } from '@/components/navbar/action/CategorySelect.tsx'; import { CategorySelect } from '@/components/navbar/action/CategorySelect.tsx';
import { MenuItem } from '@/components/menu/MenuItem.tsx'; import { MenuItem } from '@/components/menu/MenuItem.tsx';
import { createGetMenuItemTitle, createIsMenuItemDisabled, createShouldShowMenuItem } from '@/components/menu/util.ts'; import { createGetMenuItemTitle, createIsMenuItemDisabled, createShouldShowMenuItem } from '@/components/menu/util.ts';
import { defaultPromiseErrorHandler } from '@/util/defaultPromiseErrorHandler.ts';
const ACTION_DISABLES_SELECTION_MODE: MangaAction[] = ['remove_from_library'] as const; const ACTION_DISABLES_SELECTION_MODE: MangaAction[] = ['remove_from_library'] as const;
@@ -63,7 +64,7 @@ export const MangaActionMenuItems = ({ manga, handleSelection, selectedMangas =
const performAction = (action: MangaAction, mangas: TManga[]) => { const performAction = (action: MangaAction, mangas: TManga[]) => {
Mangas.performAction(action, manga ? [manga.id] : Mangas.getIds(mangas), { Mangas.performAction(action, manga ? [manga.id] : Mangas.getIds(mangas), {
wasManuallyMarkedAsRead: true, wasManuallyMarkedAsRead: true,
}).catch(() => {}); }).catch(defaultPromiseErrorHandler(`MangaActionMenuItems:performAction(${action})`));
onClose(!ACTION_DISABLES_SELECTION_MODE.includes(action)); onClose(!ACTION_DISABLES_SELECTION_MODE.includes(action));
}; };

View File

@@ -17,6 +17,7 @@ import { useTranslation } from 'react-i18next';
import { requestManager } from '@/lib/requests/RequestManager.ts'; import { requestManager } from '@/lib/requests/RequestManager.ts';
import { getVersion } from '@/screens/settings/About.tsx'; import { getVersion } from '@/screens/settings/About.tsx';
import { useLocalStorage } from '@/util/useLocalStorage.tsx'; import { useLocalStorage } from '@/util/useLocalStorage.tsx';
import { defaultPromiseErrorHandler } from '@/util/defaultPromiseErrorHandler.ts';
const UPDATE_CHECK_INTERVAL = 1000 * 60 * 60 * 24; // 1 day const UPDATE_CHECK_INTERVAL = 1000 * 60 * 60 * 24; // 1 day
@@ -54,7 +55,7 @@ export const ServerUpdateChecker = () => {
let timeout: NodeJS.Timeout | undefined; let timeout: NodeJS.Timeout | undefined;
const scheduleUpdateCheck = (timeoutMS: number) => { const scheduleUpdateCheck = (timeoutMS: number) => {
timeout = setTimeout(() => { timeout = setTimeout(() => {
checkForUpdate().catch(() => {}); checkForUpdate().catch(defaultPromiseErrorHandler('ServerUpdateChecker::checkForUpdate'));
setLastUpdateCheck(Date.now()); setLastUpdateCheck(Date.now());
scheduleUpdateCheck(UPDATE_CHECK_INTERVAL); scheduleUpdateCheck(UPDATE_CHECK_INTERVAL);
}, timeoutMS); }, timeoutMS);

View File

@@ -238,6 +238,7 @@ import { CLEAR_SERVER_CACHE } from '@/lib/graphql/mutations/ImageMutation.ts';
import { RESET_WEBUI_UPDATE_STATUS, UPDATE_WEBUI } from '@/lib/graphql/mutations/ServerInfoMutation.ts'; import { RESET_WEBUI_UPDATE_STATUS, UPDATE_WEBUI } from '@/lib/graphql/mutations/ServerInfoMutation.ts';
import { WEBUI_UPDATE_SUBSCRIPTION } from '@/lib/graphql/subscriptions/ServerInfoSubscription.ts'; import { WEBUI_UPDATE_SUBSCRIPTION } from '@/lib/graphql/subscriptions/ServerInfoSubscription.ts';
import { GET_DOWNLOAD_STATUS } from '@/lib/graphql/queries/DownloaderQuery.ts'; import { GET_DOWNLOAD_STATUS } from '@/lib/graphql/queries/DownloaderQuery.ts';
import { defaultPromiseErrorHandler } from '@/util/defaultPromiseErrorHandler.ts';
enum GQLMethod { enum GQLMethod {
QUERY = 'QUERY', QUERY = 'QUERY',
@@ -514,7 +515,7 @@ export class RequestManager {
await revalidationPromise; await revalidationPromise;
setActiveRevalidation(null); setActiveRevalidation(null);
} catch (e) { } catch (e) {
// ignore defaultPromiseErrorHandler(`RequestManager..revalidatePages(${getVariablesFor(0)})`)(e);
} finally { } finally {
setValidating(false); setValidating(false);
} }

View File

@@ -29,6 +29,7 @@ import { ChapterType, DownloadType } from '@/lib/graphql/generated/graphql.ts';
import { TChapter } from '@/typings.ts'; import { TChapter } from '@/typings.ts';
import { NavBarContext } from '@/components/context/NavbarContext.tsx'; import { NavBarContext } from '@/components/context/NavbarContext.tsx';
import { LoadingPlaceholder } from '@/components/util/LoadingPlaceholder.tsx'; import { LoadingPlaceholder } from '@/components/util/LoadingPlaceholder.tsx';
import { defaultPromiseErrorHandler } from '@/util/defaultPromiseErrorHandler.ts';
const HeightPreservingItem = ({ children, ...props }: BoxProps) => ( const HeightPreservingItem = ({ children, ...props }: BoxProps) => (
// the height is necessary to prevent the item container from collapsing, which confuses Virtuoso measurements // the height is necessary to prevent the item container from collapsing, which confuses Virtuoso measurements
@@ -203,7 +204,7 @@ export const DownloadQueue: React.FC = () => {
return; return;
} }
requestManager.startDownloads().response.catch(() => {}); requestManager.startDownloads().response.catch(defaultPromiseErrorHandler('DownloadQueue::startDownloads'));
}; };
if (isLoading) { if (isLoading) {

View File

@@ -30,6 +30,7 @@ import { NavBarContext } from '@/components/context/NavbarContext.tsx';
import { useDebounce } from '@/util/useDebounce.ts'; import { useDebounce } from '@/util/useDebounce.ts';
import { UpdateChapterPatchInput } from '@/lib/graphql/generated/graphql.ts'; import { UpdateChapterPatchInput } from '@/lib/graphql/generated/graphql.ts';
import { useMetadataServerSettings } from '@/util/metadataServerSettings.ts'; import { useMetadataServerSettings } from '@/util/metadataServerSettings.ts';
import { defaultPromiseErrorHandler } from '@/util/defaultPromiseErrorHandler.ts';
const isDupChapter = async (chapterIndex: number, currentChapter: TChapter) => { const isDupChapter = async (chapterIndex: number, currentChapter: TChapter) => {
const nextChapter = await requestManager.getChapter(currentChapter.manga.id, chapterIndex).response; const nextChapter = await requestManager.getChapter(currentChapter.manga.id, chapterIndex).response;
@@ -209,7 +210,7 @@ export function Reader() {
chapterIdToDelete: getChapterIdToDelete(), chapterIdToDelete: getChapterIdToDelete(),
downloadAheadMangaId: shouldDownloadAhead ? chapter.manga.id : undefined, downloadAheadMangaId: shouldDownloadAhead ? chapter.manga.id : undefined,
}) })
.response.catch(() => {}); .response.catch();
}; };
const setSettingValue = (key: keyof IReaderSettings, value: string | boolean) => { const setSettingValue = (key: keyof IReaderSettings, value: string | boolean) => {
@@ -264,7 +265,9 @@ export function Reader() {
useEffect(() => { useEffect(() => {
if (!areDefaultSettingsLoading && !isMangaLoading) { if (!areDefaultSettingsLoading && !isMangaLoading) {
checkAndHandleMissingStoredReaderSettings(manga, 'manga', defaultSettings).catch(() => {}); checkAndHandleMissingStoredReaderSettings(manga, 'manga', defaultSettings).catch(
defaultPromiseErrorHandler('Reader::checkAndHandleMissingStoredReaderSettings'),
);
setSettings(getReaderSettingsFor(manga, defaultSettings)); setSettings(getReaderSettingsFor(manga, defaultSettings));
} }
}, [areDefaultSettingsLoading, isMangaLoading]); }, [areDefaultSettingsLoading, isMangaLoading]);

View File

@@ -25,6 +25,7 @@ import { LoadingPlaceholder } from '@/components/util/LoadingPlaceholder';
import { GetAboutQuery, UpdateState } from '@/lib/graphql/generated/graphql.ts'; import { GetAboutQuery, UpdateState } from '@/lib/graphql/generated/graphql.ts';
import { ABOUT_WEBUI, WEBUI_UPDATE_CHECK } from '@/lib/graphql/Fragments.ts'; import { ABOUT_WEBUI, WEBUI_UPDATE_CHECK } from '@/lib/graphql/Fragments.ts';
import { makeToast } from '@/components/util/Toast.tsx'; import { makeToast } from '@/components/util/Toast.tsx';
import { defaultPromiseErrorHandler } from '@/util/defaultPromiseErrorHandler.ts';
type AboutServer = GetAboutQuery['aboutServer']; type AboutServer = GetAboutQuery['aboutServer'];
@@ -224,7 +225,9 @@ export function About() {
const resetUpdateStatus = isError || updateFinished; const resetUpdateStatus = isError || updateFinished;
if (resetUpdateStatus) { if (resetUpdateStatus) {
requestManager.resetWebUIUpdateStatus().response.catch(() => {}); requestManager
.resetWebUIUpdateStatus()
.response.catch(defaultPromiseErrorHandler('About::resetWebUIUpdateStatus'));
} }
if (!updateFinished) { if (!updateFinished) {
@@ -326,7 +329,11 @@ export function About() {
isUpdateAvailable={isWebUIUpdateAvailable} isUpdateAvailable={isWebUIUpdateAvailable}
updateCheckError={webUIUpdateCheckError} updateCheckError={webUIUpdateCheckError}
checkForUpdate={checkForWebUIUpdate} checkForUpdate={checkForWebUIUpdate}
triggerUpdate={() => requestManager.updateWebUI().response.catch(() => {})} triggerUpdate={() =>
requestManager
.updateWebUI()
.response.catch(defaultPromiseErrorHandler('About::updateWebUI'))
}
progress={webUIUpdateProgress} progress={webUIUpdateProgress}
updateState={webUIUpdateState} updateState={webUIUpdateState}
/> />

View File

@@ -20,6 +20,7 @@ import {
import { ReaderSettingsOptions } from '@/components/reader/ReaderSettingsOptions'; import { ReaderSettingsOptions } from '@/components/reader/ReaderSettingsOptions';
import { makeToast } from '@/components/util/Toast'; import { makeToast } from '@/components/util/Toast';
import { NavBarContext, useSetDefaultBackTo } from '@/components/context/NavbarContext'; import { NavBarContext, useSetDefaultBackTo } from '@/components/context/NavbarContext';
import { defaultPromiseErrorHandler } from '@/util/defaultPromiseErrorHandler.ts';
export function DefaultReaderSettings() { export function DefaultReaderSettings() {
const { t } = useTranslation(); const { t } = useTranslation();
@@ -58,7 +59,7 @@ export function DefaultReaderSettings() {
{ meta: convertToGqlMeta(metadata)! }, { meta: convertToGqlMeta(metadata)! },
'server', 'server',
getDefaultSettings(), getDefaultSettings(),
).catch(() => {}); ).catch(defaultPromiseErrorHandler('DefaultReaderSettings::checkAndHandleMissingStoredReaderSettings'));
return ( return (
<ReaderSettingsOptions <ReaderSettingsOptions

View File

@@ -0,0 +1,10 @@
/*
* Copyright (C) Contributors to the Suwayomi project
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
export const defaultPromiseErrorHandler = (name: string) => (error: any) =>
console.error(`${name} failed due to`, error);