2
2
mirror of https://github.com/octoleo/restic.git synced 2024-11-26 06:46:34 +00:00

ui/backup: Use progress.Updater for progress updates

This commit is contained in:
Michael Eischer 2022-12-29 12:31:20 +01:00
parent e499bbe3ae
commit 4a7a6b06af
3 changed files with 30 additions and 65 deletions

View File

@ -483,16 +483,12 @@ func runBackup(ctx context.Context, opts BackupOptions, gopts GlobalOptions, ter
}
progressReporter := backup.NewProgress(progressPrinter,
calculateProgressInterval(!gopts.Quiet, gopts.JSON))
defer progressReporter.Done()
if opts.DryRun {
repo.SetDryRun()
}
wg, wgCtx := errgroup.WithContext(ctx)
cancelCtx, cancel := context.WithCancel(wgCtx)
defer cancel()
wg.Go(func() error { progressReporter.Run(cancelCtx); return nil })
if !gopts.JSON {
progressPrinter.V("lock repository")
}
@ -590,6 +586,10 @@ func runBackup(ctx context.Context, opts BackupOptions, gopts GlobalOptions, ter
targets = []string{filename}
}
wg, wgCtx := errgroup.WithContext(ctx)
cancelCtx, cancel := context.WithCancel(wgCtx)
defer cancel()
if !opts.NoScan {
sc := archiver.NewScanner(targetFS)
sc.SelectByName = selectByNameFilter

View File

@ -1,13 +1,12 @@
package backup
import (
"context"
"sync"
"time"
"github.com/restic/restic/internal/archiver"
"github.com/restic/restic/internal/restic"
"github.com/restic/restic/internal/ui/signals"
"github.com/restic/restic/internal/ui/progress"
)
// A ProgressPrinter can print various progress messages.
@ -41,10 +40,10 @@ type Summary struct {
// Progress reports progress for the `backup` command.
type Progress struct {
progress.Updater
mu sync.Mutex
interval time.Duration
start time.Time
start time.Time
scanStarted, scanFinished bool
@ -52,66 +51,37 @@ type Progress struct {
processed, total Counter
errors uint
closed chan struct{}
summary Summary
printer ProgressPrinter
}
func NewProgress(printer ProgressPrinter, interval time.Duration) *Progress {
return &Progress{
interval: interval,
start: time.Now(),
p := &Progress{
start: time.Now(),
currentFiles: make(map[string]struct{}),
closed: make(chan struct{}),
printer: printer,
printer: printer,
}
}
p.Updater = *progress.NewUpdater(interval, func(runtime time.Duration, final bool) {
if final {
p.printer.Reset()
} else {
p.mu.Lock()
defer p.mu.Unlock()
if !p.scanStarted {
return
}
// Run regularly updates the status lines. It should be called in a separate
// goroutine.
func (p *Progress) Run(ctx context.Context) {
defer close(p.closed)
// Reset status when finished
defer p.printer.Reset()
var secondsRemaining uint64
if p.scanFinished {
secs := float64(runtime / time.Second)
todo := float64(p.total.Bytes - p.processed.Bytes)
secondsRemaining = uint64(secs / float64(p.processed.Bytes) * todo)
}
var tick <-chan time.Time
if p.interval != 0 {
t := time.NewTicker(p.interval)
defer t.Stop()
tick = t.C
}
signalsCh := signals.GetProgressChannel()
for {
var now time.Time
select {
case <-ctx.Done():
return
case now = <-tick:
case <-signalsCh:
now = time.Now()
p.printer.Update(p.total, p.processed, p.errors, p.currentFiles, p.start, secondsRemaining)
}
p.mu.Lock()
if !p.scanStarted {
p.mu.Unlock()
continue
}
var secondsRemaining uint64
if p.scanFinished {
secs := float64(now.Sub(p.start) / time.Second)
todo := float64(p.total.Bytes - p.processed.Bytes)
secondsRemaining = uint64(secs / float64(p.processed.Bytes) * todo)
}
p.printer.Update(p.total, p.processed, p.errors, p.currentFiles, p.start, secondsRemaining)
p.mu.Unlock()
}
})
return p
}
// Error is the error callback function for the archiver, it prints the error and returns nil.
@ -236,6 +206,6 @@ func (p *Progress) ReportTotal(item string, s archiver.ScanStats) {
// Finish prints the finishing messages.
func (p *Progress) Finish(snapshotID restic.ID, dryrun bool) {
// wait for the status update goroutine to shut down
<-p.closed
p.Updater.Done()
p.printer.Finish(snapshotID, p.start, &p.summary, dryrun)
}

View File

@ -1,7 +1,6 @@
package backup
import (
"context"
"sync"
"testing"
"time"
@ -53,9 +52,6 @@ func TestProgress(t *testing.T) {
prnt := &mockPrinter{}
prog := NewProgress(prnt, time.Millisecond)
ctx, cancel := context.WithCancel(context.Background())
go prog.Run(ctx)
prog.StartFile("foo")
prog.CompleteBlob(1024)
@ -67,7 +63,6 @@ func TestProgress(t *testing.T) {
prog.CompleteItem("foo", nil, &node, archiver.ItemStats{}, 0)
time.Sleep(10 * time.Millisecond)
cancel()
id := restic.NewRandomID()
prog.Finish(id, false)