ruby-progressbar icon indicating copy to clipboard operation
ruby-progressbar copied to clipboard

Am I being obtuse, or is there a usage gap?

Open manuelgomes opened this issue 4 years ago • 3 comments

Current Problem

Given an external "black box" library call that follows the pattern of calling an optional block to report progress result = lib_obj.do_big_slow_thing(params) { |progress| do_something_with_progress(progress) } and feeds in a float between 0 and 1, representing percentage done, is there a way of making ruby-progressbar track this progress while still keeping ETA math relatively sane?

What I ended up doing was writing a wrapper around the bar, and incrementing the bar when we were on a new "integer percentage", like thus:

class ProgressWrapper
  def initialize(format: "%a |%b>>%i| %p%% %t %E")
    @bar = ProgressBar.create(format: format)
    @showing = 0
    @start = Time.now
  end

  # @param prog [Float] current progress between `0` and `1`
  def feed(prog)
    candidate = prog_to_perc(prog)
    if candidate > @showing
      @showing = candidate
      @bar.increment
    end
    @bar.refresh
  end

  def finish
    @bar.finish
    @finish = Time.now
  end

  def duration
    return unless @finish
    @finish - @start
  end

  private

  def prog_to_perc(prog)
    (prog * 100).round
  end
end

But.. my own bad code aside, it feels kludgy. Is there already a way to do this that I simply missed, or might it be an idea to provide a method to service this use-case, along the lines of bar.percentage_complete = progress?

Thanks for both your attention to this, and the awesome gem!

manuelgomes avatar Mar 22 '21 10:03 manuelgomes

Sorry for the delay! Yeah! I'm honestly not entirely sure what you're trying to do, but I have some things that might be able to help.

First, you can explicitly set progress with progress= so if you did:

  def feed(prog)
    @bar.progress = prog * 100
  end

That should do everything you need (including the refresh). The bar, by default has a total of 100. This was picked specifically for the default use case to be handy for percentages.

Additionally, the bar will autocomplete once it gets to the total so unless you want it to finish early, you don't have to call finish. Once the bar is completed (eg it gets to the total), you can check @bar.finished? so you don't have to store another variable there. Additionally you can get a large amount of bar data by calling @bar.to_h which includes the elapsed duration of the progress run.

Lastly, depending on how you're doing your looping, you may be interested in the enumerable refinement which can allow you to iterate over an enumerable and the bar will keep track of progress along the way for each loop.

Hope this helps!

jfelchner avatar Apr 10 '21 22:04 jfelchner

Thanks for your reply, and my own apologies for the delay in getting back to you.

The above was an attempt at working around the caveat about #progress= messing up the estimated time - it keeps a parallel state and increments the bar's state only when a call to #increment is justified, rather than setting the progress to whatever it is, thereby messing up the ETA.

Or at least... that's the intent. Ultimately, any solution that accommodates the fact that progress will be an arbitrary (if monotonic) number, and doesn't mess up the ETA will be just peachy.

manuelgomes avatar May 12 '21 01:05 manuelgomes

@manuelgomes I now have a better sense of what your issue is, but it's still a bit too abstract for me. Is there any way you can get me a repro case of what the library currently does compared to what you'd like it to do? Examples that include sleep statements to repro long running tasks is perfectly fine with me.

jfelchner avatar Jun 02 '21 03:06 jfelchner

@manuelgomes I really thought I was keeping on top of things but apparently I was not. Please read this comment about new functionality I've added.

I think that if you can submit a PR that handles the use case you're trying to achieve (with a test), I'd be happy to work with you on trying to accomplish what you're trying to accomplish. I'm going to close this issue for now, but feel free to reference it if you open a PR. Thanks!

jfelchner avatar Feb 26 '23 06:02 jfelchner

Actually I went even further with this. Check out this PR. It should now be extremely extensible for someone to submit a PR to be able to include a different projector to estimate the remaining time.

jfelchner avatar Mar 03 '23 07:03 jfelchner