mirror of
				https://github.com/avatao-content/baseimage-tutorial-framework
				synced 2025-11-04 06:22:55 +00:00 
			
		
		
		
	Fix RateLimiter family debounce stuff
This commit is contained in:
		@@ -21,31 +21,28 @@ class RateLimiter:
 | 
			
		||||
    so it is only acceptable for stuff running on a separate thread.
 | 
			
		||||
 | 
			
		||||
    If this is no good for you please refer to AsyncRateLimiter in this module,
 | 
			
		||||
    which is designed not to block and use the IOLoop it is being called from,
 | 
			
		||||
    or redefine the action argument of __init__ (which defaults to time.sleep).
 | 
			
		||||
    which is designed not to block and use the IOLoop it is being called from.
 | 
			
		||||
    """
 | 
			
		||||
    def __init__(self, rate_per_second, action=sleep):
 | 
			
		||||
    def __init__(self, rate_per_second):
 | 
			
		||||
        """
 | 
			
		||||
        :param rate_per_second: max frequency the decorated method should be
 | 
			
		||||
                                invoked with
 | 
			
		||||
        :param action: what to do when rate limiting. defaults to time.sleep,
 | 
			
		||||
                       receives the number of seconds until the next invocation
 | 
			
		||||
                       should occour as an argument
 | 
			
		||||
        """
 | 
			
		||||
        self.min_interval = 1 / float(rate_per_second)
 | 
			
		||||
        self.action = action
 | 
			
		||||
        self.fun = None
 | 
			
		||||
        self.last_call = time()
 | 
			
		||||
 | 
			
		||||
    def action(self, seconds_to_next_call):
 | 
			
		||||
        if seconds_to_next_call:
 | 
			
		||||
            sleep(seconds_to_next_call)
 | 
			
		||||
        self.fun()
 | 
			
		||||
 | 
			
		||||
    def __call__(self, fun):
 | 
			
		||||
        @wraps(fun)
 | 
			
		||||
        def wrapper(*args, **kwargs):
 | 
			
		||||
            self.fun = partial(fun, *args, **kwargs)
 | 
			
		||||
            limit_seconds = self._limit_rate()
 | 
			
		||||
            if limit_seconds:
 | 
			
		||||
                self.action(limit_seconds)
 | 
			
		||||
                return
 | 
			
		||||
            self.fun()
 | 
			
		||||
            self.action(limit_seconds)
 | 
			
		||||
        return wrapper
 | 
			
		||||
 | 
			
		||||
    def _limit_rate(self):
 | 
			
		||||
@@ -62,10 +59,11 @@ class AsyncRateLimiter(RateLimiter):
 | 
			
		||||
    """
 | 
			
		||||
    Decorator class for rate limiting, non-blocking.
 | 
			
		||||
 | 
			
		||||
    The semantics of the rate limiting are similar to that of RateLimiter,
 | 
			
		||||
    but this decorator never blocks, instead it adds an async callback version
 | 
			
		||||
    of the decorated function to the IOLoop to be executed after the rate limiting
 | 
			
		||||
    has expired.
 | 
			
		||||
    The semantics of the rate limiting:
 | 
			
		||||
        - unlike RateLimiter this decorator never blocks, instead it adds an async
 | 
			
		||||
          callback version of the decorated function to the IOLoop
 | 
			
		||||
          (to be executed after the rate limiting has expired).
 | 
			
		||||
        - the timing works similarly to RateLimiter
 | 
			
		||||
    """
 | 
			
		||||
    def __init__(self, rate_per_second, ioloop_factory):
 | 
			
		||||
        """
 | 
			
		||||
@@ -79,24 +77,24 @@ class AsyncRateLimiter(RateLimiter):
 | 
			
		||||
        self._last_callback = None
 | 
			
		||||
 | 
			
		||||
        self._make_action_thread_safe()
 | 
			
		||||
 | 
			
		||||
        super().__init__(
 | 
			
		||||
            rate_per_second=rate_per_second,
 | 
			
		||||
            action=self.async_action
 | 
			
		||||
        )
 | 
			
		||||
        super().__init__(rate_per_second=rate_per_second)
 | 
			
		||||
 | 
			
		||||
    def _make_action_thread_safe(self):
 | 
			
		||||
        self.async_action = partial(self.ioloop.add_callback, self.async_action)
 | 
			
		||||
        self.action = partial(self.ioloop.add_callback, self.action)
 | 
			
		||||
 | 
			
		||||
    @lazy_property
 | 
			
		||||
    def ioloop(self):
 | 
			
		||||
        return self._ioloop_factory()
 | 
			
		||||
 | 
			
		||||
    def async_action(self, seconds_to_next_call):
 | 
			
		||||
    def action(self, seconds_to_next_call):
 | 
			
		||||
        if self._last_callback:
 | 
			
		||||
            self.ioloop.remove_timeout(self._last_callback)
 | 
			
		||||
 | 
			
		||||
        self._last_callback = self.ioloop.call_later(
 | 
			
		||||
            seconds_to_next_call,
 | 
			
		||||
            self.fun
 | 
			
		||||
            self.fun_with_debounce
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def fun_with_debounce(self):
 | 
			
		||||
        self.last_call = time()
 | 
			
		||||
        self.fun()
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user