pwi-plata-type 0.3.18 → 0.4.0
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/__BUILD__/bin/extras/create-api-cli.js +96 -0
- package/__BUILD__/bin/extras/create-api-cli.js.map +1 -0
- package/__BUILD__/bin/extras/create-lib-cli.js +62 -0
- package/__BUILD__/bin/extras/create-lib-cli.js.map +1 -0
- package/__BUILD__/bin/extras/plata-create-tools.js +94 -0
- package/__BUILD__/bin/extras/plata-create-tools.js.map +1 -0
- package/__BUILD__/bin/plata-api.js +138 -0
- package/__BUILD__/bin/plata-api.js.map +1 -0
- package/__BUILD__/bin/plata-create.js +24 -0
- package/__BUILD__/bin/plata-create.js.map +1 -0
- package/__BUILD__/bin/plata-runtime.js +156 -0
- package/__BUILD__/bin/plata-runtime.js.map +1 -0
- package/__BUILD__/bin/plata-swagger.js +82 -0
- package/__BUILD__/bin/plata-swagger.js.map +1 -0
- package/__BUILD__/bin/runtime/_setupRuntime.js +43 -0
- package/__BUILD__/bin/runtime/_setupRuntime.js.map +1 -0
- package/__BUILD__/bin/runtime/class.js +18 -0
- package/__BUILD__/bin/runtime/class.js.map +1 -0
- package/__BUILD__/bin/runtime/dirs.js +16 -0
- package/__BUILD__/bin/runtime/dirs.js.map +1 -0
- package/__BUILD__/bin/runtime/promises.js +15 -0
- package/__BUILD__/bin/runtime/promises.js.map +1 -0
- package/__BUILD__/bin/runtime/require.js +88 -0
- package/__BUILD__/bin/runtime/require.js.map +1 -0
- package/__BUILD__/index.js +42 -0
- package/__BUILD__/index.js.map +1 -0
- package/__BUILD__/libs/axios.js +42 -0
- package/__BUILD__/libs/axios.js.map +1 -0
- package/__BUILD__/libs/cluster.js +160 -0
- package/__BUILD__/libs/cluster.js.map +1 -0
- package/__BUILD__/libs/fs.js +206 -0
- package/__BUILD__/libs/fs.js.map +1 -0
- package/__BUILD__/libs/model-validations.js +356 -0
- package/__BUILD__/libs/model-validations.js.map +1 -0
- package/__BUILD__/libs/model.js +185 -0
- package/__BUILD__/libs/model.js.map +1 -0
- package/__BUILD__/libs/router.js +127 -0
- package/__BUILD__/libs/router.js.map +1 -0
- package/__BUILD__/libs/swagger.js +64 -0
- package/__BUILD__/libs/swagger.js.map +1 -0
- package/__BUILD__/libs/tasks.js +134 -0
- package/__BUILD__/libs/tasks.js.map +1 -0
- package/__BUILD__/libs/tools.js +231 -0
- package/__BUILD__/libs/tools.js.map +1 -0
- package/__BUILD__/scripts/post-install/api.js +25 -0
- package/__BUILD__/scripts/post-install/api.js.map +1 -0
- package/__BUILD__/scripts/post-install/lib.js +25 -0
- package/__BUILD__/scripts/post-install/lib.js.map +1 -0
- package/__BUILD__/scripts/post-install.js +65 -0
- package/__BUILD__/scripts/post-install.js.map +1 -0
- package/__BUILD__/scripts/pre-test.js +25 -0
- package/__BUILD__/scripts/pre-test.js.map +1 -0
- package/package.json +18 -16
- package/src/@types/cluster.actions.d.ts +7 -0
- package/src/@types/cluster.d.ts +33 -0
- package/src/@types/create-cli.d.ts +9 -0
- package/src/@types/exported.d.ts +24 -0
- package/src/@types/global.d.ts +69 -0
- package/src/@types/model.d.ts +69 -0
- package/src/@types/router.d.ts +75 -0
- package/src/@types/swagger.d.ts +23 -0
- package/{bin/extras/plata-create-api.ts → src/bin/extras/create-api-cli.ts} +5 -6
- package/{bin/extras/plata-create-lib.ts → src/bin/extras/create-lib-cli.ts} +3 -4
- package/{bin → src/bin}/extras/plata-create-tools.ts +4 -4
- package/src/bin/plata-api.ts +172 -0
- package/src/bin/plata-create.ts +21 -0
- package/src/bin/plata-runtime.ts +188 -0
- package/src/bin/plata-swagger.ts +100 -0
- package/src/bin/runtime/_setupRuntime.ts +49 -0
- package/src/bin/runtime/_types.d.ts +4 -0
- package/src/bin/runtime/class.ts +21 -0
- package/src/bin/runtime/dirs.ts +26 -0
- package/src/bin/runtime/promises.ts +15 -0
- package/src/bin/runtime/require.ts +104 -0
- package/{index.ts → src/index.ts} +2 -4
- package/{libs → src/libs}/axios.ts +0 -0
- package/src/libs/cluster.ts +189 -0
- package/src/libs/fs.ts +382 -0
- package/{libs/model.ts → src/libs/model-validations.ts} +28 -262
- package/src/libs/model.ts +233 -0
- package/src/libs/router.ts +147 -0
- package/src/libs/swagger.ts +81 -0
- package/{libs → src/libs}/tasks.ts +0 -0
- package/{libs → src/libs}/tools.ts +3 -18
- package/src/scripts/post-install/api.ts +32 -0
- package/src/scripts/post-install/lib.ts +30 -0
- package/src/scripts/post-install.ts +65 -0
- package/src/scripts/pre-test.ts +34 -0
- package/src/tests/assets/config/test.txt +1 -0
- package/src/tests/config.test.ts +13 -0
- package/src/tests/model.test.ts +115 -0
- package/templates/create-cli/cluster.ts +7 -9
- package/templates/create-cli/config.ts +2 -8
- package/templates/create-cli/lib.ts +7 -17
- package/templates/create-cli/model.ts +10 -21
- package/templates/create-cli/route.ts +1 -3
- package/templates/postinstall/api/configs/env.ts +2 -8
- package/templates/postinstall/api/tsconfig.json +20 -37
- package/templates/postinstall/lib/postinstall-tools.mjs +1 -1
- package/templates/postinstall/lib/postinstall.js +1 -0
- package/templates/postinstall/lib/tsconfig.json +21 -38
- package/tsconfig.json +25 -37
- package/Dockerfile +0 -13
- package/bin/extras/plata-build-tool.ts +0 -151
- package/bin/plata-build.ts +0 -144
- package/bin/plata-create.ts +0 -28
- package/bin/plata-reload.ts +0 -13
- package/bin/plata-swagger-gen.ts +0 -183
- package/bin/plata.ts +0 -122
- package/libs/cluster.ts +0 -219
- package/libs/env.ts +0 -28
- package/libs/routes.ts +0 -275
- package/libs/swagger.ts +0 -79
- package/postinstall-tools.mjs +0 -115
- package/postinstall.mjs +0 -42
- package/templates/postinstall/api/_install.mjs +0 -34
- package/templates/postinstall/lib/_install.mjs +0 -30
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import path from 'node:path'
|
|
2
|
+
import fs from 'node:fs'
|
|
3
|
+
import { buildExpressRouter, loadRoutesFromProject } from "++/libs/router"
|
|
4
|
+
|
|
5
|
+
export async function dumpRoutes() {
|
|
6
|
+
const requiredRoutes = await loadRoutesFromProject()
|
|
7
|
+
|
|
8
|
+
if (requiredRoutes.errorID !== undefined) {
|
|
9
|
+
console.log(requiredRoutes)
|
|
10
|
+
process.exit(1)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const router = await buildExpressRouter(requiredRoutes)
|
|
14
|
+
|
|
15
|
+
if (router.errorID !== undefined) {
|
|
16
|
+
console.log(router)
|
|
17
|
+
process.exit(1)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const dumpedRoutes: SwaggerGen.Route[] = []
|
|
21
|
+
const regex = /:(.*?)\??\//g
|
|
22
|
+
|
|
23
|
+
for (const r of router.routes) {
|
|
24
|
+
if (r.swaggerHide) {
|
|
25
|
+
continue
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
r.path = path.normalize(`${r.path ?? '/'}/`).replace(/\\/g, '/')
|
|
29
|
+
|
|
30
|
+
const dumpedRouteParams: SwaggerGen.RouteParameter[] = []
|
|
31
|
+
const urlParms = r.path.match(regex) ?? []
|
|
32
|
+
|
|
33
|
+
for (const p of urlParms) {
|
|
34
|
+
dumpedRouteParams.push({
|
|
35
|
+
name: p.replace(regex, '$1'),
|
|
36
|
+
required: p[p.length - 2] !== '?',
|
|
37
|
+
in: 'path',
|
|
38
|
+
type: 'string'
|
|
39
|
+
})
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
dumpedRoutes.push({
|
|
43
|
+
httpRoute: r.path.replace(regex, '{$1}/'),
|
|
44
|
+
method: r.method,
|
|
45
|
+
params: dumpedRouteParams,
|
|
46
|
+
})
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return dumpedRoutes
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export async function toProjectSwagger(file: string, content: any): Promise<void> {
|
|
53
|
+
try {
|
|
54
|
+
const p = path.resolve(Plata.ProjectDir, 'swagger', file)
|
|
55
|
+
|
|
56
|
+
if (!fs.existsSync(p)) {
|
|
57
|
+
fs.mkdirSync(path.dirname(p), { recursive: true })
|
|
58
|
+
fs.writeFileSync(p, JSON.stringify(content, null, 4))
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
} catch (e) {
|
|
62
|
+
console.log(e)
|
|
63
|
+
process.exit(1)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export const main = async () => {
|
|
68
|
+
const routes = await dumpRoutes()
|
|
69
|
+
|
|
70
|
+
const templateFolder = path.join(Plata.PlataDir, 'templates', 'swagger-cli')
|
|
71
|
+
|
|
72
|
+
const files: SwaggerGen.Files = {
|
|
73
|
+
swaggerHeader: require(path.join(templateFolder, 'header.json')),
|
|
74
|
+
route: {
|
|
75
|
+
header: require(path.join(templateFolder, 'route', 'header.json')),
|
|
76
|
+
body: require(path.join(templateFolder, 'route', 'body.json')),
|
|
77
|
+
response: require(path.join(templateFolder, 'route', 'response.json')),
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
for (const route of routes) {
|
|
82
|
+
|
|
83
|
+
// https://developer.mozilla.org/en-US/docs/Glossary/Deep_copy
|
|
84
|
+
const fileCopy:SwaggerGen.Files = JSON.parse(JSON.stringify(files))
|
|
85
|
+
|
|
86
|
+
for(const json in fileCopy.route) {
|
|
87
|
+
await toProjectSwagger(
|
|
88
|
+
path.join('routes', route.httpRoute, route.method.toLowerCase(), `${json}.json`),
|
|
89
|
+
fileCopy.route[json]
|
|
90
|
+
)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
await toProjectSwagger(
|
|
95
|
+
'header.json',
|
|
96
|
+
files.swaggerHeader
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
console.log('Done')
|
|
100
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import fs from 'node:fs/promises'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
|
|
4
|
+
export async function loadRuntimeLibs() {
|
|
5
|
+
const plata = new Object(null)
|
|
6
|
+
|
|
7
|
+
const runtimeLibs: PlataResult<string[]> = await fs.readdir(path.join(__dirname)).catch(err => {
|
|
8
|
+
return {
|
|
9
|
+
errorID: 'PRLORUNTIME',
|
|
10
|
+
msg: err.message,
|
|
11
|
+
error: err
|
|
12
|
+
}
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
if (runtimeLibs.errorID !== undefined) {
|
|
16
|
+
console.error(runtimeLibs)
|
|
17
|
+
process.exit(1)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const promises = runtimeLibs.map(lib => Promise.resolve().then(() => new Promise(resolve => {
|
|
21
|
+
if (lib.slice(-4) === 'd.ts')
|
|
22
|
+
return resolve(true)
|
|
23
|
+
;
|
|
24
|
+
|
|
25
|
+
if (path.extname(lib) === '.map')
|
|
26
|
+
return resolve(true)
|
|
27
|
+
;
|
|
28
|
+
|
|
29
|
+
const r: { PlataRuntimeE?: any } = require(path.join(__dirname, lib))
|
|
30
|
+
|
|
31
|
+
if (r.PlataRuntimeE === undefined) {
|
|
32
|
+
return resolve(true)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
for (const key in r.PlataRuntimeE) {
|
|
36
|
+
plata[key] = r.PlataRuntimeE[key]
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return resolve(true)
|
|
40
|
+
})))
|
|
41
|
+
|
|
42
|
+
await Promise.all(promises).catch(err => {
|
|
43
|
+
console.error(err)
|
|
44
|
+
process.exit(1)
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
return plata
|
|
49
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
declare global {
|
|
2
|
+
interface PlataRuntime extends PlataRuntimeEType {}
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
type PlataRuntimeEType = typeof PlataRuntimeE
|
|
6
|
+
|
|
7
|
+
export namespace PlataRuntimeE {
|
|
8
|
+
export function CacheClass<T>(newFunction: (...args: any) => T): T {
|
|
9
|
+
const p = process as any
|
|
10
|
+
|
|
11
|
+
if (p.cache === undefined) {
|
|
12
|
+
p.cache = new Object(null)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (p.cache[newFunction.name] === undefined) {
|
|
16
|
+
p.cache[newFunction.name] = newFunction()
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return p.cache[newFunction.name]
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import fs from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
|
|
4
|
+
declare global {
|
|
5
|
+
interface PlataRuntime extends PlataRuntimeEType {}
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
type PlataRuntimeEType = typeof PlataRuntimeE
|
|
9
|
+
|
|
10
|
+
export namespace PlataRuntimeE {
|
|
11
|
+
export const ProjectDir = path.resolve('.')
|
|
12
|
+
|
|
13
|
+
export const ProjectJson = JSON.parse(
|
|
14
|
+
fs.readFileSync(
|
|
15
|
+
path.join(ProjectDir, 'package.json')
|
|
16
|
+
).toString()
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
export const PlataDir = path.resolve('.', 'node_modules', ProjectJson.plata_name ?? '..')
|
|
20
|
+
|
|
21
|
+
export const PlataJson = JSON.parse(
|
|
22
|
+
fs.readFileSync(
|
|
23
|
+
path.join(PlataDir, 'package.json')
|
|
24
|
+
).toString()
|
|
25
|
+
)
|
|
26
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
declare global {
|
|
2
|
+
interface PlataRuntime extends PlataRuntimeEType {}
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
type PlataRuntimeEType = typeof PlataRuntimeE
|
|
6
|
+
|
|
7
|
+
export namespace PlataRuntimeE {
|
|
8
|
+
export function FastPromise<T>(p: () => Promise<T>): Promise<T> {
|
|
9
|
+
return Promise.resolve().then(p)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function BuildPlataError(e: PlataError): PlataError {
|
|
13
|
+
return e
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import glob from 'glob'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
|
|
4
|
+
declare global {
|
|
5
|
+
interface PlataRuntime extends PlataRuntimeEType {}
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
type PlataRuntimeEType = typeof PlataRuntimeE
|
|
9
|
+
|
|
10
|
+
export namespace PlataRuntimeE {
|
|
11
|
+
|
|
12
|
+
export async function RequireAsync<T = any>(p: string): RequireAsyncReturn<T> {
|
|
13
|
+
try {
|
|
14
|
+
return {
|
|
15
|
+
filePath: p,
|
|
16
|
+
name: path.basename(p).replace('.ts', '').replace('.js', ''),
|
|
17
|
+
exports: require(p) as T
|
|
18
|
+
}
|
|
19
|
+
} catch(err) {
|
|
20
|
+
return {
|
|
21
|
+
errorID: 'PLTRF0001',
|
|
22
|
+
msg: `Error while importing file ${p}`,
|
|
23
|
+
error: err
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export async function RequireFolder<T = any>(p: string): RequireFolderReturn<T> {
|
|
29
|
+
const promises: PlataPromise<RequiredInterface<T>>[] = []
|
|
30
|
+
|
|
31
|
+
glob.sync(`${p.replace(/\\/g, '/')}/**/*.+(js|ts)`)
|
|
32
|
+
.filter(file => !file.endsWith('.d.ts'))
|
|
33
|
+
.forEach(file => {
|
|
34
|
+
file = file.replace(/(\.ts|\.js)$/, '')
|
|
35
|
+
|
|
36
|
+
promises.push(Plata.FastPromise(() => Plata.RequireAsync(file)))
|
|
37
|
+
})
|
|
38
|
+
;
|
|
39
|
+
|
|
40
|
+
return Promise.all(promises).then(
|
|
41
|
+
rs => {
|
|
42
|
+
const errors: PlataError[] = []
|
|
43
|
+
const result: RequiredInterface<T>[] = []
|
|
44
|
+
|
|
45
|
+
rs.forEach(r => {
|
|
46
|
+
if (r.errorID !== undefined) {
|
|
47
|
+
errors.push(r)
|
|
48
|
+
} else {
|
|
49
|
+
result.push(r)
|
|
50
|
+
}
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
if (errors.length !== 0) {
|
|
54
|
+
return {
|
|
55
|
+
errorID: 'PLTRF0003',
|
|
56
|
+
msg: `Errors while importing folder: ${p}`,
|
|
57
|
+
error: errors
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return result
|
|
62
|
+
},
|
|
63
|
+
e => {
|
|
64
|
+
return {
|
|
65
|
+
errorID: 'PLTRF0002',
|
|
66
|
+
msg: `Error while importing folder: ${p}`,
|
|
67
|
+
error: e
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export async function ReadEnvFileToPromise(p: string) {
|
|
75
|
+
const envFile = new Object(null)
|
|
76
|
+
|
|
77
|
+
const result = await Plata.files.ReadFileAsync(p, async line => {
|
|
78
|
+
if (line[0] === '#') return
|
|
79
|
+
|
|
80
|
+
if (line !== '') {
|
|
81
|
+
const env = line.split('=')
|
|
82
|
+
|
|
83
|
+
if (env.length >= 2) {
|
|
84
|
+
const [ key, ...v ] = env
|
|
85
|
+
let value = v.join('=')
|
|
86
|
+
|
|
87
|
+
if (value[0] === '{' && value.slice(-1) === '}')
|
|
88
|
+
value = process.env[value.slice(1, -1)] ?? ''
|
|
89
|
+
;
|
|
90
|
+
|
|
91
|
+
if (value !== '')
|
|
92
|
+
envFile[key] = value
|
|
93
|
+
;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
if (result !== null) {
|
|
99
|
+
return result
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return envFile
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
import * as PlataCluster from './libs/cluster'
|
|
2
|
-
import * as
|
|
3
|
-
import * as PlataRoutes from './libs/routes'
|
|
2
|
+
import * as PlataRoutes from './libs/router'
|
|
4
3
|
import * as PlataTools from './libs/tools'
|
|
5
4
|
import * as PlataModels from './libs/model'
|
|
6
5
|
import * as PlataTasks from './libs/tasks'
|
|
7
|
-
import
|
|
6
|
+
import * as PlataSwagger from './libs/swagger'
|
|
8
7
|
import { PlataAxios, PlataAxiosUnsafe } from './libs/axios'
|
|
9
8
|
|
|
10
9
|
export {
|
|
11
10
|
PlataCluster,
|
|
12
|
-
PlataEnv,
|
|
13
11
|
PlataRoutes,
|
|
14
12
|
PlataTools,
|
|
15
13
|
PlataModels,
|
|
File without changes
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import cluster from "node:cluster";
|
|
2
|
+
import { cpus } from "node:os";
|
|
3
|
+
|
|
4
|
+
export class PlataClusterManager {
|
|
5
|
+
private readonly NodeCluster = cluster
|
|
6
|
+
|
|
7
|
+
constructor() {
|
|
8
|
+
if (this.NodeCluster.isPrimary) {
|
|
9
|
+
Plata.cluster = {
|
|
10
|
+
isPrimary: true,
|
|
11
|
+
clusters: []
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (this.NodeCluster.eventNames().indexOf('exit') === -1) {
|
|
15
|
+
this.NodeCluster.on('exit', this.onWorkerKilled)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (this.NodeCluster.eventNames().indexOf('message') === -1) {
|
|
19
|
+
this.NodeCluster.on('message', (
|
|
20
|
+
(t) => t.onMessage(t)
|
|
21
|
+
)(this))
|
|
22
|
+
}
|
|
23
|
+
} else {
|
|
24
|
+
Plata.cluster = {
|
|
25
|
+
isPrimary: false
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public async startCluster(config: Cluster.WorkerConfig): Promise<MaybePlataError> {
|
|
31
|
+
if (!Plata.cluster.isPrimary) return {
|
|
32
|
+
errorID: 'PBLCLWS0002',
|
|
33
|
+
msg: 'startCluster must be called from primary process'
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (config.workers === undefined) {
|
|
37
|
+
if (config.env === 'prod') {
|
|
38
|
+
config.workers = cpus().length
|
|
39
|
+
} else {
|
|
40
|
+
config.workers = 1
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (config.workers === -1) {
|
|
45
|
+
config.workers = cpus().length
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (config.workers === 0) {
|
|
49
|
+
return null
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
console.log(`Starting ${config.workers} workers on cluster ${config.name}`)
|
|
53
|
+
|
|
54
|
+
const cluster: Cluster.ClusterConfig = {
|
|
55
|
+
pids: [],
|
|
56
|
+
config
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
for (let i = 0; i < config.workers; i++) {
|
|
60
|
+
const w = this.fork(config)
|
|
61
|
+
|
|
62
|
+
if (w.process.pid === undefined) {
|
|
63
|
+
return {
|
|
64
|
+
errorID: 'PBLCLWS0003',
|
|
65
|
+
msg: `Erro while starting worker ${i} from cluster ${config.name}`,
|
|
66
|
+
error: w.process.exitCode
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
cluster.pids.push(w.process.pid)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (config.onExit !== undefined) {
|
|
74
|
+
this.NodeCluster.on(this.getClusterEvents(config.name).worker.exit, config.onExit)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
Plata.cluster.clusters.push(cluster)
|
|
78
|
+
|
|
79
|
+
return null
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
public isPrimary() {
|
|
83
|
+
return this.NodeCluster.isPrimary
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
public fork(config: Cluster.WorkerConfig) {
|
|
87
|
+
return this.NodeCluster.fork({
|
|
88
|
+
...config.workersEnv,
|
|
89
|
+
ENV: config.env,
|
|
90
|
+
_PLATA_WORKER_NAME: config.name
|
|
91
|
+
})
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
public getClusterEvents(clusterName: string) {
|
|
95
|
+
const base = `plata.cluster.${clusterName}`
|
|
96
|
+
return {
|
|
97
|
+
worker: {
|
|
98
|
+
exit: `${base}.worker.exit`
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
public onWorkerKilled(t: this) {
|
|
103
|
+
return (worker: Cluster.Worker, code: number, signal: string) => {
|
|
104
|
+
if (worker.process.pid === undefined) return
|
|
105
|
+
if (!Plata.cluster.isPrimary) return
|
|
106
|
+
|
|
107
|
+
const clusterIndex = Plata.cluster.clusters.findIndex(cluster =>
|
|
108
|
+
cluster.pids.indexOf(worker.process.pid ?? 0) !== -1
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
if (clusterIndex !== -1) {
|
|
112
|
+
const c = Plata.cluster.clusters[clusterIndex]
|
|
113
|
+
|
|
114
|
+
console.log(`O Worker ${worker.process.pid} do cluster ${c.config.name} morreu com o codigo ${code} ${signal ?? ''}`)
|
|
115
|
+
console.log(`Iniciando um novo worker no cluster ${c.config.name}`)
|
|
116
|
+
|
|
117
|
+
cluster.emit(
|
|
118
|
+
t.getClusterEvents(c.config.name).worker.exit, // TODO :: this !== PlataClusterManager
|
|
119
|
+
worker,
|
|
120
|
+
code,
|
|
121
|
+
signal,
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
const w = t.fork(c.config)
|
|
125
|
+
|
|
126
|
+
const pidIndex = c.pids.indexOf(worker.process.pid)
|
|
127
|
+
|
|
128
|
+
c.pids[pidIndex] = w.process.pid ?? 0
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
public async sendMsgToAllWorkers(msg: Cluster.Actions) {
|
|
134
|
+
if (this.NodeCluster.workers === undefined) return
|
|
135
|
+
|
|
136
|
+
for (const worker of Object.values(this.NodeCluster.workers)) {
|
|
137
|
+
if (worker === undefined) continue
|
|
138
|
+
|
|
139
|
+
worker.send(msg)
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
public async sendMsgToCluster(name: string, msg: Cluster.Actions) {
|
|
144
|
+
if (this.NodeCluster.workers === undefined) return
|
|
145
|
+
if (!Plata.cluster.isPrimary) return
|
|
146
|
+
|
|
147
|
+
const clusterIndex = Plata.cluster.clusters.findIndex(cluster => cluster.config.name === name)
|
|
148
|
+
|
|
149
|
+
if (clusterIndex === -1) return
|
|
150
|
+
|
|
151
|
+
const pids = Plata.cluster.clusters[clusterIndex].pids
|
|
152
|
+
|
|
153
|
+
for (const worker of Object.values(this.NodeCluster.workers)) {
|
|
154
|
+
if (worker === undefined) continue
|
|
155
|
+
|
|
156
|
+
if (pids.includes(worker.process.pid ?? 0))
|
|
157
|
+
worker.send(msg)
|
|
158
|
+
;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
public onMessage(t: this) {
|
|
163
|
+
return (worker: Cluster.Worker, actionEvent: Cluster.Actions) => {
|
|
164
|
+
switch(actionEvent.action) {
|
|
165
|
+
case 'KILL':
|
|
166
|
+
console.log(`Process kill requested: ${actionEvent.msg}`)
|
|
167
|
+
process.exit(0)
|
|
168
|
+
break
|
|
169
|
+
case 'ECHO':
|
|
170
|
+
t.sendMsgToAllWorkers(actionEvent.msg)
|
|
171
|
+
break
|
|
172
|
+
case 'ECHO-CLUSTER':
|
|
173
|
+
t.sendMsgToCluster(actionEvent.msg.name, actionEvent.msg.data)
|
|
174
|
+
break
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
public async send(msg: Cluster.Actions): PlataPromise<boolean> {
|
|
180
|
+
if (process.send === undefined) {
|
|
181
|
+
return {
|
|
182
|
+
errorID: 'PBLCLWS0001',
|
|
183
|
+
msg: `process don't have send function`
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return process.send(msg)
|
|
188
|
+
}
|
|
189
|
+
}
|