feat: Add customizable snapshot timeout support (#9537)

Refs #9502
This commit is contained in:
ssongliu 2025-07-16 18:43:52 +08:00 committed by GitHub
parent ff5cdb9a02
commit e66bd43fc6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 27 additions and 8 deletions

View file

@ -18,6 +18,7 @@ type SnapshotCreate struct {
Description string `json:"description" validate:"max=256"`
Secret string `json:"secret"`
InterruptStep string `json:"interruptStep"`
Timeout uint `json:"timeout"`
AppData []DataTree `json:"appData"`
BackupData []DataTree `json:"backupData"`

View file

@ -10,6 +10,7 @@ type Snapshot struct {
Status string `json:"status"`
Message string `json:"message"`
Version string `json:"version"`
Timeout uint `json:"timeout"`
TaskID string `json:"taskID"`
TaskRecoverID string `json:"taskRecoverID"`

View file

@ -61,6 +61,7 @@ func (u *SnapshotService) SnapshotCreate(parentTask *task.Task, req dto.Snapshot
Version: versionItem.Value,
Status: constant.StatusWaiting,
Timeout: req.Timeout,
}
if err := snapshotRepo.Create(&snap); err != nil {
global.LOG.Errorf("create snapshot record to db failed, err: %v", err)
@ -79,7 +80,7 @@ func (u *SnapshotService) SnapshotCreate(parentTask *task.Task, req dto.Snapshot
}
if jobID == 0 {
go func() {
_ = handleSnapshot(req, taskItem, jobID, 3, 0)
_ = handleSnapshot(req, taskItem, jobID, 3, snap.Timeout)
}()
return nil
}
@ -128,10 +129,6 @@ func handleSnapshot(req dto.SnapshotCreate, taskItem *task.Task, jobID, retry, t
itemHelper := snapHelper{SnapID: req.ID, Task: *taskItem, FileOp: files.NewFileOp(), Ctx: context.Background(), OpenrestyDir: openrestyDir}
baseDir := path.Join(rootDir, "base")
_ = os.MkdirAll(baseDir, os.ModePerm)
if timeout == 0 {
timeout = 1800
}
taskItem.AddSubTaskWithAliasAndOps(
"SnapDBInfo",
func(t *task.Task) error {

View file

@ -175,6 +175,7 @@ func (u *SnapshotService) SnapshotRecover(req dto.SnapshotRecover) error {
itemHelper.Task.Log("---------------------- 9 / 11 ----------------------")
itemHelper.Task.LogStart(i18n.GetWithName("RecoverWebsite", snap.Name))
webFile := path.Join(rootDir, snap.Name, "/website.tar.gz")
_ = itemHelper.FileOp.CreateDir(snapJson.OperestyDir, os.ModePerm)
var err error
if itemHelper.FileOp.Stat(webFile) {
err = itemHelper.FileOp.TarGzExtractPro(webFile, snapJson.OperestyDir, "")

View file

@ -337,7 +337,7 @@ var UpdatePHPRuntime = &gormigrate.Migration{
},
}
var AddSnapshotIgnore = &gormigrate.Migration{
ID: "20250628-add-snapshot-ignore",
ID: "20250716-add-snapshot-ignore",
Migrate: func(tx *gorm.DB) error {
return tx.AutoMigrate(
&model.Snapshot{},

View file

@ -1,5 +1,4 @@
import { DateTimeFormats } from '@intlify/core-base';
import { b } from 'vite/dist/node/types.d-aGj9QkWt';
export namespace Setting {
export interface SettingInfo {
@ -135,6 +134,7 @@ export namespace Setting {
downloadAccountID: string;
description: string;
secret: string;
timeout: number;
appData: Array<DataTree>;
panelData: Array<DataTree>;
@ -167,6 +167,7 @@ export namespace Setting {
createdAt: DateTimeFormats;
version: string;
secret: string;
timeout: number;
taskID: string;
taskRecoverID: string;

View file

@ -45,6 +45,17 @@
<el-form-item :label="$t('setting.compressPassword')" prop="secret">
<el-input v-model="form.secret"></el-input>
</el-form-item>
<el-form-item :label="$t('cronjob.timeout')" prop="timeoutItem">
<el-input type="number" class="selectClass" v-model.number="form.timeoutItem">
<template #append>
<el-select v-model="form.timeoutUint" style="width: 80px">
<el-option :label="$t('commons.units.second')" value="s" />
<el-option :label="$t('commons.units.minute')" value="m" />
<el-option :label="$t('commons.units.hour')" value="h" />
</el-select>
</template>
</el-input>
</el-form-item>
<el-form-item :label="$t('commons.table.description')" prop="description">
<el-input type="textarea" clearable v-model="form.description" />
</el-form-item>
@ -164,7 +175,7 @@
<script lang="ts" setup>
import { ref } from 'vue';
import { loadSnapshotInfo, snapshotCreate } from '@/api/modules/setting';
import { computeSize, newUUID } from '@/utils/util';
import { computeSize, newUUID, transferTimeToSecond } from '@/utils/util';
import i18n from '@/lang';
import TaskLog from '@/components/log/task/index.vue';
import IgnoreFile from '@/components/file-batch/index.vue';
@ -197,6 +208,10 @@ const form = reactive({
description: '',
secret: '',
timeout: 3600,
timeoutItem: 3600,
timeoutUint: 's',
backupAllImage: false,
withDockerConf: true,
withLoginLog: false,
@ -213,6 +228,8 @@ const form = reactive({
const rules = reactive({
fromAccounts: [Rules.requiredSelect],
downloadAccountID: [Rules.requiredSelect],
timeoutItem: [Rules.number],
});
const defaultProps = {
@ -403,6 +420,7 @@ const submitAddSnapshot = async () => {
loading.value = true;
form.taskID = newUUID();
form.sourceAccountIDs = form.fromAccounts.join(',');
form.timeout = transferTimeToSecond(form.timeoutItem + form.timeoutUint);
await snapshotCreate(form)
.then(() => {
loading.value = false;