@platformatic/runtime 3.0.0-alpha.4 → 3.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 +10 -7
- package/eslint.config.js +2 -4
- package/index.d.ts +11 -11
- package/index.js +35 -46
- package/lib/config.js +80 -102
- package/lib/dependencies.js +27 -29
- package/lib/errors.js +65 -99
- package/lib/generator.js +160 -164
- package/lib/logger.js +6 -8
- package/lib/management-api.js +36 -39
- package/lib/prom-server.js +10 -14
- package/lib/runtime.js +752 -715
- package/lib/scheduler.js +13 -15
- package/lib/schema.js +11 -8
- package/lib/shared-http-cache.js +5 -9
- package/lib/upgrade.js +5 -9
- package/lib/utils.js +6 -14
- package/lib/version.js +7 -0
- package/lib/versions/v1.36.0.js +2 -4
- package/lib/versions/v1.5.0.js +2 -4
- package/lib/versions/v2.0.0.js +3 -5
- package/lib/versions/v3.0.0.js +16 -0
- package/lib/worker/{app.js → controller.js} +46 -56
- package/lib/worker/http-cache.js +11 -14
- package/lib/worker/interceptors.js +14 -18
- package/lib/worker/itc.js +74 -74
- package/lib/worker/main.js +45 -49
- package/lib/worker/messaging.js +23 -27
- package/lib/worker/round-robin-map.js +23 -19
- package/lib/worker/shared-context.js +2 -6
- package/lib/worker/symbols.js +12 -29
- package/package.json +21 -21
- package/schema.json +254 -20
package/lib/scheduler.js
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
import { CronJob, validateCronExpression } from 'cron'
|
|
2
|
+
import { setTimeout } from 'node:timers/promises'
|
|
3
|
+
import { request } from 'undici'
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
const { setTimeout } = require('node:timers/promises')
|
|
5
|
-
const { request } = require('undici')
|
|
6
|
-
|
|
7
|
-
class SchedulerService {
|
|
5
|
+
export class SchedulerService {
|
|
8
6
|
constructor (schedulerConfig, dispatcher, logger) {
|
|
9
7
|
this.logger = logger
|
|
10
8
|
this.jobsConfig = []
|
|
@@ -49,7 +47,7 @@ class SchedulerService {
|
|
|
49
47
|
},
|
|
50
48
|
start: true,
|
|
51
49
|
timeZone: 'UTC',
|
|
52
|
-
waitForCompletion: true
|
|
50
|
+
waitForCompletion: true
|
|
53
51
|
})
|
|
54
52
|
|
|
55
53
|
this.cronJobs.push(cronJob)
|
|
@@ -71,7 +69,9 @@ class SchedulerService {
|
|
|
71
69
|
const delay = attempt > 0 ? 100 * Math.pow(2, attempt) : 0
|
|
72
70
|
|
|
73
71
|
if (delay > 0) {
|
|
74
|
-
this.logger.info(
|
|
72
|
+
this.logger.info(
|
|
73
|
+
`Retrying scheduler "${scheduler.name}" in ${delay}ms (attempt ${attempt + 1}/${scheduler.maxRetries})`
|
|
74
|
+
)
|
|
75
75
|
await setTimeout(delay)
|
|
76
76
|
}
|
|
77
77
|
const headers = {
|
|
@@ -98,7 +98,10 @@ class SchedulerService {
|
|
|
98
98
|
throw new Error(`HTTP error ${response.statusCode}`)
|
|
99
99
|
}
|
|
100
100
|
} catch (error) {
|
|
101
|
-
this.logger.error(
|
|
101
|
+
this.logger.error(
|
|
102
|
+
`Error executing scheduler "${scheduler.name}" (attempt ${attempt + 1}/${scheduler.maxRetries}):`,
|
|
103
|
+
error.message
|
|
104
|
+
)
|
|
102
105
|
attempt++
|
|
103
106
|
}
|
|
104
107
|
}
|
|
@@ -109,13 +112,8 @@ class SchedulerService {
|
|
|
109
112
|
}
|
|
110
113
|
}
|
|
111
114
|
|
|
112
|
-
|
|
115
|
+
export function startScheduler (config, interceptors, logger) {
|
|
113
116
|
const schedulerService = new SchedulerService(config, interceptors, logger)
|
|
114
117
|
schedulerService.start()
|
|
115
118
|
return schedulerService
|
|
116
119
|
}
|
|
117
|
-
|
|
118
|
-
module.exports = {
|
|
119
|
-
startScheduler,
|
|
120
|
-
SchedulerService
|
|
121
|
-
}
|
package/lib/schema.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
#! /usr/bin/env node
|
|
2
|
-
'use strict'
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const pkg = require('../package.json')
|
|
3
|
+
import { schemaComponents } from '@platformatic/foundation'
|
|
4
|
+
import { version } from './version.js'
|
|
7
5
|
|
|
8
6
|
const runtimeLogger = {
|
|
9
7
|
...schemaComponents.runtimeProperties.logger,
|
|
@@ -19,17 +17,22 @@ const runtimeLogger = {
|
|
|
19
17
|
schemaComponents.runtimeProperties.logger = runtimeLogger
|
|
20
18
|
|
|
21
19
|
const platformaticRuntimeSchema = {
|
|
22
|
-
$id: `https://schemas.platformatic.dev/@platformatic/runtime/${
|
|
20
|
+
$id: `https://schemas.platformatic.dev/@platformatic/runtime/${version}.json`,
|
|
23
21
|
$schema: 'http://json-schema.org/draft-07/schema#',
|
|
24
22
|
title: 'Platformatic Runtime Config',
|
|
25
23
|
type: 'object',
|
|
26
24
|
properties: schemaComponents.runtimeProperties,
|
|
27
|
-
anyOf: [
|
|
25
|
+
anyOf: [
|
|
26
|
+
{ required: ['autoload'] },
|
|
27
|
+
{ required: ['applications'] },
|
|
28
|
+
{ required: ['services'] },
|
|
29
|
+
{ required: ['web'] }
|
|
30
|
+
],
|
|
28
31
|
additionalProperties: false
|
|
29
32
|
}
|
|
30
33
|
|
|
31
|
-
|
|
34
|
+
export const schema = platformaticRuntimeSchema
|
|
32
35
|
|
|
33
|
-
if (
|
|
36
|
+
if (import.meta.main) {
|
|
34
37
|
console.log(JSON.stringify(platformaticRuntimeSchema, null, 2))
|
|
35
38
|
}
|
package/lib/shared-http-cache.js
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
import { loadModule } from '@platformatic/foundation'
|
|
2
|
+
import MemoryCacheStore from '@platformatic/undici-cache-memory'
|
|
3
|
+
import { createRequire } from 'node:module'
|
|
4
|
+
import { join } from 'node:path'
|
|
2
5
|
|
|
3
|
-
|
|
4
|
-
const { loadModule } = require('@platformatic/foundation')
|
|
5
|
-
const MemoryCacheStore = require('@platformatic/undici-cache-memory')
|
|
6
|
-
const { createRequire } = require('node:module')
|
|
7
|
-
|
|
8
|
-
async function createSharedStore (projectDir, httpCacheConfig = {}) {
|
|
6
|
+
export async function createSharedStore (projectDir, httpCacheConfig = {}) {
|
|
9
7
|
const runtimeRequire = createRequire(join(projectDir, 'file'))
|
|
10
8
|
|
|
11
9
|
const { store, ...storeConfig } = httpCacheConfig
|
|
@@ -43,5 +41,3 @@ async function createSharedStore (projectDir, httpCacheConfig = {}) {
|
|
|
43
41
|
|
|
44
42
|
return new SharedCacheStore(storeConfig)
|
|
45
43
|
}
|
|
46
|
-
|
|
47
|
-
module.exports = { createSharedStore }
|
package/lib/upgrade.js
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
import { abstractLogger } from '@platformatic/foundation'
|
|
2
|
+
import { join } from 'node:path'
|
|
3
|
+
import { semgrator } from 'semgrator'
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
const { join } = require('node:path')
|
|
5
|
-
const { semgrator } = require('semgrator')
|
|
6
|
-
|
|
7
|
-
async function upgrade (logger, config, version) {
|
|
5
|
+
export async function upgrade (logger, config, version) {
|
|
8
6
|
const iterator = semgrator({
|
|
9
7
|
version,
|
|
10
|
-
path: join(
|
|
8
|
+
path: join(import.meta.dirname, 'versions'),
|
|
11
9
|
input: config,
|
|
12
10
|
logger: logger?.child({ name: '@platformatic/runtime' }) ?? abstractLogger
|
|
13
11
|
})
|
|
@@ -20,5 +18,3 @@ async function upgrade (logger, config, version) {
|
|
|
20
18
|
|
|
21
19
|
return result
|
|
22
20
|
}
|
|
23
|
-
|
|
24
|
-
module.exports = { upgrade }
|
package/lib/utils.js
CHANGED
|
@@ -1,27 +1,19 @@
|
|
|
1
|
-
|
|
1
|
+
import { createHash } from 'node:crypto'
|
|
2
|
+
import { tmpdir } from 'node:os'
|
|
3
|
+
import { join } from 'node:path'
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
const { tmpdir } = require('node:os')
|
|
5
|
-
const { join } = require('node:path')
|
|
6
|
-
|
|
7
|
-
function getArrayDifference (a, b) {
|
|
5
|
+
export function getArrayDifference (a, b) {
|
|
8
6
|
return a.filter(element => {
|
|
9
7
|
return !b.includes(element)
|
|
10
8
|
})
|
|
11
9
|
}
|
|
12
10
|
|
|
13
|
-
function
|
|
11
|
+
export function getApplicationUrl (id) {
|
|
14
12
|
return `http://${id}.plt.local`
|
|
15
13
|
}
|
|
16
14
|
|
|
17
|
-
function getRuntimeTmpDir (runtimeDir) {
|
|
15
|
+
export function getRuntimeTmpDir (runtimeDir) {
|
|
18
16
|
const platformaticTmpDir = join(tmpdir(), 'platformatic', 'applications')
|
|
19
17
|
const runtimeDirHash = createHash('md5').update(runtimeDir).digest('hex')
|
|
20
18
|
return join(platformaticTmpDir, runtimeDirHash)
|
|
21
19
|
}
|
|
22
|
-
|
|
23
|
-
module.exports = {
|
|
24
|
-
getArrayDifference,
|
|
25
|
-
getRuntimeTmpDir,
|
|
26
|
-
getServiceUrl
|
|
27
|
-
}
|
package/lib/version.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs'
|
|
2
|
+
import { resolve } from 'node:path'
|
|
3
|
+
|
|
4
|
+
const packageJson = JSON.parse(readFileSync(resolve(import.meta.dirname, '../package.json'), 'utf-8'))
|
|
5
|
+
|
|
6
|
+
export const name = packageJson.name
|
|
7
|
+
export const version = packageJson.version
|
package/lib/versions/v1.36.0.js
CHANGED
package/lib/versions/v1.5.0.js
CHANGED
package/lib/versions/v2.0.0.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import { version } from '../version.js'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
module.exports = {
|
|
3
|
+
export default {
|
|
6
4
|
version: '1.99.0', // This is to account alpha versions as well
|
|
7
5
|
up: function (config) {
|
|
8
6
|
if (config.restartOnError === undefined) {
|
|
@@ -16,7 +14,7 @@ module.exports = {
|
|
|
16
14
|
|
|
17
15
|
delete config.allowCycles
|
|
18
16
|
|
|
19
|
-
config.$schema = `https://schemas.platformatic.dev/@platformatic/runtime/${
|
|
17
|
+
config.$schema = `https://schemas.platformatic.dev/@platformatic/runtime/${version}.json`
|
|
20
18
|
|
|
21
19
|
if (config.server?.logger) {
|
|
22
20
|
config.logger = config.server.logger
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
version: '2.99.0',
|
|
3
|
+
up (config) {
|
|
4
|
+
if (typeof config.gracefulShutdown?.service === 'number') {
|
|
5
|
+
config.gracefulShutdown.application = config.gracefulShutdown.service
|
|
6
|
+
delete config.gracefulShutdown.service
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
if (typeof config.serviceTimeout === 'number') {
|
|
10
|
+
config.applicationTimeout = config.serviceTimeout
|
|
11
|
+
delete config.serviceTimeout
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return config
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -1,35 +1,28 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const { existsSync } = require('node:fs')
|
|
4
|
-
const { EventEmitter } = require('node:events')
|
|
5
|
-
const { resolve } = require('node:path')
|
|
6
|
-
const {
|
|
7
|
-
performance: { eventLoopUtilization }
|
|
8
|
-
} = require('node:perf_hooks')
|
|
9
|
-
const { workerData } = require('node:worker_threads')
|
|
10
|
-
const {
|
|
1
|
+
import {
|
|
2
|
+
ensureLoggableError,
|
|
11
3
|
FileWatcher,
|
|
12
4
|
listRecognizedConfigurationFiles,
|
|
13
|
-
loadConfigurationModule,
|
|
14
5
|
loadConfiguration,
|
|
15
|
-
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
6
|
+
loadConfigurationModule
|
|
7
|
+
} from '@platformatic/foundation'
|
|
8
|
+
import debounce from 'debounce'
|
|
9
|
+
import { EventEmitter } from 'node:events'
|
|
10
|
+
import { existsSync } from 'node:fs'
|
|
11
|
+
import { resolve } from 'node:path'
|
|
12
|
+
import { workerData } from 'node:worker_threads'
|
|
13
|
+
import { getGlobalDispatcher, setGlobalDispatcher } from 'undici'
|
|
14
|
+
import { ApplicationAlreadyStartedError, RuntimeNotStartedError } from '../errors.js'
|
|
15
|
+
import { getApplicationUrl } from '../utils.js'
|
|
16
|
+
|
|
17
|
+
function fetchApplicationUrl (application, key) {
|
|
18
|
+
if (!key.endsWith('_URL') || !application.id) {
|
|
26
19
|
return null
|
|
27
20
|
}
|
|
28
21
|
|
|
29
|
-
return
|
|
22
|
+
return getApplicationUrl(application.id)
|
|
30
23
|
}
|
|
31
24
|
|
|
32
|
-
class
|
|
25
|
+
export class Controller extends EventEmitter {
|
|
33
26
|
#starting
|
|
34
27
|
#started
|
|
35
28
|
#listening
|
|
@@ -51,18 +44,18 @@ class PlatformaticApp extends EventEmitter {
|
|
|
51
44
|
) {
|
|
52
45
|
super()
|
|
53
46
|
this.appConfig = appConfig
|
|
54
|
-
this.
|
|
47
|
+
this.applicationId = this.appConfig.id
|
|
55
48
|
this.workerId = workerId
|
|
56
49
|
this.#watch = watch
|
|
57
50
|
this.#starting = false
|
|
58
51
|
this.#started = false
|
|
59
52
|
this.#listening = false
|
|
60
|
-
this.
|
|
53
|
+
this.capability = null
|
|
61
54
|
this.#fileWatcher = null
|
|
62
|
-
this.#lastELU = eventLoopUtilization()
|
|
55
|
+
this.#lastELU = performance.eventLoopUtilization()
|
|
63
56
|
|
|
64
57
|
this.#context = {
|
|
65
|
-
|
|
58
|
+
applicationId: this.applicationId,
|
|
66
59
|
workerId: this.workerId,
|
|
67
60
|
directory: this.appConfig.path,
|
|
68
61
|
isEntrypoint: this.appConfig.entrypoint,
|
|
@@ -73,8 +66,7 @@ class PlatformaticApp extends EventEmitter {
|
|
|
73
66
|
serverConfig,
|
|
74
67
|
worker: workerData?.worker,
|
|
75
68
|
hasManagementApi: !!hasManagementApi,
|
|
76
|
-
|
|
77
|
-
fetchServiceUrl: fetchServiceUrl.bind(null, appConfig)
|
|
69
|
+
fetchApplicationUrl: fetchApplicationUrl.bind(null, appConfig)
|
|
78
70
|
}
|
|
79
71
|
}
|
|
80
72
|
|
|
@@ -86,13 +78,13 @@ class PlatformaticApp extends EventEmitter {
|
|
|
86
78
|
|
|
87
79
|
async updateContext (context) {
|
|
88
80
|
this.#context = { ...this.#context, ...context }
|
|
89
|
-
if (this.
|
|
90
|
-
await this.
|
|
81
|
+
if (this.capability) {
|
|
82
|
+
await this.capability.updateContext(context)
|
|
91
83
|
}
|
|
92
84
|
}
|
|
93
85
|
|
|
94
86
|
async getBootstrapDependencies () {
|
|
95
|
-
return this.
|
|
87
|
+
return this.capability.getBootstrapDependencies?.() ?? []
|
|
96
88
|
}
|
|
97
89
|
|
|
98
90
|
async init () {
|
|
@@ -116,25 +108,25 @@ class PlatformaticApp extends EventEmitter {
|
|
|
116
108
|
if (appConfig.config) {
|
|
117
109
|
// Parse the configuration file the first time to obtain the schema
|
|
118
110
|
const unvalidatedConfig = await loadConfiguration(appConfig.config, null, {
|
|
119
|
-
onMissingEnv: this.#context.
|
|
111
|
+
onMissingEnv: this.#context.fetchApplicationUrl
|
|
120
112
|
})
|
|
121
113
|
const pkg = await loadConfigurationModule(appConfig.path, unvalidatedConfig)
|
|
122
|
-
this.
|
|
114
|
+
this.capability = await pkg.create(appConfig.path, appConfig.config, this.#context)
|
|
123
115
|
// We could not find a configuration file, we use the bundle @platformatic/basic with the runtime to load it
|
|
124
116
|
} else {
|
|
125
|
-
const pkg = await loadConfigurationModule(resolve(
|
|
126
|
-
this.
|
|
117
|
+
const pkg = await loadConfigurationModule(resolve(import.meta.dirname, '../..'), {}, '@platformatic/basic')
|
|
118
|
+
this.capability = await pkg.create(appConfig.path, {}, this.#context)
|
|
127
119
|
}
|
|
128
120
|
|
|
129
121
|
this.#updateDispatcher()
|
|
130
122
|
} catch (err) {
|
|
131
123
|
if (err.validationErrors) {
|
|
132
124
|
globalThis.platformatic.logger.error(
|
|
133
|
-
{ err: ensureLoggableError(err
|
|
125
|
+
{ err: ensureLoggableError(err) },
|
|
134
126
|
'The application threw a validation error.'
|
|
135
127
|
)
|
|
136
128
|
|
|
137
|
-
|
|
129
|
+
throw err
|
|
138
130
|
} else {
|
|
139
131
|
this.#logAndThrow(err)
|
|
140
132
|
}
|
|
@@ -143,24 +135,24 @@ class PlatformaticApp extends EventEmitter {
|
|
|
143
135
|
|
|
144
136
|
async start () {
|
|
145
137
|
if (this.#starting || this.#started) {
|
|
146
|
-
throw new
|
|
138
|
+
throw new ApplicationAlreadyStartedError()
|
|
147
139
|
}
|
|
148
140
|
|
|
149
141
|
this.#starting = true
|
|
150
142
|
|
|
151
143
|
try {
|
|
152
|
-
await this.
|
|
144
|
+
await this.capability.init?.()
|
|
153
145
|
} catch (err) {
|
|
154
146
|
this.#logAndThrow(err)
|
|
155
147
|
}
|
|
156
148
|
|
|
157
149
|
if (this.#watch) {
|
|
158
|
-
const watchConfig = await this.
|
|
150
|
+
const watchConfig = await this.capability.getWatchConfig()
|
|
159
151
|
|
|
160
152
|
if (watchConfig.enabled !== false) {
|
|
161
153
|
/* c8 ignore next 4 */
|
|
162
154
|
this.#debouncedRestart = debounce(() => {
|
|
163
|
-
this.
|
|
155
|
+
this.capability.log({ message: 'files changed', level: 'debug' })
|
|
164
156
|
this.emit('changed')
|
|
165
157
|
}, 100) // debounce restart for 100ms
|
|
166
158
|
|
|
@@ -171,11 +163,11 @@ class PlatformaticApp extends EventEmitter {
|
|
|
171
163
|
const listen = !!this.appConfig.useHttp
|
|
172
164
|
|
|
173
165
|
try {
|
|
174
|
-
await this.
|
|
166
|
+
await this.capability.start({ listen })
|
|
175
167
|
this.#listening = listen
|
|
176
168
|
/* c8 ignore next 5 */
|
|
177
169
|
} catch (err) {
|
|
178
|
-
this.
|
|
170
|
+
this.capability.log({ message: err.message, level: 'debug' })
|
|
179
171
|
this.#starting = false
|
|
180
172
|
throw err
|
|
181
173
|
}
|
|
@@ -187,11 +179,11 @@ class PlatformaticApp extends EventEmitter {
|
|
|
187
179
|
|
|
188
180
|
async stop (force = false) {
|
|
189
181
|
if (!force && (!this.#started || this.#starting)) {
|
|
190
|
-
throw new
|
|
182
|
+
throw new RuntimeNotStartedError()
|
|
191
183
|
}
|
|
192
184
|
|
|
193
185
|
await this.#stopFileWatching()
|
|
194
|
-
await this.
|
|
186
|
+
await this.capability.stop()
|
|
195
187
|
|
|
196
188
|
this.#started = false
|
|
197
189
|
this.#starting = false
|
|
@@ -205,7 +197,7 @@ class PlatformaticApp extends EventEmitter {
|
|
|
205
197
|
return
|
|
206
198
|
}
|
|
207
199
|
|
|
208
|
-
await this.
|
|
200
|
+
await this.capability.start({ listen: true })
|
|
209
201
|
}
|
|
210
202
|
|
|
211
203
|
async getMetrics ({ format }) {
|
|
@@ -221,12 +213,12 @@ class PlatformaticApp extends EventEmitter {
|
|
|
221
213
|
globalThis.platformatic.onHttpStatsSize(url, size || 0)
|
|
222
214
|
}
|
|
223
215
|
}
|
|
224
|
-
return this.
|
|
216
|
+
return this.capability.getMetrics({ format })
|
|
225
217
|
}
|
|
226
218
|
|
|
227
219
|
async getHealth () {
|
|
228
|
-
const currentELU = eventLoopUtilization()
|
|
229
|
-
const elu = eventLoopUtilization(currentELU, this.#lastELU).utilization
|
|
220
|
+
const currentELU = performance.eventLoopUtilization()
|
|
221
|
+
const elu = performance.eventLoopUtilization(currentELU, this.#lastELU).utilization
|
|
230
222
|
this.#lastELU = currentELU
|
|
231
223
|
|
|
232
224
|
const { heapUsed, heapTotal } = process.memoryUsage()
|
|
@@ -253,7 +245,7 @@ class PlatformaticApp extends EventEmitter {
|
|
|
253
245
|
fileWatcher.on('update', this.#debouncedRestart)
|
|
254
246
|
|
|
255
247
|
fileWatcher.startWatching()
|
|
256
|
-
this.
|
|
248
|
+
this.capability.log({ message: 'start watching files', level: 'debug' })
|
|
257
249
|
this.#fileWatcher = fileWatcher
|
|
258
250
|
}
|
|
259
251
|
|
|
@@ -261,7 +253,7 @@ class PlatformaticApp extends EventEmitter {
|
|
|
261
253
|
const watcher = this.#fileWatcher
|
|
262
254
|
|
|
263
255
|
if (watcher) {
|
|
264
|
-
this.
|
|
256
|
+
this.capability.log({ message: 'stop watching files', level: 'debug' })
|
|
265
257
|
await watcher.stopWatching()
|
|
266
258
|
this.#fileWatcher = null
|
|
267
259
|
}
|
|
@@ -274,7 +266,7 @@ class PlatformaticApp extends EventEmitter {
|
|
|
274
266
|
|
|
275
267
|
#updateDispatcher () {
|
|
276
268
|
const telemetryConfig = this.#context.telemetryConfig
|
|
277
|
-
const telemetryId = telemetryConfig?.
|
|
269
|
+
const telemetryId = telemetryConfig?.applicationName
|
|
278
270
|
|
|
279
271
|
const interceptor = dispatch => {
|
|
280
272
|
return function InterceptedDispatch (opts, handler) {
|
|
@@ -293,5 +285,3 @@ class PlatformaticApp extends EventEmitter {
|
|
|
293
285
|
setGlobalDispatcher(dispatcher)
|
|
294
286
|
}
|
|
295
287
|
}
|
|
296
|
-
|
|
297
|
-
module.exports = { PlatformaticApp }
|
package/lib/worker/http-cache.js
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const { interceptors } = require('undici')
|
|
6
|
-
const { kITC } = require('./symbols')
|
|
1
|
+
import { randomUUID } from 'node:crypto'
|
|
2
|
+
import { Readable, Writable } from 'node:stream'
|
|
3
|
+
import { interceptors } from 'undici'
|
|
4
|
+
import { kITC } from './symbols.js'
|
|
7
5
|
|
|
8
6
|
const kCacheIdHeader = Symbol('cacheIdHeader')
|
|
9
7
|
const CACHE_ID_HEADER = 'x-plt-http-cache-id'
|
|
10
8
|
|
|
11
9
|
const noop = () => {}
|
|
12
10
|
|
|
13
|
-
class RemoteCacheStore {
|
|
11
|
+
export class RemoteCacheStore {
|
|
14
12
|
#onRequest
|
|
15
13
|
#onCacheHit
|
|
16
14
|
#onCacheMiss
|
|
@@ -89,9 +87,10 @@ class RemoteCacheStore {
|
|
|
89
87
|
} else {
|
|
90
88
|
payload = Buffer.concat(acc)
|
|
91
89
|
}
|
|
92
|
-
itc
|
|
90
|
+
itc
|
|
91
|
+
.send('setHttpCacheValue', { request: key, response: value, payload })
|
|
93
92
|
.then(() => callback())
|
|
94
|
-
.catch(
|
|
93
|
+
.catch(err => callback(err))
|
|
95
94
|
}
|
|
96
95
|
})
|
|
97
96
|
}
|
|
@@ -116,14 +115,14 @@ class RemoteCacheStore {
|
|
|
116
115
|
}
|
|
117
116
|
}
|
|
118
117
|
|
|
119
|
-
|
|
118
|
+
export function httpCacheInterceptor (interceptorOpts) {
|
|
120
119
|
const originalInterceptor = interceptors.cache(interceptorOpts)
|
|
121
120
|
|
|
122
121
|
// AsyncLocalStorage that contains a client http request span
|
|
123
|
-
// Exists only when the nodejs
|
|
122
|
+
// Exists only when the nodejs capability telemetry is enabled
|
|
124
123
|
const clientSpansAls = globalThis.platformatic.clientSpansAls
|
|
125
124
|
|
|
126
|
-
return
|
|
125
|
+
return originalDispatch => {
|
|
127
126
|
const dispatch = (opts, handler) => {
|
|
128
127
|
const originOnResponseStart = handler.onResponseStart.bind(handler)
|
|
129
128
|
handler.onResponseStart = (ac, statusCode, headers, statusMessage) => {
|
|
@@ -170,5 +169,3 @@ const httpCacheInterceptor = (interceptorOpts) => {
|
|
|
170
169
|
}
|
|
171
170
|
}
|
|
172
171
|
}
|
|
173
|
-
|
|
174
|
-
module.exports = { RemoteCacheStore, httpCacheInterceptor }
|
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
async function setDispatcher (runtimeConfig) {
|
|
1
|
+
import { createTelemetryThreadInterceptorHooks } from '@platformatic/telemetry'
|
|
2
|
+
import { createRequire } from 'node:module'
|
|
3
|
+
import { join } from 'node:path'
|
|
4
|
+
import { pathToFileURL } from 'node:url'
|
|
5
|
+
import { parentPort, workerData } from 'node:worker_threads'
|
|
6
|
+
import { Agent, Client, Pool, setGlobalDispatcher } from 'undici'
|
|
7
|
+
import { wire } from 'undici-thread-interceptor'
|
|
8
|
+
import { RemoteCacheStore, httpCacheInterceptor } from './http-cache.js'
|
|
9
|
+
import { kInterceptors } from './symbols.js'
|
|
10
|
+
|
|
11
|
+
export async function setDispatcher (runtimeConfig) {
|
|
14
12
|
const threadDispatcher = createThreadInterceptor(runtimeConfig)
|
|
15
13
|
const threadInterceptor = threadDispatcher.interceptor
|
|
16
14
|
|
|
@@ -34,7 +32,7 @@ async function setDispatcher (runtimeConfig) {
|
|
|
34
32
|
return { threadDispatcher }
|
|
35
33
|
}
|
|
36
34
|
|
|
37
|
-
async function updateUndiciInterceptors (undiciConfig) {
|
|
35
|
+
export async function updateUndiciInterceptors (undiciConfig) {
|
|
38
36
|
const updatableInterceptors = globalThis[kInterceptors]
|
|
39
37
|
if (!updatableInterceptors) return
|
|
40
38
|
|
|
@@ -172,8 +170,8 @@ function createThreadInterceptor (runtimeConfig) {
|
|
|
172
170
|
// with requests for a domain that's never going to exist.
|
|
173
171
|
domain: '.plt.local',
|
|
174
172
|
port: parentPort,
|
|
175
|
-
timeout: runtimeConfig.
|
|
176
|
-
...telemetryHooks
|
|
173
|
+
timeout: runtimeConfig.applicationTimeout,
|
|
174
|
+
...telemetryHooks
|
|
177
175
|
})
|
|
178
176
|
return threadDispatcher
|
|
179
177
|
}
|
|
@@ -197,5 +195,3 @@ function createHttpCacheInterceptor (runtimeConfig) {
|
|
|
197
195
|
})
|
|
198
196
|
return cacheInterceptor
|
|
199
197
|
}
|
|
200
|
-
|
|
201
|
-
module.exports = { setDispatcher, updateUndiciInterceptors }
|