diff options
| author | Rapptz <[email protected]> | 2017-02-15 19:07:47 -0500 |
|---|---|---|
| committer | Rapptz <[email protected]> | 2017-02-15 19:10:32 -0500 |
| commit | 58fa5fdc9acc34661a5ceccd86a5aa23a2b2f897 (patch) | |
| tree | 9aeb5b18809ffe8e956ed0fdf89e9d44e0c297a4 /discord/backoff.py | |
| parent | Don't RESUME when given sharding related close codes. (diff) | |
| download | discord.py-58fa5fdc9acc34661a5ceccd86a5aa23a2b2f897.tar.xz discord.py-58fa5fdc9acc34661a5ceccd86a5aa23a2b2f897.zip | |
Add experimental reconnection logic.
Diffstat (limited to 'discord/backoff.py')
| -rw-r--r-- | discord/backoff.py | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/discord/backoff.py b/discord/backoff.py new file mode 100644 index 00000000..bfe87b17 --- /dev/null +++ b/discord/backoff.py @@ -0,0 +1,85 @@ +# -*- coding: utf-8 -*- + +""" +The MIT License (MIT) + +Copyright (c) 2015-2017 Rapptz + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +""" + +import time +import random + +class ExponentialBackoff: + """An implementation of the exponential backoff algorithm + + Provides a convenient interface to implement an exponential backoff + for reconnecting or retrying transmissions in a distributed network. + + Once instantiated, the delay method will return the next interval to + wait for when retrying a connection or transmission. The maximum + delay increases exponentially with each retry up to a maximum of + 2^10 * base, and is reset if no more attempts are needed in a period + of 2^11 * base seconds. + + Parameters + ---------- + base: int + The base delay in seconds. The first retry-delay will be up to + this many seconds. + integral: bool + Set to True if whole periods of base is desirable, otherwise any + number in between may be returned. + """ + + def __init__(self, base=1, *, integral=False): + self._base = base + + self._exp = 0 + self._max = 10 + self._reset_time = base * 2 ** 11 + self._last_invocation = time.monotonic() + + # Use our own random instance to avoid messing with global one + rand = random.Random() + rand.seed() + + self._randfunc = rand.rand_range if integral else rand.uniform + + def delay(self): + """Compute the next delay + + Returns the next delay to wait according to the exponential + backoff algorithm. This is a value between 0 and base * 2^exp + where exponent starts off at 1 and is incremented at every + invocation of this method up to a maximum of 10. + + If a period of more than base * 2^11 has passed since the last + retry, the exponent is reset to 1. + """ + invocation = time.monotonic() + interval = invocation - self._last_invocation + self._last_invocation = invocation + + if interval > self._reset_time: + self._exp = 0 + + self._exp = min(self._exp + 1, self._max) + return self._randfunc(0, self._base * 2 ** self._exp) |