@platformatic/runtime 1.45.1 → 1.47.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.
@@ -0,0 +1,33 @@
1
+ {
2
+ "$schema": "https://platformatic.dev/schemas/v0.20.0/runtime",
3
+ "entrypoint": "serviceApp",
4
+ "allowCycles": true,
5
+ "hotReload": false,
6
+ "managementApi": false,
7
+ "autoload": {
8
+ "path": "../monorepo",
9
+ "exclude": [
10
+ "docs",
11
+ "composerApp"
12
+ ],
13
+ "mappings": {
14
+ "serviceAppWithLogger": {
15
+ "id": "with-logger",
16
+ "config": "platformatic.service.json"
17
+ },
18
+ "serviceAppWithMultiplePlugins": {
19
+ "id": "multi-plugin-service",
20
+ "config": "platformatic.service.json"
21
+ },
22
+ "dbApp": {
23
+ "id": "db-app",
24
+ "config": "platformatic.db.json"
25
+ }
26
+ }
27
+ },
28
+ "server":{
29
+ "hostname":"127.0.0.1",
30
+ "port":"{PORT}"
31
+ }
32
+ }
33
+
package/lib/api-client.js CHANGED
@@ -265,6 +265,7 @@ class RuntimeApiClient extends EventEmitter {
265
265
  metrics = await this.getFormattedMetrics()
266
266
  } catch (error) {
267
267
  if (!(error instanceof errors.RuntimeExitedError)) {
268
+ // TODO(mcollina): use the logger
268
269
  console.error('Error collecting metrics', error)
269
270
  }
270
271
  return
@@ -449,19 +450,22 @@ class RuntimeApiClient extends EventEmitter {
449
450
 
450
451
  async #sendCommand (command, params = {}) {
451
452
  const operationId = randomUUID()
452
-
453
453
  this.worker.postMessage({ operationId, command, params })
454
454
  const [message] = await Promise.race(
455
455
  [once(this, operationId), this.#exitPromise]
456
456
  )
457
457
 
458
458
  if (this.#exitCode !== undefined) {
459
+ if (this.exitCode === 1) {
460
+ throw new errors.AddressInUseError()
461
+ }
459
462
  throw new errors.RuntimeExitedError()
460
463
  }
461
-
462
- const { error, data } = message
464
+ const { error, data, code } = message
463
465
  if (error !== null) {
464
- throw new Error(error)
466
+ const err = new Error(error)
467
+ err.code = code
468
+ throw err
465
469
  }
466
470
 
467
471
  return JSON.parse(data)
package/lib/api.js CHANGED
@@ -105,7 +105,7 @@ class RuntimeApi {
105
105
  const res = await this.#runCommandHandler(command, params)
106
106
  return { operationId, error: null, data: JSON.stringify(res || null) }
107
107
  } catch (err) {
108
- return { operationId, error: err.message }
108
+ return { operationId, error: err.message, code: err.code }
109
109
  }
110
110
  }
111
111
 
package/lib/app.js CHANGED
@@ -133,7 +133,8 @@ class PlatformaticApp extends EventEmitter {
133
133
  /* c8 ignore next 5 */
134
134
  } catch (err) {
135
135
  this.server.log.error({ err })
136
- process.exit(1)
136
+ this.#starting = false
137
+ throw err
137
138
  }
138
139
  } else {
139
140
  // Make sure the server has run all the onReady hooks before returning.
package/lib/errors.js CHANGED
@@ -5,6 +5,7 @@ const createError = require('@fastify/error')
5
5
  const ERROR_PREFIX = 'PLT_RUNTIME'
6
6
 
7
7
  module.exports = {
8
+ AddressInUseError: createError(`${ERROR_PREFIX}_EADDR_IN_USE`, 'The current port is in use by another application'),
8
9
  RuntimeExitedError: createError(`${ERROR_PREFIX}_RUNTIME_EXIT`, 'The runtime exited before the operation completed'),
9
10
  UnknownRuntimeAPICommandError: createError(`${ERROR_PREFIX}_UNKNOWN_RUNTIME_API_COMMAND`, 'Unknown Runtime API command "%s"'),
10
11
  ServiceNotFoundError: createError(`${ERROR_PREFIX}_SERVICE_NOT_FOUND`, 'Service not found. Available services are: %s'),
package/lib/start.js CHANGED
@@ -16,6 +16,8 @@ const { parseInspectorOptions, wrapConfigInRuntimeConfig } = require('./config')
16
16
  const { RuntimeApiClient, getRuntimeLogsDir } = require('./api-client.js')
17
17
  const errors = require('./errors')
18
18
  const pkg = require('../package.json')
19
+ const pino = require('pino')
20
+ const pretty = require('pino-pretty')
19
21
 
20
22
  const kLoaderFile = pathToFileURL(join(__dirname, 'loader.mjs')).href
21
23
  const kWorkerFile = join(__dirname, 'worker.js')
@@ -138,21 +140,58 @@ async function start (args) {
138
140
  return serviceStart(config.app, args)
139
141
  }
140
142
 
143
+ async function setupAndStartRuntime (config) {
144
+ const MAX_PORT = 65535
145
+ let runtimeConfig
146
+
147
+ if (config.configType === 'runtime') {
148
+ config.configManager.args = config.args
149
+ runtimeConfig = config.configManager
150
+ } else {
151
+ const wrappedConfig = await wrapConfigInRuntimeConfig(config)
152
+ wrappedConfig.args = config.args
153
+ runtimeConfig = wrappedConfig
154
+ }
155
+
156
+ let runtime = await buildRuntime(runtimeConfig)
157
+
158
+ let address = null
159
+ let startErr = null
160
+ const originalPort = runtimeConfig.current.server?.port || 0
161
+ while (address === null) {
162
+ try {
163
+ address = await runtime.start()
164
+ } catch (err) {
165
+ startErr = err
166
+ if (err.code === 'EADDRINUSE') {
167
+ await runtime.close()
168
+ if (runtimeConfig.current.server.port > MAX_PORT) throw err
169
+ runtimeConfig.current.server.port++
170
+ runtime = await buildRuntime(runtimeConfig)
171
+ } else {
172
+ throw err
173
+ }
174
+ }
175
+ }
176
+ if (startErr?.code === 'PLT_RUNTIME_EADDR_IN_USE') {
177
+ const logger = pino(pretty({
178
+ translateTime: 'SYS:HH:MM:ss',
179
+ ignore: 'hostname,pid'
180
+ }))
181
+ logger.warn(`Port: ${originalPort} is already in use!`)
182
+ logger.warn(`Starting service on port: ${runtimeConfig.current.server.port}`)
183
+ }
184
+ return { address, runtime }
185
+ }
186
+
141
187
  async function startCommand (args) {
142
188
  try {
143
189
  const config = await loadConfig({}, args)
144
- let runtime
145
-
146
- if (config.configType === 'runtime') {
147
- config.configManager.args = config.args
148
- runtime = await buildRuntime(config.configManager)
149
- } else {
150
- const wrappedConfig = await wrapConfigInRuntimeConfig(config)
151
- wrappedConfig.args = config.args
152
- runtime = await buildRuntime(wrappedConfig)
153
- }
154
190
 
155
- const res = await runtime.start()
191
+ const startResult = await setupAndStartRuntime(config)
192
+
193
+ const runtime = startResult.runtime
194
+ const res = startResult.address
156
195
 
157
196
  closeWithGrace(async (event) => {
158
197
  if (event.err instanceof Error) {
@@ -206,4 +245,4 @@ async function startCommand (args) {
206
245
  }
207
246
  }
208
247
 
209
- module.exports = { buildRuntime, start, startCommand }
248
+ module.exports = { buildRuntime, start, startCommand, setupAndStartRuntime }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platformatic/runtime",
3
- "version": "1.45.1",
3
+ "version": "1.47.0",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -20,7 +20,7 @@
20
20
  "@fastify/express": "^3.0.0",
21
21
  "@fastify/formbody": "^7.4.0",
22
22
  "@matteo.collina/tspl": "^0.1.1",
23
- "borp": "^0.14.0",
23
+ "borp": "^0.15.0",
24
24
  "c8": "^9.1.0",
25
25
  "execa": "^8.0.1",
26
26
  "express": "^4.18.3",
@@ -34,8 +34,8 @@
34
34
  "typescript": "^5.4.2",
35
35
  "undici-oidc-interceptor": "^0.5.0",
36
36
  "why-is-node-running": "^2.2.2",
37
- "@platformatic/sql-graphql": "1.45.1",
38
- "@platformatic/sql-mapper": "1.45.1"
37
+ "@platformatic/sql-graphql": "1.47.0",
38
+ "@platformatic/sql-mapper": "1.47.0"
39
39
  },
40
40
  "dependencies": {
41
41
  "@fastify/error": "^3.4.1",
@@ -63,13 +63,13 @@
63
63
  "undici": "^6.9.0",
64
64
  "why-is-node-running": "^2.2.2",
65
65
  "ws": "^8.16.0",
66
- "@platformatic/composer": "1.45.1",
67
- "@platformatic/config": "1.45.1",
68
- "@platformatic/generators": "1.45.1",
69
- "@platformatic/db": "1.45.1",
70
- "@platformatic/telemetry": "1.45.1",
71
- "@platformatic/service": "1.45.1",
72
- "@platformatic/utils": "1.45.1"
66
+ "@platformatic/composer": "1.47.0",
67
+ "@platformatic/config": "1.47.0",
68
+ "@platformatic/service": "1.47.0",
69
+ "@platformatic/db": "1.47.0",
70
+ "@platformatic/telemetry": "1.47.0",
71
+ "@platformatic/generators": "1.47.0",
72
+ "@platformatic/utils": "1.47.0"
73
73
  },
74
74
  "standard": {
75
75
  "ignore": [