diff options
Diffstat (limited to 'node_modules/throat')
| -rw-r--r-- | node_modules/throat/LICENSE | 19 | ||||
| -rw-r--r-- | node_modules/throat/README.md | 55 | ||||
| -rw-r--r-- | node_modules/throat/index.d.ts | 32 | ||||
| -rw-r--r-- | node_modules/throat/index.js | 145 | ||||
| -rw-r--r-- | node_modules/throat/index.js.flow | 7 | ||||
| -rw-r--r-- | node_modules/throat/package.json | 47 | 
6 files changed, 305 insertions, 0 deletions
diff --git a/node_modules/throat/LICENSE b/node_modules/throat/LICENSE new file mode 100644 index 0000000..35cc606 --- /dev/null +++ b/node_modules/throat/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2013 Forbes Lindesay + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE.
\ No newline at end of file diff --git a/node_modules/throat/README.md b/node_modules/throat/README.md new file mode 100644 index 0000000..ab69ac8 --- /dev/null +++ b/node_modules/throat/README.md @@ -0,0 +1,55 @@ +# throat + +Throttle the parallelism of an asynchronous, promise returning, function / functions. This has special utility when you set the concurrency to `1`. That way you get a mutually exclusive lock. + +[Professionally supported throat is now available](https://tidelift.com/subscription/pkg/npm-throat?utm_source=npm-throat&utm_medium=referral&utm_campaign=readme) + +[](https://github.com/ForbesLindesay/throat/actions?query=workflow%3ATest+branch%3Amaster) +[](https://coveralls.io/github/ForbesLindesay/throat) +[](https://rollingversions.com/ForbesLindesay/throat) +[](https://www.npmjs.com/package/throat) + +## Installation + +    npm install throat + +## API + +### throat(concurrency) + +This returns a function that acts a bit like a lock (exactly as a lock if concurrency is 1). + +Example, only 2 of the following functions will execute at any one time: + +```js +const throat = require('throat')(2); + +const resA = throat(async () => { /* async stuff... */ }); +const resB = throat(async () => { /* async stuff... */ }); +const resC = throat(async () => { /* async stuff... */ }); +const resD = throat(async () => { /* async stuff... */ }); +const resE = throat(async () => { /* async stuff... */ }); +``` + +### throat(concurrency, worker) + +This returns a function that is an exact copy of `worker` except that it will only execute up to `concurrency` times in parallel before further requests are queued: + +```js +const throat = require('throat'); + +const input = ['fileA.txt', 'fileB.txt', 'fileC.txt', 'fileD.txt']; +const data = Promise.all( +  input.map(throat(2, (fileName) => readFile(fileName))) +); +``` + +Only 2 files will be read at a time, sometimes limiting parallelism in this way can improve scalability. + +## Security contact information + +To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure. + +## License + +MIT diff --git a/node_modules/throat/index.d.ts b/node_modules/throat/index.d.ts new file mode 100644 index 0000000..038ca51 --- /dev/null +++ b/node_modules/throat/index.d.ts @@ -0,0 +1,32 @@ +/** + * Throttle the given function to only run `size` times in parallel. + * Extra calls will be queued until one of the earlier calls completes. + */ +declare function throat<TResult, TArgs extends any[]>( +  size: number, +  fn: (...args: TArgs) => Promise<TResult> +): (...args: TArgs) => Promise<TResult>; + +/** + * Throttle the given function to only run `size` times in parallel. + * Extra calls will be queued until one of the earlier calls completes. + */ +declare function throat<TResult, TArgs extends any[]>( +  fn: (...args: TArgs) => Promise<TResult>, +  size: number +): (...args: TArgs) => Promise<TResult>; + +/** + * Create a throttle that only allows `size` calls in parallel. + * Extra calls will be queued until one of the earlier calls completes. + * + * To create an exclusive lock, just use a `size` of `1`. + */ +declare function throat( +  size: number +): <TResult, TArgs extends any[] = []>( +  fn: (...args: TArgs) => Promise<TResult>, +  ...args: TArgs +) => Promise<TResult>; +export default throat; + diff --git a/node_modules/throat/index.js b/node_modules/throat/index.js new file mode 100644 index 0000000..0a589ea --- /dev/null +++ b/node_modules/throat/index.js @@ -0,0 +1,145 @@ +'use strict'; + +function throatInternal(size) { +  var queue = new Queue(); +  var s = size | 0; + +  function run(fn, self, args) { +    if ((s | 0) !== 0) { +      s = (s | 0) - 1; +      return new Promise(function (resolve) { +        resolve(fn.apply(self, args)); +      }).then(onFulfill, onReject); +    } +    return new Promise(function (resolve) { +      queue.push(new Delayed(resolve, fn, self, args)); +    }).then(runDelayed); +  } +  function runDelayed(d) { +    try { +      return Promise.resolve(d.fn.apply(d.self, d.args)).then( +        onFulfill, +        onReject +      ); +    } catch (ex) { +      onReject(ex); +    } +  } +  function onFulfill(result) { +    release(); +    return result; +  } +  function onReject(error) { +    release(); +    throw error; +  } +  function release() { +    var next = queue.shift(); +    if (next) { +      next.resolve(next); +    } else { +      s = (s | 0) + 1; +    } +  } + +  return run; +} + +function earlyBound(size, fn) { +  const run = throatInternal(size | 0); +  return function () { +    var args = new Array(arguments.length); +    for (var i = 0; i < arguments.length; i++) { +      args[i] = arguments[i]; +    } +    return run(fn, this, args); +  }; +} +function lateBound(size) { +  const run = throatInternal(size | 0); +  return function (fn) { +    if (typeof fn !== 'function') { +      throw new TypeError( +        'Expected throat fn to be a function but got ' + typeof fn +      ); +    } +    var args = new Array(arguments.length - 1); +    for (var i = 1; i < arguments.length; i++) { +      args[i - 1] = arguments[i]; +    } +    return run(fn, this, args); +  }; +} +module.exports = function throat(size, fn) { +  if (typeof size === 'function') { +    var temp = fn; +    fn = size; +    size = temp; +  } +  if (typeof size !== 'number') { +    throw new TypeError( +      'Expected throat size to be a number but got ' + typeof size +    ); +  } +  if (fn !== undefined && typeof fn !== 'function') { +    throw new TypeError( +      'Expected throat fn to be a function but got ' + typeof fn +    ); +  } +  if (typeof fn === 'function') { +    return earlyBound(size | 0, fn); +  } else { +    return lateBound(size | 0); +  } +}; + +module.exports.default = module.exports; + +function Delayed(resolve, fn, self, args) { +  this.resolve = resolve; +  this.fn = fn; +  this.self = self || null; +  this.args = args; +} + +var blockSize = 64; +function Queue() { +  this._s1 = []; +  this._s2 = []; +  this._shiftBlock = this._pushBlock = new Array(blockSize); +  this._pushIndex = 0; +  this._shiftIndex = 0; +} + +Queue.prototype.push = function (value) { +  if (this._pushIndex === blockSize) { +    this._pushIndex = 0; +    this._s1[this._s1.length] = this._pushBlock = new Array(blockSize); +  } +  this._pushBlock[this._pushIndex++] = value; +}; + +Queue.prototype.shift = function () { +  if (this._shiftIndex === blockSize) { +    this._shiftIndex = 0; +    var s2 = this._s2; +    if (s2.length === 0) { +      var s1 = this._s1; +      if (s1.length === 0) { +        return undefined; +      } +      this._s1 = s2; +      s2 = this._s2 = s1.reverse(); +    } +    this._shiftBlock = s2.pop(); +  } +  if ( +    this._pushBlock === this._shiftBlock && +    this._pushIndex === this._shiftIndex +  ) { +    return undefined; +  } +  var result = this._shiftBlock[this._shiftIndex]; +  this._shiftBlock[this._shiftIndex++] = null; +  return result; +}; diff --git a/node_modules/throat/index.js.flow b/node_modules/throat/index.js.flow new file mode 100644 index 0000000..4036f83 --- /dev/null +++ b/node_modules/throat/index.js.flow @@ -0,0 +1,7 @@ +// @flow + +declare function throat<TResult, TFn: (...args: Array<any>) => Promise<TResult>>(size: number, fn: TFn): TFn; +declare function throat<TResult, TFn: (...args: Array<any>) => Promise<TResult>>(fn: TFn, size: number): TFn; +declare function throat(size: number): <TResult>(fn: () => Promise<TResult>) => Promise<TResult>; + +module.exports = throat; diff --git a/node_modules/throat/package.json b/node_modules/throat/package.json new file mode 100644 index 0000000..9101b08 --- /dev/null +++ b/node_modules/throat/package.json @@ -0,0 +1,47 @@ +{ +  "name": "throat", +  "version": "6.0.1", +  "description": "Throttle the parallelism of an asynchronous (promise returning) function / functions", +  "keywords": [ +    "promise", +    "aplus", +    "then", +    "throttle", +    "concurrency", +    "parallelism", +    "limit" +  ], +  "files": [ +    "index.d.ts", +    "index.js", +    "index.js.flow" +  ], +  "devDependencies": { +    "coveralls": "^3.0.0", +    "flow-bin": "^0.73.0", +    "istanbul": "^0.4.5", +    "jest": "^22.1.4", +    "promise": "^8.0.0", +    "sauce-test": "^1.0.0", +    "test-result": "^2.0.0", +    "testit": "^3.1.0", +    "typescript": "^3.4.5" +  }, +  "jest": { +    "testEnvironment": "node" +  }, +  "scripts": { +    "tsc": "tsc --noEmit", +    "flow": "flow", +    "test": "node test/index.js && npm run test:types", +    "test:types": "jest", +    "coverage": "istanbul cover test/index.js", +    "coveralls": "npm run coverage && cat ./coverage/lcov.info | coveralls" +  }, +  "repository": { +    "type": "git", +    "url": "https://github.com/ForbesLindesay/throat.git" +  }, +  "author": "ForbesLindesay", +  "license": "MIT" +}  | 
