@platformatic/runtime 2.0.0-alpha.5 → 2.0.0-alpha.6
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 +1 -1
- package/lib/management-api.js +0 -14
- package/lib/runtime.js +19 -14
- package/lib/worker/itc.js +87 -83
- package/lib/worker/main.js +2 -1
- package/package.json +14 -13
- package/schema.json +1 -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 HttpsSchemasPlatformaticDevPlatformaticRuntime200Alpha6Json = {
|
|
9
9
|
[k: string]: unknown;
|
|
10
10
|
} & {
|
|
11
11
|
$schema?: string;
|
package/lib/management-api.js
CHANGED
|
@@ -72,20 +72,6 @@ async function managementApiPlugin (app, opts) {
|
|
|
72
72
|
return runtime.getServiceGraphqlSchema(id)
|
|
73
73
|
})
|
|
74
74
|
|
|
75
|
-
app.get('/services/:id/connection-strings', async request => {
|
|
76
|
-
const { id } = request.params
|
|
77
|
-
try {
|
|
78
|
-
app.log.debug('get connection strings', { id })
|
|
79
|
-
const meta = await runtime.getServiceMeta(id)
|
|
80
|
-
if (meta.db) {
|
|
81
|
-
return meta.db
|
|
82
|
-
}
|
|
83
|
-
return null
|
|
84
|
-
} catch (err) {
|
|
85
|
-
throw new errors.FailedToRetrieveMetaError(id, err.message)
|
|
86
|
-
}
|
|
87
|
-
})
|
|
88
|
-
|
|
89
75
|
app.post('/services/:id/start', async request => {
|
|
90
76
|
const { id } = request.params
|
|
91
77
|
app.log.debug('start service', { id })
|
package/lib/runtime.js
CHANGED
|
@@ -9,6 +9,7 @@ const { setTimeout: sleep } = require('node:timers/promises')
|
|
|
9
9
|
const { Worker } = require('node:worker_threads')
|
|
10
10
|
|
|
11
11
|
const { ITC } = require('@platformatic/itc')
|
|
12
|
+
const { Unpromise } = require('@watchable/unpromise')
|
|
12
13
|
const ts = require('tail-file-stream')
|
|
13
14
|
const { createThreadInterceptor } = require('undici-thread-interceptor')
|
|
14
15
|
|
|
@@ -275,13 +276,13 @@ class Runtime extends EventEmitter {
|
|
|
275
276
|
|
|
276
277
|
// Always send the stop message, it will shut down workers that only had ITC and interceptors setup
|
|
277
278
|
try {
|
|
278
|
-
await
|
|
279
|
+
await Unpromise.race([sendViaITC(service, 'stop'), sleep(10000, 'timeout', { ref: false })])
|
|
279
280
|
} catch (error) {
|
|
280
281
|
this.logger?.info(`Failed to stop service "${id}". Killing a worker thread.`, error)
|
|
281
282
|
}
|
|
282
283
|
|
|
283
284
|
// Wait for the worker thread to finish, we're going to create a new one if the service is ever restarted
|
|
284
|
-
const res = await
|
|
285
|
+
const res = await Unpromise.race([once(service, 'exit'), sleep(10000, 'timeout', { ref: false })])
|
|
285
286
|
|
|
286
287
|
// If the worker didn't exit in time, kill it
|
|
287
288
|
if (res === 'timeout') {
|
|
@@ -422,7 +423,7 @@ class Runtime extends EventEmitter {
|
|
|
422
423
|
packageName: packageJson.name ?? null,
|
|
423
424
|
packageVersion: packageJson.version ?? null,
|
|
424
425
|
url: entrypointDetails?.url ?? null,
|
|
425
|
-
platformaticVersion
|
|
426
|
+
platformaticVersion
|
|
426
427
|
}
|
|
427
428
|
}
|
|
428
429
|
|
|
@@ -449,7 +450,7 @@ class Runtime extends EventEmitter {
|
|
|
449
450
|
async getServices () {
|
|
450
451
|
return {
|
|
451
452
|
entrypoint: this.#entrypointId,
|
|
452
|
-
services: await Promise.all(this.#servicesIds.map(id => this.getServiceDetails(id)))
|
|
453
|
+
services: await Promise.all(this.#servicesIds.map(id => this.getServiceDetails(id)))
|
|
453
454
|
}
|
|
454
455
|
}
|
|
455
456
|
|
|
@@ -478,7 +479,7 @@ class Runtime extends EventEmitter {
|
|
|
478
479
|
version,
|
|
479
480
|
localUrl,
|
|
480
481
|
entrypoint,
|
|
481
|
-
dependencies
|
|
482
|
+
dependencies
|
|
482
483
|
}
|
|
483
484
|
|
|
484
485
|
if (entrypoint) {
|
|
@@ -610,9 +611,9 @@ class Runtime extends EventEmitter {
|
|
|
610
611
|
p50: p50Value,
|
|
611
612
|
p90: p90Value,
|
|
612
613
|
p95: p95Value,
|
|
613
|
-
p99: p99Value
|
|
614
|
-
}
|
|
615
|
-
}
|
|
614
|
+
p99: p99Value
|
|
615
|
+
}
|
|
616
|
+
}
|
|
616
617
|
}
|
|
617
618
|
|
|
618
619
|
return formattedMetrics
|
|
@@ -649,7 +650,7 @@ class Runtime extends EventEmitter {
|
|
|
649
650
|
}
|
|
650
651
|
runtimesLogsIds.push({
|
|
651
652
|
pid: runtime.runtimePID,
|
|
652
|
-
indexes: runtimeLogIds
|
|
653
|
+
indexes: runtimeLogIds
|
|
653
654
|
})
|
|
654
655
|
}
|
|
655
656
|
|
|
@@ -687,7 +688,7 @@ class Runtime extends EventEmitter {
|
|
|
687
688
|
serviceConfig,
|
|
688
689
|
dirname: this.#configManager.dirname,
|
|
689
690
|
runtimeLogsDir: this.#runtimeLogsDir,
|
|
690
|
-
loggingPort
|
|
691
|
+
loggingPort
|
|
691
692
|
},
|
|
692
693
|
execArgv: [], // Avoid side effects
|
|
693
694
|
env: this.#env,
|
|
@@ -700,7 +701,7 @@ class Runtime extends EventEmitter {
|
|
|
700
701
|
The author of this (Paolo and Matteo) are not proud of the solution. Forgive us.
|
|
701
702
|
*/
|
|
702
703
|
stdout: true,
|
|
703
|
-
stderr: true
|
|
704
|
+
stderr: true
|
|
704
705
|
})
|
|
705
706
|
|
|
706
707
|
// Make sure the listener can handle a lot of API requests at once before raising a warning
|
|
@@ -737,9 +738,13 @@ class Runtime extends EventEmitter {
|
|
|
737
738
|
service[kConfig] = serviceConfig
|
|
738
739
|
|
|
739
740
|
// Setup ITC
|
|
740
|
-
service[kITC] = new ITC({
|
|
741
|
+
service[kITC] = new ITC({
|
|
742
|
+
port: service,
|
|
743
|
+
handlers: {
|
|
744
|
+
getServiceMeta: this.getServiceMeta.bind(this)
|
|
745
|
+
}
|
|
746
|
+
})
|
|
741
747
|
service[kITC].listen()
|
|
742
|
-
service[kITC].handle('getServiceMeta', this.getServiceMeta.bind(this))
|
|
743
748
|
|
|
744
749
|
// Handle services changes
|
|
745
750
|
// This is not purposely activated on when this.#configManager.current.watch === true
|
|
@@ -904,7 +909,7 @@ class Runtime extends EventEmitter {
|
|
|
904
909
|
runtimesLogFiles.push({
|
|
905
910
|
runtimePID: parseInt(runtimePID),
|
|
906
911
|
runtimeLogFiles,
|
|
907
|
-
lastModified
|
|
912
|
+
lastModified
|
|
908
913
|
})
|
|
909
914
|
}
|
|
910
915
|
|
package/lib/worker/itc.js
CHANGED
|
@@ -4,6 +4,7 @@ const { once } = require('node:events')
|
|
|
4
4
|
const { parentPort } = require('node:worker_threads')
|
|
5
5
|
|
|
6
6
|
const { ITC } = require('@platformatic/itc')
|
|
7
|
+
const { Unpromise } = require('@watchable/unpromise')
|
|
7
8
|
|
|
8
9
|
const errors = require('../errors')
|
|
9
10
|
const { kITC, kId } = require('./symbols')
|
|
@@ -14,11 +15,11 @@ async function sendViaITC (worker, name, message) {
|
|
|
14
15
|
const ac = new AbortController()
|
|
15
16
|
let exitCode
|
|
16
17
|
|
|
17
|
-
const response = await
|
|
18
|
+
const response = await Unpromise.race([
|
|
18
19
|
worker[kITC].send(name, message),
|
|
19
20
|
once(worker, 'exit', { signal: ac.signal }).then(([code]) => {
|
|
20
21
|
exitCode = code
|
|
21
|
-
})
|
|
22
|
+
})
|
|
22
23
|
])
|
|
23
24
|
|
|
24
25
|
if (typeof exitCode === 'number') {
|
|
@@ -42,90 +43,93 @@ async function sendViaITC (worker, name, message) {
|
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
function setupITC (app, service, dispatcher) {
|
|
45
|
-
const itc = new ITC({
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
46
|
+
const itc = new ITC({
|
|
47
|
+
port: parentPort,
|
|
48
|
+
handlers: {
|
|
49
|
+
async start () {
|
|
50
|
+
const status = app.getStatus()
|
|
51
|
+
|
|
52
|
+
if (status === 'starting') {
|
|
53
|
+
await once(app, 'start')
|
|
54
|
+
} else {
|
|
55
|
+
await app.start()
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (service.entrypoint) {
|
|
59
|
+
await app.listen()
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const url = app.stackable.getUrl()
|
|
63
|
+
|
|
64
|
+
const dispatchFunc = await app.stackable.getDispatchFunc()
|
|
65
|
+
dispatcher.replaceServer(url ?? dispatchFunc)
|
|
66
|
+
|
|
67
|
+
return service.entrypoint ? url : null
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
async stop () {
|
|
71
|
+
const status = app.getStatus()
|
|
72
|
+
|
|
73
|
+
if (status === 'starting') {
|
|
74
|
+
await once(app, 'start')
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (status !== 'stopped') {
|
|
78
|
+
await app.stop()
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
dispatcher.interceptor.close()
|
|
82
|
+
itc.close()
|
|
83
|
+
},
|
|
84
|
+
|
|
85
|
+
getStatus () {
|
|
86
|
+
return app.getStatus()
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
getServiceInfo () {
|
|
90
|
+
return app.stackable.getInfo()
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
async getServiceConfig () {
|
|
94
|
+
const current = await app.stackable.getConfig()
|
|
95
|
+
// Remove all undefined keys from the config
|
|
96
|
+
return JSON.parse(JSON.stringify(current))
|
|
97
|
+
},
|
|
98
|
+
|
|
99
|
+
async getServiceOpenAPISchema () {
|
|
100
|
+
try {
|
|
101
|
+
return await app.stackable.getOpenapiSchema()
|
|
102
|
+
} catch (err) {
|
|
103
|
+
throw new errors.FailedToRetrieveOpenAPISchemaError(service.id, err.message)
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
|
|
107
|
+
async getServiceGraphQLSchema () {
|
|
108
|
+
try {
|
|
109
|
+
return await app.stackable.getGraphqlSchema()
|
|
110
|
+
} catch (err) {
|
|
111
|
+
throw new errors.FailedToRetrieveGraphQLSchemaError(service.id, err.message)
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
|
|
115
|
+
async getServiceMeta () {
|
|
116
|
+
try {
|
|
117
|
+
return await app.stackable.getMeta()
|
|
118
|
+
} catch (err) {
|
|
119
|
+
throw new errors.FailedToRetrieveMetaError(service.id, err.message)
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
|
|
123
|
+
getMetrics (format) {
|
|
124
|
+
return app.stackable.getMetrics({ format })
|
|
125
|
+
},
|
|
126
|
+
|
|
127
|
+
inject (injectParams) {
|
|
128
|
+
return app.stackable.inject(injectParams)
|
|
129
|
+
}
|
|
102
130
|
}
|
|
103
131
|
})
|
|
104
132
|
|
|
105
|
-
itc.handle('getServiceGraphQLSchema', async () => {
|
|
106
|
-
try {
|
|
107
|
-
return app.stackable.getGraphqlSchema()
|
|
108
|
-
} catch (err) {
|
|
109
|
-
throw new errors.FailedToRetrieveGraphQLSchemaError(service.id, err.message)
|
|
110
|
-
}
|
|
111
|
-
})
|
|
112
|
-
|
|
113
|
-
itc.handle('getServiceMeta', async () => {
|
|
114
|
-
try {
|
|
115
|
-
return app.stackable.getMeta()
|
|
116
|
-
} catch (err) {
|
|
117
|
-
throw new errors.FailedToRetrieveMetaError(service.id, err.message)
|
|
118
|
-
}
|
|
119
|
-
})
|
|
120
|
-
|
|
121
|
-
itc.handle('getMetrics', async format => {
|
|
122
|
-
return app.stackable.getMetrics({ format })
|
|
123
|
-
})
|
|
124
|
-
|
|
125
|
-
itc.handle('inject', async injectParams => {
|
|
126
|
-
return app.stackable.inject(injectParams)
|
|
127
|
-
})
|
|
128
|
-
|
|
129
133
|
app.on('changed', () => {
|
|
130
134
|
itc.notify('changed')
|
|
131
135
|
})
|
package/lib/worker/main.js
CHANGED
|
@@ -6,6 +6,7 @@ const { setTimeout: sleep } = require('node:timers/promises')
|
|
|
6
6
|
const { parentPort, workerData, threadId } = require('node:worker_threads')
|
|
7
7
|
const { pathToFileURL } = require('node:url')
|
|
8
8
|
|
|
9
|
+
const { Unpromise } = require('@watchable/unpromise')
|
|
9
10
|
const pino = require('pino')
|
|
10
11
|
const { fetch, setGlobalDispatcher, Agent } = require('undici')
|
|
11
12
|
const { wire } = require('undici-thread-interceptor')
|
|
@@ -29,7 +30,7 @@ const logger = createLogger()
|
|
|
29
30
|
function handleUnhandled (type, err) {
|
|
30
31
|
logger.error({ err }, `application ${type}`)
|
|
31
32
|
|
|
32
|
-
|
|
33
|
+
Unpromise.race([app?.stop(), sleep(1000, 'timeout', { ref: false })])
|
|
33
34
|
.catch()
|
|
34
35
|
.finally(() => {
|
|
35
36
|
process.exit(1)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platformatic/runtime",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.6",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -34,16 +34,17 @@
|
|
|
34
34
|
"typescript": "^5.5.4",
|
|
35
35
|
"undici-oidc-interceptor": "^0.5.0",
|
|
36
36
|
"why-is-node-running": "^2.2.2",
|
|
37
|
-
"@platformatic/composer": "2.0.0-alpha.
|
|
38
|
-
"@platformatic/
|
|
39
|
-
"@platformatic/sql-graphql": "2.0.0-alpha.
|
|
40
|
-
"@platformatic/sql-mapper": "2.0.0-alpha.
|
|
41
|
-
"@platformatic/
|
|
37
|
+
"@platformatic/composer": "2.0.0-alpha.6",
|
|
38
|
+
"@platformatic/service": "2.0.0-alpha.6",
|
|
39
|
+
"@platformatic/sql-graphql": "2.0.0-alpha.6",
|
|
40
|
+
"@platformatic/sql-mapper": "2.0.0-alpha.6",
|
|
41
|
+
"@platformatic/db": "2.0.0-alpha.6"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@fastify/error": "^3.4.1",
|
|
45
45
|
"@fastify/websocket": "^10.0.0",
|
|
46
46
|
"@hapi/topo": "^6.0.2",
|
|
47
|
+
"@watchable/unpromise": "^1.0.2",
|
|
47
48
|
"boring-name-generator": "^1.0.3",
|
|
48
49
|
"change-case-all": "^2.1.0",
|
|
49
50
|
"close-with-grace": "^2.0.0",
|
|
@@ -66,13 +67,13 @@
|
|
|
66
67
|
"undici": "^6.9.0",
|
|
67
68
|
"undici-thread-interceptor": "^0.5.1",
|
|
68
69
|
"ws": "^8.16.0",
|
|
69
|
-
"@platformatic/basic": "2.0.0-alpha.
|
|
70
|
-
"@platformatic/
|
|
71
|
-
"@platformatic/
|
|
72
|
-
"@platformatic/
|
|
73
|
-
"@platformatic/
|
|
74
|
-
"@platformatic/
|
|
75
|
-
"@platformatic/
|
|
70
|
+
"@platformatic/basic": "2.0.0-alpha.6",
|
|
71
|
+
"@platformatic/generators": "2.0.0-alpha.6",
|
|
72
|
+
"@platformatic/config": "2.0.0-alpha.6",
|
|
73
|
+
"@platformatic/utils": "2.0.0-alpha.6",
|
|
74
|
+
"@platformatic/itc": "2.0.0-alpha.6",
|
|
75
|
+
"@platformatic/ts-compiler": "2.0.0-alpha.6",
|
|
76
|
+
"@platformatic/telemetry": "2.0.0-alpha.6"
|
|
76
77
|
},
|
|
77
78
|
"scripts": {
|
|
78
79
|
"test": "npm run lint && borp --concurrency=1 --timeout=180000 && tsd",
|
package/schema.json
CHANGED