diff --git a/agent/app/service/app_install.go b/agent/app/service/app_install.go index de4679cd2..5e9b89d07 100644 --- a/agent/app/service/app_install.go +++ b/agent/app/service/app_install.go @@ -259,6 +259,15 @@ func (a *AppInstallService) Operate(req request.AppInstalledOperate) error { if err != nil { return err } + if install.Status == constant.StatusRestarting && (req.Operate == constant.Stop || req.Operate == constant.Delete) && !req.ForceDelete { + count, err := taskRepo.CountExecutingTask(repo.WithByType(task.TaskScopeApp), taskRepo.WithResourceID(install.ID), taskRepo.WithOperate(task.TaskRestart)) + if err != nil { + return err + } + if count > 0 { + return buserr.New("TaskIsExecuting") + } + } if !req.ForceDelete && !files.NewFileOp().Stat(install.GetPath()) { return buserr.New("ErrInstallDirNotFound") } @@ -342,9 +351,6 @@ func operateAppWithLifecycleScripts(install model.AppInstall, req request.AppIns return errors.New("lifecycle script operation not supported") } install.Message = "" - if err := appInstallRepo.Save(context.Background(), &install); err != nil { - return err - } operationTask, err := task.NewTaskWithOps(install.Name, taskType, task.TaskScopeApp, req.TaskID, install.ID) if err != nil { @@ -355,10 +361,17 @@ func operateAppWithLifecycleScripts(install model.AppInstall, req request.AppIns } return err } + ready := make(chan error, 1) + started := make(chan struct{}) operation := string(req.Operate) operationTask.AddSubTaskWithOps( task.GetTaskName(install.Name, taskType, task.TaskScopeApp), func(t *task.Task) error { + if err := appInstallRepo.Save(context.Background(), &install); err != nil { + return err + } + close(started) + ready <- nil if err := runScript(t, &install, operation); err != nil { return err } @@ -385,6 +398,12 @@ func operateAppWithLifecycleScripts(install model.AppInstall, req request.AppIns ) go func() { if taskErr := operationTask.Execute(); taskErr != nil { + select { + case <-started: + default: + ready <- taskErr + return + } if onFailure != nil { onFailure(taskErr) return @@ -394,7 +413,7 @@ func operateAppWithLifecycleScripts(install model.AppInstall, req request.AppIns _ = appInstallRepo.Save(context.Background(), &install) } }() - return nil + return <-ready } func (a *AppInstallService) UpdateAppConfig(req request.AppConfigUpdate) error { @@ -1036,8 +1055,16 @@ func syncAppInstallStatus(appInstall *model.AppInstall, force bool) error { } switch appInstall.Status { case constant.StatusInstalling, constant.StatusRebuilding, constant.StatusUpgrading, constant.StatusUninstalling, - constant.StatusStarting, constant.StatusRestarting, constant.StatusWaiting: + constant.StatusStarting, constant.StatusWaiting: return nil + case constant.StatusRestarting: + count, err := taskRepo.CountExecutingTask(repo.WithByType(task.TaskScopeApp), taskRepo.WithResourceID(appInstall.ID), taskRepo.WithOperate(task.TaskRestart)) + if err != nil { + return err + } + if count > 0 { + return nil + } case constant.StatusInstallErr, constant.StatusUpgradeErr, constant.StatusUpErr: if !force { return nil diff --git a/agent/app/task/task.go b/agent/app/task/task.go index ea6212120..701af7e20 100644 --- a/agent/app/task/task.go +++ b/agent/app/task/task.go @@ -316,6 +316,8 @@ func (t *Task) ExecuteQueued(slots chan struct{}, waitingStep string, onFinish f func (t *Task) Execute() error { if err := t.taskRepo.Save(context.Background(), t.Task); err != nil { + _ = t.logFile.Close() + global.RemoveTaskCancel(t.TaskID) return err } return t.executeRegistered() diff --git a/frontend/src/views/ai/model/components/deployment-manage/index.vue b/frontend/src/views/ai/model/components/deployment-manage/index.vue index 34cfb1a95..79bc516e2 100644 --- a/frontend/src/views/ai/model/components/deployment-manage/index.vue +++ b/frontend/src/views/ai/model/components/deployment-manage/index.vue @@ -357,7 +357,9 @@ const deploymentButtons = [ { label: i18n.global.t('commons.button.delete'), permission: true, - disabled: (row: Deployment) => operationDisabled(row) && row.status !== 'Uninstalling', + disabled: (row: Deployment) => + deleteLoading.value || + (operationDisabled(row) && !['Uninstalling', 'ReStarting', 'Restarting'].includes(row.status)), click: (row: Deployment) => { deleting.value = row; forceDelete.value = false; diff --git a/frontend/src/views/ai/model/index.vue b/frontend/src/views/ai/model/index.vue index b1bcc8961..7c881114f 100644 --- a/frontend/src/views/ai/model/index.vue +++ b/frontend/src/views/ai/model/index.vue @@ -230,8 +230,13 @@