1 import type { Server
} from
'node:http'
2 import type { AddressInfo
} from
'node:net'
4 import express
, { type Express
, type Request
, type Response
} from
'express'
13 ClusterWorkerResponse
,
19 const emptyFunction
= (): void => {
23 class ExpressWorker
extends ClusterWorker
<
27 private static server
: Server
28 private static requestHandlerPool
: DynamicThreadPool
<
29 ThreadWorkerData
<DataPayload
>,
30 ThreadWorkerResponse
<DataPayload
>
33 private static readonly startExpress
= (
34 workerData
?: ClusterWorkerData
35 ): ClusterWorkerResponse
=> {
36 const { port
, workerFile
, minWorkers
, maxWorkers
, ...poolOptions
} =
37 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
40 ExpressWorker
.requestHandlerPool
= new DynamicThreadPool
<
41 ThreadWorkerData
<DataPayload
>,
42 ThreadWorkerResponse
<DataPayload
>
45 maxWorkers
?? availableParallelism(),
50 const application
: Express
= express()
52 // Parse only JSON requests body
53 application
.use(express
.json())
55 application
.all('/api/echo', (req
: Request
, res
: Response
) => {
56 ExpressWorker
.requestHandlerPool
57 .execute({ data
: req
.body
}, 'echo')
59 return res
.send(response
.data
).end()
64 application
.get('/api/factorial/:number', (req
: Request
, res
: Response
) => {
65 const { number } = req
.params
66 ExpressWorker
.requestHandlerPool
67 .execute({ data
: { number: Number.parseInt(number) } }, 'factorial')
69 return res
.send(response
.data
).end()
74 let listenerPort
: number | undefined
75 ExpressWorker
.server
= application
.listen(port
, () => {
76 listenerPort
= (ExpressWorker
.server
.address() as AddressInfo
).port
78 `⚡️[express server]: Express server is started in cluster worker at http://localhost:${listenerPort.toString()}/`
83 port
: listenerPort
?? port
,
87 public constructor () {
88 super(ExpressWorker
.startExpress
, {
89 killHandler
: async () => {
90 await ExpressWorker
.requestHandlerPool
.destroy()
91 ExpressWorker
.server
.close()
97 export const expressWorker
= new ExpressWorker()