Use sentinels for mode instead of strings.
This commit is contained in:
parent
0be376551f
commit
7fddee51df
1 changed files with 19 additions and 8 deletions
|
@ -1,6 +1,11 @@
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
from voussoirkit import sentinel
|
||||||
|
|
||||||
|
REJECT = sentinel.Sentinel('reject mode')
|
||||||
|
SLEEP = sentinel.Sentinel('sleep mode')
|
||||||
|
|
||||||
class Ratelimiter:
|
class Ratelimiter:
|
||||||
'''
|
'''
|
||||||
The Ratelimiter class is used to limit how often you perform some other
|
The Ratelimiter class is used to limit how often you perform some other
|
||||||
|
@ -19,7 +24,7 @@ class Ratelimiter:
|
||||||
self,
|
self,
|
||||||
allowance,
|
allowance,
|
||||||
*,
|
*,
|
||||||
mode='sleep',
|
mode=SLEEP,
|
||||||
operation_cost=1,
|
operation_cost=1,
|
||||||
period=1,
|
period=1,
|
||||||
starting_balance=None,
|
starting_balance=None,
|
||||||
|
@ -29,11 +34,11 @@ class Ratelimiter:
|
||||||
Our spending balance per `period` seconds.
|
Our spending balance per `period` seconds.
|
||||||
|
|
||||||
mode:
|
mode:
|
||||||
'sleep':
|
SLEEP:
|
||||||
If we do not have the balance for an operation, sleep until we
|
If we do not have the balance for an operation, sleep until we
|
||||||
do. Then return True every time.
|
do. Then return True every time.
|
||||||
|
|
||||||
'reject':
|
REJECT:
|
||||||
If we do not have the balance for an operation, do nothing and
|
If we do not have the balance for an operation, do nothing and
|
||||||
return False. Otherwise subtract the cost and return True.
|
return False. Otherwise subtract the cost and return True.
|
||||||
|
|
||||||
|
@ -65,19 +70,25 @@ class Ratelimiter:
|
||||||
|
|
||||||
return x
|
return x
|
||||||
|
|
||||||
if mode not in ('sleep', 'reject'):
|
|
||||||
raise ValueError(f'Invalid mode {repr(mode)}.')
|
|
||||||
|
|
||||||
self.allowance = positive(allowance, 'allowance')
|
self.allowance = positive(allowance, 'allowance')
|
||||||
self.period = positive(period, 'period')
|
self.period = positive(period, 'period')
|
||||||
self.operation_cost = positive(operation_cost, 'operation_cost')
|
self.operation_cost = positive(operation_cost, 'operation_cost')
|
||||||
self.mode = mode
|
|
||||||
|
|
||||||
if starting_balance is None:
|
if starting_balance is None:
|
||||||
self.balance = operation_cost
|
self.balance = operation_cost
|
||||||
else:
|
else:
|
||||||
self.balance = positive(starting_balance, 'starting_balance')
|
self.balance = positive(starting_balance, 'starting_balance')
|
||||||
|
|
||||||
|
mode = {
|
||||||
|
'reject': REJECT,
|
||||||
|
'sleep': SLEEP,
|
||||||
|
}.get(mode, mode)
|
||||||
|
|
||||||
|
if mode is not SLEEP and mode is not REJECT:
|
||||||
|
raise ValueError(f'mode should be SLEEP or REJECT, not {repr(mode)}.')
|
||||||
|
|
||||||
|
self.mode = mode
|
||||||
|
|
||||||
self.lock = threading.Lock()
|
self.lock = threading.Lock()
|
||||||
self.last_operation = time.monotonic()
|
self.last_operation = time.monotonic()
|
||||||
|
|
||||||
|
@ -95,7 +106,7 @@ class Ratelimiter:
|
||||||
self.balance = min(self.balance, self.allowance)
|
self.balance = min(self.balance, self.allowance)
|
||||||
self.last_operation = now
|
self.last_operation = now
|
||||||
|
|
||||||
if self.mode == 'reject' and self.balance < cost:
|
if self.mode is REJECT and self.balance < cost:
|
||||||
success = False
|
success = False
|
||||||
sleep_needed = 0
|
sleep_needed = 0
|
||||||
return (success, sleep_needed)
|
return (success, sleep_needed)
|
||||||
|
|
Loading…
Reference in a new issue