atymic/twitter

Access response headers to get x-rate-limit header values

ejunker opened this issue · 1 comments

I was using the 2.x version of this library and I have a situation where I am making lots of requests to getUserTimeline() and I want to know when I am close to hitting the rate limit so I can sleep and wait for the rate limit to reset. I want to sleep before I hit the rate limit so that I can leave some api calls available for other services.

In the 2.x version I was able to do something like this:

foreach ($screenNames as $screenName) {
    $timeline = $twitter->getUserTimeline(['screen_name' => $screenName]);
    
    // do something with the timeline
    
    // check if close to rate limit
    $headers = $twitter->response['headers'];
    $rateLimitRemaining = Arr::get($headers, 'x-rate-limit-remaining', 0);
    if ($rateLimitRemaining < 50) {
        $timestamp = Arr::get($headers, 'x-rate-limit-reset', 0);
        $secondsUntilReset = max($timestamp - time(), 0);
        sleep($secondsUntilReset);
    }
}

This works because I am able to access the previous response and headers.

I am aware of getAppRateLimit() but it seems wasteful to make an extra API call given that each response includes the x-rate-limit-* headers. I could catch the RateLimitedException but at that point it is too late since I want to sleep before I hit the rate limit.

Would you be open to storing the last response like it did in the 2.x version? If so which object would be the best place to store it? I wonder if this could cause a race condition, if you make a request and then before you can access the previous response another request is made so you are not getting the response that you intended.

Alternatively, after each request it may be possible to cache the rate limit values per resource in a format similar to the response from getAppRateLimit()

[
    "/statuses/user_timeline" => [
           "limit" => 900,
           "remaining" => 899,
           "reset" => 1621035809,
     ]
]

then you could get the rate limit values without having to make a separate API call using getAppRateLimit()

If that seems like overkill then I may resort to calling getAppRateLimit() after every X requests to see if I am close to hitting the rate limit.

Another idea would be to have a config value and when the x-rate-limit-remaining header value was less than the configured value it would throw a CloseToRateLimitException

Would you be open to storing the last response like it did in the 2.x version? If so which object would be the best place to store it? I wonder if this could cause a race condition, if you make a request and then before you can access the previous response another request is made so you are not getting the response that you intended.

Think this is a great idea feel free to PR it.
Would be open to keeping track of rate limit data as well :)