コード例 #1
0
ファイル: __init__.py プロジェクト: dstufft/warehouse
class RateLimiter:
    def __init__(self, storage, limit, *, identifiers=None, metrics):
        if identifiers is None:
            identifiers = []

        self._window = MovingWindowRateLimiter(storage)
        self._limits = parse_many(limit)
        self._identifiers = identifiers
        self._metrics = metrics

    def _get_identifiers(self, identifiers):
        return [str(i) for i in list(self._identifiers) + list(identifiers)]

    @_return_on_exception(True, redis.RedisError)
    def test(self, *identifiers):
        return all(
            [
                self._window.test(limit, *self._get_identifiers(identifiers))
                for limit in self._limits
            ]
        )

    @_return_on_exception(True, redis.RedisError)
    def hit(self, *identifiers):
        return all(
            [
                self._window.hit(limit, *self._get_identifiers(identifiers))
                for limit in self._limits
            ]
        )

    @_return_on_exception(None, redis.RedisError)
    def resets_in(self, *identifiers):
        resets = []
        for limit in self._limits:
            resets_at, remaining = self._window.get_window_stats(
                limit, *self._get_identifiers(identifiers)
            )

            # If this limit has any remaining limits left, then we will skip it
            # since it doesn't need reset.
            if remaining > 0:
                continue

            current = datetime.now(tz=timezone.utc)
            reset = datetime.fromtimestamp(resets_at, tz=timezone.utc)

            # If our current datetime is either greater than or equal to when
            # the limit resets, then we will skipp it since it has either
            # already reset, or it is resetting now.
            if current >= reset:
                continue

            # Add a timedelta that represents how long until this limit resets.
            resets.append(reset - current)

        # If we have any resets, then we'll go through and find whichever one
        # is going to reset soonest and use that as our hint for when this
        # limit might be available again.
        return first(sorted(resets))
コード例 #2
0
    def __init__(self, storage, limit, identifiers=None):
        if identifiers is None:
            identifiers = []

        self._window = MovingWindowRateLimiter(storage)
        self._limits = parse_many(limit)
        self._identifiers = identifiers
コード例 #3
0
class RateLimiter:

    def __init__(self, storage, limit, identifiers=None):
        if identifiers is None:
            identifiers = []

        self._window = MovingWindowRateLimiter(storage)
        self._limits = parse_many(limit)
        self._identifiers = identifiers

    def _get_identifiers(self, identifiers):
        return [str(i) for i in list(self._identifiers) + list(identifiers)]

    def test(self, *identifiers):
        return all(
            [
                self._window.test(limit, *self._get_identifiers(identifiers))
                for limit in self._limits
            ]
        )

    def hit(self, *identifiers):
        return all(
            [
                self._window.hit(limit, *self._get_identifiers(identifiers))
                for limit in self._limits
            ]
        )

    def resets_in(self, *identifiers):
        resets = []
        for limit in self._limits:
            resets_at, remaining = self._window.get_window_stats(
                limit, *self._get_identifiers(identifiers)
            )

            # If this limit has any remaining limits left, then we will skip it
            # since it doesn't need reset.
            if remaining > 0:
                continue

            current = datetime.now(tz=timezone.utc)
            reset = datetime.fromtimestamp(resets_at, tz=timezone.utc)

            # If our current datetime is either greater than or equal to when
            # the limit resets, then we will skipp it since it has either
            # already reset, or it is resetting now.
            if current >= reset:
                continue

            # Add a timedelta that represents how long until this limit resets.
            resets.append(reset - current)

        # If we have any resets, then we'll go through and find whichever one
        # is going to reset soonest and use that as our hint for when this
        # limit might be available again.
        return first(sorted(resets))
コード例 #4
0
ファイル: __init__.py プロジェクト: yangyuanhua/warehouse
    def __init__(self, storage, limit, *, identifiers=None, metrics):
        if identifiers is None:
            identifiers = []

        self._storage = storage
        self._window = MovingWindowRateLimiter(storage)
        self._limits = parse_many(limit)
        self._identifiers = identifiers
        self._metrics = metrics
コード例 #5
0
ファイル: test_storage.py プロジェクト: protream/limits
 def test_in_memory_expiry_moving_window(self):
     with hiro.Timeline().freeze() as timeline:
         storage = MemoryStorage()
         limiter = MovingWindowRateLimiter(storage)
         per_min = RateLimitItemPerMinute(10)
         per_sec = RateLimitItemPerSecond(1)
         for i in range(0, 2):
             for i in range(0, 10):
                 self.assertTrue(limiter.hit(per_min))
             timeline.forward(60)
             self.assertTrue(limiter.hit(per_sec))
             time.sleep(1)
             self.assertEqual([], storage.events[per_min.key_for()])
コード例 #6
0
ファイル: test_storage.py プロジェクト: thestick613/limits
 def test_in_memory_expiry_moving_window(self):
     with hiro.Timeline().freeze() as timeline:
         storage = MemoryStorage()
         limiter = MovingWindowRateLimiter(storage)
         per_min = RateLimitItemPerMinute(10)
         per_sec = RateLimitItemPerSecond(1)
         for i in range(0,2):
             for i in range(0,10):
                 self.assertTrue(limiter.hit(per_min))
             timeline.forward(60)
             self.assertTrue(limiter.hit(per_sec))
             time.sleep(1)
             self.assertEqual([], storage.events[per_min.key_for()])
コード例 #7
0
ファイル: test_memory.py プロジェクト: mymedia2/python-limits
 def test_moving_window_clear(self):
     limiter = MovingWindowRateLimiter(self.storage)
     per_min = RateLimitItemPerMinute(1)
     limiter.hit(per_min)
     self.assertFalse(limiter.hit(per_min))
     limiter.clear(per_min)
     self.assertTrue(limiter.hit(per_min))
コード例 #8
0
 def test_redis_cluster_clear(self):
     storage = RedisClusterStorage("redis+cluster://localhost:7000")
     limiter = MovingWindowRateLimiter(storage)
     per_min = RateLimitItemPerMinute(1)
     limiter.hit(per_min)
     self.assertFalse(limiter.hit(per_min))
     limiter.clear(per_min)
     self.assertTrue(limiter.hit(per_min))
コード例 #9
0
ファイル: test_storage.py プロジェクト: RobertDeRose/limits
    def test_large_dataset_redis_sentinel_moving_window_expiry(self):
        storage = RedisSentinelStorage("redis+sentinel://localhost:26379",
                                       service_name="localhost-redis-sentinel")
        limiter = MovingWindowRateLimiter(storage)
        limit = RateLimitItemPerSecond(1000)
        keys_start = storage.sentinel.slave_for(
            "localhost-redis-sentinel").keys("%s/*" % limit.namespace)
        # 100 routes
        fake_routes = [uuid4().hex for _ in range(0, 100)]
        # go as fast as possible in 2 seconds.
        start = time.time()

        def smack(e):
            while not e.is_set():
                self.assertTrue(limiter.hit(limit, random.choice(fake_routes)))

        events = [threading.Event() for _ in range(0, 100)]
        threads = [threading.Thread(target=smack, args=(e, )) for e in events]
        [k.start() for k in threads]
        while time.time() - start < 2:
            time.sleep(0.1)
        [k.set() for k in events]
        time.sleep(2)
        self.assertTrue(
            storage.sentinel.slave_for("localhost-redis-sentinel").keys(
                "%s/*" % limit.namespace) == [])
コード例 #10
0
ファイル: __init__.py プロジェクト: alex/warehouse
    def __init__(self, storage, limit, identifiers=None):
        if identifiers is None:
            identifiers = []

        self._window = MovingWindowRateLimiter(storage)
        self._limits = parse_many(limit)
        self._identifiers = identifiers
コード例 #11
0
 def test_test_moving_window(self):
     with hiro.Timeline().freeze():
         store = MemoryStorage()
         limit = RateLimitItemPerSecond(2, 1)
         limiter = MovingWindowRateLimiter(store)
         self.assertTrue(limiter.hit(limit), store)
         self.assertTrue(limiter.test(limit), store)
         self.assertTrue(limiter.hit(limit), store)
         self.assertFalse(limiter.test(limit), store)
         self.assertFalse(limiter.hit(limit), store)
コード例 #12
0
    def test_memory_storage_moving_window(self):
        storage = MemoryStorage()
        limiter = MovingWindowRateLimiter(storage)
        per_second = RateLimitItemPerSecond(100)

        [limiter.hit(per_second, uuid4().hex) for _ in range(100)]

        key = uuid4().hex
        hits = []

        def hit():
            if limiter.hit(per_second, key):
                hits.append(None)

        start = time.time()

        threads = [threading.Thread(target=hit) for _ in range(1000)]
        [t.start() for t in threads]
        [t.join() for t in threads]

        self.assertTrue(time.time() - start < 1)
        self.assertEqual(len(hits), 100)
コード例 #13
0
 def test_moving_window_in_memory(self):
     storage = MemoryStorage()
     limiter = MovingWindowRateLimiter(storage)
     with hiro.Timeline().freeze() as timeline:
         limit = RateLimitItemPerMinute(10)
         for i in range(0, 5):
             self.assertTrue(limiter.hit(limit))
             self.assertTrue(limiter.hit(limit))
             self.assertEqual(
                 limiter.get_window_stats(limit)[1], 10 - ((i + 1) * 2))
             timeline.forward(10)
         self.assertEqual(limiter.get_window_stats(limit)[1], 0)
         self.assertFalse(limiter.hit(limit))
         timeline.forward(20)
         self.assertEqual(limiter.get_window_stats(limit)[1], 2)
         self.assertEqual(
             limiter.get_window_stats(limit)[0], int(time.time() + 30))
         timeline.forward(31)
         self.assertEqual(limiter.get_window_stats(limit)[1], 10)
コード例 #14
0
 def test_moving_window_redis(self):
     storage = RedisStorage("redis://localhost:6379")
     limiter = MovingWindowRateLimiter(storage)
     limit = RateLimitItemPerSecond(10, 2)
     for i in range(0, 10):
         self.assertTrue(limiter.hit(limit))
         self.assertEqual(limiter.get_window_stats(limit)[1], 10 - (i + 1))
         time.sleep(2 * 0.095)
     self.assertFalse(limiter.hit(limit))
     time.sleep(0.4)
     self.assertTrue(limiter.hit(limit))
     self.assertTrue(limiter.hit(limit))
     self.assertEqual(limiter.get_window_stats(limit)[1], 0)
コード例 #15
0
ファイル: test_strategy.py プロジェクト: GetStream/limits
 def test_test_moving_window(self):
     with hiro.Timeline().freeze() as timeline:
         store = MemoryStorage()
         limit = RateLimitItemPerSecond(2,1)
         limiter = MovingWindowRateLimiter(store)
         self.assertTrue(limiter.hit(limit), store)
         self.assertTrue(limiter.test(limit), store)
         self.assertTrue(limiter.hit(limit), store)
         self.assertFalse(limiter.test(limit), store)
         self.assertFalse(limiter.hit(limit), store)
コード例 #16
0
ファイル: test_strategy.py プロジェクト: GetStream/limits
 def test_moving_window_redis(self):
     storage = RedisStorage("redis://localhost:6379")
     limiter = MovingWindowRateLimiter(storage)
     limit = RateLimitItemPerSecond(10, 2)
     for i in range(0,10):
         self.assertTrue(limiter.hit(limit))
         self.assertEqual(limiter.get_window_stats(limit)[1], 10 - (i + 1))
         time.sleep(2*0.095)
     self.assertFalse(limiter.hit(limit))
     time.sleep(0.4)
     self.assertTrue(limiter.hit(limit))
     self.assertTrue(limiter.hit(limit))
     self.assertEqual(limiter.get_window_stats(limit)[1], 0)
コード例 #17
0
ファイル: test_storage.py プロジェクト: er0k/limits
 def test_moving_window_expiry(self):
     limiter = MovingWindowRateLimiter(self.storage)
     limit = RateLimitItemPerSecond(2)
     self.assertTrue(limiter.hit(limit))
     time.sleep(0.9)
     self.assertTrue(limiter.hit(limit))
     self.assertFalse(limiter.hit(limit))
     time.sleep(0.1)
     self.assertTrue(limiter.hit(limit))
     last = time.time()
     while time.time() - last <= 1:
         time.sleep(0.05)
     self.assertTrue(
         self.storage.storage.keys("%s/*" % limit.namespace) == [])
コード例 #18
0
ファイル: test_storage.py プロジェクト: YoApp/limits
    def test_pluggable_storage_moving_window(self):
        class MyStorage(Storage):
            STORAGE_SCHEME = "mystorage"
            def incr(self, key, expiry, elastic_expiry=False):
                return

            def get(self, key):
                return 0

            def get_expiry(self, key):
                return time.time()

            def acquire_entry(self, *a, **k):
                return True

            def get_moving_window(self, *a, **k):
                return (time.time(), 1)

        storage = storage_from_string("mystorage://")
        self.assertTrue(isinstance(storage, MyStorage))
        MovingWindowRateLimiter(storage)
コード例 #19
0
ファイル: test_strategy.py プロジェクト: GetStream/limits
 def test_moving_window_in_memory(self):
     storage = MemoryStorage()
     limiter = MovingWindowRateLimiter(storage)
     with hiro.Timeline().freeze() as timeline:
         limit = RateLimitItemPerMinute(10)
         for i in range(0,5):
             self.assertTrue(limiter.hit(limit))
             self.assertTrue(limiter.hit(limit))
             self.assertEqual(
                 limiter.get_window_stats(limit)[1],
                 10 - ((i + 1) * 2)
             )
             timeline.forward(10)
         self.assertEqual(limiter.get_window_stats(limit)[1], 0)
         self.assertFalse(limiter.hit(limit))
         timeline.forward(20)
         self.assertEqual(limiter.get_window_stats(limit)[1], 2)
         self.assertEqual(limiter.get_window_stats(limit)[0], int(time.time() + 30))
         timeline.forward(31)
         self.assertEqual(limiter.get_window_stats(limit)[1], 10)