Skip to content

Commit

Permalink
Add test() method for all ratelimit strategies
Browse files Browse the repository at this point in the history
  • Loading branch information
alisaifee committed May 12, 2015
1 parent 7dd4ff9 commit 8155f71
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 2 deletions.
6 changes: 6 additions & 0 deletions doc/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ Test the limits::
time.sleep(1)
assert True == moving_window.hit(one_per_second, "test_namespace", "foo")

Check specific limits without hitting them::

assert True == moving_window.hit(one_per_second, "test_namespace", "foo")
while not moving_window.test(one_per_second, "test_namespace", "foo"):
time.sleep(0.01)
assert True == moving_window.hit(one_per_second, "test_namespace", "foo")

Projects using *limits*
-------------------------
Expand Down
46 changes: 45 additions & 1 deletion limits/strategies.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,19 @@ def hit(self, item, *identifiers):
"""
raise NotImplementedError

@abstractmethod
def test(self, item, *identifiers):
"""
checks the rate limit and returns True if it is not
currently exceeded.
:param item: a :class:`RateLimitItem` instance
:param identifiers: variable list of strings to uniquely identify the
limit
:return: True/False
"""
raise NotImplementedError

@abstractmethod
def get_window_stats(self, item, *identifiers):
"""
Expand Down Expand Up @@ -58,7 +71,26 @@ def hit(self, item, *identifiers):
limit
:return: True/False
"""
return self.storage().acquire_entry(item.key_for(*identifiers), item.amount, item.get_expiry())
return self.storage().acquire_entry(
item.key_for(*identifiers), item.amount,
item.get_expiry()
)

def test(self, item, *identifiers):
"""
checks the rate limit and returns True if it is not
currently exceeded.
:param item: a :class:`RateLimitItem` instance
:param identifiers: variable list of strings to uniquely identify the
limit
:return: True/False
"""
return self.storage().acquire_entry(
item.key_for(*identifiers),
item.amount, item.get_expiry(),
no_add=True
)

def get_window_stats(self, item, *identifiers):
"""
Expand Down Expand Up @@ -94,6 +126,18 @@ def hit(self, item, *identifiers):
<= item.amount
)

def test(self, item, *identifiers):
"""
checks the rate limit and returns True if it is not
currently exceeded.
:param item: a :class:`RateLimitItem` instance
:param identifiers: variable list of strings to uniquely identify the
limit
:return: True/False
"""
return self.storage().get(item.key_for(*identifiers)) <= item.amount

def get_window_stats(self, item, *identifiers):
"""
returns the number of requests remaining and reset of this limit.
Expand Down
35 changes: 34 additions & 1 deletion tests/test_strategy.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,39 @@ def test_moving_window_redis(self):
self.assertTrue(limiter.hit(limit))
self.assertEqual(limiter.get_window_stats(limit)[1], 0)

def test_moving_window_memcached(self):
def xest_moving_window_memcached(self):
storage = MemcachedStorage('memcacheD://localhost:11211')
self.assertRaises(NotImplementedError, MovingWindowRateLimiter, storage)



def test_test_fixed_window(self):
stores = [
MemoryStorage(),
RedisStorage("redis:/localhost:6379"),
MemcachedStorage("memcached://localhost:11211")
]
limit = RateLimitItemPerSecond(1,1)
for store in stores:
limiter = FixedWindowRateLimiter(store)
self.assertTrue(limiter.hit(limit), store)
self.assertFalse(limiter.hit(limit), store)
self.assertFalse(limiter.test(limit), store)
time.sleep(1)
self.assertTrue(limiter.test(limit), store)
self.assertTrue(limiter.hit(limit), store)

def test_test_moving_window(self):
stores = [
MemoryStorage(),
RedisStorage("redis:/localhost:6379"),
]
limit = RateLimitItemPerSecond(1,1)
for store in stores:
limiter = MovingWindowRateLimiter(store)
self.assertTrue(limiter.hit(limit), store)
self.assertFalse(limiter.hit(limit), store)
self.assertFalse(limiter.test(limit), store)
time.sleep(1)
self.assertTrue(limiter.test(limit), store)
self.assertTrue(limiter.hit(limit), store)

0 comments on commit 8155f71

Please sign in to comment.