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