diff --git a/agenta-web/src/components/Playground/ViewNavigation.tsx b/agenta-web/src/components/Playground/ViewNavigation.tsx index 8bd925e18f..2038aa21cf 100644 --- a/agenta-web/src/components/Playground/ViewNavigation.tsx +++ b/agenta-web/src/components/Playground/ViewNavigation.tsx @@ -1,5 +1,5 @@ import React, {useEffect, useRef} from "react" -import {Col, Row, Divider, Button, Tooltip, Spin, notification, Typography} from "antd" +import {Col, Row, Divider, Button, Tooltip, notification, Typography} from "antd" import TestView from "./Views/TestView" import ParametersView from "./Views/ParametersView" import {useVariant} from "@/lib/hooks/useVariant" @@ -8,7 +8,6 @@ import {useRouter} from "next/router" import {useState} from "react" import axios from "axios" import {createUseStyles} from "react-jss" - import {fetchAppContainerURL, waitForAppToStart} from "@/services/api" import {useAppsData} from "@/contexts/app.context" import {isDemo} from "@/lib/helpers/utils" @@ -70,17 +69,24 @@ const ViewNavigation: React.FC = ({ historyStatus, setPromptOptParams, setHistoryStatus, + getVariantLogs, + isLogsLoading, + variantErrorLogs, + setIsLogsLoading, + onClickShowLogs, } = useVariant(appId, variant) const [retrying, setRetrying] = useState(false) const [isParamsCollapsed, setIsParamsCollapsed] = useState("1") const [containerURI, setContainerURI] = useState("") - const [variantErrorLogs, setVariantErrorLogs] = useState("") const [restarting, setRestarting] = useState(false) const {currentApp} = useAppsData() const retriedOnce = useRef(false) const netWorkError = (error as any)?.code === "ERR_NETWORK" const [isDrawerOpen, setIsDrawerOpen] = useState(false) + const stopperRef = useRef(null) + const [isDelayed, setIsDelayed] = useState(false) + const hasError = netWorkError || (isDemo() ? netWorkError : isError) let prevKey = "" const showNotification = (config: Parameters[0]) => { @@ -90,41 +96,89 @@ const ViewNavigation: React.FC = ({ } useEffect(() => { - if (netWorkError) { + if (hasError) { retriedOnce.current = true setRetrying(true) - waitForAppToStart({appId, variant, timeout: isDemo() ? 40000 : 6000}) - .then(() => { - refetch() + const startApp = async () => { + const {stopper, promise} = await waitForAppToStart({ + appId, + variant, + timeout: isDemo() ? 40000 : 10000, }) - .catch(() => { - showNotification({ - type: "error", - message: "Variant unreachable", - description: `Unable to connect to the variant.`, + stopperRef.current = stopper + + promise + .then(() => { + if (!onClickShowLogs.current) { + refetch() + } }) - }) - .finally(() => { - setRetrying(false) - }) - } + .catch(() => { + getVariantLogs() - if (isError) { - const getLogs = async () => { - const logs = await fetchVariantLogs(variant.variantId) - setVariantErrorLogs(logs) + showNotification({ + type: "error", + message: "Variant unreachable", + description: `Unable to connect to the variant.`, + }) + }) + .finally(() => { + setRetrying(false) + setIsDelayed(false) + }) } - getLogs() + startApp() } }, [netWorkError, isError, variant.variantId]) + useEffect(() => { + if (retrying) { + const timeout = setTimeout( + () => { + setIsDelayed(true) + }, + isDemo() ? 15000 : 5000, + ) + return () => clearTimeout(timeout) + } + }, [retrying]) + + const handleStopPolling = () => { + setIsLogsLoading(true) + if (stopperRef.current) { + onClickShowLogs.current = true + stopperRef.current() + getVariantLogs() + } + } + + if (isLoading) + return + + if (isLogsLoading && isError) + return + if (retrying || (!retriedOnce.current && netWorkError)) { return ( - + <> +
+ + {isDelayed && ( + + )} +
+ ) } @@ -245,7 +299,7 @@ const ViewNavigation: React.FC = ({ } return ( - + <> = ({ /> - + ) } diff --git a/agenta-web/src/lib/hooks/useVariant.ts b/agenta-web/src/lib/hooks/useVariant.ts index 82522d4841..239bc14f26 100644 --- a/agenta-web/src/lib/hooks/useVariant.ts +++ b/agenta-web/src/lib/hooks/useVariant.ts @@ -1,8 +1,8 @@ -import {useState, useEffect} from "react" +import {useState, useEffect, useRef} from "react" import {Variant, Parameter} from "@/lib/Types" import {getAllVariantParameters, updateInputParams} from "@/lib/helpers/variantHelper" import {PERMISSION_ERR_MSG} from "../helpers/axiosConfig" -import {createNewVariant, updateVariantParams} from "@/services/playground/api" +import {createNewVariant, fetchVariantLogs, updateVariantParams} from "@/services/playground/api" /** * Hook for using the variant. @@ -21,6 +21,21 @@ export function useVariant(appId: string, variant: Variant) { const [error, setError] = useState(null) const [isParamSaveLoading, setIsParamSaveLoading] = useState(false) const [isChatVariant, setIsChatVariant] = useState(null) + const [isLogsLoading, setIsLogsLoading] = useState(false) + const [variantErrorLogs, setVariantErrorLogs] = useState("") + const onClickShowLogs = useRef(false) + + const getVariantLogs = async () => { + try { + setIsLogsLoading(true) + const logs = await fetchVariantLogs(variant.variantId) + setVariantErrorLogs(logs) + } catch (error) { + console.error(error) + } finally { + setIsLogsLoading(false) + } + } const fetchParameters = async () => { setIsLoading(true) @@ -35,7 +50,7 @@ export function useVariant(appId: string, variant: Variant) { setInputParams(inputs) setURIPath(URIPath) setIsChatVariant(isChatVariant) - setHistoryStatus({loading: false, error: true}) + setHistoryStatus({loading: false, error: false}) } catch (error: any) { if (error.message !== PERMISSION_ERR_MSG) { console.log(error) @@ -45,7 +60,6 @@ export function useVariant(appId: string, variant: Variant) { } } finally { setIsLoading(false) - setHistoryStatus({loading: false, error: false}) } } @@ -112,6 +126,11 @@ export function useVariant(appId: string, variant: Variant) { historyStatus, setPromptOptParams, setHistoryStatus, + getVariantLogs, + isLogsLoading, + variantErrorLogs, + setIsLogsLoading, + onClickShowLogs, } } diff --git a/agenta-web/src/services/api.ts b/agenta-web/src/services/api.ts index 34196f2a06..71d684901e 100644 --- a/agenta-web/src/services/api.ts +++ b/agenta-web/src/services/api.ts @@ -205,7 +205,10 @@ export const waitForAppToStart = async ({ variant?: Variant timeout?: number interval?: number -}) => { +}): Promise<{ + stopper: () => void + promise: Promise +}> => { const _variant = variant || (await fetchVariants(appId, true))[0] if (_variant) { const {stopper, promise} = shortPoll( @@ -218,6 +221,9 @@ export const waitForAppToStart = async ({ ).then(() => stopper()), {delayMs: interval, timeoutMs: timeout}, ) - await promise + + return {stopper, promise} + } else { + return {stopper: () => {}, promise: Promise.reject(new Error("Variant not found"))} } } diff --git a/agenta-web/src/services/app-selector/api/index.ts b/agenta-web/src/services/app-selector/api/index.ts index 5bc8d63fc3..2e248b6ba0 100644 --- a/agenta-web/src/services/app-selector/api/index.ts +++ b/agenta-web/src/services/app-selector/api/index.ts @@ -90,7 +90,8 @@ export const createAndStartTemplate = async ({ onStatusChange?.("starting_app", "", app?.data?.app_id) try { - await waitForAppToStart({appId: app?.data?.app_id, timeout}) + const {promise} = await waitForAppToStart({appId: app?.data?.app_id, timeout}) + await promise } catch (error: any) { if (error.message === "timeout") { onStatusChange?.("timeout", "", app?.data?.app_id)