UNPKG

documentdb-typescript

Version:
109 lines (108 loc) 4.09 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const Client_1 = require("./Client"); /** Current number of pending requests */ var _pending = 0; /** Return a curried version of given function that appends a callback as a last parameter, which rejects or resolves a promise; the promise is returned immediately; also handles DocumentDB errors when possible */ function curryPromise(f, timeout = 60000, maxRetries = 0, retryTimer, retryOn404) { return (...args) => { // return Promise for result or error var started = false, done; var retries = maxRetries, timeoutTimer; return new Promise(function exec(resolve, reject) { if (done) return; if (!started) { if (_pending >= Client_1.Client.concurrencyLimit) { setTimeout(exec, retryTimer || 100, resolve, reject); return; } _pending++; started = true; } // set timeout timer, reject when reached function setTimeoutTimer() { let t = timeoutTimer = setTimeout(() => { if (t === timeoutTimer) { if (retries-- > 0) retry(); else reject(done = new Error("Timeout")); } }, timeout); } function clearTimeoutTimer() { clearTimeout(timeoutTimer); timeoutTimer = undefined; } var retried = false; function retry(err, headers) { if (retried) return; retried = true; clearTimeoutTimer(); var t = retryTimer || 100; if (err && err.code === 429 && headers && headers["x-ms-retry-after-ms"]) t = parseFloat(headers["x-ms-retry-after-ms"]); setTimeout(exec, t, resolve, reject); } setTimeoutTimer(); // append own callback args.push((err, result, headers) => { if (err) { // retry or reject if (err.code !== 400 && err.code !== 401 && err.code !== 403 && (retryOn404 || err.code !== 404) && err.code !== 409 && err.code !== 412 && err.code !== 413 && retries-- > 0) { retry(err, headers); } else { var error, body; try { body = JSON.parse(err.body); } catch (all) { } if (body) { error = new Error(body.message || "Database error"); error.code = err.code; error.name = body.code; } reject(error || err); done = true; clearTimeoutTimer(); } } else { // resolve the promise resolve(result); done = true; clearTimeoutTimer(); } }); try { f.apply(undefined, args); } catch (err) { reject(err); } }).then(result => { if (started) _pending--; return result; }, err => { if (started) _pending--; throw err; }); }; } exports.curryPromise = curryPromise; /** Return a promise that resolves after a given timeout */ function sleepAsync(ms, value = undefined) { return new Promise(resolve => { setTimeout(() => resolve(value), ms); }); } exports.sleepAsync = sleepAsync;