@platformatic/runtime 3.17.0 → 3.19.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
@@ -306,6 +306,7 @@ export type PlatformaticRuntimeConfig = {
306
306
  body?: string;
307
307
  };
308
308
  };
309
+ healthChecksTimeouts?: number | string;
309
310
  plugins?: string[];
310
311
  timeout?: number | string;
311
312
  /**
package/lib/errors.js CHANGED
@@ -128,10 +128,6 @@ export const MissingPprofCapture = createError(
128
128
  'Please install @platformatic/wattpm-pprof-capture'
129
129
  )
130
130
 
131
- export const GetHeapStatisticUnavailable = createError(
132
- `${ERROR_PREFIX}_GET_HEAP_STATISTIC_UNAVAILABLE`,
133
- 'The getHeapStatistics method is not available in your Node version'
134
- )
135
131
  export const FailedToSendHealthSignalsError = createError(
136
132
  `${ERROR_PREFIX}_FAILED_TO_SEND_HEALTH_SIGNALS`,
137
133
  'Cannot send health signals from application "%s": %s'
@@ -238,6 +238,7 @@ export async function managementApiPlugin (app, opts) {
238
238
  return metrics
239
239
  })
240
240
 
241
+ // TODO: Remove in next major version - deprecated endpoint
241
242
  app.get('/metrics/live', { websocket: true }, async socket => {
242
243
  const config = await runtime.getRuntimeConfig()
243
244
 
@@ -256,26 +257,32 @@ export async function managementApiPlugin (app, opts) {
256
257
  return
257
258
  }
258
259
 
259
- const cachedMetrics = runtime.getCachedMetrics()
260
- if (cachedMetrics.length > 0) {
261
- const serializedMetrics = cachedMetrics.map(metric => JSON.stringify(metric)).join('\n')
262
- socket.send(serializedMetrics + '\n')
260
+ const pollAndSendMetrics = async () => {
261
+ try {
262
+ const metrics = await runtime.getFormattedMetrics()
263
+ if (metrics) {
264
+ const serializedMetrics = JSON.stringify(metrics)
265
+ socket.send(serializedMetrics + '\n')
266
+ }
267
+ } catch (error) {
268
+ // If there's an error, stop polling and close the connection
269
+ clearInterval(pollingInterval)
270
+ socket.close()
271
+ }
263
272
  }
264
273
 
265
- const eventHandler = metrics => {
266
- const serializedMetrics = JSON.stringify(metrics)
267
- socket.send(serializedMetrics + '\n')
268
- }
274
+ // Poll every second
275
+ const pollingInterval = setInterval(pollAndSendMetrics, 1000)
269
276
 
270
- runtime.on('metrics', eventHandler)
277
+ // Send initial metrics immediately
278
+ await pollAndSendMetrics()
271
279
 
272
- socket.on('error', () => {
273
- runtime.off('metrics', eventHandler)
274
- })
280
+ const cleanup = () => {
281
+ clearInterval(pollingInterval)
282
+ }
275
283
 
276
- socket.on('close', () => {
277
- runtime.off('metrics', eventHandler)
278
- })
284
+ socket.on('error', cleanup)
285
+ socket.on('close', cleanup)
279
286
  })
280
287
 
281
288
  app.get('/logs/live', { websocket: true }, async socket => {
@@ -68,7 +68,7 @@ async function checkLiveness (runtime) {
68
68
  return check
69
69
  } else if (typeof check === 'object') {
70
70
  response = check
71
- return check.status
71
+ return check.status || false
72
72
  }
73
73
  return false
74
74
  })
@@ -85,7 +85,7 @@ export async function startPrometheusServer (runtime, opts) {
85
85
  const metricsEndpoint = opts.endpoint ?? DEFAULT_METRICS_ENDPOINT
86
86
  const auth = opts.auth ?? null
87
87
 
88
- const promServer = fastify({ name: 'Prometheus server' })
88
+ const promServer = fastify({ name: 'Prometheus server', loggerInstance: runtime.logger })
89
89
  promServer.register(fastifyAccepts)
90
90
 
91
91
  let onRequestHook
@@ -151,7 +151,7 @@ export async function startPrometheusServer (runtime, opts) {
151
151
  url: readinessEndpoint,
152
152
  method: 'GET',
153
153
  logLevel: 'warn',
154
- handler: async (req, reply) => {
154
+ handler: async (_req, reply) => {
155
155
  reply.type('text/plain')
156
156
 
157
157
  const { status, response } = await checkReadiness(runtime)
@@ -190,7 +190,7 @@ export async function startPrometheusServer (runtime, opts) {
190
190
  url: livenessEndpoint,
191
191
  method: 'GET',
192
192
  logLevel: 'warn',
193
- handler: async (req, reply) => {
193
+ handler: async (_req, reply) => {
194
194
  reply.type('text/plain')
195
195
 
196
196
  const { status, response, readiness } = await checkLiveness(runtime)
package/lib/runtime.js CHANGED
@@ -31,13 +31,11 @@ import {
31
31
  ApplicationNotStartedError,
32
32
  ApplicationStartTimeoutError,
33
33
  CannotRemoveEntrypointError,
34
- GetHeapStatisticUnavailable,
35
34
  InvalidArgumentError,
36
35
  MessagingError,
37
36
  MissingEntrypointError,
38
37
  MissingPprofCapture,
39
38
  RuntimeAbortedError,
40
- RuntimeExitedError,
41
39
  WorkerNotFoundError
42
40
  } from './errors.js'
43
41
  import { abstractLogger, createLogger } from './logger.js'
@@ -48,14 +46,13 @@ import { startScheduler } from './scheduler.js'
48
46
  import { createSharedStore } from './shared-http-cache.js'
49
47
  import { version } from './version.js'
50
48
  import { HealthSignalsQueue } from './worker/health-signals.js'
51
- import { sendViaITC, waitEventFromITC } from './worker/itc.js'
49
+ import { sendMultipleViaITC, sendViaITC, waitEventFromITC } from './worker/itc.js'
52
50
  import { RoundRobinMap } from './worker/round-robin-map.js'
53
51
  import {
54
52
  kApplicationId,
55
53
  kConfig,
56
54
  kFullId,
57
55
  kHealthCheckTimer,
58
- kHealthMetricsTimer,
59
56
  kId,
60
57
  kITC,
61
58
  kLastHealthCheckELU,
@@ -71,8 +68,6 @@ const kWorkerFile = join(import.meta.dirname, 'worker/main.js')
71
68
  const kInspectorOptions = Symbol('plt.runtime.worker.inspectorOptions')
72
69
 
73
70
  const MAX_LISTENERS_COUNT = 100
74
- const MAX_METRICS_QUEUE_LENGTH = 5 * 60 // 5 minutes in seconds
75
- const COLLECT_METRICS_TIMEOUT = 1000
76
71
 
77
72
  const MAX_CONCURRENCY = 5
78
73
  const MAX_BOOTSTRAP_ATTEMPTS = 5
@@ -98,8 +93,7 @@ export class Runtime extends EventEmitter {
98
93
  #entrypointId
99
94
  #url
100
95
 
101
- #metrics
102
- #metricsTimeout
96
+ #healthMetricsTimer
103
97
 
104
98
  #meshInterceptor
105
99
  #dispatcher
@@ -283,9 +277,8 @@ export class Runtime extends EventEmitter {
283
277
 
284
278
  this.#updateStatus('started')
285
279
 
286
- if (this.#config.metrics?.enabled !== false && typeof this.#metrics === 'undefined') {
287
- this.startCollectingMetrics()
288
- }
280
+ // Start the global health metrics timer for all workers if needed
281
+ this.#startHealthMetricsCollectionIfNeeded()
289
282
 
290
283
  await this.#dynamicWorkersScaler?.start()
291
284
  this.#showUrl()
@@ -339,7 +332,7 @@ export class Runtime extends EventEmitter {
339
332
  }
340
333
 
341
334
  async close (silent = false) {
342
- clearInterval(this.#metricsTimeout)
335
+ clearTimeout(this.#healthMetricsTimer)
343
336
 
344
337
  await this.stop(silent)
345
338
  this.#updateStatus('closing')
@@ -703,29 +696,15 @@ export class Runtime extends EventEmitter {
703
696
  }
704
697
  }
705
698
 
699
+ // TODO: Remove in next major version
706
700
  startCollectingMetrics () {
707
- this.#metrics = []
708
- this.#metricsTimeout = setInterval(async () => {
709
- if (this.#status !== 'started') {
710
- return
711
- }
712
-
713
- let metrics = null
714
- try {
715
- metrics = await this.getFormattedMetrics()
716
- } catch (error) {
717
- if (!(error instanceof RuntimeExitedError)) {
718
- this.logger.error({ err: ensureLoggableError(error) }, 'Error collecting metrics')
719
- }
720
- return
721
- }
701
+ this.logger.warn('startCollectingMetrics() is deprecated and no longer collects metrics. Metrics are now polled on-demand by the management API.')
702
+ }
722
703
 
723
- this.emitAndNotify('metrics', metrics)
724
- this.#metrics.push(metrics)
725
- if (this.#metrics.length > MAX_METRICS_QUEUE_LENGTH) {
726
- this.#metrics.shift()
727
- }
728
- }, COLLECT_METRICS_TIMEOUT).unref()
704
+ // TODO: Remove in next major version
705
+ getCachedMetrics () {
706
+ this.logger.warn('getCachedMetrics() is deprecated and returns an empty array. Metrics are no longer cached.')
707
+ return []
729
708
  }
730
709
 
731
710
  invalidateHttpCache (options = {}) {
@@ -966,31 +945,45 @@ export class Runtime extends EventEmitter {
966
945
  }
967
946
 
968
947
  async getCustomHealthChecks () {
969
- const status = {}
948
+ const invocations = []
970
949
 
971
950
  for (const id of this.#applications.keys()) {
972
951
  const workersIds = this.#workers.getKeys(id)
973
952
  for (const workerId of workersIds) {
974
- const worker = this.#workers.get(workerId)
975
- status[workerId] = await sendViaITC(worker, 'getCustomHealthCheck')
953
+ invocations.push([workerId, this.#workers.get(workerId)])
976
954
  }
977
955
  }
978
956
 
979
- return status
957
+ return sendMultipleViaITC(
958
+ invocations,
959
+ 'getCustomHealthCheck',
960
+ undefined,
961
+ [],
962
+ this.#concurrency,
963
+ this.#config.metrics.healthChecksTimeout,
964
+ {}
965
+ )
980
966
  }
981
967
 
982
968
  async getCustomReadinessChecks () {
983
- const status = {}
969
+ const invocations = []
984
970
 
985
971
  for (const id of this.#applications.keys()) {
986
972
  const workersIds = this.#workers.getKeys(id)
987
973
  for (const workerId of workersIds) {
988
- const worker = this.#workers.get(workerId)
989
- status[workerId] = await sendViaITC(worker, 'getCustomReadinessCheck')
974
+ invocations.push([workerId, this.#workers.get(workerId)])
990
975
  }
991
976
  }
992
977
 
993
- return status
978
+ return sendMultipleViaITC(
979
+ invocations,
980
+ 'getCustomReadinessCheck',
981
+ undefined,
982
+ [],
983
+ this.#concurrency,
984
+ this.#config.metrics.healthChecksTimeout,
985
+ {}
986
+ )
994
987
  }
995
988
 
996
989
  async getMetrics (format = 'json') {
@@ -1036,10 +1029,6 @@ export class Runtime extends EventEmitter {
1036
1029
  return { metrics }
1037
1030
  }
1038
1031
 
1039
- getCachedMetrics () {
1040
- return this.#metrics
1041
- }
1042
-
1043
1032
  async getFormattedMetrics () {
1044
1033
  try {
1045
1034
  const { metrics } = await this.getMetrics()
@@ -1280,10 +1269,6 @@ export class Runtime extends EventEmitter {
1280
1269
  }
1281
1270
 
1282
1271
  async getWorkerHealth (worker, options = {}) {
1283
- if (!features.node.worker.getHeapStatistics) {
1284
- throw new GetHeapStatisticUnavailable()
1285
- }
1286
-
1287
1272
  const currentELU = worker.performance.eventLoopUtilization()
1288
1273
  const previousELU = options.previousELU
1289
1274
 
@@ -1292,6 +1277,10 @@ export class Runtime extends EventEmitter {
1292
1277
  elu = worker.performance.eventLoopUtilization(elu, previousELU)
1293
1278
  }
1294
1279
 
1280
+ if (!features.node.worker.getHeapStatistics) {
1281
+ return { elu: elu.utilization, currentELU }
1282
+ }
1283
+
1295
1284
  const { used_heap_size: heapUsed, total_heap_size: heapTotal } = await worker.getHeapStatistics()
1296
1285
  return { elu: elu.utilization, heapUsed, heapTotal, currentELU }
1297
1286
  }
@@ -1460,17 +1449,26 @@ export class Runtime extends EventEmitter {
1460
1449
  workerEnv.NODE_OPTIONS = `${originalNodeOptions} ${applicationConfig.nodeOptions}`.trim()
1461
1450
  }
1462
1451
 
1463
- const maxHeapTotal =
1464
- typeof health.maxHeapTotal === 'string' ? parseMemorySize(health.maxHeapTotal) : health.maxHeapTotal
1465
- const maxYoungGeneration =
1466
- typeof health.maxYoungGeneration === 'string'
1467
- ? parseMemorySize(health.maxYoungGeneration)
1468
- : health.maxYoungGeneration
1452
+ let resourceLimits
1469
1453
 
1470
- const maxOldGenerationSizeMb = Math.floor(
1471
- (maxYoungGeneration > 0 ? maxHeapTotal - maxYoungGeneration : maxHeapTotal) / (1024 * 1024)
1472
- )
1473
- const maxYoungGenerationSizeMb = maxYoungGeneration ? Math.floor(maxYoungGeneration / (1024 * 1024)) : undefined
1454
+ {
1455
+ const maxHeapTotal =
1456
+ typeof health.maxHeapTotal === 'string' ? parseMemorySize(health.maxHeapTotal) : health.maxHeapTotal
1457
+ const maxYoungGeneration =
1458
+ typeof health.maxYoungGeneration === 'string'
1459
+ ? parseMemorySize(health.maxYoungGeneration)
1460
+ : health.maxYoungGeneration
1461
+
1462
+ const maxOldGenerationSizeMb = maxHeapTotal ? Math.floor((maxYoungGeneration > 0 ? maxHeapTotal - maxYoungGeneration : maxHeapTotal) / (1024 * 1024)) : undefined
1463
+ const maxYoungGenerationSizeMb = maxYoungGeneration ? Math.floor(maxYoungGeneration / (1024 * 1024)) : undefined
1464
+
1465
+ if (maxOldGenerationSizeMb || maxYoungGenerationSizeMb) {
1466
+ resourceLimits = {
1467
+ maxOldGenerationSizeMb,
1468
+ maxYoungGenerationSizeMb
1469
+ }
1470
+ }
1471
+ }
1474
1472
 
1475
1473
  const worker = new Worker(kWorkerFile, {
1476
1474
  workerData: {
@@ -1494,10 +1492,7 @@ export class Runtime extends EventEmitter {
1494
1492
  argv: applicationConfig.arguments,
1495
1493
  execArgv,
1496
1494
  env: workerEnv,
1497
- resourceLimits: {
1498
- maxOldGenerationSizeMb,
1499
- maxYoungGenerationSizeMb
1500
- },
1495
+ resourceLimits,
1501
1496
  stdout: true,
1502
1497
  stderr: true
1503
1498
  })
@@ -1646,36 +1641,75 @@ export class Runtime extends EventEmitter {
1646
1641
  return worker
1647
1642
  }
1648
1643
 
1649
- #setupHealthMetrics (id, index, worker, errorLabel) {
1650
- // Clear the timeout when exiting
1651
- worker.on('exit', () => clearTimeout(worker[kHealthMetricsTimer]))
1644
+ #startHealthMetricsCollectionIfNeeded () {
1645
+ // Need health metrics if dynamic workers scaler exists (for vertical scaling)
1646
+ // or if any worker has health checks enabled
1647
+ let needsHealthMetrics = !!this.#dynamicWorkersScaler
1652
1648
 
1653
- worker[kHealthMetricsTimer] = setTimeout(async () => {
1654
- if (worker[kWorkerStatus] !== 'started') return
1649
+ if (!needsHealthMetrics) {
1650
+ // Check if any worker has health checks enabled
1651
+ for (const worker of this.#workers.values()) {
1652
+ const healthConfig = worker[kConfig]?.health
1653
+ if (healthConfig?.enabled && this.#config.restartOnError > 0) {
1654
+ needsHealthMetrics = true
1655
+ break
1656
+ }
1657
+ }
1658
+ }
1655
1659
 
1656
- let health = null
1657
- try {
1658
- health = await this.getWorkerHealth(worker, {
1659
- previousELU: worker[kLastHealthCheckELU]
1660
- })
1661
- } catch (err) {
1662
- this.logger.error({ err }, `Failed to get health for ${errorLabel}.`)
1663
- } finally {
1664
- worker[kLastHealthCheckELU] = health?.currentELU ?? null
1660
+ if (needsHealthMetrics) {
1661
+ this.#startHealthMetricsCollection()
1662
+ }
1663
+ }
1664
+
1665
+ #startHealthMetricsCollection () {
1666
+ const collectHealthMetrics = async () => {
1667
+ if (this.#status !== 'started') {
1668
+ return
1665
1669
  }
1666
1670
 
1667
- const healthSignals = worker[kWorkerHealthSignals]?.getAll() ?? []
1671
+ // Iterate through all workers and collect health metrics
1672
+ for (const worker of this.#workers.values()) {
1673
+ if (worker[kWorkerStatus] !== 'started') {
1674
+ continue
1675
+ }
1668
1676
 
1669
- this.emitAndNotify('application:worker:health:metrics', {
1670
- id: worker[kId],
1671
- application: id,
1672
- worker: index,
1673
- currentHealth: health,
1674
- healthSignals
1675
- })
1677
+ const id = worker[kApplicationId]
1678
+ const index = worker[kWorkerId]
1679
+ const errorLabel = this.#workerExtendedLabel(id, index, worker[kConfig].workers)
1676
1680
 
1677
- worker[kHealthMetricsTimer].refresh()
1678
- }, 1000).unref()
1681
+ let health = null
1682
+ try {
1683
+ health = await this.getWorkerHealth(worker, {
1684
+ previousELU: worker[kLastHealthCheckELU]
1685
+ })
1686
+ } catch (err) {
1687
+ this.logger.error({ err }, `Failed to get health for ${errorLabel}.`)
1688
+ } finally {
1689
+ worker[kLastHealthCheckELU] = health?.currentELU ?? null
1690
+ }
1691
+
1692
+ const healthSignals = worker[kWorkerHealthSignals]?.getAll() ?? []
1693
+
1694
+ // We use emit instead of emitAndNotify to avoid sending a postMessages
1695
+ // to each workers even if they are not interested in health metrics.
1696
+ // No one of the known capabilities use this event yet.
1697
+ this.emit('application:worker:health:metrics', {
1698
+ id: worker[kId],
1699
+ application: id,
1700
+ worker: index,
1701
+ currentHealth: health,
1702
+ healthSignals
1703
+ })
1704
+ }
1705
+
1706
+ // Reschedule the next check. We are not using .refresh() because it's more
1707
+ // expensive (weird).
1708
+ this.#healthMetricsTimer = setTimeout(collectHealthMetrics, 1000).unref()
1709
+ }
1710
+
1711
+ // Start the collection
1712
+ this.#healthMetricsTimer = setTimeout(collectHealthMetrics, 1000).unref()
1679
1713
  }
1680
1714
 
1681
1715
  #setupHealthCheck (config, applicationConfig, workersCount, id, index, worker, errorLabel) {
@@ -1725,7 +1759,7 @@ export class Runtime extends EventEmitter {
1725
1759
  const memoryUsage = health.heapUsed / maxHeapTotal
1726
1760
  const unhealthy = health.elu > maxELU || memoryUsage > maxHeapUsed
1727
1761
 
1728
- this.emitAndNotify('application:worker:health', {
1762
+ this.emit('application:worker:health', {
1729
1763
  id: worker[kId],
1730
1764
  application: id,
1731
1765
  worker: index,
@@ -1842,8 +1876,6 @@ export class Runtime extends EventEmitter {
1842
1876
  this.logger.info(`Started the ${label}...`)
1843
1877
  }
1844
1878
 
1845
- this.#setupHealthMetrics(id, index, worker, label)
1846
-
1847
1879
  const { enabled, gracePeriod } = worker[kConfig].health
1848
1880
  if (enabled && config.restartOnError > 0) {
1849
1881
  // if gracePeriod is 0, it will be set to 1 to start health checks immediately
package/lib/worker/itc.js CHANGED
@@ -1,4 +1,4 @@
1
- import { ensureLoggableError } from '@platformatic/foundation'
1
+ import { ensureLoggableError, executeInParallel, executeWithTimeout, kTimeout } from '@platformatic/foundation'
2
2
  import { ITC } from '@platformatic/itc'
3
3
  import { Unpromise } from '@watchable/unpromise'
4
4
  import { once } from 'node:events'
@@ -65,6 +65,29 @@ export async function sendViaITC (worker, name, message, transferList) {
65
65
  return safeHandleInITC(worker, () => worker[kITC].send(name, message, { transferList }))
66
66
  }
67
67
 
68
+ export async function sendMultipleViaITC (
69
+ idsAndWorkerPairs,
70
+ name,
71
+ message,
72
+ transferList,
73
+ concurrency,
74
+ timeout = 5000,
75
+ timeoutFallbackValue = kTimeout
76
+ ) {
77
+ const results = await executeInParallel(
78
+ async (id, worker) => {
79
+ return [
80
+ id,
81
+ await executeWithTimeout(sendViaITC(worker, name, message, transferList), timeout, timeoutFallbackValue)
82
+ ]
83
+ },
84
+ idsAndWorkerPairs,
85
+ concurrency
86
+ )
87
+
88
+ return Object.fromEntries(results)
89
+ }
90
+
68
91
  export async function waitEventFromITC (worker, event) {
69
92
  return safeHandleInITC(worker, () => once(worker[kITC], event))
70
93
  }
@@ -5,7 +5,6 @@ export const kApplicationId = Symbol.for('plt.runtime.application.id')
5
5
  export const kWorkerId = Symbol.for('plt.runtime.worker.id')
6
6
  export const kITC = Symbol.for('plt.runtime.itc')
7
7
  export const kHealthCheckTimer = Symbol.for('plt.runtime.worker.healthCheckTimer')
8
- export const kHealthMetricsTimer = Symbol.for('plt.runtime.worker.healthMetricsTimer')
9
8
  export const kWorkerStatus = Symbol('plt.runtime.worker.status')
10
9
  export const kWorkerHealthSignals = Symbol.for('plt.runtime.worker.healthSignals')
11
10
  export const kWorkerStartTime = Symbol.for('plt.runtime.worker.startTime')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platformatic/runtime",
3
- "version": "3.17.0",
3
+ "version": "3.19.0",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -35,14 +35,14 @@
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": "3.17.0",
39
- "@platformatic/composer": "3.17.0",
40
- "@platformatic/gateway": "3.17.0",
41
- "@platformatic/node": "3.17.0",
42
- "@platformatic/service": "3.17.0",
43
- "@platformatic/sql-graphql": "3.17.0",
44
- "@platformatic/sql-mapper": "3.17.0",
45
- "@platformatic/wattpm-pprof-capture": "3.17.0"
38
+ "@platformatic/composer": "3.19.0",
39
+ "@platformatic/db": "3.19.0",
40
+ "@platformatic/gateway": "3.19.0",
41
+ "@platformatic/node": "3.19.0",
42
+ "@platformatic/service": "3.19.0",
43
+ "@platformatic/sql-mapper": "3.19.0",
44
+ "@platformatic/sql-graphql": "3.19.0",
45
+ "@platformatic/wattpm-pprof-capture": "3.19.0"
46
46
  },
47
47
  "dependencies": {
48
48
  "@fastify/accepts": "^5.0.0",
@@ -71,12 +71,12 @@
71
71
  "undici": "^7.0.0",
72
72
  "undici-thread-interceptor": "^0.15.0",
73
73
  "ws": "^8.16.0",
74
- "@platformatic/basic": "3.17.0",
75
- "@platformatic/itc": "3.17.0",
76
- "@platformatic/generators": "3.17.0",
77
- "@platformatic/foundation": "3.17.0",
78
- "@platformatic/metrics": "3.17.0",
79
- "@platformatic/telemetry": "3.17.0"
74
+ "@platformatic/basic": "3.19.0",
75
+ "@platformatic/generators": "3.19.0",
76
+ "@platformatic/foundation": "3.19.0",
77
+ "@platformatic/telemetry": "3.19.0",
78
+ "@platformatic/itc": "3.19.0",
79
+ "@platformatic/metrics": "3.19.0"
80
80
  },
81
81
  "engines": {
82
82
  "node": ">=22.19.0"
package/schema.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://schemas.platformatic.dev/@platformatic/runtime/3.17.0.json",
2
+ "$id": "https://schemas.platformatic.dev/@platformatic/runtime/3.19.0.json",
3
3
  "$schema": "http://json-schema.org/draft-07/schema#",
4
4
  "title": "Platformatic Runtime Config",
5
5
  "type": "object",
@@ -1626,8 +1626,7 @@
1626
1626
  {
1627
1627
  "type": "string"
1628
1628
  }
1629
- ],
1630
- "default": 4294967296
1629
+ ]
1631
1630
  },
1632
1631
  "maxYoungGeneration": {
1633
1632
  "anyOf": [
@@ -1954,6 +1953,17 @@
1954
1953
  }
1955
1954
  ]
1956
1955
  },
1956
+ "healthChecksTimeouts": {
1957
+ "anyOf": [
1958
+ {
1959
+ "type": "integer"
1960
+ },
1961
+ {
1962
+ "type": "string"
1963
+ }
1964
+ ],
1965
+ "default": 5000
1966
+ },
1957
1967
  "plugins": {
1958
1968
  "type": "array",
1959
1969
  "items": {