chore: migrate to eslint 9
[poolifier.git] / examples / typescript / http-server-pool / express-hybrid / src / express-worker.ts
CommitLineData
a449b585
JB
1import type { Server } from 'node:http'
2import type { AddressInfo } from 'node:net'
ded253e2
JB
3
4import express, { type Express, type Request, type Response } from 'express'
d0ed34c9 5import {
ded253e2 6 availableParallelism,
d0ed34c9 7 ClusterWorker,
3a502712 8 DynamicThreadPool,
d0ed34c9 9} from 'poolifier'
ded253e2 10
80115618
JB
11import type {
12 ClusterWorkerData,
13 ClusterWorkerResponse,
14 DataPayload,
15 ThreadWorkerData,
3a502712 16 ThreadWorkerResponse,
d0ed34c9
JB
17} from './types.js'
18
19const emptyFunction = (): void => {
8ea47589 20 /* Intentional */
d0ed34c9
JB
21}
22
23class ExpressWorker extends ClusterWorker<
3a502712
JB
24 ClusterWorkerData,
25 ClusterWorkerResponse
d0ed34c9
JB
26> {
27 private static server: Server
28 private static requestHandlerPool: DynamicThreadPool<
3a502712
JB
29 ThreadWorkerData<DataPayload>,
30 ThreadWorkerResponse<DataPayload>
d0ed34c9
JB
31 >
32
33 private static readonly startExpress = (
34 workerData?: ClusterWorkerData
35 ): ClusterWorkerResponse => {
7d9756e3 36 const { port, workerFile, minWorkers, maxWorkers, ...poolOptions } =
3a502712 37 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
67f3f2d6 38 workerData!
d0ed34c9
JB
39
40 ExpressWorker.requestHandlerPool = new DynamicThreadPool<
3a502712
JB
41 ThreadWorkerData<DataPayload>,
42 ThreadWorkerResponse<DataPayload>
d0ed34c9
JB
43 >(
44 minWorkers ?? 1,
45 maxWorkers ?? availableParallelism(),
46 workerFile,
7d9756e3 47 poolOptions
d0ed34c9
JB
48 )
49
50 const application: Express = express()
51
52 // Parse only JSON requests body
53 application.use(express.json())
54
55 application.all('/api/echo', (req: Request, res: Response) => {
56 ExpressWorker.requestHandlerPool
57 .execute({ data: req.body }, 'echo')
041dc05b 58 .then(response => {
d0ed34c9
JB
59 return res.send(response.data).end()
60 })
61 .catch(emptyFunction)
62 })
63
64 application.get('/api/factorial/:number', (req: Request, res: Response) => {
65 const { number } = req.params
66 ExpressWorker.requestHandlerPool
80115618 67 .execute({ data: { number: Number.parseInt(number) } }, 'factorial')
041dc05b 68 .then(response => {
d0ed34c9
JB
69 return res.send(response.data).end()
70 })
71 .catch(emptyFunction)
72 })
73
b7172bc0 74 let listenerPort: number | undefined
d0ed34c9 75 ExpressWorker.server = application.listen(port, () => {
b7172bc0 76 listenerPort = (ExpressWorker.server.address() as AddressInfo).port
d0ed34c9 77 console.info(
b7172bc0 78 `⚡️[express server]: Express server is started in cluster worker at http://localhost:${listenerPort}/`
d0ed34c9
JB
79 )
80 })
81 return {
82 status: true,
3a502712 83 port: listenerPort ?? port,
d0ed34c9
JB
84 }
85 }
86
87 public constructor () {
88 super(ExpressWorker.startExpress, {
89 killHandler: async () => {
90 await ExpressWorker.requestHandlerPool.destroy()
91 ExpressWorker.server.close()
3a502712 92 },
d0ed34c9
JB
93 })
94 }
95}
96
97export const expressWorker = new ExpressWorker()