Refactor SWR mutation handling: replace Error with NetworkError for improved error management and add error handling in fetchers
parent
8f9c03f400
commit
82a4750c76
|
@ -14,7 +14,7 @@ import {
|
|||
RestartMachine,
|
||||
ShutdownMachine
|
||||
} from "types";
|
||||
import { Key, mutationFetcher, useSWRMutation } from "units/swr";
|
||||
import { Key, NetworkError, mutationFetcher, useSWRMutation } from "units/swr";
|
||||
import { usePingTrigger } from "../hooks";
|
||||
|
||||
type Props = {
|
||||
|
@ -34,6 +34,7 @@ const MachineContainer: React.FC<Props> = ({ machine, viewMode }) => {
|
|||
|
||||
const manageActionResponse = useCallback(
|
||||
(response: MachineActionResult) => {
|
||||
debugger;
|
||||
addLog(`Success: ${response.success}. Status: ${response.status}`);
|
||||
if (response.success) {
|
||||
blip.success(response.status);
|
||||
|
@ -48,20 +49,23 @@ const MachineContainer: React.FC<Props> = ({ machine, viewMode }) => {
|
|||
onSuccess: manageActionResponse
|
||||
});
|
||||
|
||||
const { trigger: shutdownMachineTrigger } = useSWRMutation<MachineShutdown, Error, Key, ShutdownMachine>(
|
||||
const { trigger: shutdownMachineTrigger } = useSWRMutation<MachineShutdown, NetworkError, Key, ShutdownMachine>(
|
||||
endpoints.network.machine.shutdown,
|
||||
mutationFetcher<ShutdownMachine>,
|
||||
{
|
||||
onError: err => blip.error(err.message),
|
||||
onError: err => {
|
||||
debugger;
|
||||
blip.error(err.message);
|
||||
},
|
||||
onSuccess: manageActionResponse
|
||||
}
|
||||
);
|
||||
|
||||
const { trigger: restartMachineTrigger } = useSWRMutation<MachineRestarted, Error, Key, RestartMachine>(
|
||||
const { trigger: restartMachineTrigger } = useSWRMutation<MachineRestarted, NetworkError, Key, RestartMachine>(
|
||||
endpoints.network.machine.restart,
|
||||
mutationFetcher<RestartMachine>,
|
||||
{
|
||||
onError: err => blip.error(err.message),
|
||||
onError: err => blip.error(err.serverError.message || err.message),
|
||||
onSuccess: manageActionResponse
|
||||
}
|
||||
);
|
||||
|
|
|
@ -7,7 +7,7 @@ import { msToMinAndSec } from "../../../../utils/time";
|
|||
import { endpoints } from "../../../../utils/api";
|
||||
import { Machine, MachineWaked, WakeMachine } from "types";
|
||||
import { usePingTrigger } from "../../hooks";
|
||||
import { Key, mutationFetcher, useSWRMutation } from "units/swr";
|
||||
import { Key, mutationFetcher, NetworkError, useSWRMutation } from "units/swr";
|
||||
|
||||
const initialState = { on: false };
|
||||
const defaultPingInterval = 1200000; //20 minutes
|
||||
|
@ -58,7 +58,7 @@ const WakeComponent: React.FC<Props> = ({ machine, addLog, disabled }) => {
|
|||
}
|
||||
});
|
||||
|
||||
const { trigger: wakeMachineTrigger } = useSWRMutation<MachineWaked, Error, Key, WakeMachine>(
|
||||
const { trigger: wakeMachineTrigger } = useSWRMutation<MachineWaked, NetworkError, Key, WakeMachine>(
|
||||
endpoints.network.machine.wake,
|
||||
mutationFetcher<WakeMachine>,
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { useMemo } from "react";
|
||||
import { MachinePinged, PingMachine } from "types";
|
||||
import { Key, mutationFetcher, useSWRMutation } from "units/swr";
|
||||
import { Key, mutationFetcher, NetworkError, useSWRMutation } from "units/swr";
|
||||
import { blip } from "utils";
|
||||
import { endpoints } from "utils/api";
|
||||
|
||||
|
@ -12,7 +12,7 @@ const usePingTrigger = (options: PingTriggerOptions) => {
|
|||
const { onSuccess } = options;
|
||||
const onError = useMemo(() => options.onError || ((error: Error) => blip.error(error.message)), [options.onError]);
|
||||
|
||||
const { trigger: pingMachineTrigger } = useSWRMutation<MachinePinged, Error, Key, PingMachine>(
|
||||
const { trigger: pingMachineTrigger } = useSWRMutation<MachinePinged, NetworkError, Key, PingMachine>(
|
||||
endpoints.network.machine.ping,
|
||||
mutationFetcher<PingMachine>,
|
||||
{
|
||||
|
|
|
@ -3,17 +3,21 @@ import CacheSettingsComponent from "./CacheSettingsComponent";
|
|||
import { useTranslation } from "react-i18next";
|
||||
import { endpoints } from "utils/api";
|
||||
import { blip } from "utils";
|
||||
import { useSWRMutation, mutationFetcher, Key } from "units/swr";
|
||||
import { useSWRMutation, mutationFetcher, Key, NetworkError } from "units/swr";
|
||||
|
||||
const CacheSettingsContainer: React.FC = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { trigger } = useSWRMutation<void, Error, Key, void>(endpoints.system.resetCache, mutationFetcher<void>, {
|
||||
onError: err => {
|
||||
blip.error(err.message);
|
||||
},
|
||||
onSuccess: () => blip.info(t("Settings.Cache.ResetInfo"))
|
||||
});
|
||||
const { trigger } = useSWRMutation<void, NetworkError, Key, void>(
|
||||
endpoints.system.resetCache,
|
||||
mutationFetcher<void>,
|
||||
{
|
||||
onError: err => {
|
||||
blip.error(err.message);
|
||||
},
|
||||
onSuccess: () => blip.info(t("Settings.Cache.ResetInfo"))
|
||||
}
|
||||
);
|
||||
|
||||
const handleResetCache = useCallback(() => trigger(), [trigger]);
|
||||
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
export type ServerError = {
|
||||
title: string;
|
||||
status: number;
|
||||
message: string | null;
|
||||
};
|
||||
|
||||
export class NetworkError extends Error {
|
||||
status: number;
|
||||
serverError: ServerError;
|
||||
|
||||
constructor(message: string, status: number, serverError: ServerError) {
|
||||
super(message);
|
||||
this.status = status;
|
||||
this.serverError = serverError;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
import i18next from "i18next";
|
||||
import { acquire as fetchTuitioData } from "@flare/tuitio-client";
|
||||
import { NetworkError, ServerError } from "./errors";
|
||||
|
||||
const getHeaders = (): HeadersInit => {
|
||||
const { token } = fetchTuitioData();
|
||||
|
@ -20,18 +21,36 @@ const getHeaders = (): HeadersInit => {
|
|||
return headers;
|
||||
};
|
||||
|
||||
const fetcher = (url: string) => fetch(url, { method: "GET", headers: getHeaders() }).then(res => res.json());
|
||||
const fetcher = async (url: string) => {
|
||||
const res = await fetch(url, { method: "GET", headers: getHeaders() });
|
||||
|
||||
if (!res.ok) {
|
||||
const serverError = (await res.json()) as ServerError;
|
||||
const error = new NetworkError("An error occurred while fetching the data.", res.status, serverError);
|
||||
throw error;
|
||||
}
|
||||
|
||||
return res.json();
|
||||
};
|
||||
|
||||
async function mutationFetcher<Command>(url: string, { arg }: { arg: Command }) {
|
||||
const hasBody = arg !== undefined && arg !== null;
|
||||
const headers = getHeaders();
|
||||
const body = hasBody ? JSON.stringify(arg) : undefined;
|
||||
|
||||
return fetch(url, {
|
||||
const res = await fetch(url, {
|
||||
method: "POST",
|
||||
headers,
|
||||
body
|
||||
}).then(res => res.json());
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
const serverError = (await res.json()) as ServerError;
|
||||
const error = new NetworkError("An error occurred while mutating the data.", res.status, serverError);
|
||||
throw error;
|
||||
}
|
||||
|
||||
return res.json();
|
||||
}
|
||||
|
||||
export { fetcher, mutationFetcher };
|
||||
|
|
|
@ -3,6 +3,7 @@ import type { Key } from "swr";
|
|||
import useSWRMutation from "swr/mutation";
|
||||
|
||||
export * from "./fetchers";
|
||||
export * from "./errors";
|
||||
|
||||
export { useSWR, useSWRMutation };
|
||||
export type { Key };
|
||||
|
|
Loading…
Reference in New Issue