AdjustAverageDecorators for resume-able tasks
Vladimir Bauer
6 years ago
| 74 | 74 | noPop bool |
| 75 | 75 | aDecorators []decor.Decorator |
| 76 | 76 | pDecorators []decor.Decorator |
| 77 | mDecorators []decor.Decorator | |
| 77 | 78 | amountReceivers []decor.AmountReceiver |
| 78 | 79 | shutdownListeners []decor.ShutdownListener |
| 79 | 80 | bufP, bufB, bufA *bytes.Buffer |
| 169 | 170 | } |
| 170 | 171 | |
| 171 | 172 | // SetRefill sets refill, if supported by underlying Filler. |
| 173 | // Useful for resume-able tasks. | |
| 172 | 174 | func (b *Bar) SetRefill(amount int64) { |
| 175 | type refiller interface { | |
| 176 | SetRefill(int64) | |
| 177 | } | |
| 173 | 178 | b.operateState <- func(s *bState) { |
| 174 | if f, ok := s.filler.(interface{ SetRefill(int64) }); ok { | |
| 179 | if f, ok := s.filler.(refiller); ok { | |
| 175 | 180 | f.SetRefill(amount) |
| 181 | } | |
| 182 | } | |
| 183 | } | |
| 184 | ||
| 185 | // AdjustAverageDecorators updates start time of all average decorators. | |
| 186 | // Useful for resume-able tasks. | |
| 187 | func (b *Bar) AdjustAverageDecorators(startTime time.Time) { | |
| 188 | type adjustable interface { | |
| 189 | AverageAdjust(time.Time) | |
| 190 | } | |
| 191 | b.UpdateDecorators(func(d decor.Decorator) { | |
| 192 | if d, ok := d.(adjustable); ok { | |
| 193 | d.AverageAdjust(startTime) | |
| 194 | } | |
| 195 | }) | |
| 196 | } | |
| 197 | ||
| 198 | // UpdateDecorators general helper func. | |
| 199 | func (b *Bar) UpdateDecorators(cb decor.UpdateFunc) { | |
| 200 | b.operateState <- func(s *bState) { | |
| 201 | for _, decorators := range [...][]decor.Decorator{ | |
| 202 | s.pDecorators, | |
| 203 | s.aDecorators, | |
| 204 | s.mDecorators, | |
| 205 | } { | |
| 206 | for _, d := range decorators { | |
| 207 | cb(d) | |
| 208 | } | |
| 176 | 209 | } |
| 177 | 210 | } |
| 178 | 211 | } |
| 6 | 6 | // BarOption is a function option which changes the default behavior of a bar. |
| 7 | 7 | type BarOption func(*bState) |
| 8 | 8 | |
| 9 | type merger interface { | |
| 10 | CompoundDecorators() []decor.Decorator | |
| 11 | } | |
| 12 | ||
| 13 | func (s *bState) appendAmountReceiver(d decor.Decorator) { | |
| 14 | if ar, ok := d.(decor.AmountReceiver); ok { | |
| 15 | s.amountReceivers = append(s.amountReceivers, ar) | |
| 16 | } | |
| 17 | } | |
| 18 | ||
| 19 | func (s *bState) appendShutdownListener(d decor.Decorator) { | |
| 20 | if sl, ok := d.(decor.ShutdownListener); ok { | |
| 21 | s.shutdownListeners = append(s.shutdownListeners, sl) | |
| 22 | } | |
| 9 | type mergeWrapper interface { | |
| 10 | MergeUnwrap() []decor.Decorator | |
| 23 | 11 | } |
| 24 | 12 | |
| 25 | 13 | func (s *bState) addDecorators(dest *[]decor.Decorator, decorators ...decor.Decorator) { |
| 26 | 14 | for _, decorator := range decorators { |
| 27 | s.appendAmountReceiver(decorator) | |
| 28 | s.appendShutdownListener(decorator) | |
| 29 | if m, ok := decorator.(merger); ok { | |
| 30 | dd := m.CompoundDecorators() | |
| 31 | s.appendAmountReceiver(dd[0]) | |
| 32 | s.appendShutdownListener(dd[0]) | |
| 15 | if mw, ok := decorator.(mergeWrapper); ok { | |
| 16 | dd := mw.MergeUnwrap() | |
| 17 | s.mDecorators = append(s.mDecorators, dd[0]) | |
| 33 | 18 | *dest = append(*dest, dd[1:]...) |
| 34 | 19 | } |
| 35 | 20 | *dest = append(*dest, decorator) |
| 92 | 92 | Shutdown() |
| 93 | 93 | } |
| 94 | 94 | |
| 95 | // UpdateFunc convenience func type | |
| 96 | type UpdateFunc func(Decorator) | |
| 97 | ||
| 95 | 98 | // Global convenience shortcuts |
| 96 | 99 | var ( |
| 97 | 100 | WCSyncWidth = WC{C: DSyncWidth} |
| 119 | 119 | // |
| 120 | 120 | // `wcc` optional WC config |
| 121 | 121 | func AverageETA(style TimeStyle, wcc ...WC) Decorator { |
| 122 | return NewAverageETA(style, time.Now(), wcc...) | |
| 123 | } | |
| 124 | ||
| 125 | // NewAverageETA decorator with user provided start time. | |
| 126 | // | |
| 127 | // `style` one of [ET_STYLE_GO|ET_STYLE_HHMMSS|ET_STYLE_HHMM|ET_STYLE_MMSS] | |
| 128 | // | |
| 129 | // `startTime` start time | |
| 130 | // | |
| 131 | // `wcc` optional WC config | |
| 132 | func NewAverageETA(style TimeStyle, startTime time.Time, wcc ...WC) Decorator { | |
| 122 | 133 | var wc WC |
| 123 | 134 | for _, widthConf := range wcc { |
| 124 | 135 | wc = widthConf |
| 127 | 138 | d := &averageETA{ |
| 128 | 139 | WC: wc, |
| 129 | 140 | style: style, |
| 130 | startTime: time.Now(), | |
| 141 | startTime: startTime, | |
| 131 | 142 | } |
| 132 | 143 | return d |
| 133 | 144 | } |
| 177 | 188 | d.completeMsg = &msg |
| 178 | 189 | } |
| 179 | 190 | |
| 191 | func (d *averageETA) AverageAdjust(startTime time.Time) { | |
| 192 | d.startTime = startTime | |
| 193 | } | |
| 194 | ||
| 180 | 195 | func MaxTolerateTimeNormalizer(maxTolerate time.Duration) TimeNormalizer { |
| 181 | 196 | var normalized time.Duration |
| 182 | 197 | var lastCall time.Time |
| 219 | 219 | // |
| 220 | 220 | // "%.1f" = "1.0MiB/s" or "% .1f" = "1.0 MiB/s" |
| 221 | 221 | func AverageSpeed(unit int, unitFormat string, wcc ...WC) Decorator { |
| 222 | return NewAverageSpeed(unit, unitFormat, time.Now(), wcc...) | |
| 223 | } | |
| 224 | ||
| 225 | // NewAverageSpeed decorator with dynamic unit measure adjustment and | |
| 226 | // user provided start time. | |
| 227 | // | |
| 228 | // `unit` one of [0|UnitKiB|UnitKB] zero for no unit | |
| 229 | // | |
| 230 | // `unitFormat` printf compatible verb for value, like "%f" or "%d" | |
| 231 | // | |
| 232 | // `startTime` start time | |
| 233 | // | |
| 234 | // `wcc` optional WC config | |
| 235 | // | |
| 236 | // unitFormat example if UnitKiB is chosen: | |
| 237 | // | |
| 238 | // "%.1f" = "1.0MiB/s" or "% .1f" = "1.0 MiB/s" | |
| 239 | func NewAverageSpeed(unit int, unitFormat string, startTime time.Time, wcc ...WC) Decorator { | |
| 222 | 240 | var wc WC |
| 223 | 241 | for _, widthConf := range wcc { |
| 224 | 242 | wc = widthConf |
| 228 | 246 | WC: wc, |
| 229 | 247 | unit: unit, |
| 230 | 248 | unitFormat: unitFormat, |
| 231 | startTime: time.Now(), | |
| 249 | startTime: startTime, | |
| 232 | 250 | } |
| 233 | 251 | return d |
| 234 | 252 | } |
| 268 | 286 | func (d *averageSpeed) OnCompleteMessage(msg string) { |
| 269 | 287 | d.completeMsg = &msg |
| 270 | 288 | } |
| 289 | ||
| 290 | func (d *averageSpeed) AverageAdjust(startTime time.Time) { | |
| 291 | d.startTime = startTime | |
| 292 | } | |
| 10 | 10 | "time" |
| 11 | 11 | |
| 12 | 12 | "github.com/vbauerster/mpb/v4/cwriter" |
| 13 | "github.com/vbauerster/mpb/v4/decor" | |
| 13 | 14 | ) |
| 14 | 15 | |
| 15 | 16 | const ( |
| 142 | 143 | ps.idCount++ |
| 143 | 144 | result <- bar |
| 144 | 145 | }: |
| 145 | return <-result | |
| 146 | var amountReceivers []decor.AmountReceiver | |
| 147 | var shutdownListeners []decor.ShutdownListener | |
| 148 | bar := <-result | |
| 149 | bar.UpdateDecorators(func(d decor.Decorator) { | |
| 150 | if d, ok := d.(decor.AmountReceiver); ok { | |
| 151 | amountReceivers = append(amountReceivers, d) | |
| 152 | } | |
| 153 | if d, ok := d.(decor.ShutdownListener); ok { | |
| 154 | shutdownListeners = append(shutdownListeners, d) | |
| 155 | } | |
| 156 | }) | |
| 157 | bar.operateState <- func(s *bState) { | |
| 158 | s.amountReceivers = amountReceivers | |
| 159 | s.shutdownListeners = shutdownListeners | |
| 160 | } | |
| 161 | return bar | |
| 146 | 162 | case <-p.done: |
| 147 | 163 | p.bwg.Done() |
| 148 | 164 | return nil |