fix: Fix backup record loading timeout issue (#10126)

This commit is contained in:
ssongliu 2025-08-25 16:05:57 +08:00 committed by GitHub
parent dd6a709053
commit 00b25b39c5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 116 additions and 101 deletions

View file

@ -1080,7 +1080,7 @@ func runScript(task *task.Task, appInstall *model.AppInstall, operate string) er
task.LogStart(logStr) task.LogStart(logStr)
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(10*time.Minute), cmd.WithWorkDir(workDir)) cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(10*time.Minute), cmd.WithWorkDir(workDir))
out, err := cmdMgr.RunWithStdoutBashCf(scriptPath) out, err := cmdMgr.RunWithStdoutBashC(scriptPath)
if err != nil { if err != nil {
if out != "" { if out != "" {
err = errors.New(out) err = errors.New(out)

View file

@ -6,6 +6,7 @@ import (
"os" "os"
"path" "path"
"sync" "sync"
"time"
"github.com/1Panel-dev/1Panel/agent/app/dto" "github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/app/model" "github.com/1Panel-dev/1Panel/agent/app/model"
@ -256,13 +257,25 @@ func (u *BackupRecordService) LoadRecordSize(req dto.SearchForSize) ([]dto.Recor
var datas []dto.RecordFileSize var datas []dto.RecordFileSize
var wg sync.WaitGroup var wg sync.WaitGroup
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
for i := 0; i < len(list); i++ { for i := 0; i < len(list); i++ {
datas = append(datas, dto.RecordFileSize{ID: list[i].ID}) datas = append(datas, dto.RecordFileSize{ID: list[i].ID})
if val, ok := clientMap[fmt.Sprintf("%v", list[i].DownloadID)]; ok { if val, ok := clientMap[fmt.Sprintf("%v", list[i].DownloadID)]; ok {
wg.Add(1) wg.Add(1)
go func(index int) { go func(index int) {
datas[index].Size, _ = val.client.Size(path.Join(val.backupPath, list[i].FilePath)) defer wg.Done()
wg.Done() done := make(chan struct{}, 1)
go func() {
datas[index].Size, _ = val.client.Size(path.Join(val.backupPath, list[i].FilePath))
defer close(done)
}()
select {
case <-ctx.Done():
return
case <-done:
return
}
}(i) }(i)
} }
} }

View file

@ -3366,7 +3366,7 @@ func (w WebsiteService) ExecComposer(req request.ExecComposerReq) error {
execDir := strings.ReplaceAll(req.Dir, siteDir.Value, "/www") execDir := strings.ReplaceAll(req.Dir, siteDir.Value, "/www")
composerTask.AddSubTask("", func(t *task.Task) error { composerTask.AddSubTask("", func(t *task.Task) error {
cmdStr := fmt.Sprintf("docker exec -u %s %s sh -c 'composer config -g repo.packagist composer %s && composer %s --working-dir=%s'", req.User, runtime.ContainerName, req.Mirror, command, execDir) cmdStr := fmt.Sprintf("docker exec -u %s %s sh -c 'composer config -g repo.packagist composer %s && composer %s --working-dir=%s'", req.User, runtime.ContainerName, req.Mirror, command, execDir)
err = cmdMgr.RunBashCf(cmdStr) err = cmdMgr.RunBashC(cmdStr)
if err != nil { if err != nil {
return err return err
} }

View file

@ -54,7 +54,7 @@
:data="data" :data="data"
:heightDiff="300" :heightDiff="300"
> >
<el-table-column type="selection" fix /> <el-table-column type="selection" :selectable="selectable" fix />
<el-table-column <el-table-column
:label="$t('cronjob.taskName')" :label="$t('cronjob.taskName')"
:min-width="120" :min-width="120"
@ -307,6 +307,10 @@ const onOpenDialog = async (id: string) => {
routerToNameWithQuery('CronjobOperate', { id: id }); routerToNameWithQuery('CronjobOperate', { id: id });
}; };
function selectable(row) {
return row.status !== 'Pending';
}
const onDelete = async (row: Cronjob.CronjobInfo | null) => { const onDelete = async (row: Cronjob.CronjobInfo | null) => {
let names = []; let names = [];
let ids = []; let ids = [];

View file

@ -86,99 +86,103 @@
</template> </template>
<template #main> <template #main>
<div class="mainClass"> <div class="mainClass">
<el-row :gutter="20" v-show="hasRecords" class="mainRowClass"> <el-row :gutter="20" v-show="hasRecords" class="mainRowClass row-box">
<el-col :span="7"> <el-col :span="7">
<div class="infinite-list" style="overflow: auto"> <el-card class="el-card">
<el-table <div class="infinite-list" style="overflow: auto">
style="cursor: pointer" <el-table
:data="records" style="cursor: pointer"
border :data="records"
:show-header="false" border
@row-click="forDetail" :show-header="false"
> @row-click="forDetail"
<el-table-column> >
<template #default="{ row }"> <el-table-column>
<span v-if="row.id === currentRecord.id" class="select-sign"></span> <template #default="{ row }">
<Status class="mr-2 ml-1 float-left" :status="row.status" /> <span v-if="row.id === currentRecord.id" class="select-sign"></span>
<div class="mt-0.5"> <Status class="mr-2 ml-1 float-left" :status="row.status" />
<span> <div class="mt-0.5">
{{ row.startTime }} <span>
</span> {{ row.startTime }}
</div> </span>
</template> </div>
</el-table-column> </template>
</el-table> </el-table-column>
</div> </el-table>
<div class="page-item"> </div>
<el-pagination <div class="page-item">
:page-size="searchInfo.pageSize" <el-pagination
:current-page="searchInfo.page" :page-size="searchInfo.pageSize"
@current-change="handleCurrentChange" :current-page="searchInfo.page"
@size-change="handleSizeChange" @current-change="handleCurrentChange"
:pager-count="5" @size-change="handleSizeChange"
:page-sizes="[6, 8, 10, 12, 14]" :pager-count="5"
small :page-sizes="[5, 10, 20, 50, 100, 200, 500, 1000]"
layout="total, sizes, prev, pager, next" small
:total="searchInfo.recordTotal" layout="total, sizes, prev, pager, next"
/> :total="searchInfo.recordTotal"
</div> />
</div>
</el-card>
</el-col> </el-col>
<el-col :span="17"> <el-col :span="17">
<el-form label-position="top"> <el-card class="el-card">
<el-row type="flex" justify="center"> <el-form label-position="top">
<el-form-item class="descriptionWide"> <el-row type="flex" justify="center">
<template #label> <el-form-item class="descriptionWide">
<span class="status-label">{{ $t('commons.search.timeStart') }}</span> <template #label>
</template> <span class="status-label">{{ $t('commons.search.timeStart') }}</span>
<span class="status-count"> </template>
{{ dateFormat(0, 0, currentRecord?.startTime) }} <span class="status-count">
</span> {{ dateFormat(0, 0, currentRecord?.startTime) }}
</el-form-item>
<el-form-item class="description">
<template #label>
<span class="status-label">{{ $t('commons.table.interval') }}</span>
</template>
<el-button link v-if="!currentRecord?.interval" :loading="true" />
<span v-else>
<span class="status-count" v-if="currentRecord?.interval! <= 1000">
{{ currentRecord?.interval }} ms
</span> </span>
<span class="status-count" v-if="currentRecord?.interval! > 1000"> </el-form-item>
{{ currentRecord?.interval! / 1000 }} s <el-form-item class="description">
<template #label>
<span class="status-label">{{ $t('commons.table.interval') }}</span>
</template>
<el-button link v-if="!currentRecord?.interval" :loading="true" />
<span v-else>
<span class="status-count" v-if="currentRecord?.interval! <= 1000">
{{ currentRecord?.interval }} ms
</span>
<span class="status-count" v-if="currentRecord?.interval! > 1000">
{{ currentRecord?.interval! / 1000 }} s
</span>
</span> </span>
</span> </el-form-item>
</el-form-item> <el-form-item class="description">
<el-form-item class="description"> <template #label>
<template #label> <span class="status-label">{{ $t('commons.table.status') }}</span>
<span class="status-label">{{ $t('commons.table.status') }}</span> </template>
</template> <Status :status="currentRecord?.status" />
<Status :status="currentRecord?.status" /> </el-form-item>
</el-form-item> </el-row>
</el-row> <el-row v-if="currentRecord?.status === 'Failed'">
<el-row v-if="currentRecord?.status === 'Failed'"> <el-form-item class="w-full">
<el-form-item class="w-full"> <template #label>
<template #label> <span class="status-label">{{ $t('commons.table.message') }}</span>
<span class="status-label">{{ $t('commons.table.message') }}</span> </template>
</template> {{ currentRecord?.message }}
{{ currentRecord?.message }} </el-form-item>
</el-form-item> </el-row>
</el-row> <el-row v-if="currentRecord?.taskID && currentRecord?.taskID != ''">
<el-row v-if="currentRecord?.taskID && currentRecord?.taskID != ''"> <LogFile
<LogFile :defaultButton="true"
:defaultButton="true" class="w-full"
class="w-full" :key="currentRecord?.taskID"
:key="currentRecord?.taskID" @stop-reading="search(false)"
@stop-reading="search(false)" :heightDiff="420"
:heightDiff="410" :config="{
:config="{ type: 'task',
type: 'task', colorMode: 'task',
colorMode: 'task', taskID: currentRecord?.taskID,
taskID: currentRecord?.taskID, tail: true,
tail: true, }"
}" />
/> </el-row>
</el-row> </el-form>
</el-form> </el-card>
</el-col> </el-col>
</el-row> </el-row>
</div> </div>
@ -410,7 +414,7 @@ defineExpose({
<style lang="scss" scoped> <style lang="scss" scoped>
.infinite-list { .infinite-list {
height: calc(100vh - 420px); height: calc(100vh - 320px);
.select-sign { .select-sign {
&::before { &::before {
float: left; float: left;
@ -449,10 +453,4 @@ defineExpose({
min-width: 1200px; min-width: 1200px;
} }
} }
.editor-main {
height: calc(100vh - 488px);
width: 100%;
margin-top: 5px;
overflow-x: auto;
}
</style> </style>

View file

@ -646,7 +646,7 @@ onBeforeUnmount(() => {
.h-systemInfo { .h-systemInfo {
margin-left: 18px; margin-left: 18px;
height: 276px; height: 286px;
} }
@-moz-document url-prefix() { @-moz-document url-prefix() {
.h-systemInfo { .h-systemInfo {