Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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
fix: update num-msgs archive metrics every minute and not only at the beginning #2287
fix: update num-msgs archive metrics every minute and not only at the beginning #2287
Changes from all commits
8d5efa5
4a8c5b8
File filter
Filter by extension
Conversations
Jump to
There are no files selected for viewing
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 wonder, how are these started? Don't they require the
await
keyword at some point?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.
Good question!
This can be considered a "normal" proc that starts an infinite loop inside. This proc is marked with the
{.async.}
pragma, which in turn, makes the proc return aFuture[void]
, implicitly. And this returnedFuture[void]
needs to be either attended or discarded.afaik, there are two ways to attend a "future": keep a reference of it or
await
it immediately. And in this case, we keep a reference that is used to cancel the future returned. In this case, the returned future is directly linked with the internalawait sleepAsync(..
call, which in turn conforms a cancellation point.Therefore, when we are cancelling that future, we are forcing the code to break and
goto
to end that proc call, and there is no need to perform an explicit break of the infinite loop. Notice that this "cancellation point" feature is given by ournim-chronos
library.I think this should be the standard way to proceed in such infinite periodic tasks.
Nevertheless, @arnetheduck can shed more light on this and provide a more accurate reasoning.
note: in case I didn't suggested before, this is a great explanation of how async works in Nim: https://peterme.net/asynchronous-programming-in-nim.html (I revisit it now and then ;P)
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.
So, if I understood correctly, this line
self.retMetricsRepFut = self.loopReportStoredMessagesMetric()
implicitly runs awaitFor
?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.
self.retMetricsRepFut = self.loopReportStoredMessagesMetric()
<- This line should be understood as a way of starting an async and endless task.waitFor
is a mechanism by which the thread gets blocked until a certain Future is completed.waitFor
should only be used in the upper layers of every app to prevent deadlocks, and by "upper layer" I mean the procs that are at the same level as the "main" module.Looking at the
waitFor
implementation it can be seen that it simply waits synchronously (doesn't have the{.async.}
pragma) for the future to complete while callingpoll()
, which is responsible for the dispatcher to progress and attend all the timers, network events, and async tasks: https://github.com/status-im/Nim/blob/3c9b68dc157804885b14a1984efc25e8b7cc861d/lib/pure/asyncdispatch.nim#L1958-L1963There 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.
Hm, okay then. The piece I'm missing is:
Why, if just running
self.loopReportStoredMessagesMetric()
starts the async task, does the compiler tell you you need to(discard) await
it?Or does it only start the async task when the rvalue of that is assigned to a
Future
variable?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.
Good question! I think the answer is "yes". I think it only starts when the future is consumed either with
await
or assigned. Is just an assumption, I don't know 100% sure.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 would actually make sense with all other parts... I was making some assumptions from being used to Python's async 😅