From 2a4e761d6964544d7bb2967903f6c1915171eb23 Mon Sep 17 00:00:00 2001 From: im-adithya Date: Tue, 2 Jul 2024 12:22:29 +0530 Subject: [PATCH 1/7] feat: update start api to be async --- .../components/redirects/SetupRedirect.tsx | 10 +----- frontend/src/screens/Start.tsx | 33 +++++++++++++++---- frontend/src/screens/setup/SetupFinish.tsx | 33 ++++++++++++++----- frontend/src/types.ts | 8 +++++ frontend/src/utils/asyncTimeout.ts | 5 +++ http/http_service.go | 16 ++++++--- 6 files changed, 76 insertions(+), 29 deletions(-) create mode 100644 frontend/src/utils/asyncTimeout.ts diff --git a/frontend/src/components/redirects/SetupRedirect.tsx b/frontend/src/components/redirects/SetupRedirect.tsx index 9bf611522..207ed1bf2 100644 --- a/frontend/src/components/redirects/SetupRedirect.tsx +++ b/frontend/src/components/redirects/SetupRedirect.tsx @@ -3,7 +3,6 @@ import { Outlet, useLocation, useNavigate } from "react-router-dom"; import Loading from "src/components/Loading"; import { useInfo } from "src/hooks/useInfo"; -let didSetupThisSession = false; export function SetupRedirect() { const { data: info } = useInfo(); const location = useLocation(); @@ -13,17 +12,10 @@ export function SetupRedirect() { if (!info) { return; } - if (didSetupThisSession) { - // ensure redirect does not happen as node may still be starting - // which would then incorrectly redirect to the login page - console.info("Skipping setup redirect on initial setup"); - return; - } - if (info.setupCompleted) { + if (info.setupCompleted && info.running) { navigate("/"); return; } - didSetupThisSession = true; }, [info, location, navigate]); if (!info) { diff --git a/frontend/src/screens/Start.tsx b/frontend/src/screens/Start.tsx index fcd2693fd..c3e363b97 100644 --- a/frontend/src/screens/Start.tsx +++ b/frontend/src/screens/Start.tsx @@ -1,5 +1,4 @@ import React from "react"; -import { useNavigate } from "react-router-dom"; import Container from "src/components/Container"; import TwoColumnLayoutHeader from "src/components/TwoColumnLayoutHeader"; import { Input } from "src/components/ui/input"; @@ -8,21 +7,24 @@ import { LoadingButton } from "src/components/ui/loading-button"; import { useToast } from "src/components/ui/use-toast"; import { useCSRF } from "src/hooks/useCSRF"; import { useInfo } from "src/hooks/useInfo"; +import { startupMessages as messages } from "src/types"; +import { asyncTimeout } from "src/utils/asyncTimeout"; import { handleRequestError } from "src/utils/handleRequestError"; import { request } from "src/utils/request"; export default function Start() { const [unlockPassword, setUnlockPassword] = React.useState(""); const [loading, setLoading] = React.useState(false); - const navigate = useNavigate(); + const [buttonText, setButtonText] = React.useState("Login"); const { data: csrf } = useCSRF(); - const { mutate: refetchInfo } = useInfo(); + const { data: info } = useInfo(true); const { toast } = useToast(); async function onSubmit(e: React.FormEvent) { e.preventDefault(); try { setLoading(true); + setButtonText(messages[0]); if (!csrf) { throw new Error("csrf not loaded"); } @@ -36,13 +38,32 @@ export default function Start() { unlockPassword, }), }); - await refetchInfo(); - navigate("/"); + let messageIndex = 1; + const intervalId = setInterval(() => { + // we don't check for info.running as HomeRedirect takes care of it + if (messageIndex < messages.length) { + setButtonText(messages[messageIndex]); + messageIndex++; + } else { + clearInterval(intervalId); + } + }, 5000); + + await asyncTimeout(180000); // wait for 3 minutes + if (!info?.running) { + toast({ + title: "Failed to start", + description: "Please try starting the node again.", + variant: "destructive", + }); + } } catch (error) { handleRequestError(toast, "Failed to connect", error); } finally { setLoading(false); + setButtonText("Login"); + setUnlockPassword(""); } } @@ -68,7 +89,7 @@ export default function Start() { /> - Login + {buttonText} diff --git a/frontend/src/screens/setup/SetupFinish.tsx b/frontend/src/screens/setup/SetupFinish.tsx index dfcfa81e6..7f872dc57 100644 --- a/frontend/src/screens/setup/SetupFinish.tsx +++ b/frontend/src/screens/setup/SetupFinish.tsx @@ -8,7 +8,8 @@ import { toast } from "src/components/ui/use-toast"; import { useCSRF } from "src/hooks/useCSRF"; import { useInfo } from "src/hooks/useInfo"; import useSetupStore from "src/state/SetupStore"; -import { SetupNodeInfo } from "src/types"; +import { SetupNodeInfo, startupMessages as messages } from "src/types"; +import { asyncTimeout } from "src/utils/asyncTimeout"; import { handleRequestError } from "src/utils/handleRequestError"; import { request } from "src/utils/request"; @@ -16,9 +17,12 @@ export function SetupFinish() { const navigate = useNavigate(); const { nodeInfo, unlockPassword } = useSetupStore(); - const { mutate: refetchInfo } = useInfo(); + const { data: info } = useInfo(true); const { data: csrf } = useCSRF(); const [connectionError, setConnectionError] = React.useState(false); + const [loadingMessage, setLoadingMessage] = React.useState( + "Setting up your Hub..." + ); const hasFetchedRef = React.useRef(false); const defaultOptions = { @@ -40,16 +44,27 @@ export function SetupFinish() { (async () => { const succeeded = await finishSetup(csrf, nodeInfo, unlockPassword); if (succeeded) { - const info = await refetchInfo(); - if (!info) { - throw new Error("Failed to re-fetch info"); + // only setup call is successful as start is async + let messageIndex = 1; + const intervalId = setInterval(() => { + // we don't check for info.running as HomeRedirect takes care of it + if (messageIndex < messages.length) { + setLoadingMessage(messages[messageIndex]); + messageIndex++; + } else { + clearInterval(intervalId); + } + }, 5000); + + await asyncTimeout(180000); // wait for 3 minutes + if (!info?.running) { + setConnectionError(true); } - navigate("/"); } else { setConnectionError(true); } })(); - }, [csrf, nodeInfo, refetchInfo, navigate, unlockPassword]); + }, [csrf, nodeInfo, info, navigate, unlockPassword, loadingMessage]); if (connectionError) { return ( @@ -57,7 +72,7 @@ export function SetupFinish() {

Connection Failed

-

Please check your node configuration.

+

Please check your node configuration and try again.