Development of an internal social media platform with personalised dashboards for students
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

limits.py 2.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. """
  2. kombu.utils.limits
  3. ==================
  4. Token bucket implementation for rate limiting.
  5. """
  6. from __future__ import absolute_import
  7. from kombu.five import monotonic
  8. __all__ = ['TokenBucket']
  9. class TokenBucket(object):
  10. """Token Bucket Algorithm.
  11. See http://en.wikipedia.org/wiki/Token_Bucket
  12. Most of this code was stolen from an entry in the ASPN Python Cookbook:
  13. http://code.activestate.com/recipes/511490/
  14. .. admonition:: Thread safety
  15. This implementation is not thread safe. Access to a `TokenBucket`
  16. instance should occur within the critical section of any multithreaded
  17. code.
  18. """
  19. #: The rate in tokens/second that the bucket will be refilled.
  20. fill_rate = None
  21. #: Maximum number of tokens in the bucket.
  22. capacity = 1
  23. #: Timestamp of the last time a token was taken out of the bucket.
  24. timestamp = None
  25. def __init__(self, fill_rate, capacity=1):
  26. self.capacity = float(capacity)
  27. self._tokens = capacity
  28. self.fill_rate = float(fill_rate)
  29. self.timestamp = monotonic()
  30. def can_consume(self, tokens=1):
  31. """Return :const:`True` if the number of tokens can be consumed
  32. from the bucket. If they can be consumed, a call will also consume the
  33. requested number of tokens from the bucket. Calls will only consume
  34. `tokens` (the number requested) or zero tokens -- it will never consume
  35. a partial number of tokens."""
  36. if tokens <= self._get_tokens():
  37. self._tokens -= tokens
  38. return True
  39. return False
  40. def expected_time(self, tokens=1):
  41. """Return the time (in seconds) when a new token is expected
  42. to be available. This will not consume any tokens from the bucket."""
  43. _tokens = self._get_tokens()
  44. tokens = max(tokens, _tokens)
  45. return (tokens - _tokens) / self.fill_rate
  46. def _get_tokens(self):
  47. if self._tokens < self.capacity:
  48. now = monotonic()
  49. delta = self.fill_rate * (now - self.timestamp)
  50. self._tokens = min(self.capacity, self._tokens + delta)
  51. self.timestamp = now
  52. return self._tokens