pwi-plata-type 0.4.166 → 0.4.167
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/__BUILD__/libs/sql.js +4 -1
- package/__BUILD__/libs/sql.js.map +1 -1
- package/package.json +53 -53
- package/src/@types/build.d.ts +26 -26
- package/src/@types/cluster.actions.d.ts +27 -27
- package/src/@types/cluster.d.ts +55 -55
- package/src/@types/create-cli.d.ts +8 -8
- package/src/@types/exported.d.ts +31 -31
- package/src/@types/fs.d.ts +6 -6
- package/src/@types/global.d.ts +113 -113
- package/src/@types/knex.d.ts +13 -13
- package/src/@types/model.d.ts +143 -143
- package/src/@types/router.d.ts +107 -107
- package/src/@types/sql.d.ts +75 -75
- package/src/@types/swagger.d.ts +22 -22
- package/src/bin/extras/create-api-cli.ts +218 -218
- package/src/bin/extras/create-cluster-cli.ts +160 -160
- package/src/bin/extras/create-lib-cli.ts +84 -84
- package/src/bin/extras/plata-create-tools.ts +97 -97
- package/src/bin/plata-api.ts +189 -189
- package/src/bin/plata-build.ts +17 -17
- package/src/bin/plata-cluster.ts +42 -42
- package/src/bin/plata-cmd.ts +18 -18
- package/src/bin/plata-create.ts +49 -49
- package/src/bin/plata-runtime.ts +131 -131
- package/src/bin/plata-swagger.ts +99 -99
- package/src/bin/runtime/_setupRuntime.ts +48 -48
- package/src/bin/runtime/_types.d.ts +7 -7
- package/src/bin/runtime/class.ts +20 -20
- package/src/bin/runtime/dirs.ts +25 -25
- package/src/bin/runtime/effect.ts +60 -60
- package/src/bin/runtime/fs.ts +10 -10
- package/src/bin/runtime/promises.ts +18 -18
- package/src/bin/runtime/require.ts +113 -113
- package/src/bin/runtime/sql.ts +12 -12
- package/src/bin/runtime/switch.ts +60 -60
- package/src/index.ts +19 -19
- package/src/libs/axios.ts +51 -51
- package/src/libs/build.ts +162 -162
- package/src/libs/cluster/cluster-controller.ts +93 -93
- package/src/libs/cluster.ts +330 -330
- package/src/libs/custom.ts +15 -15
- package/src/libs/env.ts +10 -10
- package/src/libs/fs.ts +399 -399
- package/src/libs/hot-reload.ts +63 -63
- package/src/libs/models/index.ts +4 -4
- package/src/libs/models/model-template-combine.ts +93 -93
- package/src/libs/models/model-template-env.ts +58 -58
- package/src/libs/models/model-template-union.ts +83 -83
- package/src/libs/models/model-template.ts +107 -107
- package/src/libs/models/model-validations.ts +443 -443
- package/src/libs/models/tools.ts +194 -194
- package/src/libs/router.ts +185 -185
- package/src/libs/sql.ts +792 -788
- package/src/libs/swagger.ts +81 -81
- package/src/libs/tools.ts +240 -240
- package/src/scripts/post-install/api.ts +32 -32
- package/src/scripts/post-install/cluster.ts +28 -28
- package/src/scripts/post-install/lib.ts +25 -25
- package/src/scripts/post-install.ts +64 -64
- package/src/scripts/pre-test.ts +33 -33
- package/src/tests/assets/sql/example.sql +76 -76
- package/src/tests/config.test.ts +12 -12
- package/src/tests/effect.test.ts +62 -62
- package/src/tests/model.env.test.ts +66 -66
- package/src/tests/model.test.ts +141 -141
- package/src/tests/model.union.test.ts +160 -160
- package/src/tests/router.test.ts +44 -44
- package/src/tests/sql.test.ts +502 -502
- package/src/tests/switch.test.ts +76 -76
- package/templates/create-cli/class.ts +13 -13
- package/templates/create-cli/cluster.ts +14 -14
- package/templates/create-cli/cmd.ts +3 -3
- package/templates/create-cli/config.ts +2 -2
- package/templates/create-cli/lib.ts +3 -3
- package/templates/create-cli/model.ts +14 -14
- package/templates/create-cli/route.ts +8 -8
- package/templates/create-cli/task.ts +13 -13
- package/templates/postinstall/api/.vscode/launch.json +20 -20
- package/templates/postinstall/api/Dockerfile +24 -24
- package/templates/postinstall/api/configs/env.ts +2 -2
- package/templates/postinstall/api/envs/debug.env +15 -15
- package/templates/postinstall/api/envs/homolog.env +15 -15
- package/templates/postinstall/api/envs/prod.env +15 -15
- package/templates/postinstall/api/tsconfig.json +24 -24
- package/templates/postinstall/cluster/.vscode/launch.json +20 -20
- package/templates/postinstall/cluster/Dockerfile +24 -24
- package/templates/postinstall/cluster/configs/env.ts +2 -2
- package/templates/postinstall/cluster/envs/debug.env +10 -10
- package/templates/postinstall/cluster/envs/homolog.env +10 -10
- package/templates/postinstall/cluster/envs/prod.env +10 -10
- package/templates/postinstall/cluster/tsconfig.json +24 -24
- package/templates/postinstall/lib/postinstall-tools.mjs +111 -111
- package/templates/postinstall/lib/postinstall.js +33 -33
- package/templates/postinstall/lib/tsconfig.json +22 -22
- package/templates/swagger-cli/header.json +21 -21
- package/templates/swagger-cli/route/body.json +14 -14
- package/templates/swagger-cli/route/header.json +18 -18
- package/templates/swagger-cli/route/response.json +53 -53
- package/tsconfig.json +28 -28
package/src/libs/cluster.ts
CHANGED
|
@@ -1,331 +1,331 @@
|
|
|
1
|
-
import cluster from "node:cluster";
|
|
2
|
-
import { cpus } from "node:os";
|
|
3
|
-
import { PlataClusterController } from './cluster/cluster-controller'
|
|
4
|
-
|
|
5
|
-
export class PlataClusterManager {
|
|
6
|
-
private readonly NodeCluster = cluster
|
|
7
|
-
|
|
8
|
-
constructor() {
|
|
9
|
-
if (this.NodeCluster.isPrimary) {
|
|
10
|
-
if (!Plata.cluster?.isPrimary) {
|
|
11
|
-
Plata.cluster = {
|
|
12
|
-
isPrimary: true,
|
|
13
|
-
clusters: []
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
if (this.NodeCluster.eventNames().indexOf('exit') === -1) {
|
|
18
|
-
this.NodeCluster.on('exit', (
|
|
19
|
-
t => t._onWorkerKilled(t)
|
|
20
|
-
)(this))
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
if (this.NodeCluster.eventNames().indexOf('message') === -1) {
|
|
24
|
-
this.NodeCluster.on('message', (
|
|
25
|
-
(t) => t._onMessage(t)
|
|
26
|
-
)(this))
|
|
27
|
-
}
|
|
28
|
-
} else {
|
|
29
|
-
Plata.cluster = {
|
|
30
|
-
isPrimary: false
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
public async _startCluster(config: Cluster.WorkerConfig): Promise<MaybePlataError> {
|
|
36
|
-
if (!Plata.cluster.isPrimary) return {
|
|
37
|
-
errorID: 'PBLCLWS0002',
|
|
38
|
-
msg: 'startCluster must be called from primary process',
|
|
39
|
-
error: {
|
|
40
|
-
stack: new Error().stack
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
if (config.workers === undefined) {
|
|
45
|
-
if (config.env === 'prod') {
|
|
46
|
-
config.workers = cpus().length
|
|
47
|
-
} else {
|
|
48
|
-
config.workers = 1
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (config.workers === -1) {
|
|
53
|
-
config.workers = cpus().length
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
if (config.workers === 0) {
|
|
57
|
-
return null
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
console.log(`Starting ${config.workers} workers on cluster ${config.name}`)
|
|
61
|
-
|
|
62
|
-
const cluster: Cluster.ClusterConfig = {
|
|
63
|
-
pids: [],
|
|
64
|
-
config
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
for (let i = 0; i < config.workers; i++) {
|
|
68
|
-
const w = this._fork(config, false)
|
|
69
|
-
|
|
70
|
-
if (w.process.pid === undefined) {
|
|
71
|
-
return {
|
|
72
|
-
errorID: 'PBLCLWS0003',
|
|
73
|
-
msg: `Erro while starting worker ${i} from cluster ${config.name}`,
|
|
74
|
-
error: w.process.exitCode
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
cluster.pids.push(w.process.pid)
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
if (config.controller !== undefined) {
|
|
82
|
-
console.log(`Starting controller worker on cluster ${config.name}`)
|
|
83
|
-
const w = this._fork(config, true)
|
|
84
|
-
|
|
85
|
-
if (w.process.pid === undefined) {
|
|
86
|
-
return {
|
|
87
|
-
errorID: 'PBLCLWS0003',
|
|
88
|
-
msg: `Erro while starting controller worker from cluster ${config.name}`,
|
|
89
|
-
error: w.process.exitCode
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
cluster.controllerPid = w.process.pid
|
|
94
|
-
cluster.pids.push(w.process.pid)
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
if (config.onExit !== undefined) {
|
|
98
|
-
this.NodeCluster.on(this.getClusterEvents(config.name).worker.exit, config.onExit)
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
Plata.cluster.clusters.push(cluster)
|
|
102
|
-
|
|
103
|
-
return null
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
public isPrimary() {
|
|
107
|
-
return this.NodeCluster.isPrimary
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
public _fork(config: Cluster.WorkerConfig, isController: boolean) {
|
|
111
|
-
return this.NodeCluster.fork({
|
|
112
|
-
...config.workersEnv,
|
|
113
|
-
ENV: config.env,
|
|
114
|
-
_PLATA_WORKER_NAME: config.name,
|
|
115
|
-
_PLATA_WORKER_TYPE: isController ? 'CONTROLLER' : 'WORKER'
|
|
116
|
-
})
|
|
117
|
-
}
|
|
118
|
-
public getClusterEvents(clusterName: string) {
|
|
119
|
-
const base = `plata.cluster.${clusterName}`
|
|
120
|
-
return {
|
|
121
|
-
worker: {
|
|
122
|
-
exit: `${base}.worker.exit`
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
public _onWorkerKilled(t: this) {
|
|
127
|
-
return (worker: Cluster.Worker, code: number, signal: string) => {
|
|
128
|
-
if (worker.process.pid === undefined) return
|
|
129
|
-
if (!Plata.cluster.isPrimary) return
|
|
130
|
-
|
|
131
|
-
const clusterIndex = Plata.cluster.clusters.findIndex(cluster =>
|
|
132
|
-
cluster.pids.indexOf(worker.process.pid ?? 0) !== -1
|
|
133
|
-
)
|
|
134
|
-
|
|
135
|
-
if (clusterIndex !== -1) {
|
|
136
|
-
const c = Plata.cluster.clusters[clusterIndex]
|
|
137
|
-
|
|
138
|
-
console.log(`O Worker ${worker.process.pid} do cluster ${c.config.name} morreu com o codigo ${code} ${signal ?? ''}`)
|
|
139
|
-
console.log(`Iniciando um novo worker no cluster ${c.config.name}`)
|
|
140
|
-
|
|
141
|
-
cluster.emit(
|
|
142
|
-
t.getClusterEvents(c.config.name).worker.exit,
|
|
143
|
-
worker,
|
|
144
|
-
code,
|
|
145
|
-
signal,
|
|
146
|
-
)
|
|
147
|
-
|
|
148
|
-
const wasController = c.controllerPid === worker.process.pid
|
|
149
|
-
|
|
150
|
-
const w = t._fork(c.config, wasController)
|
|
151
|
-
|
|
152
|
-
const pidIndex = c.pids.indexOf(worker.process.pid)
|
|
153
|
-
|
|
154
|
-
c.pids[pidIndex] = w.process.pid ?? 0
|
|
155
|
-
|
|
156
|
-
if (wasController) {
|
|
157
|
-
c.controllerPid = w.process.pid ?? 0
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
if (c.controllerPid !== undefined) {
|
|
161
|
-
if (wasController) return
|
|
162
|
-
|
|
163
|
-
t._sendMsgToPid(c.controllerPid, {
|
|
164
|
-
action: 'DEAD-WORKER-NOTIFY',
|
|
165
|
-
msg: {
|
|
166
|
-
clusterName: c.config.name,
|
|
167
|
-
newPid: w.process.pid,
|
|
168
|
-
pidDead: worker.process.pid,
|
|
169
|
-
}
|
|
170
|
-
} as any)
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
public async _sendMsgToAllWorkers(msg: Cluster.Actions) {
|
|
177
|
-
if (this.NodeCluster.workers === undefined) return
|
|
178
|
-
|
|
179
|
-
for (const worker of Object.values(this.NodeCluster.workers)) {
|
|
180
|
-
if (worker === undefined) continue
|
|
181
|
-
|
|
182
|
-
worker.send(msg)
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
public async sendMsgToCluster(name: string, msg: Cluster.Actions) {
|
|
187
|
-
if (this.NodeCluster.workers === undefined) return
|
|
188
|
-
if (!Plata.cluster.isPrimary) return
|
|
189
|
-
|
|
190
|
-
const clusterIndex = Plata.cluster.clusters.findIndex(cluster => cluster.config.name === name)
|
|
191
|
-
|
|
192
|
-
if (clusterIndex === -1) return
|
|
193
|
-
|
|
194
|
-
if (Plata.cluster.clusters[clusterIndex].controllerPid !== undefined) {
|
|
195
|
-
return this._sendMsgToPid(Plata.cluster.clusters[clusterIndex].controllerPid, msg)
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
const pids = Plata.cluster.clusters[clusterIndex].pids
|
|
199
|
-
|
|
200
|
-
for (const worker of Object.values(this.NodeCluster.workers)) {
|
|
201
|
-
if (worker === undefined) continue
|
|
202
|
-
|
|
203
|
-
if (pids.includes(worker.process.pid ?? 0))
|
|
204
|
-
worker.send(msg)
|
|
205
|
-
;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
public async _sendMsgToPid<T extends Cluster.Actions>(pid: number, msg: T) {
|
|
210
|
-
if (this.NodeCluster.workers === undefined) return
|
|
211
|
-
if (!Plata.cluster.isPrimary) return
|
|
212
|
-
|
|
213
|
-
for (const worker of Object.values(this.NodeCluster.workers)) {
|
|
214
|
-
if (worker === undefined) continue
|
|
215
|
-
|
|
216
|
-
const wPid = worker.process.pid ?? 0
|
|
217
|
-
|
|
218
|
-
if (wPid === pid)
|
|
219
|
-
worker.send(msg)
|
|
220
|
-
;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
public async _getClusterPids(name: string, id: string) {
|
|
225
|
-
if (this.NodeCluster.workers === undefined)
|
|
226
|
-
return this._sendMsgToAllWorkers({
|
|
227
|
-
action: `GET-PIDS-CLUSTER-RESULT-${id}`,
|
|
228
|
-
msg: {
|
|
229
|
-
errorID: 'PCLGETCLPIDS001',
|
|
230
|
-
msg: 'não tem workers online',
|
|
231
|
-
}
|
|
232
|
-
})
|
|
233
|
-
;
|
|
234
|
-
|
|
235
|
-
if (!Plata.cluster.isPrimary)
|
|
236
|
-
return this._sendMsgToAllWorkers({
|
|
237
|
-
action: `GET-PIDS-CLUSTER-RESULT-${id}`,
|
|
238
|
-
msg: {
|
|
239
|
-
errorID: 'PCLGETCLPIDS002',
|
|
240
|
-
msg: 'não tem workers online',
|
|
241
|
-
}
|
|
242
|
-
})
|
|
243
|
-
;
|
|
244
|
-
|
|
245
|
-
const clusterIndex = Plata.cluster.clusters.findIndex(cluster => cluster.config.name === name)
|
|
246
|
-
|
|
247
|
-
if (clusterIndex === -1)
|
|
248
|
-
return this._sendMsgToAllWorkers({
|
|
249
|
-
action: `GET-PIDS-CLUSTER-RESULT-${id}`,
|
|
250
|
-
msg: {
|
|
251
|
-
errorID: 'PCLGETCLPIDS002',
|
|
252
|
-
msg: 'Cluster não encontrado',
|
|
253
|
-
error: name
|
|
254
|
-
}
|
|
255
|
-
})
|
|
256
|
-
;
|
|
257
|
-
|
|
258
|
-
return this._sendMsgToAllWorkers({
|
|
259
|
-
action: `GET-PIDS-CLUSTER-RESULT-${id}`,
|
|
260
|
-
msg: Plata.cluster.clusters[clusterIndex].pids
|
|
261
|
-
})
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
public _onMessage(t: this) {
|
|
265
|
-
return (worker: Cluster.Worker, actionEvent: Cluster.GetActions<Cluster.PlataClusterActions>) => {
|
|
266
|
-
Plata.switchUnionObject(actionEvent, 'action', {
|
|
267
|
-
_default: async (v) => console.log(`Action inválida: ${actionEvent.action}`),
|
|
268
|
-
|
|
269
|
-
"ECHO-CLUSTER": async ({ msg }) => t.sendMsgToCluster(msg.name, msg.data),
|
|
270
|
-
|
|
271
|
-
'ECHO-PID': async ({ msg }) => t._sendMsgToPid(msg.pid, msg.data),
|
|
272
|
-
|
|
273
|
-
'DEAD-WORKER-NOTIFY': async () => console.log(`Action inválida: ${actionEvent.action}`),
|
|
274
|
-
|
|
275
|
-
ECHO: async ({ msg }) => t._sendMsgToAllWorkers(msg),
|
|
276
|
-
|
|
277
|
-
KILL: async ({ msg }) => {
|
|
278
|
-
console.log(`Process kill requested: ${msg}`)
|
|
279
|
-
process.exit(0)
|
|
280
|
-
},
|
|
281
|
-
|
|
282
|
-
RELOAD: async () => t._sendMsgToAllWorkers({ action: 'RELOAD', msg: true }),
|
|
283
|
-
|
|
284
|
-
"GET-PIDS-CLUSTER": async ({ msg }) => t._getClusterPids(msg.name.toString(), msg.id),
|
|
285
|
-
})
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
public async send(msg: Cluster.Actions): PlataPromise<boolean> {
|
|
290
|
-
if (process.send === undefined) {
|
|
291
|
-
return {
|
|
292
|
-
errorID: 'PBLCLWS0001',
|
|
293
|
-
msg: `process don't have send function`,
|
|
294
|
-
error: {
|
|
295
|
-
stack: new Error().stack
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
return process.send(msg)
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
public async sendToWorkerPid(pid: number, data: Cluster.UserActions) {
|
|
304
|
-
return this.send({
|
|
305
|
-
action: 'ECHO-PID',
|
|
306
|
-
msg: {
|
|
307
|
-
pid,
|
|
308
|
-
data
|
|
309
|
-
}
|
|
310
|
-
})
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
public async _onStartCluster(name: string, type: typeof Plata.config._PLATA_WORKER_TYPE) {
|
|
314
|
-
const c: { default: Cluster.WorkerConfig } = require(`@@/clusters/${name}`)
|
|
315
|
-
|
|
316
|
-
if (type === 'CONTROLLER' && c.default.controller !== undefined) {
|
|
317
|
-
const controller = new PlataClusterController(
|
|
318
|
-
this,
|
|
319
|
-
name,
|
|
320
|
-
)
|
|
321
|
-
|
|
322
|
-
await c.default.controller(controller)
|
|
323
|
-
|
|
324
|
-
return
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
await c.default.onStart()
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
|
|
1
|
+
import cluster from "node:cluster";
|
|
2
|
+
import { cpus } from "node:os";
|
|
3
|
+
import { PlataClusterController } from './cluster/cluster-controller'
|
|
4
|
+
|
|
5
|
+
export class PlataClusterManager {
|
|
6
|
+
private readonly NodeCluster = cluster
|
|
7
|
+
|
|
8
|
+
constructor() {
|
|
9
|
+
if (this.NodeCluster.isPrimary) {
|
|
10
|
+
if (!Plata.cluster?.isPrimary) {
|
|
11
|
+
Plata.cluster = {
|
|
12
|
+
isPrimary: true,
|
|
13
|
+
clusters: []
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (this.NodeCluster.eventNames().indexOf('exit') === -1) {
|
|
18
|
+
this.NodeCluster.on('exit', (
|
|
19
|
+
t => t._onWorkerKilled(t)
|
|
20
|
+
)(this))
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (this.NodeCluster.eventNames().indexOf('message') === -1) {
|
|
24
|
+
this.NodeCluster.on('message', (
|
|
25
|
+
(t) => t._onMessage(t)
|
|
26
|
+
)(this))
|
|
27
|
+
}
|
|
28
|
+
} else {
|
|
29
|
+
Plata.cluster = {
|
|
30
|
+
isPrimary: false
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public async _startCluster(config: Cluster.WorkerConfig): Promise<MaybePlataError> {
|
|
36
|
+
if (!Plata.cluster.isPrimary) return {
|
|
37
|
+
errorID: 'PBLCLWS0002',
|
|
38
|
+
msg: 'startCluster must be called from primary process',
|
|
39
|
+
error: {
|
|
40
|
+
stack: new Error().stack
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (config.workers === undefined) {
|
|
45
|
+
if (config.env === 'prod') {
|
|
46
|
+
config.workers = cpus().length
|
|
47
|
+
} else {
|
|
48
|
+
config.workers = 1
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (config.workers === -1) {
|
|
53
|
+
config.workers = cpus().length
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (config.workers === 0) {
|
|
57
|
+
return null
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
console.log(`Starting ${config.workers} workers on cluster ${config.name}`)
|
|
61
|
+
|
|
62
|
+
const cluster: Cluster.ClusterConfig = {
|
|
63
|
+
pids: [],
|
|
64
|
+
config
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
for (let i = 0; i < config.workers; i++) {
|
|
68
|
+
const w = this._fork(config, false)
|
|
69
|
+
|
|
70
|
+
if (w.process.pid === undefined) {
|
|
71
|
+
return {
|
|
72
|
+
errorID: 'PBLCLWS0003',
|
|
73
|
+
msg: `Erro while starting worker ${i} from cluster ${config.name}`,
|
|
74
|
+
error: w.process.exitCode
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
cluster.pids.push(w.process.pid)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (config.controller !== undefined) {
|
|
82
|
+
console.log(`Starting controller worker on cluster ${config.name}`)
|
|
83
|
+
const w = this._fork(config, true)
|
|
84
|
+
|
|
85
|
+
if (w.process.pid === undefined) {
|
|
86
|
+
return {
|
|
87
|
+
errorID: 'PBLCLWS0003',
|
|
88
|
+
msg: `Erro while starting controller worker from cluster ${config.name}`,
|
|
89
|
+
error: w.process.exitCode
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
cluster.controllerPid = w.process.pid
|
|
94
|
+
cluster.pids.push(w.process.pid)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (config.onExit !== undefined) {
|
|
98
|
+
this.NodeCluster.on(this.getClusterEvents(config.name).worker.exit, config.onExit)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
Plata.cluster.clusters.push(cluster)
|
|
102
|
+
|
|
103
|
+
return null
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
public isPrimary() {
|
|
107
|
+
return this.NodeCluster.isPrimary
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
public _fork(config: Cluster.WorkerConfig, isController: boolean) {
|
|
111
|
+
return this.NodeCluster.fork({
|
|
112
|
+
...config.workersEnv,
|
|
113
|
+
ENV: config.env,
|
|
114
|
+
_PLATA_WORKER_NAME: config.name,
|
|
115
|
+
_PLATA_WORKER_TYPE: isController ? 'CONTROLLER' : 'WORKER'
|
|
116
|
+
})
|
|
117
|
+
}
|
|
118
|
+
public getClusterEvents(clusterName: string) {
|
|
119
|
+
const base = `plata.cluster.${clusterName}`
|
|
120
|
+
return {
|
|
121
|
+
worker: {
|
|
122
|
+
exit: `${base}.worker.exit`
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
public _onWorkerKilled(t: this) {
|
|
127
|
+
return (worker: Cluster.Worker, code: number, signal: string) => {
|
|
128
|
+
if (worker.process.pid === undefined) return
|
|
129
|
+
if (!Plata.cluster.isPrimary) return
|
|
130
|
+
|
|
131
|
+
const clusterIndex = Plata.cluster.clusters.findIndex(cluster =>
|
|
132
|
+
cluster.pids.indexOf(worker.process.pid ?? 0) !== -1
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
if (clusterIndex !== -1) {
|
|
136
|
+
const c = Plata.cluster.clusters[clusterIndex]
|
|
137
|
+
|
|
138
|
+
console.log(`O Worker ${worker.process.pid} do cluster ${c.config.name} morreu com o codigo ${code} ${signal ?? ''}`)
|
|
139
|
+
console.log(`Iniciando um novo worker no cluster ${c.config.name}`)
|
|
140
|
+
|
|
141
|
+
cluster.emit(
|
|
142
|
+
t.getClusterEvents(c.config.name).worker.exit,
|
|
143
|
+
worker,
|
|
144
|
+
code,
|
|
145
|
+
signal,
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
const wasController = c.controllerPid === worker.process.pid
|
|
149
|
+
|
|
150
|
+
const w = t._fork(c.config, wasController)
|
|
151
|
+
|
|
152
|
+
const pidIndex = c.pids.indexOf(worker.process.pid)
|
|
153
|
+
|
|
154
|
+
c.pids[pidIndex] = w.process.pid ?? 0
|
|
155
|
+
|
|
156
|
+
if (wasController) {
|
|
157
|
+
c.controllerPid = w.process.pid ?? 0
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (c.controllerPid !== undefined) {
|
|
161
|
+
if (wasController) return
|
|
162
|
+
|
|
163
|
+
t._sendMsgToPid(c.controllerPid, {
|
|
164
|
+
action: 'DEAD-WORKER-NOTIFY',
|
|
165
|
+
msg: {
|
|
166
|
+
clusterName: c.config.name,
|
|
167
|
+
newPid: w.process.pid,
|
|
168
|
+
pidDead: worker.process.pid,
|
|
169
|
+
}
|
|
170
|
+
} as any)
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
public async _sendMsgToAllWorkers(msg: Cluster.Actions) {
|
|
177
|
+
if (this.NodeCluster.workers === undefined) return
|
|
178
|
+
|
|
179
|
+
for (const worker of Object.values(this.NodeCluster.workers)) {
|
|
180
|
+
if (worker === undefined) continue
|
|
181
|
+
|
|
182
|
+
worker.send(msg)
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
public async sendMsgToCluster(name: string, msg: Cluster.Actions) {
|
|
187
|
+
if (this.NodeCluster.workers === undefined) return
|
|
188
|
+
if (!Plata.cluster.isPrimary) return
|
|
189
|
+
|
|
190
|
+
const clusterIndex = Plata.cluster.clusters.findIndex(cluster => cluster.config.name === name)
|
|
191
|
+
|
|
192
|
+
if (clusterIndex === -1) return
|
|
193
|
+
|
|
194
|
+
if (Plata.cluster.clusters[clusterIndex].controllerPid !== undefined) {
|
|
195
|
+
return this._sendMsgToPid(Plata.cluster.clusters[clusterIndex].controllerPid, msg)
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const pids = Plata.cluster.clusters[clusterIndex].pids
|
|
199
|
+
|
|
200
|
+
for (const worker of Object.values(this.NodeCluster.workers)) {
|
|
201
|
+
if (worker === undefined) continue
|
|
202
|
+
|
|
203
|
+
if (pids.includes(worker.process.pid ?? 0))
|
|
204
|
+
worker.send(msg)
|
|
205
|
+
;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
public async _sendMsgToPid<T extends Cluster.Actions>(pid: number, msg: T) {
|
|
210
|
+
if (this.NodeCluster.workers === undefined) return
|
|
211
|
+
if (!Plata.cluster.isPrimary) return
|
|
212
|
+
|
|
213
|
+
for (const worker of Object.values(this.NodeCluster.workers)) {
|
|
214
|
+
if (worker === undefined) continue
|
|
215
|
+
|
|
216
|
+
const wPid = worker.process.pid ?? 0
|
|
217
|
+
|
|
218
|
+
if (wPid === pid)
|
|
219
|
+
worker.send(msg)
|
|
220
|
+
;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
public async _getClusterPids(name: string, id: string) {
|
|
225
|
+
if (this.NodeCluster.workers === undefined)
|
|
226
|
+
return this._sendMsgToAllWorkers({
|
|
227
|
+
action: `GET-PIDS-CLUSTER-RESULT-${id}`,
|
|
228
|
+
msg: {
|
|
229
|
+
errorID: 'PCLGETCLPIDS001',
|
|
230
|
+
msg: 'não tem workers online',
|
|
231
|
+
}
|
|
232
|
+
})
|
|
233
|
+
;
|
|
234
|
+
|
|
235
|
+
if (!Plata.cluster.isPrimary)
|
|
236
|
+
return this._sendMsgToAllWorkers({
|
|
237
|
+
action: `GET-PIDS-CLUSTER-RESULT-${id}`,
|
|
238
|
+
msg: {
|
|
239
|
+
errorID: 'PCLGETCLPIDS002',
|
|
240
|
+
msg: 'não tem workers online',
|
|
241
|
+
}
|
|
242
|
+
})
|
|
243
|
+
;
|
|
244
|
+
|
|
245
|
+
const clusterIndex = Plata.cluster.clusters.findIndex(cluster => cluster.config.name === name)
|
|
246
|
+
|
|
247
|
+
if (clusterIndex === -1)
|
|
248
|
+
return this._sendMsgToAllWorkers({
|
|
249
|
+
action: `GET-PIDS-CLUSTER-RESULT-${id}`,
|
|
250
|
+
msg: {
|
|
251
|
+
errorID: 'PCLGETCLPIDS002',
|
|
252
|
+
msg: 'Cluster não encontrado',
|
|
253
|
+
error: name
|
|
254
|
+
}
|
|
255
|
+
})
|
|
256
|
+
;
|
|
257
|
+
|
|
258
|
+
return this._sendMsgToAllWorkers({
|
|
259
|
+
action: `GET-PIDS-CLUSTER-RESULT-${id}`,
|
|
260
|
+
msg: Plata.cluster.clusters[clusterIndex].pids
|
|
261
|
+
})
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
public _onMessage(t: this) {
|
|
265
|
+
return (worker: Cluster.Worker, actionEvent: Cluster.GetActions<Cluster.PlataClusterActions>) => {
|
|
266
|
+
Plata.switchUnionObject(actionEvent, 'action', {
|
|
267
|
+
_default: async (v) => console.log(`Action inválida: ${actionEvent.action}`),
|
|
268
|
+
|
|
269
|
+
"ECHO-CLUSTER": async ({ msg }) => t.sendMsgToCluster(msg.name, msg.data),
|
|
270
|
+
|
|
271
|
+
'ECHO-PID': async ({ msg }) => t._sendMsgToPid(msg.pid, msg.data),
|
|
272
|
+
|
|
273
|
+
'DEAD-WORKER-NOTIFY': async () => console.log(`Action inválida: ${actionEvent.action}`),
|
|
274
|
+
|
|
275
|
+
ECHO: async ({ msg }) => t._sendMsgToAllWorkers(msg),
|
|
276
|
+
|
|
277
|
+
KILL: async ({ msg }) => {
|
|
278
|
+
console.log(`Process kill requested: ${msg}`)
|
|
279
|
+
process.exit(0)
|
|
280
|
+
},
|
|
281
|
+
|
|
282
|
+
RELOAD: async () => t._sendMsgToAllWorkers({ action: 'RELOAD', msg: true }),
|
|
283
|
+
|
|
284
|
+
"GET-PIDS-CLUSTER": async ({ msg }) => t._getClusterPids(msg.name.toString(), msg.id),
|
|
285
|
+
})
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
public async send(msg: Cluster.Actions): PlataPromise<boolean> {
|
|
290
|
+
if (process.send === undefined) {
|
|
291
|
+
return {
|
|
292
|
+
errorID: 'PBLCLWS0001',
|
|
293
|
+
msg: `process don't have send function`,
|
|
294
|
+
error: {
|
|
295
|
+
stack: new Error().stack
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
return process.send(msg)
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
public async sendToWorkerPid(pid: number, data: Cluster.UserActions) {
|
|
304
|
+
return this.send({
|
|
305
|
+
action: 'ECHO-PID',
|
|
306
|
+
msg: {
|
|
307
|
+
pid,
|
|
308
|
+
data
|
|
309
|
+
}
|
|
310
|
+
})
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
public async _onStartCluster(name: string, type: typeof Plata.config._PLATA_WORKER_TYPE) {
|
|
314
|
+
const c: { default: Cluster.WorkerConfig } = require(`@@/clusters/${name}`)
|
|
315
|
+
|
|
316
|
+
if (type === 'CONTROLLER' && c.default.controller !== undefined) {
|
|
317
|
+
const controller = new PlataClusterController(
|
|
318
|
+
this,
|
|
319
|
+
name,
|
|
320
|
+
)
|
|
321
|
+
|
|
322
|
+
await c.default.controller(controller)
|
|
323
|
+
|
|
324
|
+
return
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
await c.default.onStart()
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
331
|
export * from './cluster/cluster-controller'
|