refactor: renable standard JS linter rules
[poolifier.git] / src / pools / cluster / fixed.ts
1 import cluster, { type Worker } from 'node:cluster'
2 import type { MessageValue } from '../../utility-types.js'
3 import { AbstractPool } from '../abstract-pool.js'
4 import { type PoolOptions, type PoolType, PoolTypes } from '../pool.js'
5 import { type WorkerType, WorkerTypes } from '../worker.js'
6
7 /**
8 * Options for a poolifier cluster pool.
9 */
10 export type ClusterPoolOptions = PoolOptions<Worker>
11
12 /**
13 * A cluster pool with a fixed number of workers.
14 *
15 * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data.
16 * @typeParam Response - Type of execution response. This can only be structured-cloneable data.
17 * @author [Christopher Quadflieg](https://github.com/Shinigami92)
18 * @since 2.0.0
19 */
20 export class FixedClusterPool<
21 Data = unknown,
22 Response = unknown
23 > extends AbstractPool<Worker, Data, Response> {
24 /**
25 * Constructs a new poolifier fixed cluster pool.
26 *
27 * @param numberOfWorkers - Number of workers for this pool.
28 * @param filePath - Path to an implementation of a `ClusterWorker` file, which can be relative or absolute.
29 * @param opts - Options for this fixed cluster pool.
30 */
31 public constructor (
32 numberOfWorkers: number,
33 filePath: string,
34 opts: ClusterPoolOptions = {},
35 maximumNumberOfWorkers?: number
36 ) {
37 super(numberOfWorkers, filePath, opts, maximumNumberOfWorkers)
38 }
39
40 /** @inheritDoc */
41 protected setupHook (): void {
42 cluster.setupPrimary({ ...this.opts.settings, exec: this.filePath })
43 }
44
45 /** @inheritDoc */
46 protected isMain (): boolean {
47 return cluster.isPrimary
48 }
49
50 /** @inheritDoc */
51 protected sendToWorker (
52 workerNodeKey: number,
53 message: MessageValue<Data>
54 ): void {
55 this.workerNodes[workerNodeKey].worker.send({
56 ...message,
57 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
58 workerId: this.getWorkerInfo(workerNodeKey).id!
59 })
60 }
61
62 /** @inheritDoc */
63 protected sendStartupMessageToWorker (workerNodeKey: number): void {
64 this.sendToWorker(workerNodeKey, {
65 ready: false
66 })
67 }
68
69 /** @inheritDoc */
70 protected registerWorkerMessageListener<Message extends Data | Response>(
71 workerNodeKey: number,
72 listener: (message: MessageValue<Message>) => void
73 ): void {
74 this.workerNodes[workerNodeKey].worker.on('message', listener)
75 }
76
77 /** @inheritDoc */
78 protected registerOnceWorkerMessageListener<Message extends Data | Response>(
79 workerNodeKey: number,
80 listener: (message: MessageValue<Message>) => void
81 ): void {
82 this.workerNodes[workerNodeKey].worker.once('message', listener)
83 }
84
85 /** @inheritDoc */
86 protected deregisterWorkerMessageListener<Message extends Data | Response>(
87 workerNodeKey: number,
88 listener: (message: MessageValue<Message>) => void
89 ): void {
90 this.workerNodes[workerNodeKey].worker.off('message', listener)
91 }
92
93 /** @inheritDoc */
94 protected shallCreateDynamicWorker (): boolean {
95 return false
96 }
97
98 /** @inheritDoc */
99 protected checkAndEmitDynamicWorkerCreationEvents (): void {
100 /* noop */
101 }
102
103 /** @inheritDoc */
104 protected get type (): PoolType {
105 return PoolTypes.fixed
106 }
107
108 /** @inheritDoc */
109 protected get worker (): WorkerType {
110 return WorkerTypes.cluster
111 }
112
113 /** @inheritDoc */
114 protected get busy (): boolean {
115 return this.internalBusy()
116 }
117 }