Repository navigation
Conversation
Codecov Reportâ
All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #1779 +/- ##
===========================================
- Coverage 100.00% 99.99% -0.01%
===========================================
Files 246 246
Lines 40326 40298 -28
Branches 6956 6953 -3
===========================================
- Hits 40326 40297 -29
- Partials 0 1 +1
ð New features to boost your workflow:
|
2 of 3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Description
Related issue (if applicable): none, completes the retry feature from #1739
With
retry=set, a message that overflows into several pieces sends the already accepted pieces again when a later piece fails.call_with_retry()inapprise/dispatch.pycallsservice.notify()for the whole service on every attempt, andNotifyBase.notify()sends every piece through_timed_send(). The delivery tracker (is_delivered()/mark_delivered()) is opt-in per plugin, so a plugin that does not mark anything, such asjson://, gets every piece re-sent. #1739 says a retry should only retry what failed.Reproducer with mocks only (nothing is sent):
json://localhost/?retry=1&wait=0&overflow=split, a 32883 character body that splits into three requests, and the mock answers 500 for the request containingPIECE2on the first pass only.Before:
After:
_timed_send()now does two things for the piece it is sending:Truewithout sending if the piece was already acceptedThe key is a module constant, so it does not collide with the keys a plugin tracks its own targets under. Both calls do nothing when retries are off (
is_delivered()returnsFalseandmark_delivered()has no tracker), so a notification withoutretry=is sent exactly as before. A piece is marked only when the whole piece returnedTrue, so a piece that reached only some of its targets is still retried and the plugin's own tracking decides who receives it again.async_notify()goes through_timed_send()too, so it gets the same behavior.Checklist
tox -e lintand optionallytox -e format).tox -e qa).Testing
Four tests in
tests/test_delivery_tracking.pyusejson://withoverflow=split, a body that splits into three pieces, and a mock where the last piece is refused:test_accepted_pieces_are_not_resent_on_retry: withretry=1, the first two pieces are sent once, the last one twice (refused, then accepted) and the notification succeedstest_accepted_pieces_are_sent_once_without_retry: withretry=0every piece is sent once and the failure is final (control, unchanged behavior)test_failing_piece_exhausts_retries_without_resending_others: a piece that is refused on every attempt exhaustsretry=2, the notification fails, and the first two pieces are still sent oncetest_async_accepted_pieces_are_not_resent_on_retry: the same as the first test throughasync_notify()Without the change in
base.pythe first, third and fourth tests fail (3 failed, 42 passed intests/test_delivery_tracking.py); with it all 45 pass.Not included: per-target tracking in plugins (unchanged).