diff --git a/CHANGELOG.md b/CHANGELOG.md index cd35d5d7..32ce86bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### 12.97.0 * `[passthru]` Added package with pass-thru reader and writer +* `[progress]` Migrate to `passthru` package * `[fmtutil/table]` Improved borders and separators rendering * `[usage]` Improved environment info output * `[spinner]` Improved message rendering diff --git a/progress/pass_thru_calc.go b/progress/pass_thru_calc.go deleted file mode 100644 index 36c35021..00000000 --- a/progress/pass_thru_calc.go +++ /dev/null @@ -1,73 +0,0 @@ -package progress - -// ////////////////////////////////////////////////////////////////////////////////// // -// // -// Copyright (c) 2024 ESSENTIAL KAOS // -// Apache License, Version 2.0 // -// // -// ////////////////////////////////////////////////////////////////////////////////// // - -import ( - "math" - "time" -) - -// ////////////////////////////////////////////////////////////////////////////////// // - -const _MAX_REMAINING = 5999 * time.Second - -// ////////////////////////////////////////////////////////////////////////////////// // - -// PassThruCalc is pass thru calculator struct -type PassThruCalc struct { - total float64 - prev float64 - speed float64 - decay float64 - remaining time.Duration - lastUpdate time.Time -} - -// ////////////////////////////////////////////////////////////////////////////////// // - -// NewPassThruCalc creates new pass thru calculator -func NewPassThruCalc(total int64, winSizeSec float64) *PassThruCalc { - return &PassThruCalc{ - total: float64(total), - decay: 2 / (winSizeSec + 1), - } -} - -// ////////////////////////////////////////////////////////////////////////////////// // - -// Calculate calculates number of objects per seconds and remaining time -func (p *PassThruCalc) Calculate(v int64) (float64, time.Duration) { - c := float64(v) - now := time.Now() - - if !p.lastUpdate.IsZero() && now.Sub(p.lastUpdate) < time.Second/2 { - return p.speed, p.remaining - } - - speed := math.Abs(c-p.prev) / time.Since(p.lastUpdate).Seconds() - - p.speed = (speed * p.decay) + (p.speed * (1.0 - p.decay)) - - if p.prev != 0 && p.speed > 0 { - p.remaining = time.Duration((p.total-c)/p.speed) * time.Second - } - - if p.remaining > _MAX_REMAINING { - p.remaining = _MAX_REMAINING - } - - p.prev = c - p.lastUpdate = now - - return p.speed, p.remaining -} - -// SetTotal sets total number of objects -func (p *PassThruCalc) SetTotal(v int64) { - p.total = float64(v) -} diff --git a/progress/progress.go b/progress/progress.go index b1f30d19..cee42bfe 100644 --- a/progress/progress.go +++ b/progress/progress.go @@ -21,6 +21,7 @@ import ( "github.com/essentialkaos/ek/v12/fmtc" "github.com/essentialkaos/ek/v12/fmtutil" "github.com/essentialkaos/ek/v12/mathutil" + "github.com/essentialkaos/ek/v12/passthru" ) // ////////////////////////////////////////////////////////////////////////////////// // @@ -54,11 +55,11 @@ type Bar struct { buffer string ticker *time.Ticker - passThruCalc *PassThruCalc + passThruCalc *passthru.Calculator phCounter int - reader *passThruReader - writer *passThruWriter + reader *passthru.Reader + writer *passthru.Writer mu *sync.RWMutex } @@ -91,18 +92,6 @@ type Settings struct { // ////////////////////////////////////////////////////////////////////////////////// // -type passThruReader struct { - io.Reader - bar *Bar -} - -type passThruWriter struct { - io.Writer - bar *Bar -} - -// ////////////////////////////////////////////////////////////////////////////////// // - // DefaultSettings is default progress bar settings var DefaultSettings = Settings{ RefreshRate: 100 * time.Millisecond, @@ -161,7 +150,7 @@ func (b *Bar) Start() error { b.ticker = time.NewTicker(b.settings.RefreshRate) if b.total > 0 { - b.passThruCalc = NewPassThruCalc( + b.passThruCalc = passthru.NewCalculator( b.total, math.Max(1.0, float64(b.settings.WindowSizeSec)), ) } @@ -243,7 +232,7 @@ func (b *Bar) SetTotal(v int64) { b.mu.Lock() if b.passThruCalc == nil { - b.passThruCalc = NewPassThruCalc( + b.passThruCalc = passthru.NewCalculator( v, math.Max(1.0, float64(b.settings.WindowSizeSec)), ) } else { @@ -321,40 +310,30 @@ func (b *Bar) IsStarted() bool { return b.started } -// Reader creates and returns pass thru proxy reader -func (b *Bar) Reader(r io.Reader) io.Reader { +// Reader creates and returns pass thru-proxy reader +func (b *Bar) Reader(r io.ReadCloser) io.ReadCloser { if b == nil { return nil } - if b.reader != nil { - b.reader.Reader = r - } else { - b.reader = &passThruReader{ - Reader: r, - bar: b, - } - } + pr := passthru.NewReader(r, b.total) + pr.Update = b.Add + b.reader = pr - return b.reader + return pr } -// Writer creates and returns pass thru proxy reader -func (b *Bar) Writer(w io.Writer) io.Writer { +// Writer creates and returns pass-thru proxy reader +func (b *Bar) Writer(w io.WriteCloser) io.WriteCloser { if b == nil { return nil } - if b.writer != nil { - b.writer.Writer = w - } else { - b.writer = &passThruWriter{ - Writer: w, - bar: b, - } - } + pw := passthru.NewWriter(w, b.total) + pw.Update = b.Add + b.writer = pw - return b.writer + return pw } // ////////////////////////////////////////////////////////////////////////////////// // @@ -679,30 +658,6 @@ func (s Settings) Validate() error { // ////////////////////////////////////////////////////////////////////////////////// // -// Read reads data and updates progress bar -func (r *passThruReader) Read(p []byte) (int, error) { - n, err := r.Reader.Read(p) - - if n > 0 { - r.bar.Add(n) - } - - return n, err -} - -// Write writes data and updates progress bar -func (w *passThruWriter) Write(p []byte) (int, error) { - n, err := w.Writer.Write(p) - - if n > 0 { - w.bar.Add(n) - } - - return n, err -} - -// ////////////////////////////////////////////////////////////////////////////////// // - // getPrettyCTSize returns formatted current/total size text func getPrettyCTSize(current, total int64) (string, string, string) { var mod float64 diff --git a/progress/progress_test.go b/progress/progress_test.go index 27b53920..77afc2d5 100644 --- a/progress/progress_test.go +++ b/progress/progress_test.go @@ -322,30 +322,6 @@ func (s *ProgressSuite) TestRemainingRender(c *C) { c.Assert(sz, Equals, 5) } -func (s *ProgressSuite) TestPassThruCalc(c *C) { - ptc := NewPassThruCalc(1000, 0.5) - - c.Assert(ptc, NotNil) - - ptc.SetTotal(20000) - - c.Assert(ptc.total, Equals, float64(20000)) - - sp, dr := ptc.Calculate(1) - - time.Sleep(time.Second) - - sp, dr = ptc.Calculate(2) - - c.Assert(sp, Not(Equals), 0.0) - c.Assert(dr, Not(Equals), time.Duration(0)) - - sp2, dr2 := ptc.Calculate(2) - - c.Assert(sp2, Equals, sp) - c.Assert(dr2, Equals, dr) -} - func (s *ProgressSuite) TestAux(c *C) { ct, tt, lt := getPrettyCTSize(1, 15) @@ -428,6 +404,14 @@ func (r *DummyReader) Read(p []byte) (int, error) { return 100, nil } +func (r *DummyReader) Close() error { + return nil +} + func (w *DummyWriter) Write(p []byte) (int, error) { return 100, nil } + +func (r *DummyWriter) Close() error { + return nil +}