build: reenable eslint type checking
[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
6e5d7052 57 // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
d0ed34c9 58 .execute({ data: req.body }, 'echo')
041dc05b 59 .then(response => {
d0ed34c9
JB
60 return res.send(response.data).end()
61 })
62 .catch(emptyFunction)
63 })
64
65 application.get('/api/factorial/:number', (req: Request, res: Response) => {
66 const { number } = req.params
67 ExpressWorker.requestHandlerPool
80115618 68 .execute({ data: { number: Number.parseInt(number) } }, 'factorial')
041dc05b 69 .then(response => {
d0ed34c9
JB
70 return res.send(response.data).end()
71 })
72 .catch(emptyFunction)
73 })
74
b7172bc0 75 let listenerPort: number | undefined
d0ed34c9 76 ExpressWorker.server = application.listen(port, () => {
b7172bc0 77 listenerPort = (ExpressWorker.server.address() as AddressInfo).port
d0ed34c9 78 console.info(
6e5d7052 79 `⚡️[express server]: Express server is started in cluster worker at http://localhost:${listenerPort.toString()}/`
d0ed34c9
JB
80 )
81 })
82 return {
83 status: true,
3a502712 84 port: listenerPort ?? port,
d0ed34c9
JB
85 }
86 }
87
88 public constructor () {
89 super(ExpressWorker.startExpress, {
90 killHandler: async () => {
91 await ExpressWorker.requestHandlerPool.destroy()
92 ExpressWorker.server.close()
3a502712 93 },
d0ed34c9
JB
94 })
95 }
96}
97
98export const expressWorker = new ExpressWorker()