mirror of
https://github.com/langgenius/dify.git
synced 2026-05-13 08:57:28 +08:00
fix state
This commit is contained in:
parent
64bacd1e5f
commit
79591ca7bd
@ -9,10 +9,11 @@ import type {
|
||||
} from '@/contract/console/deployments'
|
||||
import { queryOptions } from '@tanstack/react-query'
|
||||
import { getQueryClient } from '@/context/get-query-client'
|
||||
import { consoleClient } from '@/service/client'
|
||||
import { consoleClient, consoleQuery } from '@/service/client'
|
||||
|
||||
const DEPLOYMENT_PAGE_SIZE = 100
|
||||
const DEPLOYMENT_APP_DATA_STALE_TIME = 30 * 1000
|
||||
const DEPLOYMENT_READINESS_RETRY_DELAYS = [0, 300, 700, 1200]
|
||||
|
||||
export type DeploymentAppData = {
|
||||
appId: string
|
||||
@ -91,6 +92,65 @@ export const refreshDeploymentAppData = async (appId: string): Promise<Deploymen
|
||||
})
|
||||
}
|
||||
|
||||
const wait = (delay: number) => new Promise(resolve => setTimeout(resolve, delay))
|
||||
|
||||
export const refreshDeploymentAppDataWhenReady = async (appId: string): Promise<DeploymentAppData> => {
|
||||
let lastError: unknown
|
||||
|
||||
for (const delay of DEPLOYMENT_READINESS_RETRY_DELAYS) {
|
||||
if (delay > 0)
|
||||
await wait(delay)
|
||||
|
||||
try {
|
||||
return await refreshDeploymentAppData(appId)
|
||||
}
|
||||
catch (error) {
|
||||
lastError = error
|
||||
}
|
||||
}
|
||||
|
||||
throw lastError
|
||||
}
|
||||
|
||||
export const refreshDeploymentLists = async () => {
|
||||
await getQueryClient().invalidateQueries({
|
||||
queryKey: consoleQuery.deployments.list.key(),
|
||||
})
|
||||
}
|
||||
|
||||
export const waitForAppInstanceInDeploymentList = async (appInstanceId: string) => {
|
||||
let lastError: unknown
|
||||
|
||||
for (const delay of DEPLOYMENT_READINESS_RETRY_DELAYS) {
|
||||
if (delay > 0)
|
||||
await wait(delay)
|
||||
|
||||
try {
|
||||
const response = await getQueryClient().fetchQuery({
|
||||
...consoleQuery.deployments.list.queryOptions({
|
||||
input: {
|
||||
query: {
|
||||
pageNumber: 1,
|
||||
resultsPerPage: DEPLOYMENT_PAGE_SIZE,
|
||||
},
|
||||
},
|
||||
}),
|
||||
staleTime: 0,
|
||||
})
|
||||
if (response.data?.some(app => app.id === appInstanceId))
|
||||
return
|
||||
}
|
||||
catch (error) {
|
||||
lastError = error
|
||||
}
|
||||
}
|
||||
|
||||
await refreshDeploymentLists()
|
||||
|
||||
if (lastError)
|
||||
throw lastError
|
||||
}
|
||||
|
||||
export const createRelease = async (appId: string, releaseNote?: string): Promise<ConsoleReleaseSummary> => {
|
||||
const trimmedReleaseNote = releaseNote?.trim()
|
||||
const response = await consoleClient.deployments.createRelease({
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
'use client'
|
||||
|
||||
import type { FC, ReactNode } from 'react'
|
||||
import type { AppInfo, AppMode } from '../types'
|
||||
import type { InstanceDetailTabKey } from './tabs'
|
||||
import type { AppInstanceOverview } from '@/contract/console/deployments'
|
||||
import { Button } from '@langgenius/dify-ui/button'
|
||||
import { useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@ -17,6 +19,22 @@ import { deployedRows, deploymentStatus } from '../utils'
|
||||
import { DeploymentSidebar } from './deployment-sidebar'
|
||||
import { isInstanceDetailTabKey } from './tabs'
|
||||
|
||||
function toAppInfoFromOverview(instance?: AppInstanceOverview): AppInfo | undefined {
|
||||
if (!instance?.id)
|
||||
return undefined
|
||||
|
||||
return {
|
||||
id: instance.id,
|
||||
name: instance.name ?? instance.id,
|
||||
mode: (instance.mode || 'workflow') as AppMode,
|
||||
iconType: 'emoji',
|
||||
icon: instance.icon,
|
||||
description: instance.description ?? undefined,
|
||||
sourceAppId: instance.sourceAppId,
|
||||
sourceAppName: instance.sourceAppName,
|
||||
}
|
||||
}
|
||||
|
||||
type InstanceDetailProps = {
|
||||
instanceId: string
|
||||
children: ReactNode
|
||||
@ -34,18 +52,29 @@ const InstanceDetail: FC<InstanceDetailProps> = ({ instanceId, children }) => {
|
||||
const { appMap, isLoading: isLoadingApps } = useSourceApps()
|
||||
useDocumentTitle(t('documentTitle.detail'))
|
||||
|
||||
const app = useMemo(
|
||||
() => sourceApps.find(item => item.id === instanceId) ?? appMap.get(instanceId),
|
||||
[sourceApps, instanceId, appMap],
|
||||
const appDataForInstance = appData[instanceId]
|
||||
const appFromData = useMemo(
|
||||
() => toAppInfoFromOverview(appDataForInstance?.overview.instance),
|
||||
[appDataForInstance?.overview.instance],
|
||||
)
|
||||
const detailApps = useMemo(() => app ? [app] : [], [app])
|
||||
useDeploymentData(detailApps, { enabled: detailApps.length > 0 })
|
||||
const app = useMemo(
|
||||
() => sourceApps.find(item => item.id === instanceId) ?? appMap.get(instanceId) ?? appFromData,
|
||||
[sourceApps, instanceId, appMap, appFromData],
|
||||
)
|
||||
const detailApps = useMemo<AppInfo[]>(() => [
|
||||
app ?? {
|
||||
id: instanceId,
|
||||
name: instanceId,
|
||||
mode: 'workflow',
|
||||
},
|
||||
], [app, instanceId])
|
||||
const detailQuery = useDeploymentData(detailApps, { enabled: Boolean(instanceId) })
|
||||
const appDeployments = useMemo(
|
||||
() => deployedRows(appData[instanceId]?.environmentDeployments.data),
|
||||
[appData, instanceId],
|
||||
)
|
||||
|
||||
if (isLoadingApps && !app) {
|
||||
if (!app && (isLoadingApps || detailQuery.isLoading || detailQuery.isFetching)) {
|
||||
return (
|
||||
<div className="flex h-full items-center justify-center bg-background-body">
|
||||
<span className="h-6 w-6 animate-spin rounded-full border-2 border-components-panel-border border-t-transparent" />
|
||||
|
||||
@ -12,9 +12,12 @@ import {
|
||||
patchAccessChannel,
|
||||
patchDeveloperAPI,
|
||||
refreshDeploymentAppData,
|
||||
refreshDeploymentAppDataWhenReady,
|
||||
refreshDeploymentLists,
|
||||
undeployEnvironment,
|
||||
updateAppInstance,
|
||||
updateEnvironmentAccessPolicy,
|
||||
waitForAppInstanceInDeploymentList,
|
||||
} from './data'
|
||||
|
||||
export type StartDeployParams = {
|
||||
@ -138,11 +141,8 @@ export const useDeploymentsStore = create<DeploymentsState>((set, get) => ({
|
||||
openCreateInstanceModal: () => set({ createInstanceModal: { open: true } }),
|
||||
closeCreateInstanceModal: () => set({ createInstanceModal: { open: false } }),
|
||||
|
||||
seedInstancesFromApps: apps => set(state => ({
|
||||
seedInstancesFromApps: apps => set(() => ({
|
||||
sourceApps: apps,
|
||||
appData: Object.fromEntries(
|
||||
Object.entries(state.appData).filter(([appId]) => apps.some(app => app.id === appId)),
|
||||
),
|
||||
})),
|
||||
|
||||
applyAppData: data => set(state => ({
|
||||
@ -162,6 +162,11 @@ export const useDeploymentsStore = create<DeploymentsState>((set, get) => ({
|
||||
if (!response.appInstanceId)
|
||||
throw new Error('Create app instance did not return an appInstanceId.')
|
||||
set({ createInstanceModal: { open: false } })
|
||||
await Promise.allSettled([
|
||||
refreshDeploymentAppDataWhenReady(response.appInstanceId)
|
||||
.then(data => get().applyAppData(data)),
|
||||
waitForAppInstanceInDeploymentList(response.appInstanceId),
|
||||
])
|
||||
return {
|
||||
appInstanceId: response.appInstanceId,
|
||||
initialRelease: response.initialRelease,
|
||||
@ -174,6 +179,7 @@ export const useDeploymentsStore = create<DeploymentsState>((set, get) => ({
|
||||
description: patch.description,
|
||||
})
|
||||
await get().refreshAppData(appId)
|
||||
await refreshDeploymentLists()
|
||||
set(state => ({
|
||||
sourceApps: state.sourceApps.map(app => app.id === appId ? { ...app, ...patch } : app),
|
||||
}))
|
||||
@ -190,23 +196,27 @@ export const useDeploymentsStore = create<DeploymentsState>((set, get) => ({
|
||||
appData,
|
||||
}
|
||||
})
|
||||
await refreshDeploymentLists()
|
||||
},
|
||||
|
||||
startDeploy: async ({ appId, environmentId, releaseId, releaseNote }) => {
|
||||
set({ deployDrawer: { open: false } })
|
||||
await createDeployment({ appId, environmentId, releaseId, releaseNote })
|
||||
await get().refreshAppData(appId)
|
||||
await refreshDeploymentLists()
|
||||
},
|
||||
|
||||
retryDeploy: async (appId, environmentId, targetReleaseId) => {
|
||||
await createDeployment({ appId, environmentId, releaseId: targetReleaseId })
|
||||
await get().refreshAppData(appId)
|
||||
await refreshDeploymentLists()
|
||||
},
|
||||
|
||||
rollbackDeployment: async (appId, environmentId, targetReleaseId) => {
|
||||
set({ rollbackModal: { open: false } })
|
||||
await createDeployment({ appId, environmentId, releaseId: targetReleaseId })
|
||||
await get().refreshAppData(appId)
|
||||
await refreshDeploymentLists()
|
||||
},
|
||||
|
||||
undeployDeployment: async (appId, _environmentId, runtimeInstanceId, isDeploying) => {
|
||||
@ -217,6 +227,7 @@ export const useDeploymentsStore = create<DeploymentsState>((set, get) => ({
|
||||
else
|
||||
await undeployEnvironment(appId, runtimeInstanceId)
|
||||
await get().refreshAppData(appId)
|
||||
await refreshDeploymentLists()
|
||||
},
|
||||
|
||||
generateApiKey: async (appId, environmentId) => {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user