nmtjs 0.16.1 → 0.17.0-beta.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/LICENSE.md +1 -1
- package/README.md +41 -1
- package/dist/index.d.ts +22 -161
- package/dist/index.js +24 -53
- package/dist/index.js.map +1 -1
- package/package.json +11 -63
- package/src/index.ts +71 -91
- package/bin/cli.js +0 -2
- package/dist/cli.d.ts +0 -1
- package/dist/cli.js +0 -137
- package/dist/cli.js.map +0 -1
- package/dist/codegen.d.ts +0 -5
- package/dist/codegen.js +0 -18
- package/dist/codegen.js.map +0 -1
- package/dist/config.d.ts +0 -47
- package/dist/config.js +0 -16
- package/dist/config.js.map +0 -1
- package/dist/entrypoints/cli.d.ts +0 -1
- package/dist/entrypoints/cli.js +0 -12
- package/dist/entrypoints/cli.js.map +0 -1
- package/dist/entrypoints/main.d.ts +0 -5
- package/dist/entrypoints/main.js +0 -248
- package/dist/entrypoints/main.js.map +0 -1
- package/dist/entrypoints/thread.d.ts +0 -16
- package/dist/entrypoints/thread.js +0 -182
- package/dist/entrypoints/thread.js.map +0 -1
- package/dist/entrypoints/worker.d.ts +0 -9
- package/dist/entrypoints/worker.js +0 -143
- package/dist/entrypoints/worker.js.map +0 -1
- package/dist/resolver.d.ts +0 -2
- package/dist/resolver.js +0 -7
- package/dist/resolver.js.map +0 -1
- package/dist/runtime/application/index.d.ts +0 -1
- package/dist/runtime/application/index.js +0 -2
- package/dist/runtime/application/index.js.map +0 -1
- package/dist/runtime/constants.d.ts +0 -8
- package/dist/runtime/constants.js +0 -5
- package/dist/runtime/constants.js.map +0 -1
- package/dist/runtime/enums.d.ts +0 -10
- package/dist/runtime/enums.js +0 -13
- package/dist/runtime/enums.js.map +0 -1
- package/dist/runtime/hooks.d.ts +0 -1
- package/dist/runtime/hooks.js +0 -2
- package/dist/runtime/hooks.js.map +0 -1
- package/dist/runtime/index.d.ts +0 -28
- package/dist/runtime/index.js +0 -29
- package/dist/runtime/index.js.map +0 -1
- package/dist/runtime/injectables.d.ts +0 -69
- package/dist/runtime/injectables.js +0 -40
- package/dist/runtime/injectables.js.map +0 -1
- package/dist/runtime/jobs/job.d.ts +0 -146
- package/dist/runtime/jobs/job.js +0 -89
- package/dist/runtime/jobs/job.js.map +0 -1
- package/dist/runtime/jobs/manager.d.ts +0 -131
- package/dist/runtime/jobs/manager.js +0 -309
- package/dist/runtime/jobs/manager.js.map +0 -1
- package/dist/runtime/jobs/router.d.ts +0 -296
- package/dist/runtime/jobs/router.js +0 -458
- package/dist/runtime/jobs/router.js.map +0 -1
- package/dist/runtime/jobs/runner.d.ts +0 -103
- package/dist/runtime/jobs/runner.js +0 -425
- package/dist/runtime/jobs/runner.js.map +0 -1
- package/dist/runtime/jobs/step.d.ts +0 -26
- package/dist/runtime/jobs/step.js +0 -18
- package/dist/runtime/jobs/step.js.map +0 -1
- package/dist/runtime/jobs/types.d.ts +0 -86
- package/dist/runtime/jobs/types.js +0 -5
- package/dist/runtime/jobs/types.js.map +0 -1
- package/dist/runtime/metrics/metric.d.ts +0 -8
- package/dist/runtime/metrics/metric.js +0 -11
- package/dist/runtime/metrics/metric.js.map +0 -1
- package/dist/runtime/metrics/registry.d.ts +0 -3
- package/dist/runtime/metrics/registry.js +0 -5
- package/dist/runtime/metrics/registry.js.map +0 -1
- package/dist/runtime/metrics/server.d.ts +0 -7
- package/dist/runtime/metrics/server.js +0 -53
- package/dist/runtime/metrics/server.js.map +0 -1
- package/dist/runtime/plugin.d.ts +0 -2
- package/dist/runtime/plugin.js +0 -2
- package/dist/runtime/plugin.js.map +0 -1
- package/dist/runtime/runtime.d.ts +0 -27
- package/dist/runtime/runtime.js +0 -77
- package/dist/runtime/runtime.js.map +0 -1
- package/dist/runtime/scheduler/index.d.ts +0 -22
- package/dist/runtime/scheduler/index.js +0 -20
- package/dist/runtime/scheduler/index.js.map +0 -1
- package/dist/runtime/server/applications.d.ts +0 -91
- package/dist/runtime/server/applications.js +0 -171
- package/dist/runtime/server/applications.js.map +0 -1
- package/dist/runtime/server/config.d.ts +0 -148
- package/dist/runtime/server/config.js +0 -33
- package/dist/runtime/server/config.js.map +0 -1
- package/dist/runtime/server/environment.d.ts +0 -43
- package/dist/runtime/server/environment.js +0 -33
- package/dist/runtime/server/environment.js.map +0 -1
- package/dist/runtime/server/error-policy.d.ts +0 -62
- package/dist/runtime/server/error-policy.js +0 -73
- package/dist/runtime/server/error-policy.js.map +0 -1
- package/dist/runtime/server/hmr-coordinator.d.ts +0 -37
- package/dist/runtime/server/hmr-coordinator.js +0 -94
- package/dist/runtime/server/hmr-coordinator.js.map +0 -1
- package/dist/runtime/server/jobs.d.ts +0 -54
- package/dist/runtime/server/jobs.js +0 -176
- package/dist/runtime/server/jobs.js.map +0 -1
- package/dist/runtime/server/lifecycle.d.ts +0 -85
- package/dist/runtime/server/lifecycle.js +0 -177
- package/dist/runtime/server/lifecycle.js.map +0 -1
- package/dist/runtime/server/managed-worker.d.ts +0 -158
- package/dist/runtime/server/managed-worker.js +0 -420
- package/dist/runtime/server/managed-worker.js.map +0 -1
- package/dist/runtime/server/pool-manager.d.ts +0 -85
- package/dist/runtime/server/pool-manager.js +0 -129
- package/dist/runtime/server/pool-manager.js.map +0 -1
- package/dist/runtime/server/proxy.d.ts +0 -21
- package/dist/runtime/server/proxy.js +0 -76
- package/dist/runtime/server/proxy.js.map +0 -1
- package/dist/runtime/server/server.d.ts +0 -60
- package/dist/runtime/server/server.js +0 -163
- package/dist/runtime/server/server.js.map +0 -1
- package/dist/runtime/server/types.d.ts +0 -31
- package/dist/runtime/server/types.js +0 -2
- package/dist/runtime/server/types.js.map +0 -1
- package/dist/runtime/server/worker-pool.d.ts +0 -121
- package/dist/runtime/server/worker-pool.js +0 -171
- package/dist/runtime/server/worker-pool.js.map +0 -1
- package/dist/runtime/store/index.d.ts +0 -3
- package/dist/runtime/store/index.js +0 -23
- package/dist/runtime/store/index.js.map +0 -1
- package/dist/runtime/subscription/manager.d.ts +0 -49
- package/dist/runtime/subscription/manager.js +0 -170
- package/dist/runtime/subscription/manager.js.map +0 -1
- package/dist/runtime/subscription/redis.d.ts +0 -18
- package/dist/runtime/subscription/redis.js +0 -119
- package/dist/runtime/subscription/redis.js.map +0 -1
- package/dist/runtime/types.d.ts +0 -95
- package/dist/runtime/types.js +0 -2
- package/dist/runtime/types.js.map +0 -1
- package/dist/runtime/workers/application.d.ts +0 -29
- package/dist/runtime/workers/application.js +0 -77
- package/dist/runtime/workers/application.js.map +0 -1
- package/dist/runtime/workers/base.d.ts +0 -14
- package/dist/runtime/workers/base.js +0 -41
- package/dist/runtime/workers/base.js.map +0 -1
- package/dist/runtime/workers/cli.d.ts +0 -1
- package/dist/runtime/workers/cli.js +0 -2
- package/dist/runtime/workers/cli.js.map +0 -1
- package/dist/runtime/workers/job.d.ts +0 -20
- package/dist/runtime/workers/job.js +0 -170
- package/dist/runtime/workers/job.js.map +0 -1
- package/dist/vite/builder.d.ts +0 -5
- package/dist/vite/builder.js +0 -79
- package/dist/vite/builder.js.map +0 -1
- package/dist/vite/config.d.ts +0 -28
- package/dist/vite/config.js +0 -22
- package/dist/vite/config.js.map +0 -1
- package/dist/vite/plugins.d.ts +0 -2
- package/dist/vite/plugins.js +0 -43
- package/dist/vite/plugins.js.map +0 -1
- package/dist/vite/runners/worker.d.ts +0 -3
- package/dist/vite/runners/worker.js +0 -34
- package/dist/vite/runners/worker.js.map +0 -1
- package/dist/vite/server.d.ts +0 -3
- package/dist/vite/server.js +0 -36
- package/dist/vite/server.js.map +0 -1
- package/dist/vite/servers/main.d.ts +0 -8
- package/dist/vite/servers/main.js +0 -24
- package/dist/vite/servers/main.js.map +0 -1
- package/dist/vite/servers/worker.d.ts +0 -13
- package/dist/vite/servers/worker.js +0 -124
- package/dist/vite/servers/worker.js.map +0 -1
- package/src/cli.ts +0 -162
- package/src/codegen.ts +0 -30
- package/src/config.ts +0 -69
- package/src/entrypoints/cli.ts +0 -13
- package/src/entrypoints/main.ts +0 -317
- package/src/entrypoints/thread.ts +0 -223
- package/src/entrypoints/worker.ts +0 -174
- package/src/resolver.ts +0 -7
- package/src/runtime/application/index.ts +0 -1
- package/src/runtime/constants.ts +0 -13
- package/src/runtime/enums.ts +0 -12
- package/src/runtime/hooks.ts +0 -1
- package/src/runtime/index.ts +0 -29
- package/src/runtime/injectables.ts +0 -101
- package/src/runtime/jobs/job.ts +0 -467
- package/src/runtime/jobs/manager.ts +0 -454
- package/src/runtime/jobs/router.ts +0 -967
- package/src/runtime/jobs/runner.ts +0 -583
- package/src/runtime/jobs/step.ts +0 -66
- package/src/runtime/jobs/types.ts +0 -116
- package/src/runtime/metrics/metric.ts +0 -18
- package/src/runtime/metrics/registry.ts +0 -11
- package/src/runtime/metrics/server.ts +0 -69
- package/src/runtime/plugin.ts +0 -2
- package/src/runtime/runtime.ts +0 -103
- package/src/runtime/scheduler/index.ts +0 -39
- package/src/runtime/server/applications.ts +0 -264
- package/src/runtime/server/config.ts +0 -199
- package/src/runtime/server/environment.ts +0 -71
- package/src/runtime/server/error-policy.ts +0 -132
- package/src/runtime/server/hmr-coordinator.ts +0 -116
- package/src/runtime/server/jobs.ts +0 -266
- package/src/runtime/server/lifecycle.ts +0 -234
- package/src/runtime/server/managed-worker.ts +0 -546
- package/src/runtime/server/pool-manager.ts +0 -187
- package/src/runtime/server/proxy.ts +0 -119
- package/src/runtime/server/server.ts +0 -218
- package/src/runtime/server/types.ts +0 -32
- package/src/runtime/server/worker-pool.ts +0 -275
- package/src/runtime/store/index.ts +0 -30
- package/src/runtime/subscription/manager.ts +0 -307
- package/src/runtime/subscription/redis.ts +0 -159
- package/src/runtime/types.ts +0 -84
- package/src/runtime/workers/application.ts +0 -133
- package/src/runtime/workers/base.ts +0 -65
- package/src/runtime/workers/cli.ts +0 -0
- package/src/runtime/workers/job.ts +0 -142
- package/src/vite/builder.ts +0 -94
- package/src/vite/config.ts +0 -45
- package/src/vite/plugins.ts +0 -53
- package/src/vite/runners/worker.ts +0 -55
- package/src/vite/server.ts +0 -55
- package/src/vite/servers/main.ts +0 -41
- package/src/vite/servers/worker.ts +0 -177
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
import EventEmitter from 'node:events'
|
|
2
|
-
|
|
3
|
-
import type { Logger } from '@nmtjs/core'
|
|
4
|
-
|
|
5
|
-
import type { ErrorPolicy } from './error-policy.ts'
|
|
6
|
-
import type {
|
|
7
|
-
ManagedWorkerFactory,
|
|
8
|
-
PoolHealth,
|
|
9
|
-
PoolHealthReport,
|
|
10
|
-
WorkerPool,
|
|
11
|
-
WorkerPoolConfig,
|
|
12
|
-
WorkerPoolFactory,
|
|
13
|
-
} from './worker-pool.ts'
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Overall server health state.
|
|
17
|
-
*/
|
|
18
|
-
export type ServerHealth = 'healthy' | 'degraded' | 'unhealthy'
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Report on overall server health including all pools.
|
|
22
|
-
*/
|
|
23
|
-
export interface ServerHealthReport {
|
|
24
|
-
overall: ServerHealth
|
|
25
|
-
pools: PoolHealthReport[]
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Events emitted by PoolManager.
|
|
30
|
-
*/
|
|
31
|
-
export interface PoolManagerEvents {
|
|
32
|
-
'health-change': [health: ServerHealth]
|
|
33
|
-
'pool-health-change': [poolName: string, health: PoolHealth]
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* PoolManager manages multiple application pools with aggregate health tracking.
|
|
38
|
-
*
|
|
39
|
-
* Features:
|
|
40
|
-
* - Creates and manages WorkerPools for each application/job type
|
|
41
|
-
* - Aggregates health across all pools
|
|
42
|
-
* - Provides server-level health reports
|
|
43
|
-
*
|
|
44
|
-
* Each application gets its own pool for isolated failure domains.
|
|
45
|
-
* For example, if "api" is degraded but "admin" is healthy, they're tracked independently.
|
|
46
|
-
*/
|
|
47
|
-
export class PoolManager extends EventEmitter<PoolManagerEvents> {
|
|
48
|
-
private pools = new Map<string, WorkerPool>()
|
|
49
|
-
private health: ServerHealth = 'healthy'
|
|
50
|
-
private logger: Logger
|
|
51
|
-
|
|
52
|
-
constructor(
|
|
53
|
-
private readonly policy: ErrorPolicy,
|
|
54
|
-
private readonly workerFactory: ManagedWorkerFactory,
|
|
55
|
-
private readonly poolFactory: WorkerPoolFactory,
|
|
56
|
-
logger: Logger,
|
|
57
|
-
) {
|
|
58
|
-
super()
|
|
59
|
-
this.logger = logger.child({ component: 'PoolManager' })
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/** Current overall server health */
|
|
63
|
-
get currentHealth(): ServerHealth {
|
|
64
|
-
return this.health
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/** Number of pools managed */
|
|
68
|
-
get poolCount(): number {
|
|
69
|
-
return this.pools.size
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Create a new pool for an application or job type.
|
|
74
|
-
*
|
|
75
|
-
* @param config - Pool configuration
|
|
76
|
-
* @returns The created WorkerPool
|
|
77
|
-
* @throws If a pool with this name already exists
|
|
78
|
-
*/
|
|
79
|
-
createPool(config: WorkerPoolConfig): WorkerPool {
|
|
80
|
-
if (this.pools.has(config.name)) {
|
|
81
|
-
throw new Error(`Pool for "${config.name}" already exists`)
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const pool = this.poolFactory(
|
|
85
|
-
config,
|
|
86
|
-
this.policy,
|
|
87
|
-
this.workerFactory,
|
|
88
|
-
this.logger,
|
|
89
|
-
)
|
|
90
|
-
|
|
91
|
-
pool.on('health-change', (health) => {
|
|
92
|
-
this.emit('pool-health-change', config.name, health)
|
|
93
|
-
this.updateHealth()
|
|
94
|
-
})
|
|
95
|
-
|
|
96
|
-
this.pools.set(config.name, pool)
|
|
97
|
-
this.logger.debug({ pool: config.name }, 'Pool created')
|
|
98
|
-
|
|
99
|
-
return pool
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Get a pool by name.
|
|
104
|
-
*/
|
|
105
|
-
getPool(name: string): WorkerPool | undefined {
|
|
106
|
-
return this.pools.get(name)
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Get all pools.
|
|
111
|
-
*/
|
|
112
|
-
getAllPools(): Map<string, WorkerPool> {
|
|
113
|
-
return new Map(this.pools)
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Start all pools.
|
|
118
|
-
*/
|
|
119
|
-
async startAll(): Promise<void> {
|
|
120
|
-
this.logger.debug({ count: this.pools.size }, 'Starting all pools')
|
|
121
|
-
await Promise.all([...this.pools.values()].map((p) => p.startAll()))
|
|
122
|
-
this.logger.debug({ count: this.pools.size }, 'All pools started')
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Stop all pools.
|
|
127
|
-
*/
|
|
128
|
-
async stopAll(): Promise<void> {
|
|
129
|
-
this.logger.debug({ count: this.pools.size }, 'Stopping all pools')
|
|
130
|
-
await Promise.all([...this.pools.values()].map((p) => p.stopAll()))
|
|
131
|
-
this.pools.clear()
|
|
132
|
-
this.logger.debug('All pools stopped')
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Get a health report for all pools.
|
|
137
|
-
* This is for internal debugging/logging only.
|
|
138
|
-
* External health checks should use application-level procedures
|
|
139
|
-
* or external monitoring (k8s probes, process monitors).
|
|
140
|
-
*/
|
|
141
|
-
getHealthReport(): ServerHealthReport {
|
|
142
|
-
const poolReports = [...this.pools.values()].map((p) => p.getHealthReport())
|
|
143
|
-
return { overall: this.health, pools: poolReports }
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* Update overall server health based on pool states.
|
|
148
|
-
*/
|
|
149
|
-
private updateHealth(): void {
|
|
150
|
-
const poolHealths = [...this.pools.values()].map((p) => p.currentHealth)
|
|
151
|
-
|
|
152
|
-
// No pools = healthy
|
|
153
|
-
if (poolHealths.length === 0) {
|
|
154
|
-
this.setHealth('healthy')
|
|
155
|
-
return
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
let newHealth: ServerHealth
|
|
159
|
-
if (poolHealths.every((h) => h === 'healthy')) {
|
|
160
|
-
newHealth = 'healthy'
|
|
161
|
-
} else if (
|
|
162
|
-
poolHealths.some((h) => h !== 'unhealthy') &&
|
|
163
|
-
this.policy.allowDegradedMode
|
|
164
|
-
) {
|
|
165
|
-
newHealth = 'degraded'
|
|
166
|
-
} else {
|
|
167
|
-
newHealth = 'unhealthy'
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
this.setHealth(newHealth)
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
* Set the health state, emitting event if changed.
|
|
175
|
-
*/
|
|
176
|
-
private setHealth(newHealth: ServerHealth): void {
|
|
177
|
-
if (newHealth !== this.health) {
|
|
178
|
-
const oldHealth = this.health
|
|
179
|
-
this.health = newHealth
|
|
180
|
-
this.logger.info(
|
|
181
|
-
{ from: oldHealth, to: newHealth },
|
|
182
|
-
'Server health changed',
|
|
183
|
-
)
|
|
184
|
-
this.emit('health-change', newHealth)
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
}
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import type { Logger } from '@nmtjs/core'
|
|
2
|
-
import { Proxy as NeemataProxy } from '@nmtjs/proxy'
|
|
3
|
-
|
|
4
|
-
import type {
|
|
5
|
-
ApplicationProxyUpstream,
|
|
6
|
-
ApplicationServerApplications,
|
|
7
|
-
} from './applications.ts'
|
|
8
|
-
import type { ServerConfig } from './config.ts'
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Transform ApplicationProxyUpstream to the format expected by Rust proxy.
|
|
12
|
-
*/
|
|
13
|
-
function toProxyUpstream(upstream: ApplicationProxyUpstream) {
|
|
14
|
-
const url = new URL(upstream.url)
|
|
15
|
-
const secure = url.protocol === 'https:' || url.protocol === 'wss:'
|
|
16
|
-
const port = url.port ? Number.parseInt(url.port, 10) : secure ? 443 : 80
|
|
17
|
-
|
|
18
|
-
return {
|
|
19
|
-
type: 'port' as const,
|
|
20
|
-
transport: upstream.type,
|
|
21
|
-
secure,
|
|
22
|
-
hostname: url.hostname,
|
|
23
|
-
port,
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export class ApplicationServerProxy {
|
|
28
|
-
proxyServer: NeemataProxy
|
|
29
|
-
|
|
30
|
-
protected readonly onAdd: (
|
|
31
|
-
application: string,
|
|
32
|
-
upstream: ApplicationProxyUpstream,
|
|
33
|
-
) => void
|
|
34
|
-
protected readonly onRemove: (
|
|
35
|
-
application: string,
|
|
36
|
-
upstream: ApplicationProxyUpstream,
|
|
37
|
-
) => void
|
|
38
|
-
|
|
39
|
-
constructor(
|
|
40
|
-
readonly params: {
|
|
41
|
-
logger: Logger
|
|
42
|
-
config: ServerConfig['proxy']
|
|
43
|
-
applications: ApplicationServerApplications
|
|
44
|
-
},
|
|
45
|
-
) {
|
|
46
|
-
const { config } = params
|
|
47
|
-
if (!config) {
|
|
48
|
-
throw new Error('Proxy config is required')
|
|
49
|
-
}
|
|
50
|
-
this.proxyServer = new NeemataProxy({
|
|
51
|
-
listen: `${config.hostname}:${config.port}`,
|
|
52
|
-
tls: config.tls
|
|
53
|
-
? { keyPath: config.tls.key, certPath: config.tls.cert }
|
|
54
|
-
: undefined,
|
|
55
|
-
applications: Object.entries(config.applications)
|
|
56
|
-
.filter(([_, options]) => options !== undefined)
|
|
57
|
-
.map(([app, options]) => ({
|
|
58
|
-
name: app,
|
|
59
|
-
routing: options!.routing,
|
|
60
|
-
sni: options!.sni,
|
|
61
|
-
})),
|
|
62
|
-
})
|
|
63
|
-
|
|
64
|
-
this.onAdd = (application, upstream) => {
|
|
65
|
-
const proxyUpstream = toProxyUpstream(upstream)
|
|
66
|
-
this.params.logger.debug(
|
|
67
|
-
{ application, upstream: proxyUpstream },
|
|
68
|
-
'Adding upstream to proxy',
|
|
69
|
-
)
|
|
70
|
-
this.proxyServer
|
|
71
|
-
.addUpstream(application, proxyUpstream)
|
|
72
|
-
.catch((error) => {
|
|
73
|
-
this.params.logger.warn(
|
|
74
|
-
{ error, application, upstream: proxyUpstream },
|
|
75
|
-
'Failed to add upstream to proxy',
|
|
76
|
-
)
|
|
77
|
-
})
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
this.onRemove = (application, upstream) => {
|
|
81
|
-
const proxyUpstream = toProxyUpstream(upstream)
|
|
82
|
-
this.params.logger.debug(
|
|
83
|
-
{ application, upstream: proxyUpstream },
|
|
84
|
-
'Removing upstream from proxy',
|
|
85
|
-
)
|
|
86
|
-
|
|
87
|
-
this.proxyServer
|
|
88
|
-
.removeUpstream(application, proxyUpstream)
|
|
89
|
-
.catch((error) => {
|
|
90
|
-
this.params.logger.warn(
|
|
91
|
-
{ error, application, upstream: proxyUpstream },
|
|
92
|
-
'Failed to remove upstream from proxy',
|
|
93
|
-
)
|
|
94
|
-
})
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
params.applications.on('add', this.onAdd)
|
|
98
|
-
params.applications.on('remove', this.onRemove)
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
async start() {
|
|
102
|
-
const { config } = this.params
|
|
103
|
-
if (!config) {
|
|
104
|
-
throw new Error('Proxy config is required')
|
|
105
|
-
}
|
|
106
|
-
this.params.logger.info(
|
|
107
|
-
{ hostname: config.hostname, port: config.port, threads: config.threads },
|
|
108
|
-
'Proxy configuration',
|
|
109
|
-
)
|
|
110
|
-
await this.proxyServer.start()
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
async stop() {
|
|
114
|
-
this.params.applications.off('add', this.onAdd)
|
|
115
|
-
this.params.applications.off('remove', this.onRemove)
|
|
116
|
-
|
|
117
|
-
await this.proxyServer.stop()
|
|
118
|
-
}
|
|
119
|
-
}
|
|
@@ -1,218 +0,0 @@
|
|
|
1
|
-
import type { Logger } from '@nmtjs/core'
|
|
2
|
-
import { createLogger } from '@nmtjs/core'
|
|
3
|
-
|
|
4
|
-
import type { MetricsServer } from '../metrics/server.ts'
|
|
5
|
-
import type { Store } from '../types.ts'
|
|
6
|
-
import type { ServerConfig } from './config.ts'
|
|
7
|
-
import type { ErrorPolicy } from './error-policy.ts'
|
|
8
|
-
import type { ManagedWorkerConfig } from './managed-worker.ts'
|
|
9
|
-
import type {
|
|
10
|
-
ApplicationServerRunOptions,
|
|
11
|
-
ApplicationServerWorkerConfig,
|
|
12
|
-
} from './types.ts'
|
|
13
|
-
import type {
|
|
14
|
-
ManagedWorkerFactory,
|
|
15
|
-
WorkerPoolConfig,
|
|
16
|
-
WorkerPoolFactory,
|
|
17
|
-
} from './worker-pool.ts'
|
|
18
|
-
import { createMetricsServer } from '../metrics/server.ts'
|
|
19
|
-
import { createStoreClient } from '../store/index.ts'
|
|
20
|
-
import { ApplicationServerApplications } from './applications.ts'
|
|
21
|
-
import { DevErrorPolicy } from './error-policy.ts'
|
|
22
|
-
import { ApplicationServerJobs } from './jobs.ts'
|
|
23
|
-
import { ManagedWorker } from './managed-worker.ts'
|
|
24
|
-
import { ApplicationServerProxy } from './proxy.ts'
|
|
25
|
-
import { WorkerPool } from './worker-pool.ts'
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Default factory for creating ManagedWorker instances.
|
|
29
|
-
*/
|
|
30
|
-
export const defaultWorkerFactory: ManagedWorkerFactory = (
|
|
31
|
-
config: ManagedWorkerConfig,
|
|
32
|
-
policy: ErrorPolicy,
|
|
33
|
-
logger: Logger,
|
|
34
|
-
) => new ManagedWorker(config, policy, logger)
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Default factory for creating WorkerPool instances.
|
|
38
|
-
*/
|
|
39
|
-
export const defaultPoolFactory: WorkerPoolFactory = (
|
|
40
|
-
config: WorkerPoolConfig,
|
|
41
|
-
policy: ErrorPolicy,
|
|
42
|
-
workerFactory: ManagedWorkerFactory,
|
|
43
|
-
logger: Logger,
|
|
44
|
-
) => new WorkerPool(config, policy, workerFactory, logger)
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* ApplicationServer is the main server orchestrator.
|
|
48
|
-
*
|
|
49
|
-
* It manages:
|
|
50
|
-
* - Application worker pools
|
|
51
|
-
* - Job runner pools
|
|
52
|
-
* - Reverse proxy
|
|
53
|
-
* - Store connections
|
|
54
|
-
*
|
|
55
|
-
* The server integrates with ErrorPolicy for proper error handling
|
|
56
|
-
* and uses ManagedWorker for worker lifecycle management.
|
|
57
|
-
*/
|
|
58
|
-
export class ApplicationServer {
|
|
59
|
-
logger: Logger
|
|
60
|
-
|
|
61
|
-
applications?: ApplicationServerApplications
|
|
62
|
-
jobRunners?: ApplicationServerJobs
|
|
63
|
-
|
|
64
|
-
proxy?: ApplicationServerProxy
|
|
65
|
-
store?: Store
|
|
66
|
-
metrics?: MetricsServer
|
|
67
|
-
|
|
68
|
-
constructor(
|
|
69
|
-
readonly config: ServerConfig,
|
|
70
|
-
readonly applicationsConfig: Record<
|
|
71
|
-
string,
|
|
72
|
-
{ type: 'neemata' | 'custom'; specifier: string }
|
|
73
|
-
>,
|
|
74
|
-
readonly workerConfig: ApplicationServerWorkerConfig,
|
|
75
|
-
readonly runOptions: ApplicationServerRunOptions = {
|
|
76
|
-
applications: Object.keys(config.applications),
|
|
77
|
-
scheduler: false,
|
|
78
|
-
jobs: Boolean(config.jobs?.jobs.size),
|
|
79
|
-
},
|
|
80
|
-
readonly errorPolicy: ErrorPolicy = DevErrorPolicy,
|
|
81
|
-
readonly workerFactory: ManagedWorkerFactory = defaultWorkerFactory,
|
|
82
|
-
readonly poolFactory: WorkerPoolFactory = defaultPoolFactory,
|
|
83
|
-
) {
|
|
84
|
-
this.logger = createLogger(config.logger, 'Server')
|
|
85
|
-
this.logger.trace(
|
|
86
|
-
{ applications: applicationsConfig, workerConfig, runOptions },
|
|
87
|
-
'ApplicationServer initialized',
|
|
88
|
-
)
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
async start() {
|
|
92
|
-
const { config, logger, errorPolicy, workerFactory, poolFactory } = this
|
|
93
|
-
logger.info('Starting application server...')
|
|
94
|
-
|
|
95
|
-
if (config.metrics) {
|
|
96
|
-
logger.info('Starting metrics server...')
|
|
97
|
-
this.metrics = await createMetricsServer(this.logger, config.metrics)
|
|
98
|
-
await this.metrics.start()
|
|
99
|
-
logger.debug('Metrics server started')
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
if (config.store) {
|
|
103
|
-
logger.info('Connecting to store...')
|
|
104
|
-
this.store = await createStoreClient(config.store)
|
|
105
|
-
await this.store.connect()
|
|
106
|
-
logger.debug('Store connected')
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
this.applications = new ApplicationServerApplications({
|
|
110
|
-
logger: this.logger,
|
|
111
|
-
workerConfig: this.workerConfig,
|
|
112
|
-
serverConfig: this.config,
|
|
113
|
-
applicationsConfig: this.applicationsConfig,
|
|
114
|
-
applications: this.runOptions.applications,
|
|
115
|
-
errorPolicy,
|
|
116
|
-
workerFactory,
|
|
117
|
-
poolFactory,
|
|
118
|
-
})
|
|
119
|
-
|
|
120
|
-
if (this.runOptions.jobs) {
|
|
121
|
-
if (!this.store) {
|
|
122
|
-
throw new Error(
|
|
123
|
-
'Jobs feature requires a store configuration. ' +
|
|
124
|
-
'Please configure `store` in your server config or disable jobs.',
|
|
125
|
-
)
|
|
126
|
-
}
|
|
127
|
-
this.jobRunners = new ApplicationServerJobs({
|
|
128
|
-
logger: this.logger,
|
|
129
|
-
workerConfig: this.workerConfig,
|
|
130
|
-
serverConfig: this.config,
|
|
131
|
-
store: this.store,
|
|
132
|
-
errorPolicy,
|
|
133
|
-
workerFactory,
|
|
134
|
-
poolFactory,
|
|
135
|
-
})
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
if (this.config.proxy) {
|
|
139
|
-
this.logger.debug(
|
|
140
|
-
'Proxy configuration detected, creating a proxy server...',
|
|
141
|
-
)
|
|
142
|
-
this.proxy = new ApplicationServerProxy({
|
|
143
|
-
logger: this.logger,
|
|
144
|
-
config: this.config.proxy,
|
|
145
|
-
applications: this.applications,
|
|
146
|
-
})
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
await this.applications.start()
|
|
150
|
-
|
|
151
|
-
if (this.runOptions.jobs) {
|
|
152
|
-
await this.jobRunners?.start()
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
if (this.runOptions.scheduler && config.jobs?.scheduler) {
|
|
156
|
-
throw new Error(
|
|
157
|
-
'JobsScheduler is currently a work in progress and not available. ' +
|
|
158
|
-
'Scheduled jobs will be supported in a future release.',
|
|
159
|
-
)
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
if (this.proxy) {
|
|
163
|
-
logger.info('Starting proxy server...')
|
|
164
|
-
await this.proxy.start()
|
|
165
|
-
logger.debug('Proxy server started')
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
logger.info('Application server started')
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
async stop() {
|
|
172
|
-
this.logger.info('Stopping application server...')
|
|
173
|
-
|
|
174
|
-
// Stop proxy + stop accepting new jobs first
|
|
175
|
-
if (this.proxy) {
|
|
176
|
-
this.logger.info('Stopping proxy server...')
|
|
177
|
-
await this.proxy.stop()
|
|
178
|
-
this.logger.debug('Proxy server stopped')
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
if (this.jobRunners) {
|
|
182
|
-
this.logger.info('Stopping job runners...')
|
|
183
|
-
await this.jobRunners.stop()
|
|
184
|
-
this.logger.debug('Job runners stopped')
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// Stop applications
|
|
188
|
-
if (this.applications) {
|
|
189
|
-
this.logger.info('Stopping applications...')
|
|
190
|
-
await this.applications.stop()
|
|
191
|
-
this.logger.debug('Applications stopped')
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// Close store connection
|
|
195
|
-
if (this.store) {
|
|
196
|
-
this.logger.info('Closing store...')
|
|
197
|
-
this.store.disconnect(false)
|
|
198
|
-
this.logger.debug('Store disconnected')
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
if (this.metrics) {
|
|
202
|
-
this.logger.info('Stopping metrics server...')
|
|
203
|
-
await this.metrics.stop()
|
|
204
|
-
this.logger.debug('Metrics server stopped')
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
this.logger.info('Application server gracefully stopped')
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
* Restart failed workers across all pools.
|
|
212
|
-
* Called when HMR update comes in and workers may have failed.
|
|
213
|
-
* @returns Number of workers that were restarted
|
|
214
|
-
*/
|
|
215
|
-
async restartFailedWorkers(): Promise<number> {
|
|
216
|
-
return (await this.applications?.restartFailedWorkers()) ?? 0
|
|
217
|
-
}
|
|
218
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import type EventEmitter from 'node:events'
|
|
2
|
-
import type { MessagePort, Worker } from 'node:worker_threads'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Run options for the ApplicationServer.
|
|
6
|
-
*/
|
|
7
|
-
export type ApplicationServerRunOptions = {
|
|
8
|
-
applications: string[]
|
|
9
|
-
scheduler: boolean
|
|
10
|
-
jobs: boolean
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export type WorkerRegistration = { worker: Worker; vitePort?: MessagePort }
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Minimal event map required for worker management.
|
|
17
|
-
* The events emitter may have additional events (like 'hmr-update').
|
|
18
|
-
*/
|
|
19
|
-
export type WorkerEventMap = {
|
|
20
|
-
worker: [registration: WorkerRegistration]
|
|
21
|
-
[key: string]: any[]
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Configuration for worker management in ApplicationServer.
|
|
26
|
-
*/
|
|
27
|
-
export type ApplicationServerWorkerConfig = {
|
|
28
|
-
path: string
|
|
29
|
-
workerData?: any
|
|
30
|
-
worker?: (registration: WorkerRegistration) => any
|
|
31
|
-
events?: EventEmitter<WorkerEventMap>
|
|
32
|
-
}
|