diff --git a/web/features/deployments/components/deploy-drawer.tsx b/web/features/deployments/components/deploy-drawer.tsx index 2171cebc39..8ca830efe1 100644 --- a/web/features/deployments/components/deploy-drawer.tsx +++ b/web/features/deployments/components/deploy-drawer.tsx @@ -2,14 +2,12 @@ import type { FC } from 'react' import { Dialog, DialogCloseButton, DialogContent } from '@langgenius/dify-ui/dialog' -import { skipToken, useQuery } from '@tanstack/react-query' +import { useQuery } from '@tanstack/react-query' import { useMemo } from 'react' import { useTranslation } from 'react-i18next' import { consoleQuery } from '@/service/client' -import { - DEPLOYMENT_PAGE_SIZE, -} from '../data' import { useStartDeployment } from '../hooks/use-deployment-mutations' +import { deploymentReleaseHistoryQueryOptions } from '../queries' import { useDeploymentsStore } from '../store' import { environmentOptionsFromOptionsReply } from '../utils' import { DeployForm } from './deploy-drawer/form' @@ -21,18 +19,10 @@ const DeployDrawer: FC = () => { const closeDeployDrawer = useDeploymentsStore(state => state.closeDeployDrawer) const startDeploy = useStartDeployment() const open = drawer.open - const { data: releaseHistory } = useQuery(consoleQuery.deployments.releaseHistory.queryOptions({ - input: drawerAppId - ? { - params: { appInstanceId: drawerAppId }, - query: { - pageNumber: 1, - resultsPerPage: DEPLOYMENT_PAGE_SIZE, - }, - } - : skipToken, + const { data: releaseHistory } = useQuery({ + ...deploymentReleaseHistoryQueryOptions(drawerAppId), enabled: open && Boolean(drawerAppId), - })) + }) const { data: environmentOptionsReply } = useQuery({ ...consoleQuery.deployments.deploymentEnvironmentOptions.queryOptions(), enabled: open, diff --git a/web/features/deployments/components/rollback-modal.tsx b/web/features/deployments/components/rollback-modal.tsx index 108d7dd26a..fa1cc28906 100644 --- a/web/features/deployments/components/rollback-modal.tsx +++ b/web/features/deployments/components/rollback-modal.tsx @@ -9,17 +9,15 @@ import { AlertDialogDescription, AlertDialogTitle, } from '@langgenius/dify-ui/alert-dialog' -import { skipToken, useQuery } from '@tanstack/react-query' +import { useQuery } from '@tanstack/react-query' import { useMemo } from 'react' import { useTranslation } from 'react-i18next' import { consoleQuery } from '@/service/client' -import { - DEPLOYMENT_PAGE_SIZE, -} from '../data' import { useStartDeployment } from '../hooks/use-deployment-mutations' import { deploymentEnvironmentDeploymentsQueryOptions, deploymentOverviewQueryOptions, + deploymentReleaseHistoryQueryOptions, } from '../queries' import { useDeploymentsStore } from '../store' import { @@ -47,18 +45,6 @@ const RollbackModal: FC = () => { const modal = useDeploymentsStore(state => state.rollbackModal) const closeRollbackModal = useDeploymentsStore(state => state.closeRollbackModal) const rollbackDeployment = useStartDeployment() - const appInput = modal.appId - ? { params: { appInstanceId: modal.appId } } - : undefined - const pagedInput = appInput - ? { - ...appInput, - query: { - pageNumber: 1, - resultsPerPage: DEPLOYMENT_PAGE_SIZE, - }, - } - : undefined const { data: overview } = useQuery({ ...deploymentOverviewQueryOptions(modal.appId), enabled: modal.open && Boolean(modal.appId), @@ -71,10 +57,10 @@ const RollbackModal: FC = () => { ...consoleQuery.deployments.deploymentEnvironmentOptions.queryOptions(), enabled: modal.open, }) - const { data: releaseHistory } = useQuery(consoleQuery.deployments.releaseHistory.queryOptions({ - input: pagedInput ?? skipToken, + const { data: releaseHistory } = useQuery({ + ...deploymentReleaseHistoryQueryOptions(modal.appId), enabled: modal.open && Boolean(modal.appId), - })) + }) const environmentOptions = useMemo( () => environmentOptionsFromOptionsReply(environmentOptionsReply), [environmentOptionsReply], diff --git a/web/features/deployments/detail/access-tab.tsx b/web/features/deployments/detail/access-tab.tsx index b8fafe5c3b..9be1dd6390 100644 --- a/web/features/deployments/detail/access-tab.tsx +++ b/web/features/deployments/detail/access-tab.tsx @@ -78,7 +78,15 @@ const AccessTab: FC = ({ instanceId: appId }) => { } const handleGenerateApiKey = (environmentId: string) => { generateApiKey.mutate( - { appId, environmentId, name: createApiKeyLabel(environmentId) }, + { + params: { + appInstanceId: appId, + }, + body: { + environmentId, + name: createApiKeyLabel(environmentId), + }, + }, { onSuccess: (response) => { if (response.apiToken?.token) @@ -87,8 +95,13 @@ const AccessTab: FC = ({ instanceId: appId }) => { }, ) } - const handleRevokeApiKey = (environmentId: string, apiKeyId: string) => { - revokeApiKey.mutate({ appId, environmentId, apiKeyId }) + const handleRevokeApiKey = (_environmentId: string, apiKeyId: string) => { + revokeApiKey.mutate({ + params: { + appInstanceId: appId, + apiKeyId, + }, + }) } const handleSetEnvironmentAccessPolicy = async ( appId: string, @@ -97,10 +110,14 @@ const AccessTab: FC = ({ instanceId: appId }) => { subjects: AccessSubject[], ) => { await setEnvironmentAccessPolicy.mutateAsync({ - appId, - environmentId, - accessMode, - subjects, + params: { + appInstanceId: appId, + environmentId, + }, + body: { + accessMode, + subjects, + }, }) } const webappRows = accessConfig?.accessChannels?.webappRows?.filter(row => row.url) ?? [] diff --git a/web/features/deployments/detail/settings-tab.tsx b/web/features/deployments/detail/settings-tab.tsx index f4c45a96fd..3d58004f17 100644 --- a/web/features/deployments/detail/settings-tab.tsx +++ b/web/features/deployments/detail/settings-tab.tsx @@ -212,12 +212,18 @@ const SettingsTab: FC = ({ instanceId }) => { hasDeployments={hasDeployments} onSave={async (patch) => { await updateInstance.mutateAsync({ - appId: instanceId, - ...patch, + params: { + appInstanceId: instanceId, + }, + body: patch, }) }} onDelete={async () => { - await deleteInstance.mutateAsync(instanceId) + await deleteInstance.mutateAsync({ + params: { + appInstanceId: instanceId, + }, + }) router.push('/deployments') }} /> diff --git a/web/features/deployments/detail/versions-tab.tsx b/web/features/deployments/detail/versions-tab.tsx index 28c6626ad4..5411833afb 100644 --- a/web/features/deployments/detail/versions-tab.tsx +++ b/web/features/deployments/detail/versions-tab.tsx @@ -5,9 +5,10 @@ import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/too import { useQuery } from '@tanstack/react-query' import { useMemo } from 'react' import { useTranslation } from 'react-i18next' -import { consoleQuery } from '@/service/client' -import { DEPLOYMENT_PAGE_SIZE } from '../data' -import { deploymentEnvironmentDeploymentsQueryOptions } from '../queries' +import { + deploymentEnvironmentDeploymentsQueryOptions, + deploymentReleaseHistoryQueryOptions, +} from '../queries' import { deployedRows, formatDate, @@ -26,16 +27,7 @@ type VersionsTabProps = { const VersionsTab: FC = ({ instanceId: appId }) => { const { t } = useTranslation('deployments') - const query = { - pageNumber: 1, - resultsPerPage: DEPLOYMENT_PAGE_SIZE, - } - const { data: releaseHistory } = useQuery(consoleQuery.deployments.releaseHistory.queryOptions({ - input: { - params: { appInstanceId: appId }, - query, - }, - })) + const { data: releaseHistory } = useQuery(deploymentReleaseHistoryQueryOptions(appId)) const { data: environmentDeployments } = useQuery(deploymentEnvironmentDeploymentsQueryOptions(appId)) const releaseRows = useMemo( () => releaseHistory?.data?.filter(row => (row.release ?? row).id) ?? [], diff --git a/web/features/deployments/hooks/use-deployment-mutations.ts b/web/features/deployments/hooks/use-deployment-mutations.ts index 3559259cfe..7b95e504c0 100644 --- a/web/features/deployments/hooks/use-deployment-mutations.ts +++ b/web/features/deployments/hooks/use-deployment-mutations.ts @@ -1,12 +1,11 @@ 'use client' -import type { - AccessSubject, - ConsoleReleaseSummary, -} from '@/contract/console/deployments' +import type { QueryClient, QueryKey } from '@tanstack/react-query' +import type { ConsoleReleaseSummary } from '@/contract/console/deployments' import { useMutation, useQueryClient } from '@tanstack/react-query' import { consoleClient, consoleQuery } from '@/service/client' import { DEPLOYMENT_PAGE_SIZE } from '../data' +import { deploymentReleaseHistoryQueryOptions } from '../queries' export type CreateDeploymentInstanceResult = { appInstanceId: string @@ -26,50 +25,85 @@ type CreateInstanceParams = { description?: string } -type UpdateInstanceParams = { - name: string - description?: string -} - -type UpdateDeploymentInstanceParams = { - appId: string -} & UpdateInstanceParams - type UndeployDeploymentParams = { appId: string - runtimeInstanceId?: string + runtimeInstanceId: string isDeploying?: boolean } -type GenerateApiKeyParams = { - appId: string - environmentId: string - name: string -} - -type RevokeApiKeyParams = { - appId: string - environmentId: string - apiKeyId: string -} - type ToggleAccessChannelParams = { appId: string channel: string enabled: boolean } -type SetEnvironmentAccessPolicyParams = { - appId: string - environmentId: string - accessMode: string - subjects: AccessSubject[] -} - const DEPLOYMENT_READINESS_RETRY_DELAYS = [0, 300, 700, 1200] const wait = (delay: number) => new Promise(resolve => setTimeout(resolve, delay)) +const appInstanceInput = (appInstanceId: string) => ({ + input: { + params: { appInstanceId }, + }, +}) + +const environmentAccessPolicyInput = (appInstanceId: string, environmentId: string) => ({ + input: { + params: { + appInstanceId, + environmentId, + }, + }, +}) + +const invalidateQueries = (queryClient: QueryClient, queryKeys: QueryKey[]) => { + void Promise.all(queryKeys.map(queryKey => queryClient.invalidateQueries({ queryKey }))) +} + +const invalidateInstanceList = (queryClient: QueryClient) => { + void queryClient.invalidateQueries({ + queryKey: consoleQuery.deployments.list.key(), + }) +} + +const invalidateInstanceIdentity = (queryClient: QueryClient, appInstanceId: string) => { + invalidateQueries(queryClient, [ + consoleQuery.deployments.list.key(), + consoleQuery.deployments.overview.queryKey(appInstanceInput(appInstanceId)), + consoleQuery.deployments.settings.queryKey(appInstanceInput(appInstanceId)), + ]) +} + +const invalidateDeploymentState = (queryClient: QueryClient, appInstanceId: string) => { + invalidateQueries(queryClient, [ + consoleQuery.deployments.list.key(), + consoleQuery.deployments.overview.queryKey(appInstanceInput(appInstanceId)), + consoleQuery.deployments.environmentDeployments.queryKey(appInstanceInput(appInstanceId)), + deploymentReleaseHistoryQueryOptions(appInstanceId).queryKey, + consoleQuery.deployments.accessConfig.queryKey(appInstanceInput(appInstanceId)), + ]) +} + +const invalidateAccessState = (queryClient: QueryClient, appInstanceId: string) => { + invalidateQueries(queryClient, [ + consoleQuery.deployments.overview.queryKey(appInstanceInput(appInstanceId)), + consoleQuery.deployments.accessConfig.queryKey(appInstanceInput(appInstanceId)), + ]) +} + +const invalidateEnvironmentAccessPolicy = ( + queryClient: QueryClient, + appInstanceId: string, + environmentId: string, +) => { + invalidateQueries(queryClient, [ + consoleQuery.deployments.accessConfig.queryKey(appInstanceInput(appInstanceId)), + consoleQuery.deployments.environmentAccessPolicy.queryKey( + environmentAccessPolicyInput(appInstanceId, environmentId), + ), + ]) +} + export const useCreateDeploymentInstance = () => { const queryClient = useQueryClient() @@ -105,10 +139,8 @@ export const useCreateDeploymentInstance = () => { initialRelease: response.initialRelease, } }, - onSuccess: async () => { - await queryClient.invalidateQueries({ - queryKey: consoleQuery.deployments.key(), - }) + onSuccess: () => { + invalidateInstanceList(queryClient) }, }) } @@ -116,42 +148,21 @@ export const useCreateDeploymentInstance = () => { export const useUpdateDeploymentInstance = () => { const queryClient = useQueryClient() - return useMutation({ - mutationKey: consoleQuery.deployments.updateInstance.mutationKey(), - mutationFn: ({ appId, ...patch }: UpdateDeploymentInstanceParams) => - consoleClient.deployments.updateInstance({ - params: { - appInstanceId: appId, - }, - body: { - name: patch.name, - description: patch.description, - }, - }), - onSuccess: async () => { - await queryClient.invalidateQueries({ - queryKey: consoleQuery.deployments.key(), - }) + return useMutation(consoleQuery.deployments.updateInstance.mutationOptions({ + onSuccess: (_data, variables) => { + invalidateInstanceIdentity(queryClient, variables.params.appInstanceId) }, - }) + })) } export const useDeleteDeploymentInstance = () => { const queryClient = useQueryClient() - return useMutation({ - mutationKey: consoleQuery.deployments.deleteInstance.mutationKey(), - mutationFn: (appId: string) => consoleClient.deployments.deleteInstance({ - params: { - appInstanceId: appId, - }, - }), - onSuccess: async () => { - await queryClient.invalidateQueries({ - queryKey: consoleQuery.deployments.key(), - }) + return useMutation(consoleQuery.deployments.deleteInstance.mutationOptions({ + onSuccess: () => { + invalidateInstanceList(queryClient) }, - }) + })) } export const useStartDeployment = () => { @@ -204,10 +215,8 @@ export const useStartDeployment = () => { }, }) }, - onSuccess: async () => { - await queryClient.invalidateQueries({ - queryKey: consoleQuery.deployments.key(), - }) + onSuccess: (_data, variables) => { + invalidateDeploymentState(queryClient, variables.appId) }, }) } @@ -219,7 +228,7 @@ export const useUndeployDeployment = () => { mutationKey: consoleQuery.deployments.undeployEnvironment.mutationKey(), mutationFn: ({ appId, runtimeInstanceId, isDeploying }: UndeployDeploymentParams) => { if (!runtimeInstanceId) - return Promise.resolve(undefined) + throw new Error('runtimeInstanceId is required to undeploy a deployment.') if (isDeploying) { return consoleClient.deployments.cancelDeployment({ params: { @@ -235,10 +244,8 @@ export const useUndeployDeployment = () => { }, }) }, - onSuccess: async () => { - await queryClient.invalidateQueries({ - queryKey: consoleQuery.deployments.key(), - }) + onSuccess: (_data, variables) => { + invalidateDeploymentState(queryClient, variables.appId) }, }) } @@ -246,43 +253,21 @@ export const useUndeployDeployment = () => { export const useGenerateDeploymentApiKey = () => { const queryClient = useQueryClient() - return useMutation({ - mutationKey: consoleQuery.deployments.createEnvironmentAPIToken.mutationKey(), - mutationFn: ({ appId, environmentId, name }: GenerateApiKeyParams) => - consoleClient.deployments.createEnvironmentAPIToken({ - params: { - appInstanceId: appId, - }, - body: { - environmentId, - name, - }, - }), - onSuccess: async () => { - await queryClient.invalidateQueries({ - queryKey: consoleQuery.deployments.key(), - }) + return useMutation(consoleQuery.deployments.createEnvironmentAPIToken.mutationOptions({ + onSuccess: (_data, variables) => { + invalidateAccessState(queryClient, variables.params.appInstanceId) }, - }) + })) } export const useRevokeDeploymentApiKey = () => { const queryClient = useQueryClient() - return useMutation({ - mutationKey: consoleQuery.deployments.deleteEnvironmentAPIToken.mutationKey(), - mutationFn: ({ appId, apiKeyId }: RevokeApiKeyParams) => consoleClient.deployments.deleteEnvironmentAPIToken({ - params: { - appInstanceId: appId, - apiKeyId, - }, - }), - onSuccess: async () => { - await queryClient.invalidateQueries({ - queryKey: consoleQuery.deployments.key(), - }) + return useMutation(consoleQuery.deployments.deleteEnvironmentAPIToken.mutationOptions({ + onSuccess: (_data, variables) => { + invalidateAccessState(queryClient, variables.params.appInstanceId) }, - }) + })) } export const useToggleDeploymentAccessChannel = () => { @@ -310,10 +295,8 @@ export const useToggleDeploymentAccessChannel = () => { }, }) }, - onSuccess: async () => { - await queryClient.invalidateQueries({ - queryKey: consoleQuery.deployments.key(), - }) + onSuccess: (_data, variables) => { + invalidateAccessState(queryClient, variables.appId) }, }) } @@ -321,27 +304,13 @@ export const useToggleDeploymentAccessChannel = () => { export const useSetEnvironmentAccessPolicy = () => { const queryClient = useQueryClient() - return useMutation({ - mutationKey: consoleQuery.deployments.updateEnvironmentAccessPolicy.mutationKey(), - mutationFn: ({ - appId, - environmentId, - accessMode, - subjects, - }: SetEnvironmentAccessPolicyParams) => consoleClient.deployments.updateEnvironmentAccessPolicy({ - params: { - appInstanceId: appId, - environmentId, - }, - body: { - accessMode, - subjects, - }, - }), - onSuccess: async () => { - await queryClient.invalidateQueries({ - queryKey: consoleQuery.deployments.key(), - }) + return useMutation(consoleQuery.deployments.updateEnvironmentAccessPolicy.mutationOptions({ + onSuccess: (_data, variables) => { + invalidateEnvironmentAccessPolicy( + queryClient, + variables.params.appInstanceId, + variables.params.environmentId, + ) }, - }) + })) } diff --git a/web/features/deployments/queries.ts b/web/features/deployments/queries.ts index b0d95f7bb1..187aa88398 100644 --- a/web/features/deployments/queries.ts +++ b/web/features/deployments/queries.ts @@ -1,7 +1,7 @@ import type { ListAppDeploymentsQuery } from '@/contract/console/deployments' import { skipToken } from '@tanstack/react-query' import { consoleQuery } from '@/service/client' -import { SOURCE_APPS_PAGE_SIZE } from './data' +import { DEPLOYMENT_PAGE_SIZE, SOURCE_APPS_PAGE_SIZE } from './data' export const deploymentsListQueryOptions = (query: ListAppDeploymentsQuery = {}) => consoleQuery.deployments.list.queryOptions({ @@ -27,3 +27,16 @@ export const deploymentEnvironmentDeploymentsQueryOptions = (appInstanceId?: str ? { params: { appInstanceId } } : skipToken, }) + +export const deploymentReleaseHistoryQueryOptions = (appInstanceId?: string) => + consoleQuery.deployments.releaseHistory.queryOptions({ + input: appInstanceId + ? { + params: { appInstanceId }, + query: { + pageNumber: 1, + resultsPerPage: DEPLOYMENT_PAGE_SIZE, + }, + } + : skipToken, + })