!84 fix: 修复数据库备份与恢复问题

* refactor dbScheduler
* fix: 按团队名称检索团队
* feat: 创建数据库资源时支持全选数据库
* refactor dbScheduler
* fix: 修复数据库备份与恢复问题
This commit is contained in:
kanzihuang
2024-01-17 08:37:22 +00:00
committed by Coder慌
parent cc3981d99c
commit 94da6df33e
35 changed files with 846 additions and 609 deletions

View File

@@ -2,20 +2,14 @@ package application
import (
"context"
"fmt"
"mayfly-go/internal/db/domain/entity"
"mayfly-go/internal/db/domain/repository"
"mayfly-go/pkg/logx"
"mayfly-go/pkg/utils/stringx"
"mayfly-go/pkg/utils/timex"
"sync"
"time"
)
const (
binlogDownloadInterval = time.Minute * 15
)
type DbBinlogApp struct {
binlogRepo repository.DbBinlog
binlogHistoryRepo repository.DbBinlogHistory
@@ -25,19 +19,10 @@ type DbBinlogApp struct {
context context.Context
cancel context.CancelFunc
waitGroup sync.WaitGroup
scheduler *dbScheduler
}
var (
binlogResult = map[entity.DbJobStatus]string{
entity.DbJobDelay: "等待备份BINLOG",
entity.DbJobReady: "准备备份BINLOG",
entity.DbJobRunning: "BINLOG备份中",
entity.DbJobSuccess: "BINLOG备份成功",
entity.DbJobFailed: "BINLOG备份失败",
}
)
func newDbBinlogApp(repositories *repository.Repositories, dbApp Db) (*DbBinlogApp, error) {
func newDbBinlogApp(repositories *repository.Repositories, dbApp Db, scheduler *dbScheduler) (*DbBinlogApp, error) {
ctx, cancel := context.WithCancel(context.Background())
svc := &DbBinlogApp{
binlogRepo: repositories.Binlog,
@@ -45,6 +30,7 @@ func newDbBinlogApp(repositories *repository.Repositories, dbApp Db) (*DbBinlogA
backupRepo: repositories.Backup,
backupHistoryRepo: repositories.BackupHistory,
dbApp: dbApp,
scheduler: scheduler,
context: ctx,
cancel: cancel,
}
@@ -53,73 +39,47 @@ func newDbBinlogApp(repositories *repository.Repositories, dbApp Db) (*DbBinlogA
return svc, nil
}
func (app *DbBinlogApp) fetchBinlog(ctx context.Context, backup *entity.DbBackup) error {
if err := app.AddJobIfNotExists(ctx, entity.NewDbBinlog(backup.DbInstanceId)); err != nil {
return err
}
latestBinlogSequence, earliestBackupSequence := int64(-1), int64(-1)
binlogHistory, ok, err := app.binlogHistoryRepo.GetLatestHistory(backup.DbInstanceId)
if err != nil {
return err
}
if ok {
latestBinlogSequence = binlogHistory.Sequence
} else {
backupHistory, ok, err := app.backupHistoryRepo.GetEarliestHistory(backup.DbInstanceId)
if err != nil {
return err
}
if !ok {
return nil
}
earliestBackupSequence = backupHistory.BinlogSequence
}
conn, err := app.dbApp.GetDbConnByInstanceId(backup.DbInstanceId)
if err != nil {
return err
}
dbProgram := conn.GetDialect().GetDbProgram()
binlogFiles, err := dbProgram.FetchBinlogs(ctx, false, earliestBackupSequence, latestBinlogSequence)
if err == nil {
err = app.binlogHistoryRepo.InsertWithBinlogFiles(ctx, backup.DbInstanceId, binlogFiles)
}
jobStatus := entity.DbJobSuccess
if err != nil {
jobStatus = entity.DbJobFailed
}
job := &entity.DbBinlog{}
job.Id = backup.DbInstanceId
return app.updateCurJob(ctx, jobStatus, err, job)
}
func (app *DbBinlogApp) run() {
defer app.waitGroup.Done()
// todo: 实现 binlog 并发下载
timex.SleepWithContext(app.context, time.Minute)
for !app.closed() {
app.fetchFromAllInstances()
timex.SleepWithContext(app.context, binlogDownloadInterval)
}
}
func (app *DbBinlogApp) fetchFromAllInstances() {
var backups []*entity.DbBackup
if err := app.backupRepo.ListRepeating(&backups); err != nil {
logx.Errorf("DbBinlogApp: 获取数据库备份任务失败: %s", err.Error())
return
}
for _, backup := range backups {
jobs, err := app.loadJobs()
if err != nil {
logx.Errorf("DbBinlogApp: 加载 BINLOG 同步任务失败: %s", err.Error())
timex.SleepWithContext(app.context, time.Minute)
continue
}
if app.closed() {
break
}
if err := app.fetchBinlog(app.context, backup); err != nil {
logx.Errorf("DbBinlogApp: 下载 binlog 文件失败: %s", err.Error())
return
if err := app.scheduler.AddJob(app.context, false, entity.DbJobTypeBinlog, jobs); err != nil {
logx.Error("DbBinlogApp: 添加 BINLOG 同步任务失败: ", err.Error())
}
timex.SleepWithContext(app.context, entity.BinlogDownloadInterval)
}
}
func (app *DbBinlogApp) loadJobs() ([]*entity.DbBinlog, error) {
var instanceIds []uint64
if err := app.backupRepo.ListDbInstances(true, true, &instanceIds); err != nil {
return nil, err
}
jobs := make([]*entity.DbBinlog, 0, len(instanceIds))
for _, id := range instanceIds {
if app.closed() {
break
}
binlog := entity.NewDbBinlog(id)
if err := app.AddJobIfNotExists(app.context, binlog); err != nil {
return nil, err
}
jobs = append(jobs, binlog)
}
return jobs, nil
}
func (app *DbBinlogApp) Close() {
app.cancel()
app.waitGroup.Wait()
@@ -146,14 +106,3 @@ func (app *DbBinlogApp) Delete(ctx context.Context, jobId uint64) error {
}
return nil
}
func (app *DbBinlogApp) updateCurJob(ctx context.Context, status entity.DbJobStatus, lastErr error, job *entity.DbBinlog) error {
job.LastStatus = status
var result = binlogResult[status]
if lastErr != nil {
result = fmt.Sprintf("%v: %v", binlogResult[status], lastErr)
}
job.LastResult = stringx.TruncateStr(result, entity.LastResultSize)
job.LastTime = timex.NewNullTime(time.Now())
return app.binlogRepo.UpdateById(ctx, job, "last_status", "last_result", "last_time")
}