Skip to content

Implement rate limit throttling #75

@mdavis-xyz

Description

@mdavis-xyz

As I user, I expect the client to handle rate limits for me. i.e. if we're throttled, or about to be throttled, the client should sleep and retry.

Looking at the code, that's not what it currently does.


    def _check_rate_limit(self, time_diff_noauth, time_diff_auth, func):
        """
        Impose client-side rate limit.

        :param int time_diff_noauth: the minimum time between two requests in seconds if not using authentication.
        :param int time_diff_auth: the minimum time between two requests in seconds if using authentication.
        :param callable func: the API function to evaluate.
        :rtype: bool
        """
        if len(self._auth) < 2:
            return abs(time.time() - self._last_requests[func]) >= time_diff_noauth
        else:
            return abs(time.time() - self._last_requests[func]) >= time_diff_auth

and then:

    if not self._check_rate_limit(0, 1, self.get_my_states):
            logger.debug("Blocking request due to rate limit.")
            return None

I'm confused because this is not blocking. time.sleep() is blocking. Returning None is a highly unexpected behavior. What's the motivation for this? How are users supposed to handle this? Why are users supposed to handle this?

I propose:

    def _check_rate_limit(self, time_diff_noauth, time_diff_auth, func):
        """
        Impose client-side rate limit.

        :param int time_diff_noauth: the minimum time between two requests in seconds if not using authentication.
        :param int time_diff_auth: the minimum time between two requests in seconds if using authentication.
        :param callable func: the API function to evaluate.
        :rtype: bool
        """
        time_since_last = time.time() - self._last_requests[func]
        time_between_requests = time_diff_noauth if self._anonymous else time_diff_auth
        return max(time_between_requests - time_since_last, 0)
            

and:

throttle_time = self._check_rate_limit(10, 5, self.get_states)
if throttle_time > 0:
    logger.debug("Blocking request due to rate limit.")
    time.sleep(throttle_time)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions