Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Too Many Requests Issue On Pagination #55

Open
mehmet-gimo opened this issue Nov 12, 2023 · 1 comment
Open

Too Many Requests Issue On Pagination #55

mehmet-gimo opened this issue Nov 12, 2023 · 1 comment

Comments

@mehmet-gimo
Copy link

#The REST Admin API supports a limit of 40 requests per app per store per minute. This allotment replenishes at a rate of 2 requests per second. The rate limit is increased by a factor of 10 for Shopify Plus stores.

Is it possible to add 1 second sleep() between 2 requests

Many thanks

@BrandonKerr
Copy link
Contributor

I created a trait to handle this and then manually call it AFTER each Shopify request. It would be ideal to do it BEFORE making a request, but the structure of MakesHttpRequests class and its lastResponse variable make it impossible with the current code base.

I took the approach of adding configuration settings for the threshold and sleep time, so that you can configure it differently depending on the environment. Here it is, in case it can help you out until there's an official solution:

trait HandlesShopifyRateLimit
{
    protected Shopify $shopify;

    protected int $rateLimitThreshold;
    protected int $rateLimitSleepTime;

    /**
     * WARNING: Do NOT call this before the first `$this->shopify->___` call, because there will not yet be
     * an existing last response.
     *
     * Check the API call rate limit based on the last response, to see if we're approaching our limit, and
     * to sleep if so, to recover our calls.
     * This needs to be called before any `$this->shopify->___` calls that you want to protect.
     *
     * @return void
     */
    protected function handleRateLimit(): void
    {

        $limit = $this->shopify->getLastResponse()?->headers()["X-Shopify-Shop-Api-Call-Limit"][0] ?? null;
        if (is_null($limit)) {
            return;
        }

        // set up the configurable values once, sort of hacking around a constructor
        if (!isset($this->rateLimitThreshold)) {
            $this->rateLimitThreshold = $this->getRateLimitThreshold();
        }
        if (!isset($this->rateLimitSleepTime)) {
            $this->rateLimitSleepTime = $this->getRateLimitSleepTime();
        }

        $current = intval(Str::before($limit, "/"));
        $max = intval(Str::after($limit, "/"));

        if ($max - $current <= $this->rateLimitThreshold) {
            sleep($this->rateLimitSleepTime);
        }
    }

    /**
     * Get the threshold of what we'll allow the rate limit to get within
     *
     * @return int
     */
    protected function getRateLimitThreshold(): int
    {
        return config('shopify.rate_limit.threshold');
    }

    /**
     * Get the number of seconds that we'll sleep for when we hit the rate limit threshold
     *
     * @return int
     */
    protected function getRateLimitSleepTime(): int
    {
        return config('shopify.rate_limit.sleep_time');
    }
}

Then I can just make the call like this:

$shopifyProduct = $this->shopify->getProduct($shopifyProductId);
$this->handleRateLimit();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants