mirror of
https://github.com/garethgeorge/backrest.git
synced 2025-12-13 09:15:39 +00:00
feat: support restic check operation (#303)
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
package tasks
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -59,14 +58,20 @@ func (t *PruneTask) Next(now time.Time, runner TaskRunner) (ScheduledTask, error
|
||||
}
|
||||
|
||||
var lastRan time.Time
|
||||
var foundBackup bool
|
||||
if err := runner.OpLog().ForEach(oplog.Query{RepoId: t.RepoID()}, indexutil.Reversed(indexutil.CollectAll()), func(op *v1.Operation) error {
|
||||
if _, ok := op.Op.(*v1.Operation_OperationPrune); ok {
|
||||
lastRan = time.Unix(0, op.UnixTimeEndMs*int64(time.Millisecond))
|
||||
return oplog.ErrStopIteration
|
||||
}
|
||||
if _, ok := op.Op.(*v1.Operation_OperationBackup); ok {
|
||||
foundBackup = true
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return NeverScheduledTask, fmt.Errorf("finding last backup run time: %w", err)
|
||||
return NeverScheduledTask, fmt.Errorf("finding last prune run time: %w", err)
|
||||
} else if !foundBackup {
|
||||
return NeverScheduledTask, nil
|
||||
}
|
||||
|
||||
zap.L().Debug("last prune time", zap.Time("time", lastRan), zap.String("repo", t.RepoID()))
|
||||
@@ -95,6 +100,20 @@ func (t *PruneTask) Run(ctx context.Context, st ScheduledTask, runner TaskRunner
|
||||
return fmt.Errorf("couldn't get repo %q: %w", t.RepoID(), err)
|
||||
}
|
||||
|
||||
if err := runner.ExecuteHooks([]v1.Hook_Condition{
|
||||
v1.Hook_CONDITION_PRUNE_START,
|
||||
}, hook.HookVars{}); err != nil {
|
||||
op.DisplayMessage = err.Error()
|
||||
// TODO: generalize this logic
|
||||
var cancelErr *hook.HookErrorRequestCancel
|
||||
if errors.As(err, &cancelErr) {
|
||||
op.Status = v1.OperationStatus_STATUS_USER_CANCELLED // user visible cancelled status
|
||||
return nil
|
||||
}
|
||||
op.Status = v1.OperationStatus_STATUS_ERROR
|
||||
return fmt.Errorf("execute prune start hooks: %w", err)
|
||||
}
|
||||
|
||||
err = repo.UnlockIfAutoEnabled(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("auto unlock repo %q: %w", t.RepoID(), err)
|
||||
@@ -108,7 +127,7 @@ func (t *PruneTask) Run(ctx context.Context, st ScheduledTask, runner TaskRunner
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
interval := time.NewTicker(1 * time.Second)
|
||||
defer interval.Stop()
|
||||
var buf bytes.Buffer
|
||||
buf := ioutil.HeadWriter{Limit: 16 * 1024}
|
||||
bufWriter := ioutil.SynchronizedWriter{W: &buf}
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
@@ -118,14 +137,11 @@ func (t *PruneTask) Run(ctx context.Context, st ScheduledTask, runner TaskRunner
|
||||
select {
|
||||
case <-interval.C:
|
||||
bufWriter.Mu.Lock()
|
||||
output := buf.String()
|
||||
output := string(buf.Bytes())
|
||||
bufWriter.Mu.Unlock()
|
||||
if len(output) > 8*1024 { // only provide live status upto the first 8K of output.
|
||||
output = output[:len(output)-8*1024]
|
||||
}
|
||||
|
||||
if opPrune.OperationPrune.Output != output {
|
||||
opPrune.OperationPrune.Output = buf.String()
|
||||
if opPrune.OperationPrune.Output != string(output) {
|
||||
opPrune.OperationPrune.Output = string(output)
|
||||
|
||||
if err := runner.OpLog().Update(op); err != nil {
|
||||
zap.L().Error("update prune operation with status output", zap.Error(err))
|
||||
@@ -151,17 +167,18 @@ func (t *PruneTask) Run(ctx context.Context, st ScheduledTask, runner TaskRunner
|
||||
cancel()
|
||||
wg.Wait()
|
||||
|
||||
output := buf.String()
|
||||
if len(output) > 8*1024 { // only save the first 4K of output.
|
||||
output = output[:len(output)-8*1024]
|
||||
}
|
||||
|
||||
opPrune.OperationPrune.Output = output
|
||||
opPrune.OperationPrune.Output = string(buf.Bytes())
|
||||
|
||||
// Run a stats task after a successful prune
|
||||
if err := runner.ScheduleTask(NewStatsTask(t.RepoID(), PlanForSystemTasks, false), TaskPriorityStats); err != nil {
|
||||
zap.L().Error("schedule stats task", zap.Error(err))
|
||||
}
|
||||
|
||||
if err := runner.ExecuteHooks([]v1.Hook_Condition{
|
||||
v1.Hook_CONDITION_PRUNE_SUCCESS,
|
||||
}, hook.HookVars{}); err != nil {
|
||||
return fmt.Errorf("execute prune end hooks: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user