build(ci): refine autofix GH action
[poolifier.git] / README.md
CommitLineData
f2b5671a 1<div align="center">
0feeec4a 2 <img src="./images/logo.png" width="340px" height="266px"/>
ddaa3a76 3</div>
4
29527e83
JB
5<div align="center">
6
7# Node.js Worker_Threads and Cluster Worker Pool
8
9</div>
1d4f79e7 10
2030d177 11<div align="center">
29527e83
JB
12
13[![GitHub commit activity (master)](https://img.shields.io/github/commit-activity/m/poolifier/poolifier/master?color=brightgreen&logo=github)](https://github.com/poolifier/poolifier/graphs/commit-activity)
b7bb8586 14[![Npm Version](https://badgen.net/npm/v/poolifier?icon=npm)](https://www.npmjs.com/package/poolifier)
8be1fc23 15[![JSR Version](https://jsr.io/badges/@poolifier/poolifier)](https://jsr.io/@poolifier/poolifier)
4e91d15c 16[![CI Workflow](https://github.com/poolifier/poolifier/actions/workflows/ci.yml/badge.svg)](https://github.com/poolifier/poolifier/actions/workflows/ci.yml)
58c0dd01
JB
17[![Code Coverage](https://sonarcloud.io/api/project_badges/measure?project=poolifier_poolifier&metric=coverage)](https://sonarcloud.io/dashboard?id=poolifier_poolifier)
18[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=poolifier_poolifier&metric=alert_status)](https://sonarcloud.io/dashboard?id=poolifier_poolifier)
5c75390e 19[![neostandard Javascript Code Style](<https://badgen.net/static/code style/neostandard/green>)](https://github.com/neostandard/neostandard)
67c552d6 20[![Discord](https://badgen.net/discord/online-members/vXxZhyb3b6?icon=discord&label=discord&color=green)](https://discord.gg/vXxZhyb3b6)
29527e83 21[![Open Collective](https://opencollective.com/poolifier/tiers/badge.svg)](https://opencollective.com/poolifier)
ae3ab61d 22[![PRs Welcome](https://badgen.net/static/PRs/welcome/green)](https://makeapullrequest.com)
f0c6203d 23[![No Dependencies](<https://badgen.net/static/dependencies/no dependencies/green>)](<https://badgen.net/static/dependencies/no dependencies/green>)
29527e83 24
2030d177 25</div>
1d4f79e7 26
74750c7f 27## Why Poolifier?
e76f5485 28
6ec11f90 29Poolifier is used to perform CPU and/or I/O intensive tasks on Node.js servers, it implements worker pools using [worker_threads](https://nodejs.org/api/worker_threads.html) and [cluster](https://nodejs.org/api/cluster.html) Node.js modules.
50aa7901 30With poolifier you can improve your **performance** and resolve problems related to the event loop.
063f8c5b 31Moreover you can execute your tasks using an API designed to improve the **developer experience**.
b492f20e 32Please consult our [general guidelines](#general-guidelines).
e76f5485 33
bd2ff6e0 34- Easy to use :white_check_mark:
03babf6f 35- Fixed and dynamic pool size :white_check_mark:
6ec11f90 36- Easy switch from a pool type to another :white_check_mark:
5bc19860 37- Performance [benchmarks](./benchmarks/README.md) :white_check_mark:
82be29c0 38- No runtime dependencies :white_check_mark:
d0ed34c9 39- Proper integration with Node.js [async_hooks](https://nodejs.org/api/async_hooks.html) :white_check_mark:
e30fb225 40- Support for CommonJS, ESM and TypeScript :white_check_mark:
6ec11f90 41- Support for [worker_threads](https://nodejs.org/api/worker_threads.html) and [cluster](https://nodejs.org/api/cluster.html) Node.js modules :white_check_mark:
89a4abfd 42- Tasks distribution strategies :white_check_mark:
84de2e11 43- Lockless tasks queueing :white_check_mark:
72695f86 44- Queued tasks rescheduling:
65542a35 45 - Task stealing on idle :white_check_mark:
72695f86 46 - Tasks stealing under back pressure :white_check_mark:
dd951876 47 - Tasks redistribution on worker error :white_check_mark:
0c7b9e90 48- Support for sync and async task function :white_check_mark:
97dc65d9
JB
49- Support for multiple task functions with per task function queuing priority and tasks distribution strategy :white_check_mark:
50- Support for task functions [CRUD](https://en.wikipedia.org/wiki/Create,_read,_update_and_delete) operations at runtime :white_check_mark:
b492f20e 51- General guidelines on pool choice :white_check_mark:
82be29c0 52- Error handling out of the box :white_check_mark:
6ec11f90 53- Widely tested :white_check_mark:
82be29c0 54- Active community :white_check_mark:
58c0dd01
JB
55- Code quality [![Bugs](https://sonarcloud.io/api/project_badges/measure?project=poolifier_poolifier&metric=bugs)](https://sonarcloud.io/dashboard?id=poolifier_poolifier)
56 [![Code Smells](https://sonarcloud.io/api/project_badges/measure?project=poolifier_poolifier&metric=code_smells)](https://sonarcloud.io/dashboard?id=poolifier_poolifier)
57 [![Duplicated Lines (%)](https://sonarcloud.io/api/project_badges/measure?project=poolifier_poolifier&metric=duplicated_lines_density)](https://sonarcloud.io/dashboard?id=poolifier_poolifier)
58 [![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=poolifier_poolifier&metric=sqale_rating)](https://sonarcloud.io/dashboard?id=poolifier_poolifier)
59 [![Reliability Rating](https://sonarcloud.io/api/project_badges/measure?project=poolifier_poolifier&metric=reliability_rating)](https://sonarcloud.io/dashboard?id=poolifier_poolifier)
60 [![Technical Debt](https://sonarcloud.io/api/project_badges/measure?project=poolifier_poolifier&metric=sqale_index)](https://sonarcloud.io/dashboard?id=poolifier_poolifier)
61- Code security [![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=poolifier_poolifier&metric=security_rating)](https://sonarcloud.io/dashboard?id=poolifier_poolifier) [![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=poolifier_poolifier&metric=vulnerabilities)](https://sonarcloud.io/dashboard?id=poolifier_poolifier)
ddaa3a76 62
4f8e444d
JB
63## Table of contents
64
65- [Overview](#overview)
66- [Installation](#installation)
67- [Usage](#usage)
8ea47589 68- [Node.js versions](#nodejs-versions)
4f8e444d
JB
69- [API](#api)
70- [General guidelines](#general-guidelines)
71- [Worker choice strategies](#worker-choice-strategies)
72- [Contribute](#contribute)
73- [Team](#team)
74- [License](#license)
34a572eb 75
50aa7901 76## Overview
13031992 77
22c0d9a2 78Poolifier contains two [worker_threads](https://nodejs.org/api/worker_threads.html#class-worker)/[cluster](https://nodejs.org/api/cluster.html#cluster_class_worker) worker pool implementations, you don't have to deal with [worker_threads](https://nodejs.org/api/worker_threads.html)/[cluster](https://nodejs.org/api/cluster.html) complexity.
03babf6f 79The first implementation is a fixed worker pool, with a defined number of workers that are started at creation time and will be reused.
a36b9e1f 80The second implementation is a dynamic worker pool, with a number of worker started at creation time (these workers will be always active and reused) and other workers created when the load will increase (with an upper limit, these workers will be reused when active), the newly created workers will be stopped after a configurable period of inactivity.
22c0d9a2 81You have to implement your worker by extending the _ThreadWorker_ or _ClusterWorker_ class.
50aa7901
S
82
83## Installation
84
39c93c16 85### npmjs
b7bb8586 86
50aa7901 87```shell
27c5fb75 88npm install poolifier --save
1a4ec243 89```
1a4ec243 90
39c93c16 91### JSR
b7bb8586
JB
92
93```shell
94npx jsr add @poolifier/poolifier
95```
96
50aa7901
S
97## Usage
98
a087069e 99You can implement a poolifier [worker_threads](https://nodejs.org/api/worker_threads.html#class-worker) worker in a simple way by extending the class _ThreadWorker_:
1a4ec243
APA
100
101```js
d35e5717 102import { ThreadWorker } from 'poolifier'
1a4ec243 103
78cea37e 104function yourFunction(data) {
106744f7 105 // this will be executed in the worker thread,
106 // the data will be received by using the execute method
107 return { ok: 1 }
108}
109
50aa7901 110module.exports = new ThreadWorker(yourFunction, {
124119cf 111 maxInactiveTime: 60000
50aa7901 112})
1a4ec243
APA
113```
114
0feeec4a 115Instantiate your pool based on your needs :
1a4ec243
APA
116
117```js
d35e5717 118import { DynamicThreadPool, FixedThreadPool, PoolEvents, availableParallelism } from 'poolifier'
1a4ec243 119
2fbe1783 120// a fixed worker_threads pool
6961ca9a 121const pool = new FixedThreadPool(availableParallelism(), './yourWorker.js', {
3fd93ff2
JB
122 onlineHandler: () => console.info('worker is online'),
123 errorHandler: e => console.error(e)
53795b86 124})
1a4ec243 125
8538ea4c
JB
126pool.emitter?.on(PoolEvents.ready, () => console.info('Pool is ready'))
127pool.emitter?.on(PoolEvents.busy, () => console.info('Pool is busy'))
164d950a 128
2fbe1783 129// or a dynamic worker_threads pool
31a7d5be 130const pool = new DynamicThreadPool(Math.floor(availableParallelism() / 2), availableParallelism(), './yourWorker.js', {
3fd93ff2
JB
131 onlineHandler: () => console.info('worker is online'),
132 errorHandler: e => console.error(e)
53795b86 133})
106744f7 134
8538ea4c
JB
135pool.emitter?.on(PoolEvents.full, () => console.info('Pool is full'))
136pool.emitter?.on(PoolEvents.ready, () => console.info('Pool is ready'))
137pool.emitter?.on(PoolEvents.busy, () => console.info('Pool is busy'))
1a4ec243
APA
138
139// the execute method signature is the same for both implementations,
74ecb519 140// so you can easily switch from one to another
8351c9af 141pool
8923de44 142 .execute()
cb9249cf 143 .then(res => {
8351c9af
JB
144 console.info(res)
145 })
cb9249cf 146 .catch(err => {
8351c9af
JB
147 console.error(err)
148 })
1a4ec243
APA
149```
150
6ec11f90 151You can do the same with the classes _ClusterWorker_, _FixedClusterPool_ and _DynamicClusterPool_.
31b90205 152
b0834e9d 153**See [examples](./examples/) for more details**:
b2b02b3d 154
7a923e5b 155- [Javascript](./examples/javascript/)
b2b02b3d 156- [Typescript](./examples/typescript/)
5ba0cd3c 157 - [HTTP client pool](./examples/typescript/http-client-pool/)
9aef1431 158 - [SMTP client pool](./examples/typescript/smtp-client-pool/)
fac9ce96 159 - [HTTP server pool](./examples/typescript/http-server-pool/)
d2bc8d80 160 - [Express worker_threads pool](./examples/typescript/http-server-pool/express-worker_threads/)
15a9c195 161 - [Express cluster pool](./examples/typescript/http-server-pool/express-cluster/)
d0ed34c9 162 - [Express hybrid pool](./examples/typescript/http-server-pool/express-hybrid/)
d2bc8d80
JB
163 - [Fastify worker_threads pool](./examples/typescript/http-server-pool/fastify-worker_threads/)
164 - [Fastify cluster pool](./examples/typescript/http-server-pool/fastify-cluster/)
3b311539 165 - [Fastify hybrid pool](./examples/typescript/http-server-pool/fastify-hybrid/)
9e623684 166 - [WebSocket server pool](./examples/typescript/websocket-server-pool/)
d2bc8d80 167 - [ws worker_threads pool](./examples/typescript/websocket-server-pool/ws-worker_threads/)
72855e92 168 - [ws cluster pool](./examples/typescript/websocket-server-pool/ws-cluster/)
02999424 169 - [ws hybrid pool](./examples/typescript/websocket-server-pool/ws-hybrid/)
1a4ec243 170
6677a3d3 171Remember that workers can only send and receive structured-cloneable data.
deb85c12 172
8ea47589 173## Node.js versions
34a572eb 174
277c49bf 175Node.js versions >= 18.x.x are supported.
1a4ec243 176
b492f20e 177## [API](./docs/api.md)
4680c1b2 178
4f8e444d
JB
179## [General guidelines](./docs/general-guidelines.md)
180
181## [Worker choice strategies](./docs/worker-choice-strategies.md)
48211d04 182
50aa7901 183## Contribute
34a572eb 184
f097c79b 185Choose your task [here](https://github.com/orgs/poolifier/projects/1), propose an idea, a fix, an improvement.
1a4ec243 186
e6973c72 187See [CONTRIBUTING](./CONTRIBUTING.md) guidelines.
0feeec4a 188
50aa7901 189## Team
1a4ec243 190
39deb558 191**Creator/Owner:**
39deb558 192
50aa7901
S
193- [**Alessandro Pio Ardizio**](https://github.com/pioardi)
194
5c47fa7c 195**Maintainers:**
50aa7901 196
50aa7901 197- [**Jérôme Benoit**](https://github.com/jerome-benoit)
39deb558 198
5c47fa7c
JB
199**Contributors:**
200
201- [**Shinigami92**](https://github.com/Shinigami92)
202
50aa7901 203## License
1a4ec243 204
9507c1d4 205[MIT](./LICENSE)