@platformatic/runtime 2.9.1 → 2.10.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 CHANGED
@@ -5,7 +5,7 @@
5
5
  * and run json-schema-to-typescript to regenerate this file.
6
6
  */
7
7
 
8
- export type HttpsSchemasPlatformaticDevPlatformaticRuntime291Json = {
8
+ export type HttpsSchemasPlatformaticDevPlatformaticRuntime2100Json = {
9
9
  [k: string]: unknown;
10
10
  } & {
11
11
  $schema?: string;
@@ -20,6 +20,16 @@ export type HttpsSchemasPlatformaticDevPlatformaticRuntime291Json = {
20
20
  id: string;
21
21
  config?: string;
22
22
  useHttp?: boolean;
23
+ workers?: number | string;
24
+ health?: {
25
+ enabled?: boolean | string;
26
+ interval?: number | string;
27
+ gracePeriod?: number | string;
28
+ maxUnhealthyChecks?: number | string;
29
+ maxELU?: number | string;
30
+ maxHeapUsed?: number | string;
31
+ maxHeapTotal?: number | string;
32
+ };
23
33
  };
24
34
  };
25
35
  };
@@ -52,8 +62,6 @@ export type HttpsSchemasPlatformaticDevPlatformaticRuntime291Json = {
52
62
  [k: string]: unknown;
53
63
  };
54
64
  level?: string;
55
- additionalProperties?: never;
56
- [k: string]: unknown;
57
65
  }[];
58
66
  options?: {
59
67
  [k: string]: unknown;
@@ -101,6 +109,15 @@ export type HttpsSchemasPlatformaticDevPlatformaticRuntime291Json = {
101
109
  runtime: number | string;
102
110
  service: number | string;
103
111
  };
112
+ health?: {
113
+ enabled?: boolean | string;
114
+ interval?: number | string;
115
+ gracePeriod?: number | string;
116
+ maxUnhealthyChecks?: number | string;
117
+ maxELU?: number | string;
118
+ maxHeapUsed?: number | string;
119
+ maxHeapTotal?: number | string;
120
+ };
104
121
  undici?: {
105
122
  agentOptions?: {
106
123
  [k: string]: unknown;
package/lib/errors.js CHANGED
@@ -17,6 +17,7 @@ module.exports = {
17
17
  FailedToRetrieveGraphQLSchemaError: createError(`${ERROR_PREFIX}_FAILED_TO_RETRIEVE_GRAPHQL_SCHEMA`, 'Failed to retrieve GraphQL schema for service with id "%s": %s'),
18
18
  FailedToRetrieveMetaError: createError(`${ERROR_PREFIX}_FAILED_TO_RETRIEVE_META`, 'Failed to retrieve metadata for service with id "%s": %s'),
19
19
  FailedToRetrieveMetricsError: createError(`${ERROR_PREFIX}_FAILED_TO_RETRIEVE_METRICS`, 'Failed to retrieve metrics for service with id "%s": %s'),
20
+ FailedToRetrieveHealthError: createError(`${ERROR_PREFIX}_FAILED_TO_RETRIEVE_HEALTH`, 'Failed to retrieve health for service with id "%s": %s'),
20
21
  ApplicationAlreadyStartedError: createError(`${ERROR_PREFIX}_APPLICATION_ALREADY_STARTED`, 'Application is already started'),
21
22
  ApplicationNotStartedError: createError(`${ERROR_PREFIX}_APPLICATION_NOT_STARTED`, 'Application has not been started'),
22
23
  ConfigPathMustBeStringError: createError(`${ERROR_PREFIX}_CONFIG_PATH_MUST_BE_STRING`, 'Config path must be a string'),
package/lib/runtime.js CHANGED
@@ -7,7 +7,7 @@ const { join } = require('node:path')
7
7
  const { setTimeout: sleep } = require('node:timers/promises')
8
8
  const { Worker } = require('node:worker_threads')
9
9
  const { ITC } = require('@platformatic/itc')
10
- const { ensureLoggableError, executeWithTimeout } = require('@platformatic/utils')
10
+ const { ensureLoggableError, executeWithTimeout, deepmerge } = require('@platformatic/utils')
11
11
  const ts = require('tail-file-stream')
12
12
  const { createThreadInterceptor } = require('undici-thread-interceptor')
13
13
 
@@ -24,6 +24,7 @@ const {
24
24
  kServiceId,
25
25
  kWorkerId,
26
26
  kITC,
27
+ kHealthCheckTimer,
27
28
  kConfig,
28
29
  kLoggerDestination,
29
30
  kLoggingPort,
@@ -763,6 +764,9 @@ class Runtime extends EventEmitter {
763
764
  }
764
765
  }
765
766
 
767
+ const errorLabel = this.#workerExtendedLabel(serviceId, index, workersCount)
768
+ const health = deepmerge(config.health ?? {}, serviceConfig.health ?? {})
769
+
766
770
  const worker = new Worker(kWorkerFile, {
767
771
  workerData: {
768
772
  config,
@@ -783,6 +787,9 @@ class Runtime extends EventEmitter {
783
787
  execArgv: serviceConfig.isPLTService ? [] : ['--require', openTelemetrySetupPath],
784
788
  env: this.#env,
785
789
  transferList: [loggingPort],
790
+ resourceLimits: {
791
+ maxOldGenerationSizeMb: health.maxHeapTotal
792
+ },
786
793
  /*
787
794
  Important: always set stdout and stderr to true, so that worker's output is not automatically
788
795
  piped to the parent thread. We actually never output the thread output since we replace it
@@ -814,8 +821,6 @@ class Runtime extends EventEmitter {
814
821
 
815
822
  // Wait for the next tick so that crashed from the thread are logged first
816
823
  setImmediate(() => {
817
- const errorLabel = workersCount > 1 ? `worker ${index} of the service "${serviceId}"` : `service "${serviceId}"`
818
-
819
824
  if (started && (!config.watch || code !== 0)) {
820
825
  this.logger.warn(`The ${errorLabel} unexpectedly exited with code ${code}.`)
821
826
  }
@@ -837,7 +842,6 @@ class Runtime extends EventEmitter {
837
842
  worker[kId] = workersCount > 1 ? workerId : serviceId
838
843
  worker[kServiceId] = serviceId
839
844
  worker[kWorkerId] = workersCount > 1 ? index : undefined
840
- worker[kConfig] = serviceConfig
841
845
  worker[kLoggerDestination] = loggerDestination
842
846
  worker[kLoggingPort] = loggingPort
843
847
 
@@ -900,7 +904,6 @@ class Runtime extends EventEmitter {
900
904
 
901
905
  // Store dependencies
902
906
  const [{ dependencies }] = await waitEventFromITC(worker, 'init')
903
- worker[kWorkerStatus] = 'boot'
904
907
 
905
908
  if (autoload) {
906
909
  serviceConfig.dependencies = dependencies
@@ -910,11 +913,50 @@ class Runtime extends EventEmitter {
910
913
  }
911
914
  }
912
915
  }
916
+
917
+ // This must be done here as the dependencies are filled above
918
+ worker[kConfig] = { ...serviceConfig, health }
919
+ worker[kWorkerStatus] = 'boot'
920
+ }
921
+
922
+ #setupHealthCheck (worker, errorLabel) {
923
+ // Clear the timeout when exiting
924
+ worker.on('exit', () => clearTimeout(worker[kHealthCheckTimer]))
925
+
926
+ const { maxELU, maxHeapUsed, maxHeapTotal, maxUnhealthyChecks, interval } = worker[kConfig].health
927
+ let unhealthyChecks = 0
928
+
929
+ worker[kHealthCheckTimer] = setTimeout(async () => {
930
+ const health = await worker[kITC].send('getHealth')
931
+ this.emit('health', {
932
+ id: worker[kId],
933
+ service: worker[kServiceId],
934
+ worker: worker[kWorkerId],
935
+ currentHealth: health,
936
+ healthConfig: worker[kConfig].health
937
+ })
938
+
939
+ const { elu, heapUsed } = health
940
+ const memoryUsage = heapUsed / maxHeapTotal
941
+ if (elu > maxELU || memoryUsage > maxHeapUsed) {
942
+ unhealthyChecks++
943
+ } else {
944
+ unhealthyChecks = 0
945
+ }
946
+
947
+ if (unhealthyChecks >= maxUnhealthyChecks) {
948
+ this.logger.error(`The ${errorLabel} is unhealthy. Forcefully terminating it ...`)
949
+ worker.terminate()
950
+ return
951
+ }
952
+
953
+ worker[kHealthCheckTimer].refresh()
954
+ }, interval)
913
955
  }
914
956
 
915
957
  async #startWorker (config, serviceConfig, workersCount, id, index, silent, bootstrapAttempt = 0) {
916
958
  const workerId = `${id}:${index}`
917
- const label = workersCount > 1 ? `worker ${index} of the service "${id}"` : `service "${id}"`
959
+ const label = this.#workerExtendedLabel(id, index, workersCount)
918
960
 
919
961
  if (!silent) {
920
962
  this.logger?.info(`Starting the ${label}...`)
@@ -941,6 +983,13 @@ class Runtime extends EventEmitter {
941
983
  if (!silent) {
942
984
  this.logger?.info(`Started the ${label}...`)
943
985
  }
986
+
987
+ const { enabled, gracePeriod } = worker[kConfig].health
988
+ if (enabled && config.restartOnError > 0) {
989
+ worker[kHealthCheckTimer] = setTimeout(() => {
990
+ this.#setupHealthCheck(worker, label)
991
+ }, gracePeriod > 0 ? gracePeriod : 1)
992
+ }
944
993
  } catch (error) {
945
994
  // TODO: handle port allocation error here
946
995
  if (error.code === 'EADDRINUSE') throw error
@@ -983,7 +1032,7 @@ class Runtime extends EventEmitter {
983
1032
 
984
1033
  worker[kWorkerStatus] = 'stopping'
985
1034
 
986
- const label = workersCount > 1 ? `worker ${index} of the service "${id}"` : `service "${id}"`
1035
+ const label = this.#workerExtendedLabel(id, index, workersCount)
987
1036
 
988
1037
  if (!silent) {
989
1038
  this.logger?.info(`Stopping the ${label}...`)
@@ -1022,6 +1071,11 @@ class Runtime extends EventEmitter {
1022
1071
  worker[kITC].close()
1023
1072
  worker[kLoggerDestination].close()
1024
1073
  worker[kLoggingPort].close()
1074
+ clearTimeout(worker[kHealthCheckTimer])
1075
+ }
1076
+
1077
+ #workerExtendedLabel (serviceId, workerId, workersCount) {
1078
+ return workersCount > 1 ? `worker ${workerId} of the service "${serviceId}"` : `service "${serviceId}"`
1025
1079
  }
1026
1080
 
1027
1081
  async #restartCrashedWorker (config, serviceConfig, workersCount, id, index, silent, bootstrapAttempt) {
@@ -1037,6 +1091,12 @@ class Runtime extends EventEmitter {
1037
1091
  setTimeout(async () => {
1038
1092
  this.#restartingWorkers.delete(workerId)
1039
1093
 
1094
+ // If some processes were scheduled to restart
1095
+ // but the runtime is stopped, ignore it
1096
+ if (!this.#status.startsWith('start')) {
1097
+ return
1098
+ }
1099
+
1040
1100
  try {
1041
1101
  await this.#setupWorker(config, serviceConfig, workersCount, id, index)
1042
1102
  await this.#startWorker(config, serviceConfig, workersCount, id, index, silent, bootstrapAttempt)
package/lib/schema.js CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  const telemetry = require('@platformatic/telemetry').schema
5
5
  const {
6
- schemaComponents: { server, logger }
6
+ schemaComponents: { server, logger, health }
7
7
  } = require('@platformatic/utils')
8
8
 
9
9
  const workers = {
@@ -38,7 +38,8 @@ const services = {
38
38
  useHttp: {
39
39
  type: 'boolean'
40
40
  },
41
- workers
41
+ workers,
42
+ health: { ...health, default: undefined }
42
43
  }
43
44
  }
44
45
  }
@@ -94,7 +95,9 @@ const platformaticRuntimeSchema = {
94
95
  },
95
96
  useHttp: {
96
97
  type: 'boolean'
97
- }
98
+ },
99
+ workers,
100
+ health: { ...health, default: undefined }
98
101
  }
99
102
  }
100
103
  }
@@ -143,6 +146,7 @@ const platformaticRuntimeSchema = {
143
146
  required: ['runtime', 'service'],
144
147
  additionalProperties: false
145
148
  },
149
+ health,
146
150
  undici: {
147
151
  type: 'object',
148
152
  properties: {
package/lib/worker/app.js CHANGED
@@ -3,6 +3,7 @@
3
3
  const { existsSync } = require('node:fs')
4
4
  const { EventEmitter } = require('node:events')
5
5
  const { resolve } = require('node:path')
6
+ const { performance: { eventLoopUtilization } } = require('node:perf_hooks')
6
7
  const { workerData } = require('node:worker_threads')
7
8
  const { ConfigManager } = require('@platformatic/config')
8
9
  const { FileWatcher } = require('@platformatic/utils')
@@ -21,6 +22,7 @@ class PlatformaticApp extends EventEmitter {
21
22
  #fileWatcher
22
23
  #debouncedRestart
23
24
  #context
25
+ #lastELU
24
26
 
25
27
  constructor (
26
28
  appConfig,
@@ -42,6 +44,7 @@ class PlatformaticApp extends EventEmitter {
42
44
  this.#listening = false
43
45
  this.stackable = null
44
46
  this.#fileWatcher = null
47
+ this.#lastELU = eventLoopUtilization()
45
48
 
46
49
  this.#context = {
47
50
  serviceId: this.serviceId,
@@ -209,6 +212,20 @@ class PlatformaticApp extends EventEmitter {
209
212
  return this.stackable.getMetrics({ format })
210
213
  }
211
214
 
215
+ async getHealth () {
216
+ const currentELU = eventLoopUtilization()
217
+ const elu = eventLoopUtilization(currentELU, this.#lastELU).utilization
218
+ this.#lastELU = currentELU
219
+
220
+ const { heapUsed, heapTotal } = process.memoryUsage()
221
+
222
+ return {
223
+ elu,
224
+ heapUsed,
225
+ heapTotal
226
+ }
227
+ }
228
+
212
229
  #fetchServiceUrl (key, { parent, context: service }) {
213
230
  if (service.localServiceEnvVars.has(key)) {
214
231
  return service.localServiceEnvVars.get(key)
package/lib/worker/itc.js CHANGED
@@ -150,6 +150,14 @@ function setupITC (app, service, dispatcher) {
150
150
  }
151
151
  },
152
152
 
153
+ async getHealth () {
154
+ try {
155
+ return await app.getHealth()
156
+ } catch (err) {
157
+ throw new errors.FailedToRetrieveHealthError(service.id, err.message)
158
+ }
159
+ },
160
+
153
161
  inject (injectParams) {
154
162
  return app.stackable.inject(injectParams)
155
163
  }
@@ -5,8 +5,19 @@ const kId = Symbol.for('plt.runtime.id') // This is also used to detect if we ar
5
5
  const kServiceId = Symbol.for('plt.runtime.service.id')
6
6
  const kWorkerId = Symbol.for('plt.runtime.worker.id')
7
7
  const kITC = Symbol.for('plt.runtime.itc')
8
+ const kHealthCheckTimer = Symbol.for('plt.runtime.worker.healthCheckTimer')
8
9
  const kLoggerDestination = Symbol.for('plt.runtime.loggerDestination')
9
10
  const kLoggingPort = Symbol.for('plt.runtime.logginPort')
10
11
  const kWorkerStatus = Symbol('plt.runtime.worker.status')
11
12
 
12
- module.exports = { kConfig, kId, kServiceId, kWorkerId, kITC, kLoggerDestination, kLoggingPort, kWorkerStatus }
13
+ module.exports = {
14
+ kConfig,
15
+ kId,
16
+ kServiceId,
17
+ kWorkerId,
18
+ kITC,
19
+ kHealthCheckTimer,
20
+ kLoggerDestination,
21
+ kLoggingPort,
22
+ kWorkerStatus
23
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platformatic/runtime",
3
- "version": "2.9.1",
3
+ "version": "2.10.0",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -35,12 +35,12 @@
35
35
  "typescript": "^5.5.4",
36
36
  "undici-oidc-interceptor": "^0.5.0",
37
37
  "why-is-node-running": "^2.2.2",
38
- "@platformatic/db": "2.9.1",
39
- "@platformatic/composer": "2.9.1",
40
- "@platformatic/service": "2.9.1",
41
- "@platformatic/node": "2.9.1",
42
- "@platformatic/sql-graphql": "2.9.1",
43
- "@platformatic/sql-mapper": "2.9.1"
38
+ "@platformatic/composer": "2.10.0",
39
+ "@platformatic/db": "2.10.0",
40
+ "@platformatic/node": "2.10.0",
41
+ "@platformatic/service": "2.10.0",
42
+ "@platformatic/sql-mapper": "2.10.0",
43
+ "@platformatic/sql-graphql": "2.10.0"
44
44
  },
45
45
  "dependencies": {
46
46
  "@fastify/error": "^4.0.0",
@@ -62,22 +62,22 @@
62
62
  "help-me": "^5.0.0",
63
63
  "minimist": "^1.2.8",
64
64
  "pino": "^8.19.0",
65
- "pino-pretty": "^11.0.0",
65
+ "pino-pretty": "^12.0.0",
66
66
  "pino-roll": "^2.0.0",
67
67
  "prom-client": "^15.1.2",
68
68
  "semgrator": "^0.3.0",
69
69
  "tail-file-stream": "^0.2.0",
70
70
  "thread-cpu-usage": "^0.2.0",
71
71
  "undici": "^6.9.0",
72
- "undici-thread-interceptor": "^0.7.0",
72
+ "undici-thread-interceptor": "^0.8.0",
73
73
  "ws": "^8.16.0",
74
- "@platformatic/basic": "2.9.1",
75
- "@platformatic/config": "2.9.1",
76
- "@platformatic/itc": "2.9.1",
77
- "@platformatic/ts-compiler": "2.9.1",
78
- "@platformatic/generators": "2.9.1",
79
- "@platformatic/utils": "2.9.1",
80
- "@platformatic/telemetry": "2.9.1"
74
+ "@platformatic/basic": "2.10.0",
75
+ "@platformatic/generators": "2.10.0",
76
+ "@platformatic/config": "2.10.0",
77
+ "@platformatic/itc": "2.10.0",
78
+ "@platformatic/telemetry": "2.10.0",
79
+ "@platformatic/utils": "2.10.0",
80
+ "@platformatic/ts-compiler": "2.10.0"
81
81
  },
82
82
  "scripts": {
83
83
  "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.9.1.json",
2
+ "$id": "https://schemas.platformatic.dev/@platformatic/runtime/2.10.0.json",
3
3
  "$schema": "http://json-schema.org/draft-07/schema#",
4
4
  "type": "object",
5
5
  "properties": {
@@ -51,6 +51,108 @@
51
51
  },
52
52
  "useHttp": {
53
53
  "type": "boolean"
54
+ },
55
+ "workers": {
56
+ "anyOf": [
57
+ {
58
+ "type": "number",
59
+ "minimum": 1
60
+ },
61
+ {
62
+ "type": "string"
63
+ }
64
+ ]
65
+ },
66
+ "health": {
67
+ "type": "object",
68
+ "properties": {
69
+ "enabled": {
70
+ "default": true,
71
+ "anyOf": [
72
+ {
73
+ "type": "boolean"
74
+ },
75
+ {
76
+ "type": "string"
77
+ }
78
+ ]
79
+ },
80
+ "interval": {
81
+ "default": 30000,
82
+ "anyOf": [
83
+ {
84
+ "type": "number",
85
+ "minimum": 0
86
+ },
87
+ {
88
+ "type": "string"
89
+ }
90
+ ]
91
+ },
92
+ "gracePeriod": {
93
+ "default": 30000,
94
+ "anyOf": [
95
+ {
96
+ "type": "number",
97
+ "minimum": 0
98
+ },
99
+ {
100
+ "type": "string"
101
+ }
102
+ ]
103
+ },
104
+ "maxUnhealthyChecks": {
105
+ "default": 3,
106
+ "anyOf": [
107
+ {
108
+ "type": "number",
109
+ "minimum": 1
110
+ },
111
+ {
112
+ "type": "string"
113
+ }
114
+ ]
115
+ },
116
+ "maxELU": {
117
+ "default": 0.95,
118
+ "anyOf": [
119
+ {
120
+ "type": "number",
121
+ "minimum": 0,
122
+ "maximum": 1
123
+ },
124
+ {
125
+ "type": "string"
126
+ }
127
+ ]
128
+ },
129
+ "maxHeapUsed": {
130
+ "default": 0.95,
131
+ "anyOf": [
132
+ {
133
+ "type": "number",
134
+ "minimum": 0,
135
+ "maximum": 1
136
+ },
137
+ {
138
+ "type": "string"
139
+ }
140
+ ]
141
+ },
142
+ "maxHeapTotal": {
143
+ "default": 4294967296,
144
+ "anyOf": [
145
+ {
146
+ "type": "number",
147
+ "minimum": 0
148
+ },
149
+ {
150
+ "type": "string"
151
+ }
152
+ ]
153
+ }
154
+ },
155
+ "additionalProperties": false
54
156
  }
55
157
  }
56
158
  }
@@ -102,6 +204,97 @@
102
204
  "type": "string"
103
205
  }
104
206
  ]
207
+ },
208
+ "health": {
209
+ "type": "object",
210
+ "properties": {
211
+ "enabled": {
212
+ "default": true,
213
+ "anyOf": [
214
+ {
215
+ "type": "boolean"
216
+ },
217
+ {
218
+ "type": "string"
219
+ }
220
+ ]
221
+ },
222
+ "interval": {
223
+ "default": 30000,
224
+ "anyOf": [
225
+ {
226
+ "type": "number",
227
+ "minimum": 0
228
+ },
229
+ {
230
+ "type": "string"
231
+ }
232
+ ]
233
+ },
234
+ "gracePeriod": {
235
+ "default": 30000,
236
+ "anyOf": [
237
+ {
238
+ "type": "number",
239
+ "minimum": 0
240
+ },
241
+ {
242
+ "type": "string"
243
+ }
244
+ ]
245
+ },
246
+ "maxUnhealthyChecks": {
247
+ "default": 3,
248
+ "anyOf": [
249
+ {
250
+ "type": "number",
251
+ "minimum": 1
252
+ },
253
+ {
254
+ "type": "string"
255
+ }
256
+ ]
257
+ },
258
+ "maxELU": {
259
+ "default": 0.95,
260
+ "anyOf": [
261
+ {
262
+ "type": "number",
263
+ "minimum": 0,
264
+ "maximum": 1
265
+ },
266
+ {
267
+ "type": "string"
268
+ }
269
+ ]
270
+ },
271
+ "maxHeapUsed": {
272
+ "default": 0.95,
273
+ "anyOf": [
274
+ {
275
+ "type": "number",
276
+ "minimum": 0,
277
+ "maximum": 1
278
+ },
279
+ {
280
+ "type": "string"
281
+ }
282
+ ]
283
+ },
284
+ "maxHeapTotal": {
285
+ "default": 4294967296,
286
+ "anyOf": [
287
+ {
288
+ "type": "number",
289
+ "minimum": 0
290
+ },
291
+ {
292
+ "type": "string"
293
+ }
294
+ ]
295
+ }
296
+ },
297
+ "additionalProperties": false
105
298
  }
106
299
  }
107
300
  }
@@ -163,6 +356,97 @@
163
356
  "type": "string"
164
357
  }
165
358
  ]
359
+ },
360
+ "health": {
361
+ "type": "object",
362
+ "properties": {
363
+ "enabled": {
364
+ "default": true,
365
+ "anyOf": [
366
+ {
367
+ "type": "boolean"
368
+ },
369
+ {
370
+ "type": "string"
371
+ }
372
+ ]
373
+ },
374
+ "interval": {
375
+ "default": 30000,
376
+ "anyOf": [
377
+ {
378
+ "type": "number",
379
+ "minimum": 0
380
+ },
381
+ {
382
+ "type": "string"
383
+ }
384
+ ]
385
+ },
386
+ "gracePeriod": {
387
+ "default": 30000,
388
+ "anyOf": [
389
+ {
390
+ "type": "number",
391
+ "minimum": 0
392
+ },
393
+ {
394
+ "type": "string"
395
+ }
396
+ ]
397
+ },
398
+ "maxUnhealthyChecks": {
399
+ "default": 3,
400
+ "anyOf": [
401
+ {
402
+ "type": "number",
403
+ "minimum": 1
404
+ },
405
+ {
406
+ "type": "string"
407
+ }
408
+ ]
409
+ },
410
+ "maxELU": {
411
+ "default": 0.95,
412
+ "anyOf": [
413
+ {
414
+ "type": "number",
415
+ "minimum": 0,
416
+ "maximum": 1
417
+ },
418
+ {
419
+ "type": "string"
420
+ }
421
+ ]
422
+ },
423
+ "maxHeapUsed": {
424
+ "default": 0.95,
425
+ "anyOf": [
426
+ {
427
+ "type": "number",
428
+ "minimum": 0,
429
+ "maximum": 1
430
+ },
431
+ {
432
+ "type": "string"
433
+ }
434
+ ]
435
+ },
436
+ "maxHeapTotal": {
437
+ "default": 4294967296,
438
+ "anyOf": [
439
+ {
440
+ "type": "number",
441
+ "minimum": 0
442
+ },
443
+ {
444
+ "type": "string"
445
+ }
446
+ ]
447
+ }
448
+ },
449
+ "additionalProperties": false
166
450
  }
167
451
  }
168
452
  }
@@ -214,17 +498,25 @@
214
498
  "type": "object",
215
499
  "properties": {
216
500
  "target": {
217
- "type": "string",
218
- "resolveModule": true
501
+ "anyOf": [
502
+ {
503
+ "type": "string",
504
+ "resolveModule": true
505
+ },
506
+ {
507
+ "type": "string",
508
+ "resolvePath": true
509
+ }
510
+ ]
219
511
  },
220
512
  "options": {
221
513
  "type": "object"
222
514
  },
223
515
  "level": {
224
516
  "type": "string"
225
- },
226
- "additionalProperties": false
227
- }
517
+ }
518
+ },
519
+ "additionalProperties": false
228
520
  }
229
521
  },
230
522
  "options": {
@@ -409,6 +701,98 @@
409
701
  ],
410
702
  "additionalProperties": false
411
703
  },
704
+ "health": {
705
+ "type": "object",
706
+ "default": {},
707
+ "properties": {
708
+ "enabled": {
709
+ "default": true,
710
+ "anyOf": [
711
+ {
712
+ "type": "boolean"
713
+ },
714
+ {
715
+ "type": "string"
716
+ }
717
+ ]
718
+ },
719
+ "interval": {
720
+ "default": 30000,
721
+ "anyOf": [
722
+ {
723
+ "type": "number",
724
+ "minimum": 0
725
+ },
726
+ {
727
+ "type": "string"
728
+ }
729
+ ]
730
+ },
731
+ "gracePeriod": {
732
+ "default": 30000,
733
+ "anyOf": [
734
+ {
735
+ "type": "number",
736
+ "minimum": 0
737
+ },
738
+ {
739
+ "type": "string"
740
+ }
741
+ ]
742
+ },
743
+ "maxUnhealthyChecks": {
744
+ "default": 3,
745
+ "anyOf": [
746
+ {
747
+ "type": "number",
748
+ "minimum": 1
749
+ },
750
+ {
751
+ "type": "string"
752
+ }
753
+ ]
754
+ },
755
+ "maxELU": {
756
+ "default": 0.95,
757
+ "anyOf": [
758
+ {
759
+ "type": "number",
760
+ "minimum": 0,
761
+ "maximum": 1
762
+ },
763
+ {
764
+ "type": "string"
765
+ }
766
+ ]
767
+ },
768
+ "maxHeapUsed": {
769
+ "default": 0.95,
770
+ "anyOf": [
771
+ {
772
+ "type": "number",
773
+ "minimum": 0,
774
+ "maximum": 1
775
+ },
776
+ {
777
+ "type": "string"
778
+ }
779
+ ]
780
+ },
781
+ "maxHeapTotal": {
782
+ "default": 4294967296,
783
+ "anyOf": [
784
+ {
785
+ "type": "number",
786
+ "minimum": 0
787
+ },
788
+ {
789
+ "type": "string"
790
+ }
791
+ ]
792
+ }
793
+ },
794
+ "additionalProperties": false
795
+ },
412
796
  "undici": {
413
797
  "type": "object",
414
798
  "properties": {