From bf1276f7679808fd3e82b10e7ef26de318dd3dd7 Mon Sep 17 00:00:00 2001 From: Matthias Freund Date: Mon, 20 Jan 2020 15:26:07 +0100 Subject: [PATCH] status: port status-v1 ETA calculation patch Must have forgotten to integrate it into the status-v2 branch at the time. refs https://github.com/zrepl/zrepl/issues/98#issuecomment-872154091 cc @dcdamien --- client/status/viewmodel/render.go | 32 +++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/client/status/viewmodel/render.go b/client/status/viewmodel/render.go index 4edf49e..7e29e6c 100644 --- a/client/status/viewmodel/render.go +++ b/client/status/viewmodel/render.go @@ -356,9 +356,17 @@ func renderReplicationReport(t *stringbuilder.B, rep *report.Report, history *by // Progress: [---------------] expected, replicated, containsInvalidSizeEstimates := latest.BytesSum() rate, changeCount := history.Update(replicated) + eta := time.Duration(0) + if rate > 0 { + eta = time.Duration((expected-replicated)/rate) * time.Second + } + t.Write("Progress: ") t.DrawBar(50, replicated, expected, changeCount) t.Write(fmt.Sprintf(" %s / %s @ %s/s", ByteCountBinary(replicated), ByteCountBinary(expected), ByteCountBinary(rate))) + if eta != 0 { + t.Write(fmt.Sprintf(" (%s remaining)", humanizeDuration(eta))) + } t.Newline() if containsInvalidSizeEstimates { t.Write("NOTE: not all steps could be size-estimated, total estimate is likely imprecise!") @@ -383,6 +391,30 @@ func renderReplicationReport(t *stringbuilder.B, rep *report.Report, history *by } } +func humanizeDuration(duration time.Duration) string { + days := int64(duration.Hours() / 24) + hours := int64(math.Mod(duration.Hours(), 24)) + minutes := int64(math.Mod(duration.Minutes(), 60)) + seconds := int64(math.Mod(duration.Seconds(), 60)) + + var parts []string + + force := false + chunks := []int64{days, hours, minutes, seconds} + for i, chunk := range chunks { + if force || chunk > 0 { + padding := 0 + if force { + padding = 2 + } + parts = append(parts, fmt.Sprintf("%*d%c", padding, chunk, "dhms"[i])) + force = true + } + } + + return strings.Join(parts, " ") +} + func renderPrunerReport(t *stringbuilder.B, r *pruner.Report, fsfilter FilterFunc) { if r == nil { t.Printf("...\n")