-
Notifications
You must be signed in to change notification settings - Fork 6
Fix dispatch dict passed to MergeStrategy
not getting updated for future fetch's
#174
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
base: v0.x.x
Are you sure you want to change the base?
Conversation
Signed-off-by: Mathias L. Baumann <[email protected]>
Signed-off-by: Mathias L. Baumann <[email protected]>
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.
As usual, the PR and commit title and description could use some improvement. It is hard to review when they say so little. Could you please please please put a bit more thought into those? Please 🙏 ? For the PR description just copying the copilot review summary is a big improvement.
For example in this PR it is mostly irrelevant that you are using started_at
, that tells me almost nothing. What is important is you are fixing a bug caused by not having a consistent now
used in different path of the code to decide on how to merge dispatches.
MergeStrategy
not getting updated for future fetch's
Requires v0.11.1 of `frequenz-client-dispatch` for the new `started_at` method. Signed-off-by: Mathias L. Baumann <[email protected]>
tbh, I disagree. The commit titles and descriptions are all perfectly fine imo. PR, yeah, okay, that grew a bit and needed updating. I also don't think a required dependency update necessarily needs to be mentioned if it is so minor as here, and the fact that its part of that particular commit is in itself a documentation of its need, at least that was my perspective.... I don't really see how any of the other commit titles & content is lacking anything to make them understandable. |
|
Without wanting to make a huge thing about this, I will just comment on this one, as I think it can bring some clarity:
I've seen many times people that sneak an unrelated change into a commit just because it was there. And I don't even think that's obscenely wrong, I can live with that when there is intention. The problem is when it was a mistake, and you were working on something else that needed the bump, but this PR doesn't really need it, and that dependency bump can have real world impact. So what it is important for me is declaring intention. If the bump was needed by the commit, that's good to know, and good to know why, even if it could be inferred from the diff, just as an extra verification. If the bump was just done because one is lazy about putting it in a separate commit, and the bump is harmless, that should also be explicitly stated, so I can actually do a review, which is about detecting issues early. This is my main point. I want to be able to tell between mistakes and intended changes. |
Signed-off-by: Mathias L. Baumann <[email protected]>
Signed-off-by: Mathias L. Baumann <[email protected]>
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.
LGTM, but one thing to check and one small suggestion.
By using a workflow that avoids reassigning the dispatches dict. When `fetch()`, which runs periodically, would assign a fresh map to `self._dispatches` the filter would not see the latest dispatches, as it would still reference the old map. Signed-off-by: Mathias L. Baumann <[email protected]>
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.
Pull Request Overview
This pull request fixes an issue where the dispatch dictionary passed to MergeStrategy
was not getting updated for future fetches, causing the merge filter to work with stale data. The fix ensures the dispatch cache is properly maintained and updated during fetch operations.
Key changes:
- Fixed cache update logic in
_fetch()
to properly update the_dispatches
dictionary with new data - Enhanced consistency by using the same
now
timestamp when evaluating multiple dispatches in the merge strategy - Improved logging throughout the codebase to use proper logger paths and provide better debugging information
Reviewed Changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
Show a summary per file
File | Description |
---|---|
src/frequenz/dispatch/_bg_service.py |
Fixed dispatch cache update logic and improved error handling for deleted dispatches |
src/frequenz/dispatch/_merge_strategies.py |
Updated to use consistent timestamp and proper logger path |
src/frequenz/dispatch/_dispatch.py |
Added started_at() method to accept external timestamp for consistency |
src/frequenz/dispatch/_actor_dispatcher.py |
Improved logging messages for actor lifecycle events |
pyproject.toml |
Updated dependency version for frequenz-client-dispatch |
RELEASE_NOTES.md |
Updated release notes to reflect bug fixes |
Comments suppressed due to low confidence (2)
src/frequenz/dispatch/_merge_strategies.py:61
- Variable name collision:
dispatch
is used both as the parameter to thefilter
method and as the iteration variable in this generator expression. This shadows the outerdispatch
variable and could cause confusion. Consider renaming the iteration variable torunning_dispatch
.
dispatch.started_at(now) for dispatch in running_dispatch_list
src/frequenz/dispatch/_merge_strategies.py:74
- Variable name collision:
dispatch
is used both as the parameter to thefilter
method and as the iteration variable in this generator expression. This shadows the outerdispatch
variable and could cause confusion. Consider renaming the iteration variable torunning_dispatch
.
list(dispatch.id for dispatch in running_dispatch_list),
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.
LGTM, just one more suggestion, removing auto-merge in case you want to change it.
@@ -366,8 +366,8 @@ async def _fetch(self, timer: Timer) -> None: | |||
""" | |||
self._initial_fetch_event.clear() | |||
|
|||
old_dispatches = self._dispatches | |||
self._dispatches = {} | |||
old_dispatches = set(self._dispatches.keys()) |
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.
old_dispatches = set(self._dispatches.keys()) |
for dispatch_id in old_dispatches - new_dispatches.keys(): | ||
try: | ||
dispatch = self._dispatches.pop(dispatch_id) | ||
_logger.debug("Deleted dispatch: %s", dispatch) | ||
await self._update_dispatch_schedule_and_notify(None, dispatch, timer) | ||
|
||
# Set deleted only here as it influences the result of dispatch.started | ||
# which is used in the func call above ^ | ||
dispatch._set_deleted() # pylint: disable=protected-access | ||
await self._lifecycle_events_tx.send(Deleted(dispatch=dispatch)) | ||
except KeyError: | ||
_logger.warning( | ||
"Inconsistency in cache detected. Tried to delete non-existing dispatch %s", | ||
dispatch_id, | ||
) |
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.
It is usually recommended to narrow the try/except to only the code you expect to fail, otherwise you could catch other failures that maybe are not OK to ignore. For example if some code in await self._lifecycle_events_tx.send(Deleted(dispatch=dispatch))
(suppose send()
uses some internal cache and there is a bug that also make it raise a KeyError
).
Also if old_dispatches
== self._dispatches.keys()
, maybe it makes more sense to use self._dispatches.keys()
directly now, I see in the new code old_dispatches
is only being used here. This would make the code more obvious and actually guarantee the pop()
can't fail, old_dispatches
and self._dispatches
can't get out of sync.
So I suggest removing old_dispatches
and just do:
for dispatch_id in old_dispatches - new_dispatches.keys(): | |
try: | |
dispatch = self._dispatches.pop(dispatch_id) | |
_logger.debug("Deleted dispatch: %s", dispatch) | |
await self._update_dispatch_schedule_and_notify(None, dispatch, timer) | |
# Set deleted only here as it influences the result of dispatch.started | |
# which is used in the func call above ^ | |
dispatch._set_deleted() # pylint: disable=protected-access | |
await self._lifecycle_events_tx.send(Deleted(dispatch=dispatch)) | |
except KeyError: | |
_logger.warning( | |
"Inconsistency in cache detected. Tried to delete non-existing dispatch %s", | |
dispatch_id, | |
) | |
# We make a copy because we mutate self._dispatch.keys() inside the loop | |
for dispatch_id in frozenset(self._dispatches.keys() - new_dispatches.keys()): | |
dispatch = self._dispatches.pop(dispatch_id) | |
_logger.debug("Deleted dispatch: %s", dispatch) | |
await self._update_dispatch_schedule_and_notify(None, dispatch, timer) | |
# Set deleted only here as it influences the result of dispatch.started | |
# which is used in the func call above ^ | |
dispatch._set_deleted() # pylint: disable=protected-access | |
await self._lifecycle_events_tx.send(Deleted(dispatch=dispatch)) |
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.
Not sure if the copy is necessary, as we are using the -
which I guess produces a copy in itself, but I'm not 100% sure. Also making it a frozenset
guarantees our items being iterated will never change, so it makes everything more explicit.
now
while evaluating other dispatches in the MergeStrategy, but this is just an enhancement and not a fix