{"_id":"@elite-libs/promise-pool","_rev":"3-210e08e7fff555ebe8684fd90e5ec32f","name":"@elite-libs/promise-pool","dist-tags":{"latest":"1.3.1"},"versions":{"1.0.0":{"name":"@elite-libs/promise-pool","version":"1.0.0","description":"Configurable async task queue, w/ throttling, retries, progress, error handling.","keywords":[],"type":"commonjs","homepage":"https://github.com/elite-libs/promise-pool","repository":{"type":"git","url":"git+https://github.com/elite-libs/promise-pool.git"},"source":"./src/index.ts","main":"./dist/index.cjs","module":"./dist/index.mjs","browser":"./dist/index.global.js","types":"./dist/index.d.ts","private":false,"packageManager":"npm@6.0.0-9.0.0","engineStrict":true,"engines":{"npm":">=6","node":">=12.0.0"},"scripts":{"prepublishOnly":"NODE_ENV=production  npm run build","release:npm":"npm publish --access public --registry https://registry.npmjs.org/","release:github":"npm publish --access public --registry https://npm.pkg.github.com/","test":"npm run build && jest --coverage","test:coverage":"npm run build && jest --coverage","build":"npx rimraf ./dist/* && npm run build:bundle && npm run build:types","build:types":"npx tsc --project ./tsconfig.types.json","build:bundle":"npx tsup && cp dist/index.js dist/index.cjs","lint":"eslint .","format":"eslint --fix ."},"author":{"name":"@justsml","url":"https://danlevy.net"},"license":"BSD-3-Clause","devDependencies":{"@types/eslint":"^8.4.3","@types/jest":"^26.0.0","@types/lodash":"^4.14.182","@types/node":"^14.0.0","@typescript-eslint/eslint-plugin":"^5.30.6","@typescript-eslint/parser":"^5.30.6","eslint":"^8.17.0","eslint-config-airbnb-base":"^15.0.0","eslint-config-airbnb-typescript":"^17.0.0","eslint-plugin-import":"^2.26.0","jest":"^26.0.0","ts-jest":"^26.0.0","ts-node":"^10.8.1","tsup":"^6.1.2","typescript":"^4.7.4"},"prettier":{"printWidth":80,"tabWidth":2,"singleQuote":true},"gitHead":"581994170e0ce9fef226d8cb6d70c8319e9aad31","bugs":{"url":"https://github.com/elite-libs/promise-pool/issues"},"_id":"@elite-libs/promise-pool@1.0.0","_nodeVersion":"12.20.1","_npmVersion":"6.14.10","dist":{"integrity":"sha512-R+RQOhNK/lryrhMlFB0STJmYl6hH1DBu8PDl0BBgiuk46sqB7bkFYwGU+7AnUfHpPM0fBnqrlEGWqEEOIvQ94A==","shasum":"13b3eebb755d89ff4a354ae737ee0123c6c9eb2b","tarball":"https://registry.npmjs.org/@elite-libs/promise-pool/-/promise-pool-1.0.0.tgz","fileCount":16,"unpackedSize":62406,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDKx+xFVdNh8fUvybr7ICnr8Bjm+5zD9kd7EJGd1Wr3DgIgV1FkEN30FWY6COYj01SwM+m4gnVkOkSMgq4o0H6RjC8="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJi3zI2ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmq85A/9GxciphbbCGihJYMbN6QxujuT2xqfK9CaAM4rZBDQwC0qLZ2z\r\noF8oZ9n6/N2e04OsroFyAPGltjYz2D5OOYEfUH7i9V2BeXAWKAblFEBt9OE3\r\nFYDEg3IAAJFISen7QUd70dODqAPOWtWZsGVvFi7ldAUxSrZ59ZiEr6Wi7Mda\r\netDlJW1PD3LuHF2wvmXhCDloMqO6xSYEFDC7odtSpa87yTYfA9ig1evWR0Zc\r\noWZMuWAZJ3ppwFCINs8auBYk+YGCD6uDBKa+awgNMNOygALc90xN9gQAUaS/\r\ny+7+kFI4o3vtmI9l5yJEpV3C/71RRhZrxcew1ewX1x3J7oG3GJXD9THXa9aB\r\n+/9uVCKsnBd+Hs0oewuCfzOyfr/8AZ+S2O/uUjdA3fsAqYTAAqeZ6TkMgJPR\r\n+g0vBOZvgbDhI09z8Njd7dsmpooVZjf1UtKi2rxIUS7dz3JkfGT4KbGDQ+7L\r\nY4WhJGwQltGup9Vle95uZki3RrIO9IjJEpW9ox4vbn4ygv6gn7gfM7UV5/X/\r\n7MBhDBoLdK15nv6FrNjcaCpC/HuvVhdxLTmotgOCqGFuS3gfb5JCuLBmKx1+\r\nOvLWJbWPGuQpF9los3rbpvDiRotgke4kgjsTT6jLXLwsLe7TcBz29VC2wWBA\r\noXHl1EetkjJW/1mitqlaKLWd7ZtzXMxn4n4=\r\n=sEQR\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"justsml","email":"dan@danlevy.net"},"directories":{},"maintainers":[{"name":"justsml","email":"dan@danlevy.net"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/promise-pool_1.0.0_1658794550462_0.10148621442752037"},"_hasShrinkwrap":false},"1.1.0":{"name":"@elite-libs/promise-pool","version":"1.1.0","description":"Configurable async task queue, w/ throttling, retries, progress, error handling.","keywords":[],"type":"commonjs","homepage":"https://github.com/elite-libs/promise-pool","repository":{"type":"git","url":"git+https://github.com/elite-libs/promise-pool.git"},"source":"./src/index.ts","main":"./dist/index.cjs","module":"./dist/index.mjs","browser":"./dist/index.global.js","types":"./dist/index.d.ts","private":false,"packageManager":"npm@6.0.0-9.0.0","engineStrict":true,"engines":{"npm":">=6","node":">=12.0.0"},"scripts":{"prepublishOnly":"NODE_ENV=production  npm run build","release:npm":"npm publish --access public --registry https://registry.npmjs.org/","release:github":"npm publish --access public --registry https://npm.pkg.github.com/","test":"npm run build && jest --coverage --detectOpenHandles --runInBand","test:coverage":"npm run build && jest --coverage","build":"npx rimraf ./dist/* && npm run build:bundle && npm run build:types","build:types":"npx tsc --project ./tsconfig.types.json","build:bundle":"npx tsup && cp dist/index.js dist/index.cjs","lint":"eslint .","format":"eslint --fix ."},"author":{"name":"@justsml","url":"https://danlevy.net"},"license":"BSD-3-Clause","devDependencies":{"@types/eslint":"^8.4.3","@types/jest":"^26.0.0","@types/lodash":"^4.14.182","@types/node":"^14.0.0","@typescript-eslint/eslint-plugin":"^5.30.6","@typescript-eslint/parser":"^5.30.6","eslint":"^8.17.0","eslint-config-airbnb-base":"^15.0.0","eslint-config-airbnb-typescript":"^17.0.0","eslint-plugin-import":"^2.26.0","jest":"^26.0.0","ts-jest":"^26.0.0","ts-node":"^10.8.1","tsup":"^6.1.2","typescript":"^4.7.4"},"prettier":{"printWidth":80,"tabWidth":2,"singleQuote":true},"gitHead":"47419dadac51553c5cdbc162f07a230a918c4162","bugs":{"url":"https://github.com/elite-libs/promise-pool/issues"},"_id":"@elite-libs/promise-pool@1.1.0","_nodeVersion":"12.20.1","_npmVersion":"6.14.10","dist":{"integrity":"sha512-YI9DZfXWOPLsSh+ZPaeIefvxVhuulqaTG4FDP/YlJvk3Pcwp9TM01MLfxZHxwKqT8LBpu3Qvpq6VGBMstkdMIw==","shasum":"af47ac990142b2a1d710ecb7dc8b3718e942ef76","tarball":"https://registry.npmjs.org/@elite-libs/promise-pool/-/promise-pool-1.1.0.tgz","fileCount":16,"unpackedSize":79094,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDsuGti37DRduy2kcyxXXsYaXayJnUq/mGLOcfqw66r4AIhAORuMaPxhmjoShwJvDRVbj9qq/PWQlBCOUAvOjvhoeGe"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJi4JuOACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpR+hAAgQSgf61xU5YKARmrcDtC6Gv1bhqzQVIs6KvgrqX1sDJadJ4c\r\nJSzPAKJ3zXeHPKTSrsEpnLNVDfmq8DDStFQpE50qYCjRfjjKGuCC3G3JXrEb\r\nQ+5JlZ/qk/1n2t+Bm9GVMzPfGwDR5kmxglgUaLMCe0x+uh16uFJUG661+28k\r\nawLu3wPFhyO88GCV4bborqYPqhpnEk6zZmOwq/S3Rw64ZJ1WtBKWwbGQTfAw\r\nZkK/Bt/+ZKDDKQpTHfo5OSS2d5++OCUBtYxAECa6q9EHoldIKc1YM31e5XH7\r\ndXxf2q+G8xAITiWdHfmCHr8WL2T/PNFhVzbIG9Ka4NVGj7yX0hhyR9/7UWv4\r\nRck4yCSXA8PZC5jCsc2CwKphfaeFgdpmlwauJ18UvI/1wE2E6ZMoGjHIE0Mv\r\nhBgGf4w6GQP+Ltjp1Q3ucjmr3SoSv4TY+qDX76veekDx3RWsYwyMcT5QIQK8\r\nF3SvE8cvFCt6MOgiPBIfRF82H0WJZsKf2qDbJrrmiz0ZDjJ91P26vdYd01iA\r\nnvfbk21jKwBv7vfi60hjqMFeq7Yt61PNK+iQcLoH0H8TfsbY6HNoFuQknIhO\r\n8uHAGYW75+Rq9WYnjxuXV4FgNybWPjG/Ahcbq5qJDhBr8jwQT+vSK8LlUaAx\r\nKnuRo2Q/Dd8fBZABjMlciqhoqKfAYpcpldk=\r\n=gXiM\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"justsml","email":"dan@danlevy.net"},"directories":{},"maintainers":[{"name":"justsml","email":"dan@danlevy.net"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/promise-pool_1.1.0_1658887053935_0.9974669537739851"},"_hasShrinkwrap":false},"1.3.0":{"name":"@elite-libs/promise-pool","version":"1.3.0","description":"Configurable async task queue, w/ throttling, retries, progress, error handling.","keywords":[],"type":"commonjs","homepage":"https://github.com/elite-libs/promise-pool","repository":{"type":"git","url":"git+https://github.com/elite-libs/promise-pool.git"},"source":"./src/index.ts","main":"./dist/index.cjs","module":"./dist/index.mjs","browser":"./dist/index.global.js","types":"./dist/index.d.ts","private":false,"packageManager":"npm@6.0.0-9.0.0","engineStrict":true,"engines":{"npm":">=6","node":">=12.0.0"},"scripts":{"prepublishOnly":"NODE_ENV=production  npm run build","release:npm":"npm publish --access public --registry https://registry.npmjs.org/","release:github":"npm publish --access public --registry https://npm.pkg.github.com/","test":"npm run build && jest --coverage --detectOpenHandles --runInBand","test:coverage":"npm run build && jest --coverage","build":"npx rimraf ./dist/* && npm run build:bundle && npm run build:types","build:types":"npx tsc --project ./tsconfig.types.json","build:bundle":"npx tsup && cp dist/index.js dist/index.cjs","lint":"eslint .","format":"eslint --fix ."},"author":{"name":"@justsml","url":"https://danlevy.net"},"license":"BSD-3-Clause","devDependencies":{"@types/eslint":"^8.4.3","@types/jest":"^26.0.0","@types/lodash":"^4.14.182","@types/node":"^14.0.0","@typescript-eslint/eslint-plugin":"^5.30.6","@typescript-eslint/parser":"^5.30.6","eslint":"^8.17.0","eslint-config-airbnb-base":"^15.0.0","eslint-config-airbnb-typescript":"^17.0.0","eslint-plugin-import":"^2.26.0","jest":"^26.0.0","ts-jest":"^26.0.0","ts-node":"^10.8.1","tsup":"^6.1.2","typescript":"^4.7.4"},"prettier":{"printWidth":80,"tabWidth":2,"singleQuote":true},"gitHead":"b07b4c92d19f15b9332a905c74d9c33e9424adc2","bugs":{"url":"https://github.com/elite-libs/promise-pool/issues"},"_id":"@elite-libs/promise-pool@1.3.0","_nodeVersion":"18.9.0","_npmVersion":"8.19.1","dist":{"integrity":"sha512-lRSl5u2GLxXGpXZlmsjj3o/4Q1EAONiQxZUe9BDrDGv6KmOM5dnXSdsx+aQoZ0Bz2yq+DJb8hHlChrJNGTPf1Q==","shasum":"1bf36629986c799ace8a0bf5f63cc2929ea09c29","tarball":"https://registry.npmjs.org/@elite-libs/promise-pool/-/promise-pool-1.3.0.tgz","fileCount":16,"unpackedSize":103981,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCzrcB0HtyQemupAm3HvCbGaKg9ffVW4E+3+oEX5b6NNwIgHx92x/sCcBys6TBDrGd1TdNAftde6ewIwkRX3w/wpus="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjG4OxACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrhGA//fC5WkeRVXAbFEVBX3VWKIDn3m+bsTofihfx2KoNYTSUysX1p\r\nGgtBs7Wi3tAx/0LebPX5yVJ+g2IcD0QYdDebPOvs/kbKRaZlgeD33264bXs9\r\nuIFogRoYGTXObmnIU+Izjmwtz4pkSL/1PMQsdT0h0b3opeqK6Kly27MTzKHR\r\nSRK/Ax1VaPGkKkbtfMFH8tLnFyauwEh5aJET0HcYAJMrwBRH3NJrzLN8ko7V\r\nqNX8K6x1zcjZhJduVo0TxaAzg48rQBaol9yJd6KWoW6OoH+gzvvN94ogqcKE\r\nbxhfdgcp5WP3c4ZCYN3f6MamDaBy7boWgqJHPoVOmL2I4dvGp7Y3LbVW+tfW\r\nzynPUwVQksGYGuuXTe5z8IH0fUpo12t1VcOYMoDXMPsUj9e9Jqe6v4Zfj+p2\r\n9+4SIlMq0doWMrM5V5vDxVziVcI4cetbaTXOYZL3+83ii7Yx7lcjcPsE8F4V\r\n+NW99hQaFo3yoBfvbVhwNTKkIm3stsUrq0jwp5ww94UJnliWQOx9kJJ8l0Th\r\n9sATee03slDDXHeRP28aAi8zhxr1fmAjsYKAzRZ8bOvAMo0heuScNfVTVGFr\r\n6KxnsXu2dNWsuMkG4SP/oLaNoyHPshD1rJwx90zr6DKC9uggecVL+kCWm+yS\r\nrDcx8uQtgr0D3OxYwZ4tfT7H12w2F/pTMAU=\r\n=+UUf\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"justsml","email":"dan@danlevy.net"},"directories":{},"maintainers":[{"name":"justsml","email":"dan@danlevy.net"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/promise-pool_1.3.0_1662747568795_0.7853921790275946"},"_hasShrinkwrap":false},"1.3.1":{"name":"@elite-libs/promise-pool","version":"1.3.1","description":"Configurable async task queue, w/ throttling, retries, progress, error handling.","keywords":[],"type":"commonjs","homepage":"https://github.com/elite-libs/promise-pool","repository":{"type":"git","url":"git+https://github.com/elite-libs/promise-pool.git"},"source":"./src/index.ts","main":"./dist/index.cjs","module":"./dist/index.mjs","browser":"./dist/index.global.js","types":"./dist/index.d.ts","private":false,"packageManager":"npm@6.0.0-9.0.0","engineStrict":true,"engines":{"npm":">=6","node":">=12.0.0"},"scripts":{"prepublishOnly":"NODE_ENV=production  npm run build","release:npm":"npm publish --access public --registry https://registry.npmjs.org/","release:github":"npm publish --access public --registry https://npm.pkg.github.com/","test":"npm run build && jest --coverage --detectOpenHandles --runInBand","test:coverage":"npm run build && jest --coverage","build":"npx rimraf ./dist/* && npm run build:bundle && npm run build:types","build:types":"npx tsc --project ./tsconfig.types.json","build:bundle":"npx tsup && cp dist/index.js dist/index.cjs","lint":"eslint .","format":"eslint --fix ."},"author":{"name":"@justsml","url":"https://danlevy.net"},"license":"BSD-3-Clause","devDependencies":{"@types/eslint":"^8.4.3","@types/jest":"^26.0.0","@types/lodash":"^4.14.182","@types/node":"^14.0.0","@typescript-eslint/eslint-plugin":"^5.30.6","@typescript-eslint/parser":"^5.30.6","eslint":"^8.17.0","eslint-config-airbnb-base":"^15.0.0","eslint-config-airbnb-typescript":"^17.0.0","eslint-plugin-import":"^2.26.0","jest":"^26.0.0","ts-jest":"^26.0.0","ts-node":"^10.8.1","tsup":"^6.1.2","typescript":"^4.7.4"},"prettier":{"printWidth":80,"tabWidth":2,"singleQuote":true},"gitHead":"065486ee4fb84b0a80b9df77266573e25f55aabd","bugs":{"url":"https://github.com/elite-libs/promise-pool/issues"},"_id":"@elite-libs/promise-pool@1.3.1","_nodeVersion":"18.9.0","_npmVersion":"8.19.1","dist":{"integrity":"sha512-EHQcpdfvd/wMzCxi/Y3SGB9qAMGksryVdyr5+IYHVRIqXFBUz/CJ5n1T+wUT2n05exPJcL5c092L+kApfLI9Ug==","shasum":"6d66a476f66a2d525eb3b1786e3fa2e7488e8c00","tarball":"https://registry.npmjs.org/@elite-libs/promise-pool/-/promise-pool-1.3.1.tgz","fileCount":16,"unpackedSize":105305,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIA/imTRmseDf++2ZD7kYnaz9Ur+VzwqhSI7OiN2e6qsEAiBbwWo7pqIGyN+NpWlEN5RDvGxMLtfs/G16KEmiqLXaiA=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkOeLQACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpbGA//bo51Bk19bFhwBmc5gwJiMRrhZCNS8tk2TVQ3Y+iwPoUatWLD\r\ncSO5g/dDUZeY8L1sQLru26kJZ1DBvf9Qy4X+j1sBK+8FlE830cEXn7VED8MA\r\nLiLXK/ZviwmG412Os9tJ4uTHJgILr+DBdXd4w2vH+oS5i/al+D+qZdHMUUOO\r\nBh2CUogD/q9llFdKE/nxOQMESR1B0viosPptb/v1w620cd8cUCkgLxm8ca4S\r\nmUGnxWH11XQWlI5wuhlfWVcdPXyMfL27gf7922MkVBjAd3ExBweLcfQOnQde\r\nq41N7OwKpLVW6XNBGdY3LFlg1ukzEbKjilYuU28uaOtmlA2XbLEDaCQB/Pjg\r\nwQbw0SC76dPCmUNrAG5La6dT6L2CStG3gb2lmd3lqHgpRZdrZdVwevcnYsJQ\r\nicvOq6cqc5mDUNoHXP2yHFwD4MEj8AW8DKdUljKXkdnqXNoIddyGWwCiwzDl\r\nfah9gxzFSiapjBImQHJ1SEoXpSi1lSg7267A/Y0Grk6zc1Hi/IbTVAYwjweF\r\naGPoxgiKod6/Hsu5b1rEhg+5U3PeBZJ09NwZOQDLcBu9xfavmB9eD1y4BgX1\r\nPeNAUVpLSS2BvxN1BKFL/0VDqJrVUZC1bOxgXfJXZj2UWbQFI42RZKib/T8J\r\njTGTTErEEMxjm3Q0QtewbzlqHrVpWHzPdck=\r\n=zqHt\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"justsml","email":"dan@danlevy.net"},"directories":{},"maintainers":[{"name":"justsml","email":"dan@danlevy.net"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/promise-pool_1.3.1_1681515216189_0.5514101673801033"},"_hasShrinkwrap":false}},"time":{"created":"2022-07-26T00:15:50.402Z","1.0.0":"2022-07-26T00:15:50.707Z","modified":"2023-04-14T23:33:36.525Z","1.1.0":"2022-07-27T01:57:34.148Z","1.3.0":"2022-09-09T18:19:29.014Z","1.3.1":"2023-04-14T23:33:36.394Z"},"maintainers":[{"name":"justsml","email":"dan@danlevy.net"}],"description":"Configurable async task queue, w/ throttling, retries, progress, error handling.","homepage":"https://github.com/elite-libs/promise-pool","keywords":[],"repository":{"type":"git","url":"git+https://github.com/elite-libs/promise-pool.git"},"author":{"name":"@justsml","url":"https://danlevy.net"},"bugs":{"url":"https://github.com/elite-libs/promise-pool/issues"},"license":"BSD-3-Clause","readme":"# Promise Pool 🏖️\n\n[![CI Status](https://github.com/elite-libs/promise-pool/workflows/test/badge.svg)](https://github.com/elite-libs/promise-pool/actions)\n[![NPM version](https://img.shields.io/npm/v/@elite-libs/promise-pool.svg)](https://www.npmjs.com/package/@elite-libs/promise-pool)\n[![GitHub stars](https://img.shields.io/github/stars/elite-libs/promise-pool.svg?style=social)](https://github.com/elite-libs/promise-pool)\n\n> A background task processor focused on performance, reliability, and durability.\n\nTLDR; An upgraded Promise queue that's essentially a stateful `Promise.all()` wrapper.\n\n| **Table of Contents**\n\n- [Smart Multi-Threaded Execution](#smart-multi-threaded-execution)\n  - [Key `Promise Pool` Features](#key-promise-pool-features)\n  - [Who needs a `Promise Pool`?](#who-needs-a-promise-pool)\n- [Features](#features)\n- [API](#api)\n- [Install](#install)\n- [Usage](#usage)\n  - [Minimal Example](#minimal-example)\n  - [Singleton Pattern](#singleton-pattern)\n- [Recipes](#recipes)\n  - [AWS Lambda \\& Middy](#aws-lambda--middy)\n  - [Express Middleware](#express-middleware)\n- [Changelog](#changelog)\n  - [v1.3.1 - **April 2023**](#v131---april-2023)\n  - [v1.3.0 - **September 2022**](#v130---september-2022)\n\n## Smart Multi-Threaded Execution\n\n> Diagram of Promise Pool's 'Minimal Blocking' design\n\n<img src=\"/public/PromisePool-drain-behavior-draft-2022-09-13.png\" alt=\"Diagram: Visual of our minimal blocking design\" />\n\n### Key `Promise Pool` Features\n\nPromise Pool strives to excel at 4 key goals:\n\n1. Durability - won't fail in unpredictable ways - even under extreme load.\n2. Extensible by Design - supports Promise-based libraries (examples include: [retry handling](https://github.com/sindresorhus/p-retry), [debounce/throttle](https://github.com/sindresorhus/p-throttle))\n3. Reliability - control your pool with a total runtime limit (align to max HTTP/Lambda request limit), idle timeout (catch orphan or zombie situations), plus a concurrent worker limit.\n4. Performance - the work pool queue uses a speedy Ring Buffer design!*\n\n\\* Since this is JavaScript, our Ring Buffer is more like three JS Arrays in a trenchcoat.\n\n### Who needs a `Promise Pool`?\n\n- Any Node Services (Lambda functions, etc.) which does background work, defined as:\n  - Long-running async function(s),\n    - where the `return` value isn't used (in the current request.)\n    - And failures are handled by logging.\n\n## Features\n\n- [x] Configurable.\n- [x] Concurrency limit.\n- [x] Retries. (Use `p-retry` for this.)\n- [x] Zero dependencies.\n- [x] Error handling.\n- [x] Singleton mode: Option to auto-reset when `.done()`. (Added `.drain()` method.)\n- [x] Task scheduling & prioritization.\n  - [x] Support or `return` hints/stats? (Time in Event Loop? Event Loop wait time? Pending/Complete task counts?)\n  - [x] Support smart 'Rate Limit' logic.\n    - Recommended solution: conditionally delay (using `await delay(requestedWaitTime)`) before (or after) each HTTP call.\n    - Typically you'll detect Rate Limits via HTTP headers (or Payload/body data.) For example, check for any headers like `X-RateLimit-WaitTimeMS`.)\n\n\n## API\n\n`PromisePool` exposes 3 methods:\n\n- **`.add(...tasks)`** - add one (or more) tasks for background processing. (A task is a function that wraps a `Promise` value. e.g. `() => Promise.resolve(1)`).\n- **`.drain()`** - Returns a promise that resolves when all tasks have been processed, or another thread takes over waiting by calling `.drain()` again.\n- **`.done()`** - Drains AND 'finalizes' the pool. _No more tasks can be added after this._ Can be called from multiple threads, only runs once.\n\n> See either the [Usage](#usage) Section below, or checkout the [`/examples`](/examples/) folder for more complete examples.\n\n## Install\n  \n```sh\n# with npm\nnpm install @elite-libs/promise-pool\n# or using yarn\nyarn add @elite-libs/promise-pool\n```\n\n## Usage\n\n### Minimal Example\n\n```typescript\nimport PromisePool from '@elite-libs/promise-pool';\n// 1/3: Either use the default instance or create a new one.\nconst pool = new PromisePool();\n\n(async () => {\n  // 2/3: Add task(s) to the pool as needed.\n  // PromisePool will execute them in parallel as soon as possible.\n  pool.add(() => saveToS3(data));\n  pool.add(() => expensiveBackgroundWork(data));\n  \n  // 3/3: REQUIRED: in order to ensure your tasks are executed, \n  // you must await either `pool.drain()` or `pool.done()` at some point in your code (`done` prevents additional tasks from being added).\n  await pool.drain();\n})();\n```\n\n### Singleton Pattern\n\n> **Recommended** for virtually all projects. (API, CLI, Lambda, Frontend, etc.)\n\nThe singleton pattern creates exactly 1 `Promise Pool` - as soon as the script is imported (typically on the first run).\n\nThis ensures the `maxWorkers` value will act as a **global limit** on the number of tasks that can run at the same time.\n\n#### **File `/services/taskPoolSingleton.ts`**\n\n```typescript\nimport PromisePool from '@elite-libs/promise-pool';\n\nexport const taskPool = new PromisePool({\n  maxWorkers: 6, // Optional. Default is `4`.\n});\n```\n\n<!-- ### Multiple Pools (Factory Pattern)\n\nHere a Factory Function (a fancy name for a _function that makes things_) is used to standardize options for this particular app.\n\n#### **File `/services/taskPoolFactory.ts`**\n\n```typescript\nimport PromisePool from '@elite-libs/promise-pool';\n\nexport function taskPoolFactory() {\n  return new PromisePool({\n    maxWorkers: 6, // Optional. Default is `4`.\n  });\n}\n``` -->\n\n<!-- Then from inside your app (Lambda function, Express app, etc.), you can use the `taskPool` instance to add tasks to the pool. -->\n\n## Recipes\n\nSee examples below, or check out the [`/examples`](/examples/) folder for more complete examples.\n\n### AWS Lambda & Middy\n\n`Promise Pool` in some [`middy`](https://middy.js.org/) middleware:\n\n#### **File 1/2 `./services/taskPoolMiddleware.ts`**\n\n**Note:** The imported `taskPool` is a [singleton instance defined in the `taskPoolSingleton` file](#singleton-pattern).\n\n```typescript\nimport { taskPool } from './services/taskPoolSingleton';\n\nexport const taskPoolMiddleware = () => ({\n  before: (request) => {\n    Object.assign(request.context, { taskPool });\n  },\n  after: async (request) => {\n    await request.context.taskPool.drain();\n  }\n});\n```\n\nNow you can use `taskPool` in your Lambda function via `event.context.taskPool`:\n\n#### **File 2/2 `./handlers/example.handler.ts`**\n\n```typescript\nimport middy from '@middy/core';\nimport { taskPoolMiddleware } from './services/taskPoolMiddleware';\n\nconst handleEvent = (event) => {\n  const { taskPool } = event.context;\n\n  const data = getDataFromEvent(event);\n\n  taskPool.add(() => saveToS3(data));\n  taskPool.add(() => expensiveBackgroundWork(data));\n  \n  return {\n    statusCode: 200,\n    body: JSON.stringify({\n      message: 'Success',\n    }),\n  }\n}\n\nexport const handler = middy(handleEvent)\n  .use(taskPoolMiddleware());\n\n```\n\n<!-- The `.drain()` method will be called automatically `after()` every Lambda function returns. -->\n\n### Express Middleware\n\n#### **File 1/3 `/services/taskPoolSingleton.mjs`**\n\n```js\nimport PromisePool from '@elite-libs/promise-pool'\n\nexport const taskPool = new PromisePool({\n  maxWorkers: 6 // Optional. Default is `4`.\n})\n```\n\n#### **File 2/3 `/middleware/taskPool.middleware.mjs`**\n\n```js\nimport { taskPool } from \"../services/taskPoolSingleton.mjs\";\n\nconst taskPoolMiddleware = {\n  setup: (request, response, next) => {\n    request.taskPool = taskPool\n    next()\n  },\n  cleanup: (request, response, next) => {\n    if (request.taskPool && 'drain' in request.taskPool) {\n      taskPool.drain()\n    }\n    next()\n  }\n}\n\nexport default taskPoolMiddleware\n```\n\nTo use the `taskPoolMiddleware` in your Express app, you'd include `taskPoolMiddleware.setup()` and `taskPoolMiddleware.cleanup()`.\n\n#### **File 3/3 `/app.mjs`**\n\n```js\nimport taskPoolMiddleware from \"../middleware/taskPool.middleware.mjs\"\n\nexport const app = express()\n\n// Step 1/2: Setup the taskPool\napp.use(taskPoolMiddleware.setup)\napp.use(express.bodyParser())\n\napp.post('/users/', function post(request, response, next) {\n    const { taskPool } = request\n\n    const data = getDataFromBody(request.body)\n\n    // You can .add() tasks wherever needed,\n    //   - they'll run in the background.\n    taskPool.add(() => logMetrics(data))\n    taskPool.add(() => saveToS3(request))\n    taskPool.add(() => expensiveBackgroundWork(data))\n    \n    // Or, 'schedule' multiple tasks at once.\n    taskPool.add(\n      () => logMetrics(data), \n      () => saveToS3(request),\n      () => expensiveBackgroundWork(data)\n    )\n\n    next()\n  })\n\n// Step 2/2: Drain the taskPool\napp.use(taskPoolMiddleware.cleanup)\n```\n\n<!-- ### Lambda & `Promise Pool` Usage\n\n#### **File `/handlers/user.handler.ts`**\n\n```typescript\nimport { taskPool } from './services/taskPoolSingleton';\n\nexport const handler = async (event, context) => {\n  const data = getDataFromEvent(event);\n\n// The following tasks will execute (roughly) at the same time\n  taskPool.add(() => logMetrics(data));\n  taskPool.add(() => saveToS3(request));\n  taskPool.add(() => expensiveBackgroundWork(data));\n  \n// Calling `await taskPool.drain()` will wait for all tasks to complete.\n  await taskPool.drain();\n\n  return {\n    statusCode: 200,\n    body: JSON.stringify({\n      message: 'Success',\n    }),\n  }\n}\n```\n\n⚠️ Note the `await taskPool.drain()` call. This is required to ensure your tasks are executed. -->\n\n## Changelog\n\n### v1.3.1 - **April 2023**\n\n- Upgraded dev dependencies (dependabot).\n- Cleaned up README code & description.\n\n### v1.3.0 - **September 2022**\n\n- _What?_ Adds Smart `.drain()` behavior.\n- _Why?_\n  1. Speeds up concurrent server environments!\n  1. prevents several types of difficult (ghost) bugs!\n      - stack overflows/mem access violations,\n      - exceeding rarely hit OS limits, (e.g. max open handle/file/socket limits)\n      - exceeding limits of Network hardware (e.g. connections/sec, total open socket limit, etc.)\n      - uneven observed wait times.\n- _How?_ Only awaits the latest `.drain()` caller.\n- _Who?_ `Server` + `Singleton` use cases will see a major benefit to this design.\n- _Huh?_ [See diagram](#smart-multi-threaded-execution)\n","readmeFilename":"README.md"}