fix: Change container image building to asynchronous operation (#9462)

Refs #8463
This commit is contained in:
ssongliu 2025-07-08 19:06:47 +08:00 committed by GitHub
parent 96208c786d
commit 383bdd5f15
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 45 additions and 5 deletions

View file

@ -164,6 +164,8 @@ type ContainerCommit struct {
Comment string `json:"comment"` Comment string `json:"comment"`
Author string `json:"author"` Author string `json:"author"`
Pause bool `json:"pause"` Pause bool `json:"pause"`
TaskID string `json:"taskID"`
} }
type ContainerPrune struct { type ContainerPrune struct {

View file

@ -809,10 +809,23 @@ func (u *ContainerService) ContainerCommit(req dto.ContainerCommit) error {
Pause: req.Pause, Pause: req.Pause,
Config: nil, Config: nil,
} }
_, err = client.ContainerCommit(ctx, req.ContainerId, options)
taskItem, err := task.NewTaskWithOps(req.NewImageName, task.TaskCommit, task.TaskScopeContainer, req.TaskID, 1)
if err != nil { if err != nil {
return fmt.Errorf("failed to commit container, err: %v", err) return fmt.Errorf("new task for container commit failed, err: %v", err)
} }
go func() {
taskItem.AddSubTask(i18n.GetWithName("TaskCommit", req.NewImageName), func(t *task.Task) error {
res, err := client.ContainerCommit(ctx, req.ContainerId, options)
if err != nil {
return fmt.Errorf("failed to commit container, err: %v", err)
}
taskItem.Log(res.ID)
return nil
}, nil)
_ = taskItem.Execute()
}()
return nil return nil
} }

View file

@ -164,10 +164,12 @@ func (u *ImageRepoService) Update(req dto.ImageRepoUpdate) error {
needRestart = repo.DownloadUrl == req.DownloadUrl needRestart = repo.DownloadUrl == req.DownloadUrl
} }
if repo.Protocol == "https" && req.Protocol == "http" { if repo.Protocol == "https" && req.Protocol == "http" {
if err := u.handleRegistries(req.DownloadUrl, "", "create"); err != nil { if req.DownloadUrl != repo.DownloadUrl {
return fmt.Errorf("create registry %s failed, err: %v", req.DownloadUrl, err) if err := u.handleRegistries(req.DownloadUrl, repo.DownloadUrl, "update"); err != nil {
return fmt.Errorf("update registry %s => %s failed, err: %v", repo.DownloadUrl, req.DownloadUrl, err)
}
needRestart = true
} }
needRestart = true
} }
if needRestart { if needRestart {
if err := stopBeforeUpdateRepo(); err != nil { if err := stopBeforeUpdateRepo(); err != nil {

View file

@ -63,6 +63,7 @@ const (
TaskSync = "TaskSync" TaskSync = "TaskSync"
TaskBuild = "TaskBuild" TaskBuild = "TaskBuild"
TaskPull = "TaskPull" TaskPull = "TaskPull"
TaskCommit = "TaskCommit"
TaskPush = "TaskPush" TaskPush = "TaskPush"
TaskHandle = "TaskHandle" TaskHandle = "TaskHandle"
) )

View file

@ -287,6 +287,7 @@ TaskBackup: 'Backup'
TaskRecover: 'Recover' TaskRecover: 'Recover'
TaskRollback: 'Rollback' TaskRollback: 'Rollback'
TaskPull: 'Pull' TaskPull: 'Pull'
TaskCommit: 'Commit'
TaskBuild: 'Build' TaskBuild: 'Build'
TaskPush: 'Push' TaskPush: 'Push'
TaskHandle: 'Execute' TaskHandle: 'Execute'

View file

@ -287,6 +287,7 @@ TaskBackup: 'バックアップ'
TaskRecover: '回復' TaskRecover: '回復'
TaskRollback: 'ロールバック' TaskRollback: 'ロールバック'
TaskPull: 'プル' TaskPull: 'プル'
TaskCommit: 'コミット'
TaskBuild: 'ビルド' TaskBuild: 'ビルド'
TaskPush: 'プッシュ' TaskPush: 'プッシュ'
TaskHandle: '実行' TaskHandle: '実行'

View file

@ -287,6 +287,7 @@ TaskBackup: '백업'
TaskRecover: '복구' TaskRecover: '복구'
TaskRollback: '롤백' TaskRollback: '롤백'
TaskPull: '당기기' TaskPull: '당기기'
TaskCommit: '커밋'
TaskBuild: '빌드' TaskBuild: '빌드'
TaskPush: '푸시' TaskPush: '푸시'
TaskHandle: '실행' TaskHandle: '실행'

View file

@ -286,6 +286,7 @@ TaskBackup: 'Sandaran'
TaskRecover: 'Pulihkan' TaskRecover: 'Pulihkan'
TaskRollback: 'Rollback' TaskRollback: 'Rollback'
TaskPull: 'Tarik' TaskPull: 'Tarik'
TaskCommit: 'Komit'
TaskBuild: 'Bina' TaskBuild: 'Bina'
TaskPush: 'Tolak' TaskPush: 'Tolak'
TaskHandle: 'Laksanakan' TaskHandle: 'Laksanakan'

View file

@ -287,6 +287,7 @@ Backup de Tarefa: 'Backup'
TaskRecover: 'Recuperar' TaskRecover: 'Recuperar'
TaskRollback: 'Reverter' TaskRollback: 'Reverter'
TaskPull: 'Puxar' TaskPull: 'Puxar'
TaskCommit: 'Commit'
TaskBuild: 'Construir' TaskBuild: 'Construir'
TaskPush: 'Empurrar' TaskPush: 'Empurrar'
TaskHandle: 'Executar' TaskHandle: 'Executar'

View file

@ -287,6 +287,7 @@ TaskBackup: 'Резервное копирование'
TaskRecover: 'Восстановить' TaskRecover: 'Восстановить'
TaskRollback: 'Откат' TaskRollback: 'Откат'
TaskPull: 'Вытянуть' TaskPull: 'Вытянуть'
TaskCommit: 'Kоммит'
ЗадачаСборка: 'Сборка' ЗадачаСборка: 'Сборка'
TaskPush: 'Push' TaskPush: 'Push'
TaskHandle: 'Выполнить' TaskHandle: 'Выполнить'

View file

@ -285,6 +285,7 @@ TaskBackup: 'Yedekle'
TaskRecover: 'Kurtar' TaskRecover: 'Kurtar'
TaskRollback: 'Geri Al' TaskRollback: 'Geri Al'
TaskPull: 'Çek' TaskPull: 'Çek'
TaskCommit: 'işleme'
TaskBuild: 'Yapı' TaskBuild: 'Yapı'
TaskPush: 'Gönder' TaskPush: 'Gönder'
TaskHandle: 'Yürüt' TaskHandle: 'Yürüt'

View file

@ -286,6 +286,7 @@ TaskBackup: '備份'
TaskRecover: '復原' TaskRecover: '復原'
TaskRollback: '回滾' TaskRollback: '回滾'
TaskPull: '拉取' TaskPull: '拉取'
TaskCommit: '制作'
TaskBuild: '建置' TaskBuild: '建置'
TaskPush: '推送' TaskPush: '推送'
TaskHandle: '執行' TaskHandle: '執行'

View file

@ -286,6 +286,7 @@ TaskBackup: "备份"
TaskRecover: "恢复" TaskRecover: "恢复"
TaskRollback: "回滚" TaskRollback: "回滚"
TaskPull: "拉取" TaskPull: "拉取"
TaskCommit: "制作"
TaskBuild: "构建" TaskBuild: "构建"
TaskPush: "推送" TaskPush: "推送"
TaskHandle: "执行" TaskHandle: "执行"

View file

@ -16,6 +16,7 @@ export namespace Container {
comment: string; comment: string;
author: string; author: string;
pause: boolean; pause: boolean;
taskID: string;
} }
export interface ContainerSearch extends ReqPage { export interface ContainerSearch extends ReqPage {
name: string; name: string;

View file

@ -42,6 +42,7 @@
</span> </span>
</template> </template>
</DrawerPro> </DrawerPro>
<TaskLog ref="taskLogRef" width="70%" />
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@ -50,7 +51,9 @@ import { ElForm } from 'element-plus';
import { Rules } from '@/global/form-rules'; import { Rules } from '@/global/form-rules';
import i18n from '@/lang'; import i18n from '@/lang';
import { commitContainer } from '@/api/modules/container'; import { commitContainer } from '@/api/modules/container';
import TaskLog from '@/components/log/task/index.vue';
import { MsgSuccess } from '@/utils/message'; import { MsgSuccess } from '@/utils/message';
import { newUUID } from '@/utils/util';
const drawerVisible = ref<boolean>(false); const drawerVisible = ref<boolean>(false);
const emit = defineEmits<{ (e: 'search'): void }>(); const emit = defineEmits<{ (e: 'search'): void }>();
@ -62,8 +65,11 @@ const form = reactive({
comment: '', comment: '',
author: '', author: '',
pause: false, pause: false,
taskID: '',
}); });
const taskLogRef = ref();
interface DialogProps { interface DialogProps {
containerID: string; containerID: string;
containerName: string; containerName: string;
@ -89,11 +95,13 @@ const onSubmit = async (formEl: FormInstance | undefined) => {
cancelButtonText: i18n.global.t('commons.button.cancel'), cancelButtonText: i18n.global.t('commons.button.cancel'),
}).then(async () => { }).then(async () => {
loading.value = true; loading.value = true;
form.taskID = newUUID();
await commitContainer(form) await commitContainer(form)
.then(() => { .then(() => {
loading.value = false; loading.value = false;
emit('search'); emit('search');
drawerVisible.value = false; drawerVisible.value = false;
openTaskLog(form.taskID);
MsgSuccess(i18n.global.t('commons.msg.operationSuccess')); MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
}) })
.catch(() => { .catch(() => {
@ -103,6 +111,10 @@ const onSubmit = async (formEl: FormInstance | undefined) => {
}); });
}; };
const openTaskLog = (taskID: string) => {
taskLogRef.value.openWithTaskID(taskID);
};
const handleClose = async () => { const handleClose = async () => {
drawerVisible.value = false; drawerVisible.value = false;
emit('search'); emit('search');