Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Queuing Guzzle Requests With Limits

I'm working on a Laravel application, using Guzzle 6. A lot of functionality relies on an API, of which I've created a wrapper for.

My wrapper's a single class, that creates the Guzzle client in the __construct(), and has a variety of public functions which return responses from Guzzle requests.

The API I'm using has a limit of 40 requests every 10 seconds. I am caching things, so it would be very rare to hit this limit, but I'd like to know that my application wouldn't just die if it did!

Some notes about my app:

  • API calls are only made if the same call hasn't been made in the past 6 hours. If it has, the call is never made and the response is served directly from my redis cache.
  • In most cases, API calls are made via user actions. The application would never get close to hitting these limits itself.
  • In most cases, I already have the required data to show the requested pages to users. An API call may be done in the background to see if anything needs to be updated on my end, but if I already have the data, and the API request failed, this wouldn't render the page useless.
  • The app is live, https://likethis.tv if you'd like to look. I'm using TMDb API.

So, my question is, how should I make sure I do not hit this limit? A few ideas of mine are the following:

  • Use the Laravel queuing system to place the Guzzle requests into a queue, and only process them if we still have requests left. If not, wait until the 10 second cooldown has passed...
  • Use a HandlerStack for Guzzle directly. Not sure if this is possible, but I've used the HandlerStack for caching responses before.

I'm trying to not to provoke too opinionated responses, but I'm sure there's probably a better and/or easier way than the above, or if they are good ideas, any pointers or recommendations would be great.

Thanks in advance.

like image 729
Daniel Dewhurst Avatar asked May 21 '17 01:05

Daniel Dewhurst


2 Answers

  1. Wrap your API calls with Jobs and push them to separate queue:

    ApiJob::dispatch()->onQueue('api');
    
  2. Use mxl/laravel-queue-rate-limit package (I'm the author) to rate limit api queue. Add this to config/queue.php:

    'rateLimit' => [
        'api' => [
            'allows' => 40,
            'every' => 10
        ]
    ]
    
  3. Run queue worker:

    $ php artisan queue:work --queue api
    

See also this answer.

like image 147
mixel Avatar answered Oct 01 '22 09:10

mixel


There's not enough information to really dig deep into this, but to get you started, good APIs typically return a 429 response code when you're exceeding their throttled limit.

You could use $res->getStatusCode() from guzzle to check for this and flash a message back to the user if they're making too many requests too quickly.

Can you give some more information about what your app is doing? Are you making requests in a foreach loop? Is the view dependent on data from this API?

like image 24
Kyle Avatar answered Oct 01 '22 08:10

Kyle