1 import { dirname
, extname
, join
} from
'node:path'
2 import { fileURLToPath
} from
'node:url'
8 import { type RawData
, WebSocketServer
} from
'ws'
10 type ClusterWorkerData
,
11 type ClusterWorkerResponse
,
15 type ThreadWorkerData
,
16 type ThreadWorkerResponse
19 const emptyFunction
= (): void => {
23 class WebSocketServerWorker
extends ClusterWorker
<
27 private static readonly startWebSocketServer
= (
28 workerData
?: ClusterWorkerData
29 ): ClusterWorkerResponse
=> {
30 const { port
} = workerData
as ClusterWorkerData
31 const wss
= new WebSocketServer({ port
}, () => {
33 `⚡️[ws server]: WebSocket server is started in cluster worker at ws://localhost:${port}/`
37 wss
.on('connection', ws
=> {
38 ws
.on('error', console
.error
)
39 ws
.on('message', (message
: RawData
) => {
40 const { type, data
} = JSON
.parse(
41 // eslint-disable-next-line @typescript-eslint/no-base-to-string
43 ) as MessagePayload
<DataPayload
>
45 case MessageType
.echo
:
46 this.requestHandlerPool
47 .execute({ data
}, 'echo')
51 type: MessageType
.echo
,
59 case MessageType
.factorial
:
60 this.requestHandlerPool
61 .execute({ data
}, 'factorial')
65 type: MessageType
.factorial
,
78 port
: wss
.options
.port
82 private static readonly requestHandlerWorkerFile
= join(
83 dirname(fileURLToPath(import.meta
.url
)),
84 `request-handler-worker${extname(fileURLToPath(import.meta.url))}`
87 private static readonly requestHandlerPool
= new DynamicThreadPool
<
88 ThreadWorkerData
<DataPayload
>,
89 ThreadWorkerResponse
<DataPayload
>
92 Math.round(availableParallelism() / 2),
93 WebSocketServerWorker
.requestHandlerWorkerFile
,
95 enableTasksQueue
: true,
99 errorHandler
: (e
: Error) => {
100 console
.error('Thread worker error:', e
)
105 public constructor () {
106 super(WebSocketServerWorker
.startWebSocketServer
)
110 export const webSocketServerWorker
= new WebSocketServerWorker()