UNPKG

mws-zodane-advanced

Version:

fixed throtal resend

291 lines (262 loc) 18.2 kB
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <base data-ice="baseUrl" href="../../"> <title data-ice="title">lib/callEndpoint.js | mws-advanced</title> <link type="text/css" rel="stylesheet" href="css/style.css"> <link type="text/css" rel="stylesheet" href="css/prettify-tomorrow.css"> <script src="script/prettify/prettify.js"></script> <script src="script/manual.js"></script> </head> <body class="layout-container" data-ice="rootContainer"> <header> <a href="./">Home</a> <a href="identifiers.html">Reference</a> <a href="source.html">Source</a> <div class="search-box"> <span> <img src="./image/search.png"> <span class="search-input-edge"></span><input class="search-input"><span class="search-input-edge"></span> </span> <ul class="search-result"></ul> </div> </header> <nav class="navigation" data-ice="nav"><div> <ul> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/lib/errors.js~InvalidUsage.html">InvalidUsage</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/lib/errors.js~RequestCancelled.html">RequestCancelled</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/lib/errors.js~ServiceError.html">ServiceError</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/lib/errors.js~ValidationError.html">ValidationError</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-callEndpoint">callEndpoint</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-init">init</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-getLowestPricedOffersForASIN">getLowestPricedOffersForASIN</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-getMarketplaces">getMarketplaces</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-getMatchingProductForId">getMatchingProductForId</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-listFinancialEvents">listFinancialEvents</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-listInventorySupply">listInventorySupply</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-listOrderItems">listOrderItems</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-listOrders">listOrders</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-getReport">getReport</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-getReportList">getReportList</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-getReportListAll">getReportListAll</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-getReportListByNextToken">getReportListByNextToken</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-getReportRequestList">getReportRequestList</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-requestAndDownloadReport">requestAndDownloadReport</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-requestReport">requestReport</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-variable">V</span><span data-ice="name"><span><a href="variable/index.html#static-variable-MWS_ENDPOINTS">MWS_ENDPOINTS</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-variable">V</span><span data-ice="name"><span><a href="variable/index.html#static-variable-MWS_MARKETPLACES">MWS_MARKETPLACES</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-typedef">T</span><span data-ice="name"><span><a href="typedef/index.html#static-typedef-BuyBoxPrice">BuyBoxPrice</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-typedef">T</span><span data-ice="name"><span><a href="typedef/index.html#static-typedef-DetailedShippingTime">DetailedShippingTime</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-typedef">T</span><span data-ice="name"><span><a href="typedef/index.html#static-typedef-LowestPrice">LowestPrice</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-typedef">T</span><span data-ice="name"><span><a href="typedef/index.html#static-typedef-LowestPricedOffers">LowestPricedOffers</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-typedef">T</span><span data-ice="name"><span><a href="typedef/index.html#static-typedef-Money">Money</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-typedef">T</span><span data-ice="name"><span><a href="typedef/index.html#static-typedef-Offer">Offer</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-typedef">T</span><span data-ice="name"><span><a href="typedef/index.html#static-typedef-OfferCount">OfferCount</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-typedef">T</span><span data-ice="name"><span><a href="typedef/index.html#static-typedef-OfferSummary">OfferSummary</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-typedef">T</span><span data-ice="name"><span><a href="typedef/index.html#static-typedef-SellerFeedbackRating">SellerFeedbackRating</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-typedef">T</span><span data-ice="name"><span><a href="typedef/index.html#static-typedef-ShipsFrom">ShipsFrom</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-typedef">T</span><span data-ice="name"><span><a href="typedef/index.html#static-typedef-MarketDetail">MarketDetail</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-typedef">T</span><span data-ice="name"><span><a href="typedef/index.html#static-typedef-OrderItemList">OrderItemList</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-typedef">T</span><span data-ice="name"><span><a href="typedef/index.html#static-typedef-GetReportRequestListResult">GetReportRequestListResult</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-typedef">T</span><span data-ice="name"><span><a href="typedef/index.html#static-typedef-GetReportRequestListResult">GetReportRequestListResult</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-typedef">T</span><span data-ice="name"><span><a href="typedef/index.html#static-typedef-ReportRequestInfo">ReportRequestInfo</a></span></span></li> <li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#endpoints">endpoints</a><span data-ice="kind" class="kind-variable">V</span><span data-ice="name"><span><a href="variable/index.html#static-variable-REPORT_PROCESSING_STATUS_TYPES">REPORT_PROCESSING_STATUS_TYPES</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-variable">V</span><span data-ice="name"><span><a href="variable/index.html#static-variable-REQUEST_REPORT_TYPES">REQUEST_REPORT_TYPES</a></span></span></li> </ul> </div> </nav> <div class="content" data-ice="content"><h1 data-ice="title">lib/callEndpoint.js</h1> <pre class="source-code line-number raw-source-code"><code class="prettyprint linenums" data-ice="content">const MWS = require(&apos;mws-simple&apos;); const { MWS_ENDPOINTS } = require(&apos;./constants&apos;); const sleep = require(&apos;./util/sleep&apos;); const fs = require(&apos;fs&apos;); const errors = require(&apos;./errors.js&apos;); /* * TODO: split the &quot;init&quot; function out of the &quot;callEndpoint&quot; file, difficulty: callEndpoint * depends on having init modify the mws value, which doesn&apos;t carry between module pieces in that * case -- exporting &apos;mws&apos; to callEndpoint just results in null every time it&apos;s accessed, even * when requiring it inline in code, rather than at the top of the file. Ugh. Big design * problem, that is a holdover from when the entire module was all located in a single file. */ /** holds the mws-simple reference after init() is called */ let mws = null; /** * Initialize mws-advanced with your MWS access keys, merchantId, optionally authtoken, host, port * If accessKeyId, secretAccessKey, and/or merchantId are not provided, they will be read from * the environment variables MWS_ACESS_KEY, MWS_SECRET_ACCESS_KEY, and MWS_MERCHANT_ID respectively * * @public * @example * const mws = MWS.init({ region: &apos;NA&apos;, accessKeyId: &apos;1234&apos;, secretAccessKey: &apos;2345&apos;, merchantId: &apos;1234567890&apos; }); * const mws = MWS.init({ region: &apos;EU&apos;, accessKeyId, ... }); * const mws = MWS.init({ authToken: &apos;qwerty&apos;, accessKeyId, ...}); * const mws = MWS.init({ host: &apos;alternate-mws-server.com&apos;, accessKeyId, ... }); * @param {object} config Contains your MWS Access Keys/Tokens and options to configure the API * @param {string} [config.accessKeyId=process.env.MWS_ACCESS_KEY] Your MWS Access Key * @param {string} [config.secretAccessKey=process.env.MWS_SECRET_ACCESS_KEY] Your MWS Secret Access Key * @param {string} [config.merchantId=process.env.MWS_MERCHANT_ID] Your MWS Merchant ID * @param {string} [config.authToken] If making a call for a third party account, the Auth Token provided * for the third party account * @param {string} [config.region=&apos;NA&apos;] One of the Amazon regions as specified in https://docs.developer.amazonservices.com/en_US/dev_guide/DG_Endpoints.html * @param {string} [config.host=&apos;mws.amazonservices.com&apos;] Set MWS host server name, see https://docs.developer.amazonservices.com/en_US/dev_guide/DG_Endpoints.html * @param {number} [config.port=443] Set MWS host port * @returns {mws-simple} - The mws-simple instance used to communicate with the API */ const init = ({ region = &apos;NA&apos;, // marketplace = &apos;US&apos;, // TODO: maybe someday we will want to keep track of a &apos;default&apos; marketplace. accessKeyId = process.env.MWS_ACCESS_KEY, secretAccessKey = process.env.MWS_SECRET_ACCESS_KEY, merchantId = process.env.MWS_MERCHANT_ID, authToken, host = MWS_ENDPOINTS[region] || &apos;mws.amazonservices.com&apos;, port, } = {}) =&gt; { mws = new MWS({ accessKeyId, secretAccessKey, merchantId, authToken, host, port, }); return mws; }; const { flattenResult } = require(&apos;./flatten-result&apos;); const { validateAndTransformParameters } = require(&apos;./validation&apos;); const { digResponseResult } = require(&apos;./dig-response-result.js&apos;); // TODO: add Subscriptions and Recommendations categories const { feeds, finances, inbound, inventory, outbound, merchFulfillment, orders, products, sellers, reports, } = require(&apos;./endpoints&apos;); // TODO: THIS MAY BE A BAD IDEA CONSIDERING THAT SOME CATEGORIES SHARE SOME ENDPOINT NAMES // TODO: WE MAY NEED TO COME UP WITH A WAY TO DEAL WITH THAT. /** simple flat list of all the endpoints required from individual modules above */ const endpoints = { ...feeds, ...finances, ...inbound, ...inventory, ...merchFulfillment, ...orders, ...outbound, ...products, ...sellers, ...reports, }; /** * Return a promise for making the desired request, flattening the response out to something * that will hopefully make a little more sense. * * @async * @private * @param {any} requestData * @param {object} [opt] - options * @param {boolean} [opt.noFlatten] - do not run flattenResult on the output */ const requestPromise = (requestData, opt = {}) =&gt; new Promise((resolve, reject) =&gt; { // eslint-disable-next-line global-require mws.request(requestData, (err, result) =&gt; { if (err) { reject(err); } else { resolve(opt.noFlatten ? result : flattenResult(result)); } }); }); /** * Call a known endpoint at MWS, returning the raw data from the function. Parameters are * transformed and validated according to the rules defined in lib/endpoints * * @async * @public * @param {string} name - name of MWS API function to call * @param {object} [callOptions] - named hash object of the parameters to pass to the API * @param {object} [opt] - options for callEndpoint * @param {boolean} [opt.noFlatten] - do not flatten results * @param {boolean} [opt.returnRaw] - return only the raw data (may or may not be flattened) * @param {string} [opt.saveRaw] - filename to save raw data to (may or may not be flattened) * @param {string} [opt.saveParsed] - filename to save final parsed data to (not compatible with returnRaw, since parsing won&apos;t happen) * @returns {any} - Results of the call to MWS */ const callEndpoint = async (name, callOptions = {}, opt = {}) =&gt; { const endpoint = endpoints[name]; if (!endpoint) { throw new errors.InvalidUsage(&apos;No endpoint name supplied to callEndpoint&apos;); } const newOptions = endpoint.params ? validateAndTransformParameters(endpoint.params, callOptions) : callOptions; const queryOptions = { ...newOptions, Action: endpoint.action, Version: endpoint.version, }; const params = { path: `/${endpoint.category}/${endpoint.version}`, query: queryOptions, }; try { const result = await requestPromise(params, { noFlatten: opt.noFlatten }); if (opt.saveRaw) { fs.writeFileSync(opt.saveRaw, JSON.stringify(result)); } if (opt.returnRaw) { return result; } const digResult = digResponseResult(name, result); if (opt.saveParsed) { fs.writeFileSync(opt.saveParsed, JSON.stringify(digResult)); } return digResult; } catch (err) { if (err instanceof MWS.ServerError) { if (err.code === 503) { console.warn(&apos;***** Error 503 .. throttling?&apos;, name); let ms = 2000; if (!endpoint.throttle) { console.warn(`***** throttle information missing for API ${name}`); console.warn(&apos;***** &apos;, JSON.stringify(endpoint)); } else { // restoreRate = how many you get back in a minute of time. there&apos;s an assumption here // that you&apos;re spamming a lot of requests if you&apos;re hitting throttling, and this // throttle management system is first version, here -- so we&apos;re going to throttle it // not to the minimum possible time frame, but to the length of time that it will take // to restore your entire maxInFlight -- assuming you&apos;re probably going to hit the max // again as soon as we start letting more requests in. // ultimately, an upgraded version of this throttling handler would keep track of how // many of every request are in flight, and try to throttle it to the minimum amount // of time that you can go, automatically throttling future calls without having to // even encounter the 503 from the server. // that day is not today. it might be tomorrow. maybe next weekend. i don&apos;t know. :-) const restoreMaxInFlightMin = (endpoint.throttle.maxInFlight / endpoint.throttle.restoreRate) * (callOptions.IdList ? callOptions.IdList.length : 1); ms = (restoreMaxInFlightMin * 60 * 1000) + 100; } console.warn(`***** trying again in ${ms}ms`); await sleep(ms + 100); return callEndpoint(name, callOptions, opt); } } throw err; } }; module.exports = { init, callEndpoint, }; </code></pre> </div> <footer class="footer"> Generated by <a href="https://esdoc.org">ESDoc<span data-ice="esdocVersion">(1.0.4)</span><img src="./image/esdoc-logo-mini-black.png"></a> </footer> <script src="script/search_index.js"></script> <script src="script/search.js"></script> <script src="script/pretty-print.js"></script> <script src="script/inherited-summary.js"></script> <script src="script/test-summary.js"></script> <script src="script/inner-link.js"></script> <script src="script/patch-for-local.js"></script> </body> </html>