-
Notifications
You must be signed in to change notification settings - Fork 242
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Document when with_key
callbacks get invoked, and in which order
#578
base: main
Are you sure you want to change the base?
Conversation
With some types of callbacks, it may matter what order the callbacks get called in, and when in the formatting of the progress bar they're called. For instance, if a `with_key` callback calls `ProgressBar::set_position`, a *subsequent* reference to `eta` should take that update into account.
/// template, in order with other formatting and computation in the template. The caller can | ||
/// rely on this ordering. | ||
/// | ||
/// It's safe to call back into the `ProgressBar` from within this callback. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's this for? I'm not all that comfortable with making this last sentence explicit. Changing the ProgressBar
during ProgressTracker::write()
is definitely not something I had in mind and really want to spend time considering as something that I should keep working.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also think this might get into locking issues? Like, the ProgressTracker
impl gets immutable access to the &ProgressState
, which lives inside the BarState
which is inside an Arc<Mutex<_>>
inside the ProgressBar
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason this works right now seems to be that (fortunately) the first thing the implementation does is to update its last-updated time with the current one before continuing with the update. Future calls to tick()
will now immediately bounce off as the update seems to have just been done.
With that said, we also use the ticker-thread which may change the codepath, but the above is what I could gather by looking at the code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ProgressBar::set_position()
is rate-limited, yes, like ProgressBar::inc()
, but ProgressBar::tick()
isn't. So this is pretty nuanced, and not something that I want to guarantee to this level of detail going forward.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Anyway, it would be interesting to know why you want to do this. Presumably you can pass a ProgressBar
clone into whatever thing that is making progress and call that outside of the ProgressTracker
implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a great question: what problem is calling set_position()
on a clone of the progress-bar from within the with_key()
callback actually solving?
We have an ongoing operation which keeps updating an atomic counter which should be mapped to the pos
of the progress bar. In order to do it with the current API it's necessary to use a callback which typically is more involved and noisy than passing a reference to an atomic down to where it needs to be. That noisiness was avoided by calling set_position()
from within the with_key()
callback.
An alternative solution could be to make the atomic counter that's used within the progress bar directly accessible - we use an auto-ticker so communicating via shared state would (seemingly) work.
I hope this context helps.
The use case for this is a piece of code that keeps stats in its own What approach would you suggest for this use case? Assume the code that keeps stats doesn't have any indicatif-specific interface. |
So here's what I think might make sense and wouldn't add too much complexity even though it's a bit involved: pub trait ProgressInput {
fn tick(&mut self, state: &mut ProgressState);
} Then we'd add a method The (Maybe not the best names, feel free to come up with better ones.) How does that sound? @chris-laplante any thoughts? |
This sounds like |
Would be great if someone working on the original issue (some Cargo/gitoxide thing?) could take a stab at implementing my proposal to see if it addresses the use case. Should be straightforward from my detailed comment before. |
Thanks for suggesting the fix and I hope it will be implemented eventually to not be lost in this PR. For us it seems less time consuming to use the current API as intended and make the With that said, I think this PR can be closed as it had to be rejected. |
With some types of callbacks, it may matter what order the callbacks get
called in, and when in the formatting of the progress bar they're
called. For instance, if a
with_key
callback callsProgressBar::set_position
, a subsequent reference toeta
shouldtake that update into account.
Would appreciate having this documented as something callers can rely on.