@platformatic/basic 3.14.0 → 3.15.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
@@ -110,6 +110,7 @@ export interface PlatformaticBasicConfig {
110
110
  rejectUnauthorized?: boolean;
111
111
  };
112
112
  };
113
+ reuseTcpPorts?: boolean;
113
114
  startTimeout?: number;
114
115
  restartOnError?: boolean | number;
115
116
  exitOnUnhandledErrors?: boolean;
package/lib/capability.js CHANGED
@@ -2,6 +2,7 @@ import {
2
2
  buildPinoOptions,
3
3
  deepmerge,
4
4
  executeWithTimeout,
5
+ features,
5
6
  kHandledError,
6
7
  kMetadata,
7
8
  kTimeout
@@ -9,6 +10,7 @@ import {
9
10
  import { client, collectMetrics, ensureMetricsGroup, setupOtlpExporter } from '@platformatic/metrics'
10
11
  import { parseCommandString } from 'execa'
11
12
  import { spawn } from 'node:child_process'
13
+ import { tracingChannel } from 'node:diagnostics_channel'
12
14
  import EventEmitter, { once } from 'node:events'
13
15
  import { existsSync } from 'node:fs'
14
16
  import { platform } from 'node:os'
@@ -34,6 +36,7 @@ export class BaseCapability extends EventEmitter {
34
36
  workerId
35
37
  telemetryConfig
36
38
  serverConfig
39
+ reuseTcpPorts
37
40
  openapiSchema
38
41
  graphqlSchema
39
42
  connectionString
@@ -56,6 +59,7 @@ export class BaseCapability extends EventEmitter {
56
59
  #subprocessStarted
57
60
  #metricsCollected
58
61
  #pendingDependenciesWaits
62
+ #reuseTcpPortsSubscribers
59
63
 
60
64
  constructor (type, version, root, config, context, standardStreams = {}) {
61
65
  super()
@@ -89,6 +93,7 @@ export class BaseCapability extends EventEmitter {
89
93
  this.subprocessForceClose = false
90
94
  this.subprocessTerminationSignal = 'SIGINT'
91
95
  this.logger = this._initializeLogger()
96
+ this.reuseTcpPorts = this.config.reuseTcpPorts ?? this.runtimeConfig.reuseTcpPorts
92
97
  // True by default, can be overridden in subclasses. If false, it takes precedence over the runtime configuration
93
98
  this.exitOnUnhandledErrors = true
94
99
 
@@ -129,6 +134,8 @@ export class BaseCapability extends EventEmitter {
129
134
  return
130
135
  }
131
136
 
137
+ // TODO@PI: Handle reusePort
138
+
132
139
  // Wait for explicit dependencies to start
133
140
  await this.waitForDependenciesStart(this.dependencies)
134
141
 
@@ -159,6 +166,11 @@ export class BaseCapability extends EventEmitter {
159
166
  await Promise.allSettled(this.#pendingDependenciesWaits)
160
167
  }
161
168
 
169
+ if (this.#reuseTcpPortsSubscribers) {
170
+ tracingChannel('net.server.listen').unsubscribe(this.#reuseTcpPortsSubscribers)
171
+ this.#reuseTcpPortsSubscribers = null
172
+ }
173
+
162
174
  // Stop OTLP bridge if running
163
175
  if (this.otlpBridge) {
164
176
  this.otlpBridge.stop()
@@ -562,6 +574,7 @@ export class BaseCapability extends EventEmitter {
562
574
  basePath,
563
575
  logLevel: this.logger.level,
564
576
  isEntrypoint: this.isEntrypoint,
577
+ reuseTcpPorts: this.reuseTcpPorts,
565
578
  runtimeBasePath: this.runtimeConfig?.basePath ?? null,
566
579
  wantsAbsoluteUrls: meta.gateway?.wantsAbsoluteUrls ?? false,
567
580
  exitOnUnhandledErrors: this.runtimeConfig.exitOnUnhandledErrors ?? true,
@@ -615,6 +628,23 @@ export class BaseCapability extends EventEmitter {
615
628
  return pino(pinoOptions, this.standardStreams?.stdout)
616
629
  }
617
630
 
631
+ _start () {
632
+ if (this.reuseTcpPorts) {
633
+ if (!features.node.reusePort) {
634
+ this.reuseTcpPorts = false
635
+ this.logger.warn('Cannot enable reusePort as it is not available in your OS.')
636
+ } else {
637
+ this.#reuseTcpPortsSubscribers = {
638
+ asyncStart ({ options }) {
639
+ options.reusePort = true
640
+ }
641
+ }
642
+
643
+ tracingChannel('net.server.listen').subscribe(this.#reuseTcpPortsSubscribers)
644
+ }
645
+ }
646
+ }
647
+
618
648
  async _collectMetrics () {
619
649
  if (this.#metricsCollected) {
620
650
  return
@@ -757,18 +787,17 @@ export class BaseCapability extends EventEmitter {
757
787
  }
758
788
 
759
789
  // Setup and start OTLP exporter bridge
760
- this.otlpBridge = await setupOtlpExporter(
761
- this.metricsRegistry,
762
- metricsConfig.otlpExporter,
763
- this.applicationId
764
- )
790
+ this.otlpBridge = await setupOtlpExporter(this.metricsRegistry, metricsConfig.otlpExporter, this.applicationId)
765
791
 
766
792
  if (this.otlpBridge) {
767
793
  this.otlpBridge.start()
768
- this.logger.info({
769
- endpoint: metricsConfig.otlpExporter.endpoint,
770
- interval: metricsConfig.otlpExporter.interval || 60000
771
- }, 'OTLP metrics exporter started')
794
+ this.logger.info(
795
+ {
796
+ endpoint: metricsConfig.otlpExporter.endpoint,
797
+ interval: metricsConfig.otlpExporter.interval || 60000
798
+ },
799
+ 'OTLP metrics exporter started'
800
+ )
772
801
  }
773
802
  }
774
803
 
@@ -2,8 +2,7 @@ import {
2
2
  buildPinoFormatters,
3
3
  buildPinoTimestamp,
4
4
  disablePinoDirectWrite,
5
- ensureLoggableError,
6
- features
5
+ ensureLoggableError
7
6
  } from '@platformatic/foundation'
8
7
  import { ITC } from '@platformatic/itc/lib/index.js'
9
8
  import { client, collectMetrics } from '@platformatic/metrics'
@@ -131,6 +130,10 @@ export class ChildProcess extends ITC {
131
130
  this.#setupServer()
132
131
  this.#setupInterceptors()
133
132
 
133
+ if (globalThis.platformatic.reuseTcpPorts) {
134
+ this.#setupTcpPortsHandling()
135
+ }
136
+
134
137
  this.registerGlobals({
135
138
  logger: this.#logger,
136
139
  setOpenapiSchema: this.setOpenapiSchema.bind(this),
@@ -359,10 +362,6 @@ export class ChildProcess extends ITC {
359
362
  if (port !== false) {
360
363
  const hasFixedPort = typeof port === 'number'
361
364
  options.port = hasFixedPort ? port : 0
362
-
363
- if (hasFixedPort && features.node.reusePort) {
364
- options.reusePort = true
365
- }
366
365
  }
367
366
 
368
367
  if (typeof host === 'string') {
@@ -399,6 +398,14 @@ export class ChildProcess extends ITC {
399
398
  }
400
399
  }
401
400
 
401
+ #setupTcpPortsHandling () {
402
+ tracingChannel('net.server.listen').subscribe({
403
+ asyncStart ({ options }) {
404
+ options.reusePort = true
405
+ }
406
+ })
407
+ }
408
+
402
409
  #setupInterceptors () {
403
410
  const globalDispatcher = new Agent().compose(createInterceptor(this))
404
411
  setGlobalDispatcher(globalDispatcher)
@@ -1,4 +1,3 @@
1
- import { features } from '@platformatic/foundation'
2
1
  import { subscribe, tracingChannel, unsubscribe } from 'node:diagnostics_channel'
3
2
 
4
3
  export function createServerListener (overridePort = true, overrideHost) {
@@ -14,10 +13,6 @@ export function createServerListener (overridePort = true, overrideHost) {
14
13
  if (overridePort !== false) {
15
14
  const hasFixedPort = typeof overridePort === 'number'
16
15
  options.port = hasFixedPort ? overridePort : 0
17
-
18
- if (hasFixedPort && features.node.reusePort) {
19
- options.reusePort = true
20
- }
21
16
  }
22
17
 
23
18
  if (typeof overrideHost === 'string') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platformatic/basic",
3
- "version": "3.14.0",
3
+ "version": "3.15.0",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -25,10 +25,10 @@
25
25
  "split2": "^4.2.0",
26
26
  "undici": "^7.0.0",
27
27
  "ws": "^8.18.0",
28
- "@platformatic/itc": "3.14.0",
29
- "@platformatic/foundation": "3.14.0",
30
- "@platformatic/metrics": "3.14.0",
31
- "@platformatic/telemetry": "3.14.0"
28
+ "@platformatic/foundation": "3.15.0",
29
+ "@platformatic/itc": "3.15.0",
30
+ "@platformatic/metrics": "3.15.0",
31
+ "@platformatic/telemetry": "3.15.0"
32
32
  },
33
33
  "devDependencies": {
34
34
  "cleaner-spec-reporter": "^0.5.0",
package/schema.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://schemas.platformatic.dev/@platformatic/basic/3.14.0.json",
2
+ "$id": "https://schemas.platformatic.dev/@platformatic/basic/3.15.0.json",
3
3
  "$schema": "http://json-schema.org/draft-07/schema#",
4
4
  "title": "Platformatic Basic Config",
5
5
  "type": "object",
@@ -68,6 +68,10 @@
68
68
  "useHttp": {
69
69
  "type": "boolean"
70
70
  },
71
+ "reuseTcpPorts": {
72
+ "type": "boolean",
73
+ "default": true
74
+ },
71
75
  "workers": {
72
76
  "anyOf": [
73
77
  {
@@ -634,6 +638,10 @@
634
638
  },
635
639
  "additionalProperties": false
636
640
  },
641
+ "reuseTcpPorts": {
642
+ "type": "boolean",
643
+ "default": true
644
+ },
637
645
  "startTimeout": {
638
646
  "default": 30000,
639
647
  "type": "number",