@platformatic/runtime 1.15.0 → 1.16.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/fixtures/dbApp/platformatic.db.json +2 -1
- package/fixtures/start-command-in-runtime.js +10 -1
- package/lib/api.js +9 -3
- package/lib/config.js +8 -1
- package/lib/start.js +12 -3
- package/lib/worker.js +32 -19
- package/package.json +15 -14
- package/test.js +0 -20
|
@@ -1,14 +1,23 @@
|
|
|
1
1
|
'use strict'
|
|
2
|
+
|
|
2
3
|
const assert = require('node:assert')
|
|
3
|
-
const { request } = require('undici')
|
|
4
|
+
const { request, setGlobalDispatcher, Agent } = require('undici')
|
|
4
5
|
const { startCommand } = require('..')
|
|
5
6
|
|
|
7
|
+
setGlobalDispatcher(new Agent({
|
|
8
|
+
keepAliveTimeout: 1,
|
|
9
|
+
keepAliveMaxTimeout: 1
|
|
10
|
+
}))
|
|
11
|
+
|
|
6
12
|
async function main () {
|
|
7
13
|
const entrypoint = await startCommand(['-c', process.argv[2]])
|
|
8
14
|
const endpoint = process.argv[3] ?? '/'
|
|
9
15
|
const res = await request(entrypoint + endpoint)
|
|
10
16
|
|
|
11
17
|
assert.strictEqual(res.statusCode, 200)
|
|
18
|
+
|
|
19
|
+
// Consume the body so the service can end
|
|
20
|
+
await res.body.text()
|
|
12
21
|
process.exit(42)
|
|
13
22
|
}
|
|
14
23
|
|
package/lib/api.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const FastifyUndiciDispatcher = require('fastify-undici-dispatcher')
|
|
4
|
-
const {
|
|
4
|
+
const { setGlobalDispatcher, getGlobalDispatcher } = require('undici')
|
|
5
5
|
const { PlatformaticApp } = require('./app')
|
|
6
6
|
const errors = require('./errors')
|
|
7
7
|
const { printSchema } = require('graphql')
|
|
@@ -34,7 +34,7 @@ class RuntimeApi {
|
|
|
34
34
|
this.#services.set(service.id, app)
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
const globalAgent =
|
|
37
|
+
const globalAgent = getGlobalDispatcher()
|
|
38
38
|
const globalDispatcher = new FastifyUndiciDispatcher({
|
|
39
39
|
dispatcher: globalAgent,
|
|
40
40
|
// setting the domain here allows for fail-fast scenarios
|
|
@@ -73,6 +73,10 @@ class RuntimeApi {
|
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
+
if (this.#dispatcher) {
|
|
77
|
+
await this.#dispatcher.close()
|
|
78
|
+
}
|
|
79
|
+
|
|
76
80
|
process.exit() // Exit the worker thread if all services are stopped
|
|
77
81
|
}
|
|
78
82
|
|
|
@@ -132,12 +136,14 @@ class RuntimeApi {
|
|
|
132
136
|
}
|
|
133
137
|
|
|
134
138
|
async stopServices () {
|
|
139
|
+
const stopServiceReqs = [this.#dispatcher.close()]
|
|
135
140
|
for (const service of this.#services.values()) {
|
|
136
141
|
const serviceStatus = service.getStatus()
|
|
137
142
|
if (serviceStatus === 'started') {
|
|
138
|
-
|
|
143
|
+
stopServiceReqs.push(service.stop())
|
|
139
144
|
}
|
|
140
145
|
}
|
|
146
|
+
await Promise.all(stopServiceReqs)
|
|
141
147
|
}
|
|
142
148
|
|
|
143
149
|
async #restartServices () {
|
package/lib/config.js
CHANGED
|
@@ -33,7 +33,14 @@ async function _transformConfig (configManager) {
|
|
|
33
33
|
|
|
34
34
|
const config = join(entryPath, configFilename)
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
const service = { id, config, path: entryPath, useHttp: !!mapping.useHttp }
|
|
37
|
+
const existingServiceId = services.findIndex(service => service.id === id)
|
|
38
|
+
|
|
39
|
+
if (existingServiceId !== -1) {
|
|
40
|
+
services[existingServiceId] = service
|
|
41
|
+
} else {
|
|
42
|
+
services.push(service)
|
|
43
|
+
}
|
|
37
44
|
}
|
|
38
45
|
}
|
|
39
46
|
|
package/lib/start.js
CHANGED
|
@@ -48,7 +48,11 @@ async function startWithConfig (configManager, env = process.env) {
|
|
|
48
48
|
})
|
|
49
49
|
|
|
50
50
|
let exited = null
|
|
51
|
-
|
|
51
|
+
let isWorkerAlive = true
|
|
52
|
+
worker.on('exit', (code) => {
|
|
53
|
+
// TODO(mcollina): refactor to not set this here
|
|
54
|
+
process.exitCode = code
|
|
55
|
+
isWorkerAlive = false
|
|
52
56
|
configManager.fileWatcher?.stopWatching()
|
|
53
57
|
if (typeof exited === 'function') {
|
|
54
58
|
exited()
|
|
@@ -70,9 +74,14 @@ async function startWithConfig (configManager, env = process.env) {
|
|
|
70
74
|
worker.postMessage({ signal: 'SIGUSR2' })
|
|
71
75
|
})
|
|
72
76
|
|
|
77
|
+
// TODO(mcollina): refactor to not alter globals here
|
|
73
78
|
closeWithGrace((event, cb) => {
|
|
74
|
-
|
|
75
|
-
|
|
79
|
+
if (isWorkerAlive) {
|
|
80
|
+
worker.postMessage(event)
|
|
81
|
+
exited = cb
|
|
82
|
+
} else {
|
|
83
|
+
setImmediate(cb)
|
|
84
|
+
}
|
|
76
85
|
})
|
|
77
86
|
|
|
78
87
|
/* c8 ignore next 3 */
|
package/lib/worker.js
CHANGED
|
@@ -58,25 +58,6 @@ if (config.server) {
|
|
|
58
58
|
config.server.logger = logger
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
/* c8 ignore next 4 */
|
|
62
|
-
process.once('uncaughtException', (err) => {
|
|
63
|
-
logger.error({ err }, 'runtime error')
|
|
64
|
-
logger[pino.symbols.streamSym].flushSync?.()
|
|
65
|
-
setImmediate(() => {
|
|
66
|
-
process.exit(1)
|
|
67
|
-
})
|
|
68
|
-
})
|
|
69
|
-
|
|
70
|
-
// Tested by test/cli/start.test.mjs by C8 does not see it.
|
|
71
|
-
/* c8 ignore next 4 */
|
|
72
|
-
process.once('unhandledRejection', (err) => {
|
|
73
|
-
logger.error({ err }, 'runtime error')
|
|
74
|
-
logger[pino.symbols.streamSym].flushSync?.()
|
|
75
|
-
setImmediate(() => {
|
|
76
|
-
process.exit(1)
|
|
77
|
-
})
|
|
78
|
-
})
|
|
79
|
-
|
|
80
61
|
function main () {
|
|
81
62
|
const { inspectorOptions } = workerData.config
|
|
82
63
|
|
|
@@ -93,6 +74,38 @@ function main () {
|
|
|
93
74
|
runtime.startListening(parentPort)
|
|
94
75
|
|
|
95
76
|
parentPort.postMessage('plt:init')
|
|
77
|
+
|
|
78
|
+
let stopping = false
|
|
79
|
+
|
|
80
|
+
async function stop () {
|
|
81
|
+
if (stopping) {
|
|
82
|
+
return
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
stopping = true
|
|
86
|
+
try {
|
|
87
|
+
await runtime.stopServices()
|
|
88
|
+
} catch (err) {
|
|
89
|
+
logger.error({ err }, 'error while stopping services')
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/* c8 ignore next 4 */
|
|
94
|
+
process.on('uncaughtException', (err) => {
|
|
95
|
+
logger.error({ err }, 'runtime error')
|
|
96
|
+
stop().then(() => {
|
|
97
|
+
process.exit(1)
|
|
98
|
+
})
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
// Tested by test/cli/start.test.mjs by C8 does not see it.
|
|
102
|
+
/* c8 ignore next 4 */
|
|
103
|
+
process.on('unhandledRejection', (err) => {
|
|
104
|
+
logger.error({ err }, 'runtime error')
|
|
105
|
+
stop().then(() => {
|
|
106
|
+
process.exit(1)
|
|
107
|
+
})
|
|
108
|
+
})
|
|
96
109
|
}
|
|
97
110
|
|
|
98
111
|
main()
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platformatic/runtime",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.16.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
"standard": "^17.1.0",
|
|
29
29
|
"tsd": "^0.29.0",
|
|
30
30
|
"typescript": "^5.2.2",
|
|
31
|
-
"@platformatic/sql-
|
|
32
|
-
"@platformatic/sql-
|
|
31
|
+
"@platformatic/sql-graphql": "1.16.0",
|
|
32
|
+
"@platformatic/sql-mapper": "1.16.0"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@fastify/error": "^3.4.0",
|
|
@@ -44,18 +44,19 @@
|
|
|
44
44
|
"fastify": "^4.24.1",
|
|
45
45
|
"fastify-undici-dispatcher": "^0.5.0",
|
|
46
46
|
"graphql": "^16.8.1",
|
|
47
|
-
"help-me": "^
|
|
47
|
+
"help-me": "^5.0.0",
|
|
48
48
|
"minimist": "^1.2.8",
|
|
49
49
|
"pino": "^8.16.0",
|
|
50
50
|
"pino-pretty": "^10.2.3",
|
|
51
|
-
"undici": "^6.
|
|
52
|
-
"
|
|
53
|
-
"@platformatic/
|
|
54
|
-
"@platformatic/
|
|
55
|
-
"@platformatic/generators": "1.
|
|
56
|
-
"@platformatic/
|
|
57
|
-
"@platformatic/
|
|
58
|
-
"@platformatic/
|
|
51
|
+
"undici": "^6.2.0",
|
|
52
|
+
"why-is-node-running": "^2.2.2",
|
|
53
|
+
"@platformatic/composer": "1.16.0",
|
|
54
|
+
"@platformatic/config": "1.16.0",
|
|
55
|
+
"@platformatic/generators": "1.16.0",
|
|
56
|
+
"@platformatic/service": "1.16.0",
|
|
57
|
+
"@platformatic/db": "1.16.0",
|
|
58
|
+
"@platformatic/telemetry": "1.16.0",
|
|
59
|
+
"@platformatic/utils": "1.16.0"
|
|
59
60
|
},
|
|
60
61
|
"standard": {
|
|
61
62
|
"ignore": [
|
|
@@ -64,8 +65,8 @@
|
|
|
64
65
|
]
|
|
65
66
|
},
|
|
66
67
|
"scripts": {
|
|
67
|
-
"test": "npm run lint && node test.js
|
|
68
|
-
"coverage": "npm run lint && c8 -x fixtures -x test node test.js && tsd",
|
|
68
|
+
"test": "npm run lint && node ./test/runner.js && tsd",
|
|
69
|
+
"coverage": "npm run lint && c8 -x fixtures -x test node ./test/runner.js && tsd",
|
|
69
70
|
"lint": "standard | snazzy"
|
|
70
71
|
}
|
|
71
72
|
}
|
package/test.js
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const { tap, spec } = require('node:test/reporters')
|
|
4
|
-
const { run } = require('node:test')
|
|
5
|
-
const path = require('node:path')
|
|
6
|
-
const glob = require('glob').globSync
|
|
7
|
-
|
|
8
|
-
/* eslint-disable new-cap */
|
|
9
|
-
const reporter = process.stdout.isTTY ? new spec() : tap
|
|
10
|
-
|
|
11
|
-
const files = [
|
|
12
|
-
...glob(path.join(__dirname, 'test', '*.test.js')),
|
|
13
|
-
...glob(path.join(__dirname, 'test', 'cli', '*.test.mjs'))
|
|
14
|
-
]
|
|
15
|
-
|
|
16
|
-
run({
|
|
17
|
-
files,
|
|
18
|
-
concurrency: 1,
|
|
19
|
-
timeout: 30000
|
|
20
|
-
}).compose(reporter).pipe(process.stdout)
|