saloonphp / rate-limit-plugin

🤠 Handle rate limits beautifully in your Saloon API integrations or SDKs
https://docs.saloon.dev
MIT License
15 stars 0 forks source link

Limit by request? #9

Closed aarondfrancis closed 1 year ago

aarondfrancis commented 1 year ago

Is there any way to limit based on the Request? Specifically I'd like to set the name of the limiter based on a device ID of the request. I'm using Govee's API to turn lights on and off and the rate limits are device-specific. I tried just letting it react to 429s but that didn't work very well.

CleanShot 2023-10-09 at 20 55 48@2x

Lemme know what you think!

Sammyjo20 commented 1 year ago

Hey @aarondfrancis!

So at this point in time - the Limit class is not request-aware, but I've already started looking to see if I can make it nice for the developer to define a custom name - maybe in the form of a closure like this? Let me know if you have any other ideas.

protected function resolveLimits(): array
{
    return [
        Limit::allow(10)->everyMinute()->name(function (PendingRequest $pendingRequest) {
             return $pendingRequest->getRequest()->getDeviceName();
        }),
    ];
}

I tried making a proof of concept but I haven't cracked it yet - in the meantime, while it's not the most seamless approach, you can achieve this by adding the HasRateLimits trait to your request too! Saloon will invoke both traits independently so you can have your limits on your connector, and your limits on your requests! 🤠

You could make your own trait that implements the resolveRateLimitStore method so you don't have to define it in both your connector and request.

class UpdateLightRequest extends Request
{
    use HasRateLimits;

    protected function resolveLimits(): array
    {
        return [
            Limit::allow(10)->everyMinute()->name('device-light-limit-' . $this->deviceId),
        ];
    }

    protected function resolveRateLimitStore(): RateLimitStore
    {
        $redis = new Redis;
        $redis->connect('127.0.0.1');

        return new RedisStore($redis);
    }
}

Let me know your thoughts.

aarondfrancis commented 1 year ago

Oh I had no idea you could add it to a request! That's definitely what I'll do. Thank you!