Repository navigation
Pause usage sharing sends after repeated failures - #62
Draft
jwrosewell wants to merge 4 commits into
Draft
jwrosewell wants to merge 4 commits into
jwrosewell wants to merge 4 commits into
Conversation
Usage sharing in Java has no back-off. Every batch is sent while the service is failing, and is lost. These tests expect the back-off .NET is being given, at its default settings of ten failed sends within 100 seconds and a first pause of two seconds: - after ten failed sends nothing is sent during the pause, and the evidence processed during it is all sent once the pause ends and the service answers, with no more requests processed; - closing while paused returns at once and sends nothing. They fail until the back-off is added.
Java now has the same back-off as .NET, with the same five settings and defaults. - After setFailuresToEnterRecovery sends fail within setFailuresWindowSeconds, sending pauses for setInitialRecoveryDelaySeconds. A send fails when it throws or the answer is not 200. - When a pause ends one send is tried. If it fails the delay is multiplied by setRecoveryMultiplier, up to setMaxRecoveryDelaySeconds. If it succeeds the back-off ends. - Processing is not affected. Evidence is queued during a pause and new evidence is dropped only when the queue is full. - The consumer waits out the pause itself, on a latch that closing releases, and then sends until fewer than the minimum entries per message are queued, so the queue drains when a pause ends without more requests being processed. - Closing ends a pause at once and sends nothing while paused, logging how many entries were not sent. ShareUsageBackOff holds the rules and takes the time from the caller, so its tests set the time. The consumer calls the new protected waitWhilePaused before each message and recordSendResult after it. New constructors take the five settings, and the existing ones use the defaults.
The builder setter rejects a value outside 1 to 100, and the back-off now does too, so a class derived from ShareUsageBase gets the same check through its constructor.
The comments in the functions this change touches described what the code used to do. They now say only what the code does and why.
This was referenced Nov 7, 2026
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.
Java's usage sharing has no back-off, so every message is sent, and lost, while the service is failing. This adds the back-off that 51degrees-dotnet#88 restores in .NET, with the same five settings and defaults.
Problem
ShareUsageElement.sendUsageData(lines 341 to 379) sends every batch it takes from the queue, and a failed send is logged and the batch dropped. During an outage every batch is lost, and each one is another request to a failing service. .NET had a back-off from pipeline-dotnet#218, but it blocked processing as well as sending and was removed in pipeline-dotnet#261. The back-off is now to be part of the specification and of every usage sharing element.Change
sendAsXMLalready reports.setFailuresToEnterRecoverysends fail withinsetFailuresWindowSeconds, sending pauses forsetInitialRecoveryDelaySeconds. Successful sends in between do not reset the count.setRecoveryMultiplier, up tosetMaxRecoveryDelaySeconds. If it succeeds, the back-off ends and the next pause starts again from the initial delay.setFailuresToEnterRecoverysetFailuresWindowSecondssetInitialRecoveryDelaySecondssetMaxRecoveryDelaySecondssetRecoveryMultiplierHow it is built:
ShareUsageBackOff(ShareUsageBackOff.java) holds the rules. Each method takes the time from the caller, so its tests set the time.ShareUsageBasegains the protectedwaitWhilePausedandrecordSendResult, whichShareUsageElement.sendUsageDatacalls before and after each message. A class derived fromShareUsageBasewith its own consumer gets no back-off until it calls them.ShareUsageBaseandShareUsageElementtake the five settings. The existing ones pass the defaults, so code built against them is unchanged.Constantsunder the .NET names.Tests
The element tests in ShareUsageElementBackOffTests.java were written first. The first two use only the default settings and the constructor rc already has, so they compiled on rc and were run there with only the tests added (run 42347851766). Both failed on Ubuntu and Windows, and the other 27 usage sharing tests passed, with one skipped as before.
ShareUsageElement_BackOff_PausesThenDrainsQueueShareUsageElement_BackOff_CloseWhilePausedDoesNotWaitOrSendThe two tests that set the delays,
ShareUsageElement_BackOff_DelayGrowsToMaximumandShareUsageElement_BackOff_FullQueueDropsNewEvidence, need the new constructor, so they were added with the change, as were ShareUsageBackOffTests.java, which checks the rules with set times, and the setter checks.With the change (run 42348489883) all 39 usage sharing tests pass on Ubuntu and Windows, with the same one skipped.
The full pull request build, common-ci's
nightly-pull-request.ymlrun as a dry run from a temporary branch, built 033155f, this branch's head, merged withrc(run 42350514885). All 15 build and test jobs passed on the first attempt, on Ubuntu x64 with Java 8, 11, 17 and 21, Ubuntu arm64 with Java 17, Windows with Java 8, 11, 17 and 21, and macOS arm64 and x64 with Java 11, 17 and 21.Found, not changed
ShareUsageBuilderBaseTestuses JUnit 4 annotations, and its tests did not run in the runs above, which ran every other usage sharing test class. Whether the build runs JUnit 4 tests at all has not been checked.Related