Browse Source
561: Replicate missing functionality into new taker UI r=klochowicz a=klochowicz - display information about errors when possible (e.g. when cfd action failed), - inform the user if the daemon got shut down also, as a separate commit, remove checking for daemon's presence in the maker's UI (automation can poll for it by itself). Co-authored-by: Mariusz Klochowicz <mariusz@klochowicz.com>new-http-api
bors[bot]
3 years ago
committed by
GitHub
6 changed files with 103 additions and 30 deletions
@ -0,0 +1,50 @@ |
|||||
|
import { useEffect, useRef } from "react"; |
||||
|
|
||||
|
async function fetchWithTimeout(resource: any, timeout: number) { |
||||
|
const controller = new AbortController(); |
||||
|
const id = setTimeout(() => controller.abort(), timeout); |
||||
|
const response = await fetch(resource, { |
||||
|
signal: controller.signal, |
||||
|
}); |
||||
|
clearTimeout(id); |
||||
|
return response; |
||||
|
} |
||||
|
|
||||
|
// Check for backend's presence by sending a request to '/alive' endpoint.
|
||||
|
// When the backend's not there, the request is likely to timeout, triggering a
|
||||
|
// persistent toast notification that goes away when the daemon is back online.
|
||||
|
export function useBackendMonitor(toast: any, timeout_ms: number): void { |
||||
|
const toastIdRef = useRef(); |
||||
|
|
||||
|
const checkForBackend: () => void = async () => { |
||||
|
try { |
||||
|
const res = await fetchWithTimeout("/alive", timeout_ms); |
||||
|
// In case we get a response, but it's not what we expected
|
||||
|
if (res.status.toString().startsWith("2")) { |
||||
|
if (toastIdRef.current) { |
||||
|
toast.close(toastIdRef.current); |
||||
|
} |
||||
|
} else { |
||||
|
throw new Error(res.statusText); |
||||
|
} |
||||
|
} catch (e) { |
||||
|
if (!toastIdRef.current) { |
||||
|
toastIdRef.current = toast({ |
||||
|
title: "Connection Error", |
||||
|
description: "Daemon process is not running", |
||||
|
status: "error", |
||||
|
position: "top", |
||||
|
duration: timeout_ms * 100000, // we don't want this to be closed
|
||||
|
isClosable: false, |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
useEffect(() => { |
||||
|
const interval = setInterval(() => checkForBackend(), timeout_ms); |
||||
|
return () => { |
||||
|
clearInterval(interval); |
||||
|
}; |
||||
|
}); |
||||
|
} |
@ -0,0 +1,28 @@ |
|||||
|
import { HttpError } from "./HttpError"; |
||||
|
|
||||
|
// A generic way of creating an error toast
|
||||
|
// TODO: Don't use any (`toast: typeof useToast` did not work :( )
|
||||
|
export default function createErrorToast(toast: any, e: any) { |
||||
|
if (e instanceof HttpError) { |
||||
|
const description = e.detail ? e.detail : ""; |
||||
|
|
||||
|
toast({ |
||||
|
title: "Error: " + e.title, |
||||
|
description, |
||||
|
status: "error", |
||||
|
duration: 10000, |
||||
|
isClosable: true, |
||||
|
}); |
||||
|
} else { |
||||
|
console.log(e); |
||||
|
const description = typeof e === "string" ? e : JSON.stringify(e); |
||||
|
|
||||
|
toast({ |
||||
|
title: "Error", |
||||
|
description, |
||||
|
status: "error", |
||||
|
duration: 10000, |
||||
|
isClosable: true, |
||||
|
}); |
||||
|
} |
||||
|
} |
@ -0,0 +1,18 @@ |
|||||
|
// A wrapper to parse RFC 7807
|
||||
|
// Pass result of `await response.json()` into the constructor.
|
||||
|
export class HttpError extends Error { |
||||
|
title: string; |
||||
|
detail?: string; |
||||
|
|
||||
|
// FIXME: Constructor can't be async, so we can't pass `Response` here
|
||||
|
constructor(json_resp: any) { |
||||
|
let title = json_resp.title; |
||||
|
super(title); |
||||
|
this.title = title; |
||||
|
if (json_resp.detail) { |
||||
|
this.detail = json_resp.detail; |
||||
|
} |
||||
|
|
||||
|
Object.setPrototypeOf(this, HttpError.prototype); |
||||
|
} |
||||
|
} |
Loading…
Reference in new issue