@platformatic/runtime 2.48.0 → 2.50.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/config.d.ts +29 -1
- package/lib/errors.js +1 -0
- package/lib/prom-server.js +86 -3
- package/lib/runtime.js +16 -1
- package/lib/schema.js +59 -3
- package/lib/worker/default-stackable.js +1 -0
- package/lib/worker/itc.js +8 -0
- package/package.json +14 -14
- package/schema.json +84 -4
package/config.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* and run json-schema-to-typescript to regenerate this file.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
export type
|
|
8
|
+
export type HttpsSchemasPlatformaticDevPlatformaticRuntime2500Json = {
|
|
9
9
|
[k: string]: unknown;
|
|
10
10
|
} & {
|
|
11
11
|
$schema?: string;
|
|
@@ -173,6 +173,34 @@ export type HttpsSchemasPlatformaticDevPlatformaticRuntime2480Json = {
|
|
|
173
173
|
labels?: {
|
|
174
174
|
[k: string]: string;
|
|
175
175
|
};
|
|
176
|
+
readiness?:
|
|
177
|
+
| boolean
|
|
178
|
+
| {
|
|
179
|
+
endpoint?: string;
|
|
180
|
+
success?: {
|
|
181
|
+
statusCode?: number;
|
|
182
|
+
body?: string;
|
|
183
|
+
};
|
|
184
|
+
fail?: {
|
|
185
|
+
statusCode?: number;
|
|
186
|
+
body?: string;
|
|
187
|
+
};
|
|
188
|
+
};
|
|
189
|
+
liveness?:
|
|
190
|
+
| boolean
|
|
191
|
+
| {
|
|
192
|
+
endpoint?: string;
|
|
193
|
+
success?: {
|
|
194
|
+
statusCode?: number;
|
|
195
|
+
body?: string;
|
|
196
|
+
};
|
|
197
|
+
fail?: {
|
|
198
|
+
statusCode?: number;
|
|
199
|
+
body?: string;
|
|
200
|
+
};
|
|
201
|
+
};
|
|
202
|
+
additionalProperties?: never;
|
|
203
|
+
[k: string]: unknown;
|
|
176
204
|
};
|
|
177
205
|
telemetry?: OpenTelemetry;
|
|
178
206
|
inspectorOptions?: {
|
package/lib/errors.js
CHANGED
|
@@ -20,6 +20,7 @@ module.exports = {
|
|
|
20
20
|
FailedToRetrieveMetaError: createError(`${ERROR_PREFIX}_FAILED_TO_RETRIEVE_META`, 'Failed to retrieve metadata for service with id "%s": %s'),
|
|
21
21
|
FailedToRetrieveMetricsError: createError(`${ERROR_PREFIX}_FAILED_TO_RETRIEVE_METRICS`, 'Failed to retrieve metrics for service with id "%s": %s'),
|
|
22
22
|
FailedToRetrieveHealthError: createError(`${ERROR_PREFIX}_FAILED_TO_RETRIEVE_HEALTH`, 'Failed to retrieve health for service with id "%s": %s'),
|
|
23
|
+
FailedToPerformCustomHealthCheckError: createError(`${ERROR_PREFIX}_FAILED_TO_PERFORM_CUSTOM_HEALTH_CHECK`, 'Failed to perform custom healthcheck for service with id "%s": %s'),
|
|
23
24
|
ApplicationAlreadyStartedError: createError(`${ERROR_PREFIX}_APPLICATION_ALREADY_STARTED`, 'Application is already started'),
|
|
24
25
|
ApplicationNotStartedError: createError(`${ERROR_PREFIX}_APPLICATION_NOT_STARTED`, 'Application has not been started'),
|
|
25
26
|
ConfigPathMustBeStringError: createError(`${ERROR_PREFIX}_CONFIG_PATH_MUST_BE_STRING`, 'Config path must be a string'),
|
package/lib/prom-server.js
CHANGED
|
@@ -2,13 +2,48 @@
|
|
|
2
2
|
|
|
3
3
|
const fastify = require('fastify')
|
|
4
4
|
|
|
5
|
+
const DEFAULT_HOSTNAME = '0.0.0.0'
|
|
6
|
+
const DEFAULT_PORT = 9090
|
|
7
|
+
const DEFAULT_METRICS_ENDPOINT = '/metrics'
|
|
8
|
+
const DEFAULT_READINESS_ENDPOINT = '/ready'
|
|
9
|
+
const DEFAULT_READINESS_SUCCESS_STATUS_CODE = 200
|
|
10
|
+
const DEFAULT_READINESS_SUCCESS_BODY = 'OK'
|
|
11
|
+
const DEFAULT_READINESS_FAIL_STATUS_CODE = 500
|
|
12
|
+
const DEFAULT_READINESS_FAIL_BODY = 'ERR'
|
|
13
|
+
const DEFAULT_LIVENESS_ENDPOINT = '/status'
|
|
14
|
+
const DEFAULT_LIVENESS_SUCCESS_STATUS_CODE = 200
|
|
15
|
+
const DEFAULT_LIVENESS_SUCCESS_BODY = 'OK'
|
|
16
|
+
const DEFAULT_LIVENESS_FAIL_STATUS_CODE = 500
|
|
17
|
+
const DEFAULT_LIVENESS_FAIL_BODY = 'ERR'
|
|
18
|
+
|
|
19
|
+
async function checkReadiness (runtime) {
|
|
20
|
+
const workers = await runtime.getWorkers()
|
|
21
|
+
|
|
22
|
+
for (const worker of Object.values(workers)) {
|
|
23
|
+
if (worker.status !== 'started') {
|
|
24
|
+
return false
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return true
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async function checkLiveness (runtime) {
|
|
31
|
+
if (!(await checkReadiness(runtime))) {
|
|
32
|
+
return false
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const checks = await runtime.getCustomHealthChecks()
|
|
36
|
+
|
|
37
|
+
return Object.values(checks).every(check => check)
|
|
38
|
+
}
|
|
39
|
+
|
|
5
40
|
async function startPrometheusServer (runtime, opts) {
|
|
6
41
|
if (opts.enabled === false) {
|
|
7
42
|
return
|
|
8
43
|
}
|
|
9
|
-
const host = opts.hostname ??
|
|
10
|
-
const port = opts.port ??
|
|
11
|
-
const metricsEndpoint = opts.endpoint ??
|
|
44
|
+
const host = opts.hostname ?? DEFAULT_HOSTNAME
|
|
45
|
+
const port = opts.port ?? DEFAULT_PORT
|
|
46
|
+
const metricsEndpoint = opts.endpoint ?? DEFAULT_METRICS_ENDPOINT
|
|
12
47
|
const auth = opts.auth ?? null
|
|
13
48
|
|
|
14
49
|
const promServer = fastify({ name: 'Prometheus server' })
|
|
@@ -40,6 +75,54 @@ async function startPrometheusServer (runtime, opts) {
|
|
|
40
75
|
},
|
|
41
76
|
})
|
|
42
77
|
|
|
78
|
+
if (opts.readiness !== false) {
|
|
79
|
+
const successStatusCode = opts.readiness?.success?.statusCode ?? DEFAULT_READINESS_SUCCESS_STATUS_CODE
|
|
80
|
+
const successBody = opts.readiness?.success?.body ?? DEFAULT_READINESS_SUCCESS_BODY
|
|
81
|
+
const failStatusCode = opts.readiness?.fail?.statusCode ?? DEFAULT_READINESS_FAIL_STATUS_CODE
|
|
82
|
+
const failBody = opts.readiness?.fail?.body ?? DEFAULT_READINESS_FAIL_BODY
|
|
83
|
+
|
|
84
|
+
promServer.route({
|
|
85
|
+
url: opts.readiness?.endpoint ?? DEFAULT_READINESS_ENDPOINT,
|
|
86
|
+
method: 'GET',
|
|
87
|
+
logLevel: 'warn',
|
|
88
|
+
handler: async (req, reply) => {
|
|
89
|
+
reply.type('text/plain')
|
|
90
|
+
|
|
91
|
+
const ready = await checkReadiness(runtime)
|
|
92
|
+
|
|
93
|
+
if (ready) {
|
|
94
|
+
reply.status(successStatusCode).send(successBody)
|
|
95
|
+
} else {
|
|
96
|
+
reply.status(failStatusCode).send(failBody)
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
})
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (opts.liveness !== false) {
|
|
103
|
+
const successStatusCode = opts.liveness?.success?.statusCode ?? DEFAULT_LIVENESS_SUCCESS_STATUS_CODE
|
|
104
|
+
const successBody = opts.liveness?.success?.body ?? DEFAULT_LIVENESS_SUCCESS_BODY
|
|
105
|
+
const failStatusCode = opts.liveness?.fail?.statusCode ?? DEFAULT_LIVENESS_FAIL_STATUS_CODE
|
|
106
|
+
const failBody = opts.liveness?.fail?.body ?? DEFAULT_LIVENESS_FAIL_BODY
|
|
107
|
+
|
|
108
|
+
promServer.route({
|
|
109
|
+
url: opts.liveness?.endpoint ?? DEFAULT_LIVENESS_ENDPOINT,
|
|
110
|
+
method: 'GET',
|
|
111
|
+
logLevel: 'warn',
|
|
112
|
+
handler: async (req, reply) => {
|
|
113
|
+
reply.type('text/plain')
|
|
114
|
+
|
|
115
|
+
const live = await checkLiveness(runtime)
|
|
116
|
+
|
|
117
|
+
if (live) {
|
|
118
|
+
reply.status(successStatusCode).send(successBody)
|
|
119
|
+
} else {
|
|
120
|
+
reply.status(failStatusCode).send(failBody)
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
})
|
|
124
|
+
}
|
|
125
|
+
|
|
43
126
|
await promServer.listen({ port, host })
|
|
44
127
|
return promServer
|
|
45
128
|
}
|
package/lib/runtime.js
CHANGED
|
@@ -66,7 +66,7 @@ class Runtime extends EventEmitter {
|
|
|
66
66
|
#loggerDestination
|
|
67
67
|
#metrics
|
|
68
68
|
#metricsTimeout
|
|
69
|
-
#status
|
|
69
|
+
#status // starting, started, stopping, stopped, closed
|
|
70
70
|
#meshInterceptor
|
|
71
71
|
#dispatcher
|
|
72
72
|
#managementApi
|
|
@@ -648,6 +648,21 @@ class Runtime extends EventEmitter {
|
|
|
648
648
|
return status
|
|
649
649
|
}
|
|
650
650
|
|
|
651
|
+
async getCustomHealthChecks () {
|
|
652
|
+
const status = {}
|
|
653
|
+
|
|
654
|
+
for (const [service, { count }] of Object.entries(this.#workers.configuration)) {
|
|
655
|
+
for (let i = 0; i < count; i++) {
|
|
656
|
+
const label = `${service}:${i}`
|
|
657
|
+
const worker = this.#workers.get(label)
|
|
658
|
+
|
|
659
|
+
status[label] = await sendViaITC(worker, 'getCustomHealthCheck')
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
return status
|
|
664
|
+
}
|
|
665
|
+
|
|
651
666
|
async getServiceDetails (id, allowUnloaded = false) {
|
|
652
667
|
let service
|
|
653
668
|
|
package/lib/schema.js
CHANGED
|
@@ -380,9 +380,65 @@ const platformaticRuntimeSchema = {
|
|
|
380
380
|
labels: {
|
|
381
381
|
type: 'object',
|
|
382
382
|
additionalProperties: { type: 'string' }
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
|
|
383
|
+
},
|
|
384
|
+
readiness: {
|
|
385
|
+
anyOf: [
|
|
386
|
+
{ type: 'boolean' },
|
|
387
|
+
{
|
|
388
|
+
type: 'object',
|
|
389
|
+
properties: {
|
|
390
|
+
endpoint: { type: 'string' },
|
|
391
|
+
success: {
|
|
392
|
+
type: 'object',
|
|
393
|
+
properties: {
|
|
394
|
+
statusCode: { type: 'number' },
|
|
395
|
+
body: { type: 'string' }
|
|
396
|
+
},
|
|
397
|
+
additionalProperties: false
|
|
398
|
+
},
|
|
399
|
+
fail: {
|
|
400
|
+
type: 'object',
|
|
401
|
+
properties: {
|
|
402
|
+
statusCode: { type: 'number' },
|
|
403
|
+
body: { type: 'string' }
|
|
404
|
+
},
|
|
405
|
+
additionalProperties: false
|
|
406
|
+
}
|
|
407
|
+
},
|
|
408
|
+
additionalProperties: false
|
|
409
|
+
}
|
|
410
|
+
]
|
|
411
|
+
},
|
|
412
|
+
liveness: {
|
|
413
|
+
anyOf: [
|
|
414
|
+
{ type: 'boolean' },
|
|
415
|
+
{
|
|
416
|
+
type: 'object',
|
|
417
|
+
properties: {
|
|
418
|
+
endpoint: { type: 'string' },
|
|
419
|
+
success: {
|
|
420
|
+
type: 'object',
|
|
421
|
+
properties: {
|
|
422
|
+
statusCode: { type: 'number' },
|
|
423
|
+
body: { type: 'string' }
|
|
424
|
+
},
|
|
425
|
+
additionalProperties: false
|
|
426
|
+
},
|
|
427
|
+
fail: {
|
|
428
|
+
type: 'object',
|
|
429
|
+
properties: {
|
|
430
|
+
statusCode: { type: 'number' },
|
|
431
|
+
body: { type: 'string' }
|
|
432
|
+
},
|
|
433
|
+
additionalProperties: false
|
|
434
|
+
}
|
|
435
|
+
},
|
|
436
|
+
additionalProperties: false
|
|
437
|
+
}
|
|
438
|
+
]
|
|
439
|
+
},
|
|
440
|
+
additionalProperties: false
|
|
441
|
+
}
|
|
386
442
|
}
|
|
387
443
|
]
|
|
388
444
|
},
|
package/lib/worker/itc.js
CHANGED
|
@@ -166,6 +166,14 @@ function setupITC (app, service, dispatcher) {
|
|
|
166
166
|
} catch (err) {
|
|
167
167
|
throw new errors.FailedToRetrieveHealthError(service.id, err.message)
|
|
168
168
|
}
|
|
169
|
+
},
|
|
170
|
+
|
|
171
|
+
async getCustomHealthCheck () {
|
|
172
|
+
try {
|
|
173
|
+
return await app.stackable.getCustomHealthCheck()
|
|
174
|
+
} catch (err) {
|
|
175
|
+
throw new errors.FailedToPerformCustomHealthCheckError(service.id, err.message)
|
|
176
|
+
}
|
|
169
177
|
}
|
|
170
178
|
}
|
|
171
179
|
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platformatic/runtime",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.50.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -37,12 +37,12 @@
|
|
|
37
37
|
"typescript": "^5.5.4",
|
|
38
38
|
"undici-oidc-interceptor": "^0.5.0",
|
|
39
39
|
"why-is-node-running": "^2.2.2",
|
|
40
|
-
"@platformatic/
|
|
41
|
-
"@platformatic/node": "2.
|
|
42
|
-
"@platformatic/service": "2.
|
|
43
|
-
"@platformatic/
|
|
44
|
-
"@platformatic/sql-mapper": "2.
|
|
45
|
-
"@platformatic/
|
|
40
|
+
"@platformatic/db": "2.50.0",
|
|
41
|
+
"@platformatic/node": "2.50.0",
|
|
42
|
+
"@platformatic/service": "2.50.0",
|
|
43
|
+
"@platformatic/composer": "2.50.0",
|
|
44
|
+
"@platformatic/sql-mapper": "2.50.0",
|
|
45
|
+
"@platformatic/sql-graphql": "2.50.0"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@fastify/accepts": "^5.0.0",
|
|
@@ -76,13 +76,13 @@
|
|
|
76
76
|
"undici": "^7.0.0",
|
|
77
77
|
"undici-thread-interceptor": "^0.13.1",
|
|
78
78
|
"ws": "^8.16.0",
|
|
79
|
-
"@platformatic/
|
|
80
|
-
"@platformatic/
|
|
81
|
-
"@platformatic/
|
|
82
|
-
"@platformatic/itc": "2.
|
|
83
|
-
"@platformatic/telemetry": "2.
|
|
84
|
-
"@platformatic/ts-compiler": "2.
|
|
85
|
-
"@platformatic/utils": "2.
|
|
79
|
+
"@platformatic/basic": "2.50.0",
|
|
80
|
+
"@platformatic/generators": "2.50.0",
|
|
81
|
+
"@platformatic/config": "2.50.0",
|
|
82
|
+
"@platformatic/itc": "2.50.0",
|
|
83
|
+
"@platformatic/telemetry": "2.50.0",
|
|
84
|
+
"@platformatic/ts-compiler": "2.50.0",
|
|
85
|
+
"@platformatic/utils": "2.50.0"
|
|
86
86
|
},
|
|
87
87
|
"scripts": {
|
|
88
88
|
"test": "npm run lint && borp --concurrency=1 --timeout=300000 && tsd",
|
package/schema.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$id": "https://schemas.platformatic.dev/@platformatic/runtime/2.
|
|
2
|
+
"$id": "https://schemas.platformatic.dev/@platformatic/runtime/2.50.0.json",
|
|
3
3
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
4
4
|
"type": "object",
|
|
5
5
|
"properties": {
|
|
@@ -1153,9 +1153,89 @@
|
|
|
1153
1153
|
"additionalProperties": {
|
|
1154
1154
|
"type": "string"
|
|
1155
1155
|
}
|
|
1156
|
-
}
|
|
1157
|
-
|
|
1158
|
-
|
|
1156
|
+
},
|
|
1157
|
+
"readiness": {
|
|
1158
|
+
"anyOf": [
|
|
1159
|
+
{
|
|
1160
|
+
"type": "boolean"
|
|
1161
|
+
},
|
|
1162
|
+
{
|
|
1163
|
+
"type": "object",
|
|
1164
|
+
"properties": {
|
|
1165
|
+
"endpoint": {
|
|
1166
|
+
"type": "string"
|
|
1167
|
+
},
|
|
1168
|
+
"success": {
|
|
1169
|
+
"type": "object",
|
|
1170
|
+
"properties": {
|
|
1171
|
+
"statusCode": {
|
|
1172
|
+
"type": "number"
|
|
1173
|
+
},
|
|
1174
|
+
"body": {
|
|
1175
|
+
"type": "string"
|
|
1176
|
+
}
|
|
1177
|
+
},
|
|
1178
|
+
"additionalProperties": false
|
|
1179
|
+
},
|
|
1180
|
+
"fail": {
|
|
1181
|
+
"type": "object",
|
|
1182
|
+
"properties": {
|
|
1183
|
+
"statusCode": {
|
|
1184
|
+
"type": "number"
|
|
1185
|
+
},
|
|
1186
|
+
"body": {
|
|
1187
|
+
"type": "string"
|
|
1188
|
+
}
|
|
1189
|
+
},
|
|
1190
|
+
"additionalProperties": false
|
|
1191
|
+
}
|
|
1192
|
+
},
|
|
1193
|
+
"additionalProperties": false
|
|
1194
|
+
}
|
|
1195
|
+
]
|
|
1196
|
+
},
|
|
1197
|
+
"liveness": {
|
|
1198
|
+
"anyOf": [
|
|
1199
|
+
{
|
|
1200
|
+
"type": "boolean"
|
|
1201
|
+
},
|
|
1202
|
+
{
|
|
1203
|
+
"type": "object",
|
|
1204
|
+
"properties": {
|
|
1205
|
+
"endpoint": {
|
|
1206
|
+
"type": "string"
|
|
1207
|
+
},
|
|
1208
|
+
"success": {
|
|
1209
|
+
"type": "object",
|
|
1210
|
+
"properties": {
|
|
1211
|
+
"statusCode": {
|
|
1212
|
+
"type": "number"
|
|
1213
|
+
},
|
|
1214
|
+
"body": {
|
|
1215
|
+
"type": "string"
|
|
1216
|
+
}
|
|
1217
|
+
},
|
|
1218
|
+
"additionalProperties": false
|
|
1219
|
+
},
|
|
1220
|
+
"fail": {
|
|
1221
|
+
"type": "object",
|
|
1222
|
+
"properties": {
|
|
1223
|
+
"statusCode": {
|
|
1224
|
+
"type": "number"
|
|
1225
|
+
},
|
|
1226
|
+
"body": {
|
|
1227
|
+
"type": "string"
|
|
1228
|
+
}
|
|
1229
|
+
},
|
|
1230
|
+
"additionalProperties": false
|
|
1231
|
+
}
|
|
1232
|
+
},
|
|
1233
|
+
"additionalProperties": false
|
|
1234
|
+
}
|
|
1235
|
+
]
|
|
1236
|
+
},
|
|
1237
|
+
"additionalProperties": false
|
|
1238
|
+
}
|
|
1159
1239
|
}
|
|
1160
1240
|
]
|
|
1161
1241
|
},
|