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.
Files changed (224) hide show
  1. package/LICENSE.md +1 -1
  2. package/README.md +41 -1
  3. package/dist/index.d.ts +22 -161
  4. package/dist/index.js +24 -53
  5. package/dist/index.js.map +1 -1
  6. package/package.json +11 -63
  7. package/src/index.ts +71 -91
  8. package/bin/cli.js +0 -2
  9. package/dist/cli.d.ts +0 -1
  10. package/dist/cli.js +0 -137
  11. package/dist/cli.js.map +0 -1
  12. package/dist/codegen.d.ts +0 -5
  13. package/dist/codegen.js +0 -18
  14. package/dist/codegen.js.map +0 -1
  15. package/dist/config.d.ts +0 -47
  16. package/dist/config.js +0 -16
  17. package/dist/config.js.map +0 -1
  18. package/dist/entrypoints/cli.d.ts +0 -1
  19. package/dist/entrypoints/cli.js +0 -12
  20. package/dist/entrypoints/cli.js.map +0 -1
  21. package/dist/entrypoints/main.d.ts +0 -5
  22. package/dist/entrypoints/main.js +0 -248
  23. package/dist/entrypoints/main.js.map +0 -1
  24. package/dist/entrypoints/thread.d.ts +0 -16
  25. package/dist/entrypoints/thread.js +0 -182
  26. package/dist/entrypoints/thread.js.map +0 -1
  27. package/dist/entrypoints/worker.d.ts +0 -9
  28. package/dist/entrypoints/worker.js +0 -143
  29. package/dist/entrypoints/worker.js.map +0 -1
  30. package/dist/resolver.d.ts +0 -2
  31. package/dist/resolver.js +0 -7
  32. package/dist/resolver.js.map +0 -1
  33. package/dist/runtime/application/index.d.ts +0 -1
  34. package/dist/runtime/application/index.js +0 -2
  35. package/dist/runtime/application/index.js.map +0 -1
  36. package/dist/runtime/constants.d.ts +0 -8
  37. package/dist/runtime/constants.js +0 -5
  38. package/dist/runtime/constants.js.map +0 -1
  39. package/dist/runtime/enums.d.ts +0 -10
  40. package/dist/runtime/enums.js +0 -13
  41. package/dist/runtime/enums.js.map +0 -1
  42. package/dist/runtime/hooks.d.ts +0 -1
  43. package/dist/runtime/hooks.js +0 -2
  44. package/dist/runtime/hooks.js.map +0 -1
  45. package/dist/runtime/index.d.ts +0 -28
  46. package/dist/runtime/index.js +0 -29
  47. package/dist/runtime/index.js.map +0 -1
  48. package/dist/runtime/injectables.d.ts +0 -69
  49. package/dist/runtime/injectables.js +0 -40
  50. package/dist/runtime/injectables.js.map +0 -1
  51. package/dist/runtime/jobs/job.d.ts +0 -146
  52. package/dist/runtime/jobs/job.js +0 -89
  53. package/dist/runtime/jobs/job.js.map +0 -1
  54. package/dist/runtime/jobs/manager.d.ts +0 -131
  55. package/dist/runtime/jobs/manager.js +0 -309
  56. package/dist/runtime/jobs/manager.js.map +0 -1
  57. package/dist/runtime/jobs/router.d.ts +0 -296
  58. package/dist/runtime/jobs/router.js +0 -458
  59. package/dist/runtime/jobs/router.js.map +0 -1
  60. package/dist/runtime/jobs/runner.d.ts +0 -103
  61. package/dist/runtime/jobs/runner.js +0 -425
  62. package/dist/runtime/jobs/runner.js.map +0 -1
  63. package/dist/runtime/jobs/step.d.ts +0 -26
  64. package/dist/runtime/jobs/step.js +0 -18
  65. package/dist/runtime/jobs/step.js.map +0 -1
  66. package/dist/runtime/jobs/types.d.ts +0 -86
  67. package/dist/runtime/jobs/types.js +0 -5
  68. package/dist/runtime/jobs/types.js.map +0 -1
  69. package/dist/runtime/metrics/metric.d.ts +0 -8
  70. package/dist/runtime/metrics/metric.js +0 -11
  71. package/dist/runtime/metrics/metric.js.map +0 -1
  72. package/dist/runtime/metrics/registry.d.ts +0 -3
  73. package/dist/runtime/metrics/registry.js +0 -5
  74. package/dist/runtime/metrics/registry.js.map +0 -1
  75. package/dist/runtime/metrics/server.d.ts +0 -7
  76. package/dist/runtime/metrics/server.js +0 -53
  77. package/dist/runtime/metrics/server.js.map +0 -1
  78. package/dist/runtime/plugin.d.ts +0 -2
  79. package/dist/runtime/plugin.js +0 -2
  80. package/dist/runtime/plugin.js.map +0 -1
  81. package/dist/runtime/runtime.d.ts +0 -27
  82. package/dist/runtime/runtime.js +0 -77
  83. package/dist/runtime/runtime.js.map +0 -1
  84. package/dist/runtime/scheduler/index.d.ts +0 -22
  85. package/dist/runtime/scheduler/index.js +0 -20
  86. package/dist/runtime/scheduler/index.js.map +0 -1
  87. package/dist/runtime/server/applications.d.ts +0 -91
  88. package/dist/runtime/server/applications.js +0 -171
  89. package/dist/runtime/server/applications.js.map +0 -1
  90. package/dist/runtime/server/config.d.ts +0 -148
  91. package/dist/runtime/server/config.js +0 -33
  92. package/dist/runtime/server/config.js.map +0 -1
  93. package/dist/runtime/server/environment.d.ts +0 -43
  94. package/dist/runtime/server/environment.js +0 -33
  95. package/dist/runtime/server/environment.js.map +0 -1
  96. package/dist/runtime/server/error-policy.d.ts +0 -62
  97. package/dist/runtime/server/error-policy.js +0 -73
  98. package/dist/runtime/server/error-policy.js.map +0 -1
  99. package/dist/runtime/server/hmr-coordinator.d.ts +0 -37
  100. package/dist/runtime/server/hmr-coordinator.js +0 -94
  101. package/dist/runtime/server/hmr-coordinator.js.map +0 -1
  102. package/dist/runtime/server/jobs.d.ts +0 -54
  103. package/dist/runtime/server/jobs.js +0 -176
  104. package/dist/runtime/server/jobs.js.map +0 -1
  105. package/dist/runtime/server/lifecycle.d.ts +0 -85
  106. package/dist/runtime/server/lifecycle.js +0 -177
  107. package/dist/runtime/server/lifecycle.js.map +0 -1
  108. package/dist/runtime/server/managed-worker.d.ts +0 -158
  109. package/dist/runtime/server/managed-worker.js +0 -420
  110. package/dist/runtime/server/managed-worker.js.map +0 -1
  111. package/dist/runtime/server/pool-manager.d.ts +0 -85
  112. package/dist/runtime/server/pool-manager.js +0 -129
  113. package/dist/runtime/server/pool-manager.js.map +0 -1
  114. package/dist/runtime/server/proxy.d.ts +0 -21
  115. package/dist/runtime/server/proxy.js +0 -76
  116. package/dist/runtime/server/proxy.js.map +0 -1
  117. package/dist/runtime/server/server.d.ts +0 -60
  118. package/dist/runtime/server/server.js +0 -163
  119. package/dist/runtime/server/server.js.map +0 -1
  120. package/dist/runtime/server/types.d.ts +0 -31
  121. package/dist/runtime/server/types.js +0 -2
  122. package/dist/runtime/server/types.js.map +0 -1
  123. package/dist/runtime/server/worker-pool.d.ts +0 -121
  124. package/dist/runtime/server/worker-pool.js +0 -171
  125. package/dist/runtime/server/worker-pool.js.map +0 -1
  126. package/dist/runtime/store/index.d.ts +0 -3
  127. package/dist/runtime/store/index.js +0 -23
  128. package/dist/runtime/store/index.js.map +0 -1
  129. package/dist/runtime/subscription/manager.d.ts +0 -49
  130. package/dist/runtime/subscription/manager.js +0 -170
  131. package/dist/runtime/subscription/manager.js.map +0 -1
  132. package/dist/runtime/subscription/redis.d.ts +0 -18
  133. package/dist/runtime/subscription/redis.js +0 -119
  134. package/dist/runtime/subscription/redis.js.map +0 -1
  135. package/dist/runtime/types.d.ts +0 -95
  136. package/dist/runtime/types.js +0 -2
  137. package/dist/runtime/types.js.map +0 -1
  138. package/dist/runtime/workers/application.d.ts +0 -29
  139. package/dist/runtime/workers/application.js +0 -77
  140. package/dist/runtime/workers/application.js.map +0 -1
  141. package/dist/runtime/workers/base.d.ts +0 -14
  142. package/dist/runtime/workers/base.js +0 -41
  143. package/dist/runtime/workers/base.js.map +0 -1
  144. package/dist/runtime/workers/cli.d.ts +0 -1
  145. package/dist/runtime/workers/cli.js +0 -2
  146. package/dist/runtime/workers/cli.js.map +0 -1
  147. package/dist/runtime/workers/job.d.ts +0 -20
  148. package/dist/runtime/workers/job.js +0 -170
  149. package/dist/runtime/workers/job.js.map +0 -1
  150. package/dist/vite/builder.d.ts +0 -5
  151. package/dist/vite/builder.js +0 -79
  152. package/dist/vite/builder.js.map +0 -1
  153. package/dist/vite/config.d.ts +0 -28
  154. package/dist/vite/config.js +0 -22
  155. package/dist/vite/config.js.map +0 -1
  156. package/dist/vite/plugins.d.ts +0 -2
  157. package/dist/vite/plugins.js +0 -43
  158. package/dist/vite/plugins.js.map +0 -1
  159. package/dist/vite/runners/worker.d.ts +0 -3
  160. package/dist/vite/runners/worker.js +0 -34
  161. package/dist/vite/runners/worker.js.map +0 -1
  162. package/dist/vite/server.d.ts +0 -3
  163. package/dist/vite/server.js +0 -36
  164. package/dist/vite/server.js.map +0 -1
  165. package/dist/vite/servers/main.d.ts +0 -8
  166. package/dist/vite/servers/main.js +0 -24
  167. package/dist/vite/servers/main.js.map +0 -1
  168. package/dist/vite/servers/worker.d.ts +0 -13
  169. package/dist/vite/servers/worker.js +0 -124
  170. package/dist/vite/servers/worker.js.map +0 -1
  171. package/src/cli.ts +0 -162
  172. package/src/codegen.ts +0 -30
  173. package/src/config.ts +0 -69
  174. package/src/entrypoints/cli.ts +0 -13
  175. package/src/entrypoints/main.ts +0 -317
  176. package/src/entrypoints/thread.ts +0 -223
  177. package/src/entrypoints/worker.ts +0 -174
  178. package/src/resolver.ts +0 -7
  179. package/src/runtime/application/index.ts +0 -1
  180. package/src/runtime/constants.ts +0 -13
  181. package/src/runtime/enums.ts +0 -12
  182. package/src/runtime/hooks.ts +0 -1
  183. package/src/runtime/index.ts +0 -29
  184. package/src/runtime/injectables.ts +0 -101
  185. package/src/runtime/jobs/job.ts +0 -467
  186. package/src/runtime/jobs/manager.ts +0 -454
  187. package/src/runtime/jobs/router.ts +0 -967
  188. package/src/runtime/jobs/runner.ts +0 -583
  189. package/src/runtime/jobs/step.ts +0 -66
  190. package/src/runtime/jobs/types.ts +0 -116
  191. package/src/runtime/metrics/metric.ts +0 -18
  192. package/src/runtime/metrics/registry.ts +0 -11
  193. package/src/runtime/metrics/server.ts +0 -69
  194. package/src/runtime/plugin.ts +0 -2
  195. package/src/runtime/runtime.ts +0 -103
  196. package/src/runtime/scheduler/index.ts +0 -39
  197. package/src/runtime/server/applications.ts +0 -264
  198. package/src/runtime/server/config.ts +0 -199
  199. package/src/runtime/server/environment.ts +0 -71
  200. package/src/runtime/server/error-policy.ts +0 -132
  201. package/src/runtime/server/hmr-coordinator.ts +0 -116
  202. package/src/runtime/server/jobs.ts +0 -266
  203. package/src/runtime/server/lifecycle.ts +0 -234
  204. package/src/runtime/server/managed-worker.ts +0 -546
  205. package/src/runtime/server/pool-manager.ts +0 -187
  206. package/src/runtime/server/proxy.ts +0 -119
  207. package/src/runtime/server/server.ts +0 -218
  208. package/src/runtime/server/types.ts +0 -32
  209. package/src/runtime/server/worker-pool.ts +0 -275
  210. package/src/runtime/store/index.ts +0 -30
  211. package/src/runtime/subscription/manager.ts +0 -307
  212. package/src/runtime/subscription/redis.ts +0 -159
  213. package/src/runtime/types.ts +0 -84
  214. package/src/runtime/workers/application.ts +0 -133
  215. package/src/runtime/workers/base.ts +0 -65
  216. package/src/runtime/workers/cli.ts +0 -0
  217. package/src/runtime/workers/job.ts +0 -142
  218. package/src/vite/builder.ts +0 -94
  219. package/src/vite/config.ts +0 -45
  220. package/src/vite/plugins.ts +0 -53
  221. package/src/vite/runners/worker.ts +0 -55
  222. package/src/vite/server.ts +0 -55
  223. package/src/vite/servers/main.ts +0 -41
  224. 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
- }