@platformatic/runtime 3.0.0-alpha.8 → 3.0.0-rc.1
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/config.d.ts +1 -0
- package/index.js +24 -3
- package/lib/errors.js +5 -0
- package/lib/prom-server.js +11 -3
- package/lib/runtime.js +18 -3
- package/lib/worker/main.js +12 -2
- package/package.json +16 -16
- package/schema.json +5 -1
package/config.d.ts
CHANGED
package/index.js
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
loadConfigurationModule,
|
|
9
9
|
loadConfiguration as utilsLoadConfiguration
|
|
10
10
|
} from '@platformatic/foundation'
|
|
11
|
+
import closeWithGrace from 'close-with-grace'
|
|
11
12
|
import inspector from 'node:inspector'
|
|
12
13
|
import { transform, wrapInRuntimeConfig } from './lib/config.js'
|
|
13
14
|
import { NodeInspectorFlagsNotSupportedError } from './lib/errors.js'
|
|
@@ -25,12 +26,32 @@ async function restartRuntime (runtime) {
|
|
|
25
26
|
}
|
|
26
27
|
}
|
|
27
28
|
|
|
28
|
-
function handleSignal (runtime) {
|
|
29
|
+
function handleSignal (runtime, config) {
|
|
30
|
+
// The very first time we add a listener for SIGUSR2,
|
|
31
|
+
// ignore it since it comes from close-with-grace and we want to use to restart the runtime
|
|
32
|
+
function filterCloseWithGraceSIGUSR2 (event, listener) {
|
|
33
|
+
if (event === 'SIGUSR2') {
|
|
34
|
+
process.removeListener('SIGUSR2', listener)
|
|
35
|
+
process.removeListener('newListener', filterCloseWithGraceSIGUSR2)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
process.on('newListener', filterCloseWithGraceSIGUSR2)
|
|
40
|
+
|
|
41
|
+
const cwg = closeWithGrace({ delay: config.gracefulShutdown?.runtime ?? 10000 }, async event => {
|
|
42
|
+
if (event.err instanceof Error) {
|
|
43
|
+
console.error(event.err)
|
|
44
|
+
}
|
|
45
|
+
await runtime.close()
|
|
46
|
+
})
|
|
47
|
+
|
|
29
48
|
/* c8 ignore next 3 */
|
|
30
49
|
const restartListener = restartRuntime.bind(null, runtime)
|
|
31
50
|
process.on('SIGUSR2', restartListener)
|
|
51
|
+
|
|
32
52
|
runtime.on('closed', () => {
|
|
33
53
|
process.removeListener('SIGUSR2', restartListener)
|
|
54
|
+
cwg.uninstall()
|
|
34
55
|
})
|
|
35
56
|
}
|
|
36
57
|
|
|
@@ -109,7 +130,7 @@ export async function create (configOrRoot, sourceOrConfig, context) {
|
|
|
109
130
|
}
|
|
110
131
|
|
|
111
132
|
let runtime = new Runtime(config, context)
|
|
112
|
-
handleSignal(runtime)
|
|
133
|
+
handleSignal(runtime, config)
|
|
113
134
|
|
|
114
135
|
// Handle port handling
|
|
115
136
|
if (context?.start) {
|
|
@@ -135,7 +156,7 @@ export async function create (configOrRoot, sourceOrConfig, context) {
|
|
|
135
156
|
|
|
136
157
|
config.server.port = ++port
|
|
137
158
|
runtime = new Runtime(config, context)
|
|
138
|
-
handleSignal(runtime)
|
|
159
|
+
handleSignal(runtime, config)
|
|
139
160
|
}
|
|
140
161
|
}
|
|
141
162
|
}
|
package/lib/errors.js
CHANGED
|
@@ -122,3 +122,8 @@ export const MessagingError = createError(
|
|
|
122
122
|
`${ERROR_PREFIX}_MESSAGING_ERROR`,
|
|
123
123
|
'Cannot send a message to application "%s": %s'
|
|
124
124
|
)
|
|
125
|
+
|
|
126
|
+
export const MissingPprofCapture = createError(
|
|
127
|
+
`${ERROR_PREFIX}_MISSING_PPROF_CAPTURE`,
|
|
128
|
+
'Please install @platformatic/wattpm-pprof-capture'
|
|
129
|
+
)
|
package/lib/prom-server.js
CHANGED
|
@@ -19,13 +19,21 @@ const DEFAULT_LIVENESS_FAIL_BODY = 'ERR'
|
|
|
19
19
|
async function checkReadiness (runtime) {
|
|
20
20
|
const workers = await runtime.getWorkers()
|
|
21
21
|
|
|
22
|
-
//
|
|
22
|
+
// Make sure there is at least one started worker
|
|
23
|
+
const applications = new Set()
|
|
24
|
+
const started = new Set()
|
|
23
25
|
for (const worker of Object.values(workers)) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
+
applications.add(worker.application)
|
|
27
|
+
|
|
28
|
+
if (worker.status === 'started') {
|
|
29
|
+
started.add(worker.application)
|
|
26
30
|
}
|
|
27
31
|
}
|
|
28
32
|
|
|
33
|
+
if (started.size !== applications.size) {
|
|
34
|
+
return { status: false }
|
|
35
|
+
}
|
|
36
|
+
|
|
29
37
|
// perform custom readiness checks, get custom response content if any
|
|
30
38
|
const checks = await runtime.getCustomReadinessChecks()
|
|
31
39
|
|
package/lib/runtime.js
CHANGED
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
InvalidArgumentError,
|
|
32
32
|
MessagingError,
|
|
33
33
|
MissingEntrypointError,
|
|
34
|
+
MissingPprofCapture,
|
|
34
35
|
RuntimeAbortedError,
|
|
35
36
|
RuntimeExitedError,
|
|
36
37
|
WorkerNotFoundError
|
|
@@ -514,12 +515,14 @@ export class Runtime extends EventEmitter {
|
|
|
514
515
|
|
|
515
516
|
async startApplicationProfiling (id, options = {}, ensureStarted = true) {
|
|
516
517
|
const service = await this.#getApplicationById(id, ensureStarted)
|
|
518
|
+
this.#validatePprofCapturePreload()
|
|
517
519
|
|
|
518
520
|
return sendViaITC(service, 'startProfiling', options)
|
|
519
521
|
}
|
|
520
522
|
|
|
521
523
|
async stopApplicationProfiling (id, ensureStarted = true) {
|
|
522
524
|
const service = await this.#getApplicationById(id, ensureStarted)
|
|
525
|
+
this.#validatePprofCapturePreload()
|
|
523
526
|
|
|
524
527
|
return sendViaITC(service, 'stopProfiling')
|
|
525
528
|
}
|
|
@@ -810,7 +813,9 @@ export class Runtime extends EventEmitter {
|
|
|
810
813
|
const label = `${application}:${i}`
|
|
811
814
|
const worker = this.#workers.get(label)
|
|
812
815
|
|
|
813
|
-
|
|
816
|
+
if (worker) {
|
|
817
|
+
status[label] = await sendViaITC(worker, 'getCustomHealthCheck')
|
|
818
|
+
}
|
|
814
819
|
}
|
|
815
820
|
}
|
|
816
821
|
|
|
@@ -825,7 +830,9 @@ export class Runtime extends EventEmitter {
|
|
|
825
830
|
const label = `${application}:${i}`
|
|
826
831
|
const worker = this.#workers.get(label)
|
|
827
832
|
|
|
828
|
-
|
|
833
|
+
if (worker) {
|
|
834
|
+
status[label] = await sendViaITC(worker, 'getCustomReadinessCheck')
|
|
835
|
+
}
|
|
829
836
|
}
|
|
830
837
|
}
|
|
831
838
|
|
|
@@ -1689,7 +1696,7 @@ export class Runtime extends EventEmitter {
|
|
|
1689
1696
|
this.logger.info(`Stopping the ${label}...`)
|
|
1690
1697
|
}
|
|
1691
1698
|
|
|
1692
|
-
const exitTimeout = this.#config.gracefulShutdown.
|
|
1699
|
+
const exitTimeout = this.#config.gracefulShutdown.application
|
|
1693
1700
|
const exitPromise = once(worker, 'exit')
|
|
1694
1701
|
|
|
1695
1702
|
// Always send the stop message, it will shut down workers that only had ITC and interceptors setup
|
|
@@ -2374,4 +2381,12 @@ export class Runtime extends EventEmitter {
|
|
|
2374
2381
|
}
|
|
2375
2382
|
return report
|
|
2376
2383
|
}
|
|
2384
|
+
|
|
2385
|
+
#validatePprofCapturePreload () {
|
|
2386
|
+
const found = this.#config.preload?.some(p => p.includes('wattpm-pprof-capture'))
|
|
2387
|
+
|
|
2388
|
+
if (!found) {
|
|
2389
|
+
throw new MissingPprofCapture()
|
|
2390
|
+
}
|
|
2391
|
+
}
|
|
2377
2392
|
}
|
package/lib/worker/main.js
CHANGED
|
@@ -177,8 +177,18 @@ async function main () {
|
|
|
177
177
|
!!config.watch
|
|
178
178
|
)
|
|
179
179
|
|
|
180
|
-
|
|
181
|
-
|
|
180
|
+
if (config.exitOnUnhandledErrors) {
|
|
181
|
+
process.on('uncaughtException', handleUnhandled.bind(null, controller, 'uncaught exception'))
|
|
182
|
+
process.on('unhandledRejection', handleUnhandled.bind(null, controller, 'unhandled rejection'))
|
|
183
|
+
|
|
184
|
+
process.on('newListener', event => {
|
|
185
|
+
if (event === 'uncaughtException' || event === 'unhandledRejection') {
|
|
186
|
+
globalThis.platformatic.logger.warn(
|
|
187
|
+
`A listener has been added for the "process.${event}" event. This listener will be never triggered as Watt default behavior will kill the process before.\n To disable this behavior, set "exitOnUnhandledErrors" to false in the runtime config.`
|
|
188
|
+
)
|
|
189
|
+
}
|
|
190
|
+
})
|
|
191
|
+
}
|
|
182
192
|
|
|
183
193
|
await controller.init()
|
|
184
194
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platformatic/runtime",
|
|
3
|
-
"version": "3.0.0-
|
|
3
|
+
"version": "3.0.0-rc.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -34,14 +34,14 @@
|
|
|
34
34
|
"typescript": "^5.5.4",
|
|
35
35
|
"undici-oidc-interceptor": "^0.5.0",
|
|
36
36
|
"why-is-node-running": "^2.2.2",
|
|
37
|
-
"@platformatic/
|
|
38
|
-
"@platformatic/
|
|
39
|
-
"@platformatic/
|
|
40
|
-
"@platformatic/node": "3.0.0-
|
|
41
|
-
"@platformatic/
|
|
42
|
-
"@platformatic/
|
|
43
|
-
"@platformatic/sql-mapper": "3.0.0-
|
|
44
|
-
"@platformatic/wattpm-pprof-capture": "3.0.0-
|
|
37
|
+
"@platformatic/db": "3.0.0-rc.1",
|
|
38
|
+
"@platformatic/composer": "3.0.0-rc.1",
|
|
39
|
+
"@platformatic/gateway": "3.0.0-rc.1",
|
|
40
|
+
"@platformatic/node": "3.0.0-rc.1",
|
|
41
|
+
"@platformatic/sql-graphql": "3.0.0-rc.1",
|
|
42
|
+
"@platformatic/service": "3.0.0-rc.1",
|
|
43
|
+
"@platformatic/sql-mapper": "3.0.0-rc.1",
|
|
44
|
+
"@platformatic/wattpm-pprof-capture": "3.0.0-rc.1"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@fastify/accepts": "^5.0.0",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"@platformatic/undici-cache-memory": "^0.8.1",
|
|
52
52
|
"@watchable/unpromise": "^1.0.2",
|
|
53
53
|
"change-case-all": "^2.1.0",
|
|
54
|
-
"close-with-grace": "^2.
|
|
54
|
+
"close-with-grace": "^2.2.0",
|
|
55
55
|
"colorette": "^2.0.20",
|
|
56
56
|
"cron": "^4.1.0",
|
|
57
57
|
"debounce": "^2.0.0",
|
|
@@ -70,12 +70,12 @@
|
|
|
70
70
|
"undici": "^7.0.0",
|
|
71
71
|
"undici-thread-interceptor": "^0.14.0",
|
|
72
72
|
"ws": "^8.16.0",
|
|
73
|
-
"@platformatic/basic": "3.0.0-
|
|
74
|
-
"@platformatic/
|
|
75
|
-
"@platformatic/
|
|
76
|
-
"@platformatic/
|
|
77
|
-
"@platformatic/
|
|
78
|
-
"@platformatic/
|
|
73
|
+
"@platformatic/basic": "3.0.0-rc.1",
|
|
74
|
+
"@platformatic/foundation": "3.0.0-rc.1",
|
|
75
|
+
"@platformatic/generators": "3.0.0-rc.1",
|
|
76
|
+
"@platformatic/metrics": "3.0.0-rc.1",
|
|
77
|
+
"@platformatic/telemetry": "3.0.0-rc.1",
|
|
78
|
+
"@platformatic/itc": "3.0.0-rc.1"
|
|
79
79
|
},
|
|
80
80
|
"engines": {
|
|
81
81
|
"node": ">=22.18.0"
|
package/schema.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$id": "https://schemas.platformatic.dev/@platformatic/runtime/3.0.0-
|
|
2
|
+
"$id": "https://schemas.platformatic.dev/@platformatic/runtime/3.0.0-rc.1.json",
|
|
3
3
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
4
4
|
"title": "Platformatic Runtime Config",
|
|
5
5
|
"type": "object",
|
|
@@ -1217,6 +1217,10 @@
|
|
|
1217
1217
|
}
|
|
1218
1218
|
]
|
|
1219
1219
|
},
|
|
1220
|
+
"exitOnUnhandledErrors": {
|
|
1221
|
+
"default": true,
|
|
1222
|
+
"type": "boolean"
|
|
1223
|
+
},
|
|
1220
1224
|
"gracefulShutdown": {
|
|
1221
1225
|
"type": "object",
|
|
1222
1226
|
"properties": {
|