@platformatic/runtime 2.19.0 → 2.20.0-alpha.2
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 +2 -1
- package/lib/config.js +3 -2
- package/lib/errors.js +1 -0
- package/lib/runtime.js +48 -10
- package/lib/schema.js +6 -0
- package/lib/start.js +4 -2
- package/lib/worker/main.js +6 -2
- package/package.json +14 -14
- package/schema.json +7 -1
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 HttpsSchemasPlatformaticDevPlatformaticRuntime2200Alpha2Json = {
|
|
9
9
|
[k: string]: unknown;
|
|
10
10
|
} & {
|
|
11
11
|
$schema?: string;
|
|
@@ -176,6 +176,7 @@ export type HttpsSchemasPlatformaticDevPlatformaticRuntime2190Json = {
|
|
|
176
176
|
[k: string]: unknown;
|
|
177
177
|
};
|
|
178
178
|
serviceTimeout?: number | string;
|
|
179
|
+
resolvedServicesBasePath?: string;
|
|
179
180
|
};
|
|
180
181
|
|
|
181
182
|
export interface UndiciInterceptor {
|
package/lib/config.js
CHANGED
|
@@ -87,8 +87,9 @@ async function _transformConfig (configManager, args) {
|
|
|
87
87
|
for (let i = 0; i < services.length; ++i) {
|
|
88
88
|
const service = services[i]
|
|
89
89
|
|
|
90
|
-
// We need to have
|
|
91
|
-
if
|
|
90
|
+
// We need to have absolute paths here, ot the `loadConfig` will fail
|
|
91
|
+
// Make sure we don't resolve if env var was not replaced
|
|
92
|
+
if (service.path && !isAbsolute(service.path) && !service.path.match(/^\{.*\}$/)) {
|
|
92
93
|
service.path = pathResolve(configManager.dirname, service.path)
|
|
93
94
|
}
|
|
94
95
|
|
package/lib/errors.js
CHANGED
|
@@ -7,6 +7,7 @@ const ERROR_PREFIX = 'PLT_RUNTIME'
|
|
|
7
7
|
module.exports = {
|
|
8
8
|
AddressInUseError: createError(`${ERROR_PREFIX}_EADDR_IN_USE`, 'The current port is in use by another application'),
|
|
9
9
|
RuntimeExitedError: createError(`${ERROR_PREFIX}_RUNTIME_EXIT`, 'The runtime exited before the operation completed'),
|
|
10
|
+
RuntimeAbortedError: createError(`${ERROR_PREFIX}_RUNTIME_ABORT`, 'The runtime aborted the operation'),
|
|
10
11
|
// The following two use the same code as we only need to differentiate the label
|
|
11
12
|
ServiceExitedError: createError(`${ERROR_PREFIX}_SERVICE_EXIT`, 'The service "%s" exited prematurely with error code %d'),
|
|
12
13
|
WorkerExitedError: createError(`${ERROR_PREFIX}_SERVICE_EXIT`, 'The worker %s of the service "%s" exited prematurely with error code %d'),
|
package/lib/runtime.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { once, EventEmitter } = require('node:events')
|
|
4
|
-
const { createReadStream, watch } = require('node:fs')
|
|
4
|
+
const { createReadStream, watch, existsSync } = require('node:fs')
|
|
5
5
|
const { readdir, readFile, stat, access } = require('node:fs/promises')
|
|
6
6
|
const { join } = require('node:path')
|
|
7
7
|
const { setTimeout: sleep } = require('node:timers/promises')
|
|
@@ -124,6 +124,31 @@ class Runtime extends EventEmitter {
|
|
|
124
124
|
|
|
125
125
|
// Create all services, each in is own worker thread
|
|
126
126
|
for (const serviceConfig of config.services) {
|
|
127
|
+
// If there is no service path, check if the service was resolved
|
|
128
|
+
if (!serviceConfig.path) {
|
|
129
|
+
if (serviceConfig.url) {
|
|
130
|
+
// Try to backfill the path for external services
|
|
131
|
+
serviceConfig.path = join(this.#configManager.dirname, config.resolvedServicesBasePath, serviceConfig.id)
|
|
132
|
+
|
|
133
|
+
if (!existsSync(serviceConfig.path)) {
|
|
134
|
+
const executable = globalThis.platformatic?.executable ?? 'platformatic'
|
|
135
|
+
this.logger.error(
|
|
136
|
+
`The path for service "%s" does not exist. Please run "${executable} resolve" and try again.`,
|
|
137
|
+
serviceConfig.id
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
throw new errors.RuntimeAbortedError()
|
|
141
|
+
}
|
|
142
|
+
} else {
|
|
143
|
+
this.logger.error(
|
|
144
|
+
'The service "%s" has no path defined. Please check your configuration and try again.',
|
|
145
|
+
serviceConfig.id
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
throw new errors.RuntimeAbortedError()
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
127
152
|
await this.#setupService(serviceConfig)
|
|
128
153
|
}
|
|
129
154
|
|
|
@@ -137,6 +162,21 @@ class Runtime extends EventEmitter {
|
|
|
137
162
|
|
|
138
163
|
// Recompute the list of services after sorting
|
|
139
164
|
this.#servicesIds = config.services.map(service => service.id)
|
|
165
|
+
|
|
166
|
+
// When autoloading is disabled, add a warning if a service is defined before its dependencies
|
|
167
|
+
if (!autoloadEnabled) {
|
|
168
|
+
for (let i = 0; i < config.services.length; i++) {
|
|
169
|
+
const current = config.services[i]
|
|
170
|
+
|
|
171
|
+
for (const dep of current.dependencies ?? []) {
|
|
172
|
+
if (config.services.findIndex(s => s.id === dep.id) > i) {
|
|
173
|
+
this.logger.warn(
|
|
174
|
+
`Service "${current.id}" depends on service "${dep.id}", but it is defined and it will be started before it. Please check your configuration file.`
|
|
175
|
+
)
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
140
180
|
} catch (e) {
|
|
141
181
|
await this.close()
|
|
142
182
|
throw e
|
|
@@ -282,7 +322,7 @@ class Runtime extends EventEmitter {
|
|
|
282
322
|
this.#updateStatus('closed')
|
|
283
323
|
}
|
|
284
324
|
|
|
285
|
-
async startService (id, silent) {
|
|
325
|
+
async startService (id, silent = false) {
|
|
286
326
|
// Since when a service is stopped the worker is deleted, we consider a service start if its first service
|
|
287
327
|
// is no longer in the init phase
|
|
288
328
|
const firstWorker = this.#workers.get(`${id}:0`)
|
|
@@ -304,7 +344,7 @@ class Runtime extends EventEmitter {
|
|
|
304
344
|
}
|
|
305
345
|
}
|
|
306
346
|
|
|
307
|
-
async stopService (id, silent) {
|
|
347
|
+
async stopService (id, silent = false) {
|
|
308
348
|
const config = this.#configManager.current
|
|
309
349
|
const serviceConfig = config.services.find(s => s.id === id)
|
|
310
350
|
|
|
@@ -795,7 +835,7 @@ class Runtime extends EventEmitter {
|
|
|
795
835
|
}
|
|
796
836
|
|
|
797
837
|
async #setupWorker (config, serviceConfig, workersCount, serviceId, index) {
|
|
798
|
-
const {
|
|
838
|
+
const { restartOnError } = config
|
|
799
839
|
const workerId = `${serviceId}:${index}`
|
|
800
840
|
|
|
801
841
|
const { port1: loggerDestination, port2: loggingPort } = new MessageChannel()
|
|
@@ -969,12 +1009,10 @@ class Runtime extends EventEmitter {
|
|
|
969
1009
|
// Store dependencies
|
|
970
1010
|
const [{ dependencies }] = await waitEventFromITC(worker, 'init')
|
|
971
1011
|
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
serviceConfig.localServiceEnvVars.set(envVar, url)
|
|
977
|
-
}
|
|
1012
|
+
serviceConfig.dependencies = dependencies
|
|
1013
|
+
for (const { envVar, url } of dependencies) {
|
|
1014
|
+
if (envVar) {
|
|
1015
|
+
serviceConfig.localServiceEnvVars.set(envVar, url)
|
|
978
1016
|
}
|
|
979
1017
|
}
|
|
980
1018
|
|
package/lib/schema.js
CHANGED
|
@@ -27,6 +27,8 @@ const services = {
|
|
|
27
27
|
},
|
|
28
28
|
path: {
|
|
29
29
|
type: 'string',
|
|
30
|
+
// This is required for the resolve command to allow empty paths after environment variable replacement
|
|
31
|
+
allowEmptyPaths: true,
|
|
30
32
|
resolvePath: true
|
|
31
33
|
},
|
|
32
34
|
config: {
|
|
@@ -310,6 +312,10 @@ const platformaticRuntimeSchema = {
|
|
|
310
312
|
{ type: 'string' }
|
|
311
313
|
],
|
|
312
314
|
default: 300000 // 5 minutes
|
|
315
|
+
},
|
|
316
|
+
resolvedServicesBasePath: {
|
|
317
|
+
type: 'string',
|
|
318
|
+
default: 'external'
|
|
313
319
|
}
|
|
314
320
|
},
|
|
315
321
|
anyOf: [{ required: ['autoload'] }, { required: ['services'] }, { required: ['web'] }],
|
package/lib/start.js
CHANGED
|
@@ -146,7 +146,7 @@ async function startCommand (args, throwAllErrors = false, returnRuntime = false
|
|
|
146
146
|
|
|
147
147
|
return returnRuntime ? runtime : res
|
|
148
148
|
} catch (err) {
|
|
149
|
-
if (throwAllErrors) {
|
|
149
|
+
if (throwAllErrors && err.code !== 'PLT_RUNTIME_RUNTIME_ABORT') {
|
|
150
150
|
throw err
|
|
151
151
|
}
|
|
152
152
|
|
|
@@ -187,7 +187,9 @@ async function startCommand (args, throwAllErrors = false, returnRuntime = false
|
|
|
187
187
|
process.exit(1)
|
|
188
188
|
}
|
|
189
189
|
|
|
190
|
-
|
|
190
|
+
if (err.code !== 'PLT_RUNTIME_RUNTIME_ABORT') {
|
|
191
|
+
console.error(err)
|
|
192
|
+
}
|
|
191
193
|
|
|
192
194
|
process.exit(1)
|
|
193
195
|
}
|
package/lib/worker/main.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const { EventEmitter } = require('node:events')
|
|
3
4
|
const { createRequire } = require('node:module')
|
|
4
5
|
const { hostname } = require('node:os')
|
|
5
6
|
const { join } = require('node:path')
|
|
@@ -37,7 +38,10 @@ globalThis[kId] = threadId
|
|
|
37
38
|
let app
|
|
38
39
|
|
|
39
40
|
const config = workerData.config
|
|
40
|
-
globalThis.platformatic = Object.assign(globalThis.platformatic ?? {}, {
|
|
41
|
+
globalThis.platformatic = Object.assign(globalThis.platformatic ?? {}, {
|
|
42
|
+
logger: createLogger(),
|
|
43
|
+
events: new EventEmitter()
|
|
44
|
+
})
|
|
41
45
|
|
|
42
46
|
function handleUnhandled (type, err) {
|
|
43
47
|
const label =
|
|
@@ -200,7 +204,7 @@ async function main () {
|
|
|
200
204
|
globalThis[kITC] = itc
|
|
201
205
|
|
|
202
206
|
// Get the dependencies
|
|
203
|
-
const dependencies =
|
|
207
|
+
const dependencies = await app.getBootstrapDependencies()
|
|
204
208
|
itc.notify('init', { dependencies })
|
|
205
209
|
}
|
|
206
210
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platformatic/runtime",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.20.0-alpha.2",
|
|
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/composer": "2.
|
|
39
|
-
"@platformatic/
|
|
40
|
-
"@platformatic/
|
|
41
|
-
"@platformatic/service": "2.
|
|
42
|
-
"@platformatic/
|
|
43
|
-
"@platformatic/sql-
|
|
38
|
+
"@platformatic/composer": "2.20.0-alpha.2",
|
|
39
|
+
"@platformatic/node": "2.20.0-alpha.2",
|
|
40
|
+
"@platformatic/sql-mapper": "2.20.0-alpha.2",
|
|
41
|
+
"@platformatic/service": "2.20.0-alpha.2",
|
|
42
|
+
"@platformatic/db": "2.20.0-alpha.2",
|
|
43
|
+
"@platformatic/sql-graphql": "2.20.0-alpha.2"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"@fastify/error": "^4.0.0",
|
|
@@ -72,13 +72,13 @@
|
|
|
72
72
|
"undici": "^7.0.0",
|
|
73
73
|
"undici-thread-interceptor": "^0.10.0",
|
|
74
74
|
"ws": "^8.16.0",
|
|
75
|
-
"@platformatic/basic": "2.
|
|
76
|
-
"@platformatic/config": "2.
|
|
77
|
-
"@platformatic/generators": "2.
|
|
78
|
-
"@platformatic/
|
|
79
|
-
"@platformatic/
|
|
80
|
-
"@platformatic/
|
|
81
|
-
"@platformatic/
|
|
75
|
+
"@platformatic/basic": "2.20.0-alpha.2",
|
|
76
|
+
"@platformatic/config": "2.20.0-alpha.2",
|
|
77
|
+
"@platformatic/generators": "2.20.0-alpha.2",
|
|
78
|
+
"@platformatic/telemetry": "2.20.0-alpha.2",
|
|
79
|
+
"@platformatic/ts-compiler": "2.20.0-alpha.2",
|
|
80
|
+
"@platformatic/itc": "2.20.0-alpha.2",
|
|
81
|
+
"@platformatic/utils": "2.20.0-alpha.2"
|
|
82
82
|
},
|
|
83
83
|
"scripts": {
|
|
84
84
|
"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.20.0-alpha.2.json",
|
|
3
3
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
4
4
|
"type": "object",
|
|
5
5
|
"properties": {
|
|
@@ -183,6 +183,7 @@
|
|
|
183
183
|
},
|
|
184
184
|
"path": {
|
|
185
185
|
"type": "string",
|
|
186
|
+
"allowEmptyPaths": true,
|
|
186
187
|
"resolvePath": true
|
|
187
188
|
},
|
|
188
189
|
"config": {
|
|
@@ -335,6 +336,7 @@
|
|
|
335
336
|
},
|
|
336
337
|
"path": {
|
|
337
338
|
"type": "string",
|
|
339
|
+
"allowEmptyPaths": true,
|
|
338
340
|
"resolvePath": true
|
|
339
341
|
},
|
|
340
342
|
"config": {
|
|
@@ -1107,6 +1109,10 @@
|
|
|
1107
1109
|
}
|
|
1108
1110
|
],
|
|
1109
1111
|
"default": 300000
|
|
1112
|
+
},
|
|
1113
|
+
"resolvedServicesBasePath": {
|
|
1114
|
+
"type": "string",
|
|
1115
|
+
"default": "external"
|
|
1110
1116
|
}
|
|
1111
1117
|
},
|
|
1112
1118
|
"anyOf": [
|