mirror of
https://gitee.com/dromara/mayfly-go
synced 2025-12-29 02:46:35 +08:00
feat: 实现数据库备份与恢复
This commit is contained in:
136
server/internal/db/api/db_backup.go
Normal file
136
server/internal/db/api/db_backup.go
Normal file
@@ -0,0 +1,136 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"mayfly-go/internal/db/api/form"
|
||||
"mayfly-go/internal/db/api/vo"
|
||||
"mayfly-go/internal/db/application"
|
||||
"mayfly-go/internal/db/domain/entity"
|
||||
"mayfly-go/pkg/biz"
|
||||
"mayfly-go/pkg/ginx"
|
||||
"mayfly-go/pkg/req"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type DbBackup struct {
|
||||
DbBackupApp *application.DbBackupApp
|
||||
DbApp application.Db
|
||||
}
|
||||
|
||||
// todo: 鉴权,避免未经授权进行数据库备份和恢复
|
||||
|
||||
// GetPageList 获取数据库备份任务
|
||||
// @router /api/dbs/:dbId/backups [GET]
|
||||
func (d *DbBackup) GetPageList(rc *req.Ctx) {
|
||||
dbId := uint64(ginx.PathParamInt(rc.GinCtx, "dbId"))
|
||||
biz.IsTrue(dbId > 0, "无效的 dbId: %v", dbId)
|
||||
db, err := d.DbApp.GetById(new(entity.Db), dbId, "db_instance_id", "database")
|
||||
biz.ErrIsNilAppendErr(err, "获取数据库信息失败: %v")
|
||||
|
||||
queryCond, page := ginx.BindQueryAndPage[*entity.DbBackupQuery](rc.GinCtx, new(entity.DbBackupQuery))
|
||||
queryCond.DbInstanceId = db.InstanceId
|
||||
queryCond.InDbNames = strings.Fields(db.Database)
|
||||
res, err := d.DbBackupApp.GetPageList(queryCond, page, new([]vo.DbBackup))
|
||||
biz.ErrIsNilAppendErr(err, "获取数据库备份任务失败: %v")
|
||||
rc.ResData = res
|
||||
}
|
||||
|
||||
// Create 保存数据库备份任务
|
||||
// @router /api/dbs/:dbId/backups [POST]
|
||||
func (d *DbBackup) Create(rc *req.Ctx) {
|
||||
form := &form.DbBackupForm{}
|
||||
ginx.BindJsonAndValid(rc.GinCtx, form)
|
||||
rc.ReqParam = form
|
||||
|
||||
dbNames := strings.Fields(form.DbNames)
|
||||
biz.IsTrue(len(dbNames) > 0, "解析数据库备份任务失败:数据库名称未定义")
|
||||
|
||||
dbId := uint64(ginx.PathParamInt(rc.GinCtx, "dbId"))
|
||||
biz.IsTrue(dbId > 0, "无效的 dbId: %v", dbId)
|
||||
db, err := d.DbApp.GetById(new(entity.Db), dbId, "instanceId")
|
||||
biz.ErrIsNilAppendErr(err, "获取数据库信息失败: %v")
|
||||
|
||||
tasks := make([]*entity.DbBackup, 0, len(dbNames))
|
||||
for _, dbName := range dbNames {
|
||||
task := &entity.DbBackup{
|
||||
DbName: dbName,
|
||||
Name: form.Name,
|
||||
StartTime: form.StartTime,
|
||||
Interval: form.Interval,
|
||||
Enabled: true,
|
||||
Repeated: form.Repeated,
|
||||
DbInstanceId: db.InstanceId,
|
||||
}
|
||||
tasks = append(tasks, task)
|
||||
}
|
||||
biz.ErrIsNilAppendErr(d.DbBackupApp.Create(rc.MetaCtx, tasks...), "添加数据库备份任务失败: %v")
|
||||
}
|
||||
|
||||
// Save 保存数据库备份任务
|
||||
// @router /api/dbs/:dbId/backups/:backupId [PUT]
|
||||
func (d *DbBackup) Save(rc *req.Ctx) {
|
||||
form := &form.DbBackupForm{}
|
||||
ginx.BindJsonAndValid(rc.GinCtx, form)
|
||||
rc.ReqParam = form
|
||||
|
||||
task := &entity.DbBackup{
|
||||
Name: form.Name,
|
||||
StartTime: form.StartTime,
|
||||
Interval: form.Interval,
|
||||
}
|
||||
task.Id = form.Id
|
||||
biz.ErrIsNilAppendErr(d.DbBackupApp.Save(rc.MetaCtx, task), "保存数据库备份任务失败: %v")
|
||||
}
|
||||
|
||||
func (d *DbBackup) walk(rc *req.Ctx, fn func(ctx context.Context, backupId uint64) error) error {
|
||||
idsStr := ginx.PathParam(rc.GinCtx, "backupId")
|
||||
biz.NotEmpty(idsStr, "backupId 为空")
|
||||
rc.ReqParam = idsStr
|
||||
ids := strings.Fields(idsStr)
|
||||
for _, v := range ids {
|
||||
value, err := strconv.Atoi(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
taskId := uint64(value)
|
||||
err = fn(rc.MetaCtx, taskId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Delete 删除数据库备份任务
|
||||
// @router /api/dbs/:dbId/backups/:taskId [DELETE]
|
||||
func (d *DbBackup) Delete(rc *req.Ctx) {
|
||||
err := d.walk(rc, d.DbBackupApp.Delete)
|
||||
biz.ErrIsNilAppendErr(err, "删除数据库备份任务失败: %v")
|
||||
}
|
||||
|
||||
// Enable 启用数据库备份任务
|
||||
// @router /api/dbs/:dbId/backups/:taskId/enable [PUT]
|
||||
func (d *DbBackup) Enable(rc *req.Ctx) {
|
||||
err := d.walk(rc, d.DbBackupApp.Enable)
|
||||
biz.ErrIsNilAppendErr(err, "启用数据库备份任务失败: %v")
|
||||
}
|
||||
|
||||
// Disable 禁用数据库备份任务
|
||||
// @router /api/dbs/:dbId/backups/:taskId/disable [PUT]
|
||||
func (d *DbBackup) Disable(rc *req.Ctx) {
|
||||
err := d.walk(rc, d.DbBackupApp.Disable)
|
||||
biz.ErrIsNilAppendErr(err, "禁用数据库备份任务失败: %v")
|
||||
}
|
||||
|
||||
// GetDbNamesWithoutBackup 获取未配置定时备份的数据库名称
|
||||
// @router /api/dbs/:dbId/db-names-without-backup [GET]
|
||||
func (d *DbBackup) GetDbNamesWithoutBackup(rc *req.Ctx) {
|
||||
dbId := uint64(ginx.PathParamInt(rc.GinCtx, "dbId"))
|
||||
db, err := d.DbApp.GetById(new(entity.Db), dbId, "instance_id", "database")
|
||||
biz.ErrIsNilAppendErr(err, "获取数据库信息失败: %v")
|
||||
dbNames := strings.Fields(db.Database)
|
||||
dbNamesWithoutBackup, err := d.DbBackupApp.GetDbNamesWithoutBackup(db.InstanceId, dbNames)
|
||||
biz.ErrIsNilAppendErr(err, "获取未配置定时备份的数据库名称失败: %v")
|
||||
rc.ResData = dbNamesWithoutBackup
|
||||
}
|
||||
Reference in New Issue
Block a user