meteor-shopify
meteor-shopify copied to clipboard
Rate limiting
In terms of this package, is the rate-limiting global or per-instance? From the way it is described, it sounds like I am expected to pass the backoff rate to the instance.
In terms of Shopify itself, is the rate limit per APP ID + ACCESS TOKEN or per APP ID?
I'm having a problem where some of my users have these apps that update products in bulk, each product that is updated fires an individual webhook request, and the webhook fires a function to get the new product details and update them on our servers. Since the rate-limiting does not appear to be globally aware it throws an error and crashes server.
Should I instead be instantiating api
globally on the server and then somehow passing in the current shop
and keyset
parameters dynamically in each Method function? I was under the impression that I needed to supply those parameters at instantiation so every Method has it's own var api = new Shopify.API(opts)
Hey @dbnoble,
As far as I know, the rate limits from shopify are per app, not per accessToken :(.
I'm sorry that meteor-shopify
is crashing for you! It's possible that the rate limiting is just broken (and it might be -- I don't think I ever hit the rate limits, and only have tested with the shopify api simulator in tests/
), but hopefully the following will help.
Quick Fix
All of Shopify.API
internals are exposed in this.config
and this._authenticator
. So make your Shopify.API
objects as normal, in order to authenticate and stuff, but before you fire any API calls, copy the config
and _authenticator
to some global Shopify.API
and use that. I hope this will fix your issues!
var globalAPI = new Shopify.API({ shop: "non-empty but doesn't matter what you put here" });
WebApp.connectHandlers.use("/yourWebhook", function ShopifyAuthRedirect(req, res) {
var shop = uri.query.shop;
var id = uri.query.productId; // I don't know how you choose the product
// TODO verify signature
var api = apis[shop];
if (!api) {
res.writeHead(401, { });
res.end("No way!");
return;
}
globalAPI.config = api.config;
globalAPI._authenticator = api._authenticator;
var product = globalAPI.getProduct(id);
// Do your business
});
Proper Solution
I think the "proper" solution would be to do per-api_key
rate-limiting, not per Shopify.API
rate-limiting.
This can be implemented by:
- Add
api_key
param toAPI.prototype._waitAsync
- Make an
api_key => { lastCallLimit, queueLength }
object,rateLimits
in that file above_waitAsync
- In
_waitAsync
, uselastCallLimit
andqueueLength
fromrateLimits
instead of fromthis
- In the generated code in
API.define, update
lastCallLimitin
rateLimitsinstead of
this`
I'm not doing any shopify development at the moment, so feel free to make a pull request! If I need a break or something, I may implement this at some point :).