-
Couldn't load subscription status.
- Fork 1.4k
Add burst control to the existing Stream throttling combinators #1205
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
Conversation
|
@vasilmkd would it be possible to add burst as a default parameter on all the variants instead of a separate variant? |
|
The current implementation of the token bucket algorithm should now closely match the one described here: Token Bucket Wikipedia. |
| _ <- assertPositive(units).toManaged_ | ||
| current <- clock.currentTime(TimeUnit.NANOSECONDS).toManaged_ | ||
| bucket <- Ref.make((units, current)).toManaged_ | ||
| def checkTokens(sum: Long, max: Long): Long = if (sum < 0) max else math.min(sum, max) |
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.
Question: when sum < 0, should we subtract it from max? Otherwise when the bucket is depleted, there is always constant amount of max available in addition.
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.
You're right, I'll fix this.
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.
Actually, on second thought, the checkTokens function is called to guard against overflow. sum is computed exclusively from positive values, whose total value might exceed Long.MaxValue (which is what the if statement checks). If that happens, we want max tokens to be available, otherwise, if we are dealing with positive values (sum and max), just get the minimum value.
|
Also, I believe the default value for |
|
There are 2 ways to do this.
Interested to hear your thoughts on this. I'm happy to implement any of them. |
|
Idea. I can implement the second proposal from the last comment by wrapping the existing functions in That way we get the semantics of the second proposal with the "overflow safety" of the first one, and as a bonus, it requires minimal code changes. |
|
Hi @vasilmkd, could you explain why you say that I infer from what you say that the
WDYT? |
|
Yes, |
|
Oh that's true! Thank you for pointing that out. So I'll read your comments about the burst implementation again and reply. |
|
No problem. I was reading through the source code of akka-streams and the implementation of this is quite similar. It seems that they don't care about clock precision as much though. |
|
@vasilmkd The current implementation (and the This is good to merge by me, unless there's anything else you wanted to address. |
|
Happy with how everything works now. |
|
Awesome work, thank you @vasilmkd! |
…1205) * Change managed sink environment and error type * Add burst control to throttleEnforceM * Test ZSink.throttleEnforce with no burst * Add burst control to ZSink.throttleShape * Change the burst control API and default arguments for enforcing throttle * Change burst control API and default argument value for shape throttle * Tweak ZSink.throttleShape test to show lack of burst * Add ZSink.throttleShape test with burst
Also fix potential token overflow.
Should be enough to close #1027.