@gravito/launchpad 1.2.2 → 1.3.1
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/CHANGELOG.md +49 -0
- package/README.md +51 -43
- package/README.zh-TW.md +110 -0
- package/dist/index.d.mts +248 -5
- package/dist/index.d.ts +248 -5
- package/dist/index.js +393 -20
- package/dist/index.mjs +381 -20
- package/package.json +7 -5
- package/scripts/check-coverage.ts +64 -0
- package/src/Application/MissionQueue.ts +143 -0
- package/src/Application/PoolManager.ts +169 -17
- package/src/Application/RefurbishUnit.ts +24 -12
- package/src/Domain/Events.ts +46 -0
- package/src/Domain/Interfaces.ts +82 -0
- package/src/Domain/Rocket.ts +18 -0
- package/src/Infrastructure/Docker/DockerAdapter.ts +79 -2
- package/src/index.ts +3 -0
- package/tests/Deployment.test.ts +3 -1
- package/tests/pool-manager.test.ts +3 -1
- package/tests/resource-limits.test.ts +241 -0
- package/tsconfig.json +14 -26
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as _gravito_ripple from '@gravito/ripple';
|
|
2
2
|
import { OrbitRipple } from '@gravito/ripple';
|
|
3
3
|
import { GravitoOrbit, PlanetCore } from '@gravito/core';
|
|
4
|
-
import { ValueObject, AggregateRoot } from '@gravito/enterprise';
|
|
4
|
+
import { ValueObject, AggregateRoot, DomainEvent } from '@gravito/enterprise';
|
|
5
5
|
|
|
6
6
|
interface MissionProps {
|
|
7
7
|
id: string;
|
|
@@ -81,6 +81,17 @@ declare class Rocket extends AggregateRoot<string> {
|
|
|
81
81
|
* 火箭除役 (移除容器)
|
|
82
82
|
*/
|
|
83
83
|
decommission(): void;
|
|
84
|
+
/**
|
|
85
|
+
* 替換底層容器(僅在 REFURBISHING 狀態時允許)
|
|
86
|
+
* 用於 destroy-recreate 策略
|
|
87
|
+
*
|
|
88
|
+
* @param newContainerId - 新容器 ID
|
|
89
|
+
* @throws {Error} 當火箭不在 REFURBISHING 狀態時
|
|
90
|
+
*
|
|
91
|
+
* @public
|
|
92
|
+
* @since 1.3.0
|
|
93
|
+
*/
|
|
94
|
+
replaceContainer(newContainerId: string): void;
|
|
84
95
|
toJSON(): {
|
|
85
96
|
id: string;
|
|
86
97
|
containerId: string;
|
|
@@ -148,6 +159,13 @@ interface IRouterAdapter {
|
|
|
148
159
|
unregister(domain: string): void;
|
|
149
160
|
start(port: number): void;
|
|
150
161
|
}
|
|
162
|
+
/**
|
|
163
|
+
* 負責與 GitHub API 互動的轉接器
|
|
164
|
+
*/
|
|
165
|
+
interface IGitHubAdapter {
|
|
166
|
+
verifySignature(payload: string, signature: string, secret: string): boolean;
|
|
167
|
+
postComment(repoOwner: string, repoName: string, prNumber: number, comment: string): Promise<void>;
|
|
168
|
+
}
|
|
151
169
|
/**
|
|
152
170
|
* 負責持久化火箭狀態的儲存庫介面
|
|
153
171
|
*/
|
|
@@ -158,6 +176,58 @@ interface IRocketRepository {
|
|
|
158
176
|
findAll(): Promise<Rocket[]>;
|
|
159
177
|
delete(id: string): Promise<void>;
|
|
160
178
|
}
|
|
179
|
+
/**
|
|
180
|
+
* Pool 管理配置
|
|
181
|
+
*
|
|
182
|
+
* @public
|
|
183
|
+
* @since 1.3.0
|
|
184
|
+
*/
|
|
185
|
+
interface PoolConfig {
|
|
186
|
+
/** 最大 Rocket 數量(硬限制) */
|
|
187
|
+
maxRockets: number;
|
|
188
|
+
/** 初始預熱數量 */
|
|
189
|
+
warmupCount: number;
|
|
190
|
+
/** 最大等待隊列長度 */
|
|
191
|
+
maxQueueSize: number;
|
|
192
|
+
/** 隊列超時時間(毫秒) */
|
|
193
|
+
queueTimeoutMs: number;
|
|
194
|
+
/** 資源不足時的策略:'queue' | 'reject' | 'dynamic' */
|
|
195
|
+
exhaustionStrategy: 'queue' | 'reject' | 'dynamic';
|
|
196
|
+
/** 動態建立的限制(僅當 exhaustionStrategy 為 'dynamic' 時) */
|
|
197
|
+
dynamicLimit?: number;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Pool 管理預設配置
|
|
201
|
+
*
|
|
202
|
+
* @public
|
|
203
|
+
* @since 1.3.0
|
|
204
|
+
*/
|
|
205
|
+
declare const DEFAULT_POOL_CONFIG: PoolConfig;
|
|
206
|
+
/**
|
|
207
|
+
* 容器清理策略配置
|
|
208
|
+
*
|
|
209
|
+
* @public
|
|
210
|
+
* @since 1.3.0
|
|
211
|
+
*/
|
|
212
|
+
interface RefurbishConfig {
|
|
213
|
+
/** 清理策略:'deep-clean' | 'destroy-recreate' */
|
|
214
|
+
strategy: 'deep-clean' | 'destroy-recreate';
|
|
215
|
+
/** 深度清理命令(僅 deep-clean 策略) */
|
|
216
|
+
cleanupCommands?: string[];
|
|
217
|
+
/** 清理超時(毫秒) */
|
|
218
|
+
cleanupTimeoutMs: number;
|
|
219
|
+
/** 清理失敗時的處理:'decommission' | 'retry' */
|
|
220
|
+
failureAction: 'decommission' | 'retry';
|
|
221
|
+
/** 最大重試次數(僅 retry 模式) */
|
|
222
|
+
maxRetries: number;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* 容器清理預設配置
|
|
226
|
+
*
|
|
227
|
+
* @public
|
|
228
|
+
* @since 1.3.0
|
|
229
|
+
*/
|
|
230
|
+
declare const DEFAULT_REFURBISH_CONFIG: RefurbishConfig;
|
|
161
231
|
|
|
162
232
|
/**
|
|
163
233
|
* PayloadInjector is responsible for deploying application code into Rocket containers.
|
|
@@ -187,7 +257,8 @@ declare class PayloadInjector {
|
|
|
187
257
|
*/
|
|
188
258
|
declare class RefurbishUnit {
|
|
189
259
|
private docker;
|
|
190
|
-
|
|
260
|
+
private readonly config;
|
|
261
|
+
constructor(docker: IDockerAdapter, config?: Partial<RefurbishConfig>);
|
|
191
262
|
/**
|
|
192
263
|
* 執行火箭翻新邏輯
|
|
193
264
|
*/
|
|
@@ -208,19 +279,49 @@ declare class PoolManager {
|
|
|
208
279
|
private rocketRepository;
|
|
209
280
|
private refurbishUnit?;
|
|
210
281
|
private router?;
|
|
211
|
-
|
|
282
|
+
private readonly config;
|
|
283
|
+
private readonly missionQueue;
|
|
284
|
+
private dynamicRocketCount;
|
|
285
|
+
constructor(dockerAdapter: IDockerAdapter, rocketRepository: IRocketRepository, refurbishUnit?: RefurbishUnit | undefined, router?: IRouterAdapter | undefined, config?: Partial<PoolConfig>);
|
|
286
|
+
/**
|
|
287
|
+
* 取得當前 Pool 狀態
|
|
288
|
+
*/
|
|
289
|
+
getPoolStatus(): Promise<{
|
|
290
|
+
total: number;
|
|
291
|
+
idle: number;
|
|
292
|
+
orbiting: number;
|
|
293
|
+
refurbishing: number;
|
|
294
|
+
decommissioned: number;
|
|
295
|
+
dynamicCount: number;
|
|
296
|
+
maxRockets: number;
|
|
297
|
+
queueLength: number;
|
|
298
|
+
}>;
|
|
212
299
|
/**
|
|
213
300
|
* 初始化發射場:預先準備指定數量的火箭
|
|
214
301
|
*/
|
|
215
|
-
warmup(count
|
|
302
|
+
warmup(count?: number): Promise<void>;
|
|
216
303
|
/**
|
|
217
304
|
* 獲取一架可用的火箭並分配任務
|
|
305
|
+
*
|
|
306
|
+
* @throws {PoolExhaustedException} 當 Pool 耗盡且無法處理請求時
|
|
218
307
|
*/
|
|
219
308
|
assignMission(mission: Mission): Promise<Rocket>;
|
|
220
309
|
/**
|
|
221
310
|
* 回收指定任務的火箭
|
|
222
311
|
*/
|
|
223
312
|
recycle(missionId: string): Promise<void>;
|
|
313
|
+
/**
|
|
314
|
+
* 處理等待隊列中的任務
|
|
315
|
+
*/
|
|
316
|
+
private processQueue;
|
|
317
|
+
/**
|
|
318
|
+
* 取得隊列統計資訊
|
|
319
|
+
*/
|
|
320
|
+
getQueueStats(): {
|
|
321
|
+
length: number;
|
|
322
|
+
maxSize: number;
|
|
323
|
+
oldestWaitMs: number | null;
|
|
324
|
+
};
|
|
224
325
|
}
|
|
225
326
|
|
|
226
327
|
/**
|
|
@@ -241,6 +342,148 @@ declare class MissionControl {
|
|
|
241
342
|
launch(mission: Mission, onTelemetry: (type: string, data: any) => void): Promise<string>;
|
|
242
343
|
}
|
|
243
344
|
|
|
345
|
+
interface QueuedMission {
|
|
346
|
+
mission: Mission;
|
|
347
|
+
resolve: (rocket: Rocket) => void;
|
|
348
|
+
reject: (error: Error) => void;
|
|
349
|
+
enqueuedAt: number;
|
|
350
|
+
timeoutId: ReturnType<typeof setTimeout>;
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* MissionQueue manages pending mission requests when pool is exhausted.
|
|
354
|
+
*
|
|
355
|
+
* Implements FIFO queue with timeout handling and backpressure support.
|
|
356
|
+
*
|
|
357
|
+
* @public
|
|
358
|
+
* @since 1.3.0
|
|
359
|
+
*/
|
|
360
|
+
declare class MissionQueue {
|
|
361
|
+
private queue;
|
|
362
|
+
private readonly maxSize;
|
|
363
|
+
private readonly timeoutMs;
|
|
364
|
+
constructor(maxSize?: number, timeoutMs?: number);
|
|
365
|
+
get length(): number;
|
|
366
|
+
get isFull(): boolean;
|
|
367
|
+
/**
|
|
368
|
+
* 將任務加入隊列,返回 Promise 等待分配
|
|
369
|
+
*/
|
|
370
|
+
enqueue(mission: Mission): Promise<Rocket>;
|
|
371
|
+
/**
|
|
372
|
+
* 取出下一個等待的任務
|
|
373
|
+
*/
|
|
374
|
+
dequeue(): QueuedMission | null;
|
|
375
|
+
/**
|
|
376
|
+
* 從隊列中移除指定任務
|
|
377
|
+
*/
|
|
378
|
+
private removeFromQueue;
|
|
379
|
+
/**
|
|
380
|
+
* 清空隊列並拒絕所有等待的任務
|
|
381
|
+
*/
|
|
382
|
+
clear(reason: string): void;
|
|
383
|
+
/**
|
|
384
|
+
* 取得隊列統計資訊
|
|
385
|
+
*/
|
|
386
|
+
getStats(): {
|
|
387
|
+
length: number;
|
|
388
|
+
maxSize: number;
|
|
389
|
+
oldestWaitMs: number | null;
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Pool 資源耗盡異常
|
|
394
|
+
*
|
|
395
|
+
* @public
|
|
396
|
+
* @since 1.3.0
|
|
397
|
+
*/
|
|
398
|
+
declare class PoolExhaustedException extends Error {
|
|
399
|
+
constructor(message: string);
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* 隊列等待超時異常
|
|
403
|
+
*
|
|
404
|
+
* @public
|
|
405
|
+
* @since 1.3.0
|
|
406
|
+
*/
|
|
407
|
+
declare class QueueTimeoutException extends Error {
|
|
408
|
+
constructor(message: string);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* Event emitted when a mission is assigned to a rocket.
|
|
413
|
+
*
|
|
414
|
+
* @public
|
|
415
|
+
* @since 3.0.0
|
|
416
|
+
*/
|
|
417
|
+
declare class MissionAssigned extends DomainEvent {
|
|
418
|
+
readonly rocketId: string;
|
|
419
|
+
readonly missionId: string;
|
|
420
|
+
constructor(rocketId: string, missionId: string);
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* Event emitted when a rocket starts its mission (application started).
|
|
424
|
+
*
|
|
425
|
+
* @public
|
|
426
|
+
* @since 3.0.0
|
|
427
|
+
*/
|
|
428
|
+
declare class RocketIgnited extends DomainEvent {
|
|
429
|
+
readonly rocketId: string;
|
|
430
|
+
constructor(rocketId: string);
|
|
431
|
+
}
|
|
432
|
+
/**
|
|
433
|
+
* Event emitted when a rocket mission is completed or terminated.
|
|
434
|
+
*
|
|
435
|
+
* @public
|
|
436
|
+
* @since 3.0.0
|
|
437
|
+
*/
|
|
438
|
+
declare class RocketSplashedDown extends DomainEvent {
|
|
439
|
+
readonly rocketId: string;
|
|
440
|
+
constructor(rocketId: string);
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* Event emitted when a rocket has finished the refurbishment process.
|
|
444
|
+
*
|
|
445
|
+
* @public
|
|
446
|
+
* @since 3.0.0
|
|
447
|
+
*/
|
|
448
|
+
declare class RefurbishmentCompleted extends DomainEvent {
|
|
449
|
+
readonly rocketId: string;
|
|
450
|
+
constructor(rocketId: string);
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* Event emitted when the rocket pool is exhausted.
|
|
454
|
+
*
|
|
455
|
+
* @public
|
|
456
|
+
* @since 1.3.0
|
|
457
|
+
*/
|
|
458
|
+
declare class PoolExhausted extends DomainEvent {
|
|
459
|
+
readonly totalRockets: number;
|
|
460
|
+
readonly maxRockets: number;
|
|
461
|
+
readonly queueLength: number;
|
|
462
|
+
constructor(totalRockets: number, maxRockets: number, queueLength: number);
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* Event emitted when a mission is queued due to pool exhaustion.
|
|
466
|
+
*
|
|
467
|
+
* @public
|
|
468
|
+
* @since 1.3.0
|
|
469
|
+
*/
|
|
470
|
+
declare class MissionQueued extends DomainEvent {
|
|
471
|
+
readonly missionId: string;
|
|
472
|
+
readonly queuePosition: number;
|
|
473
|
+
constructor(missionId: string, queuePosition: number);
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* Event emitted when a queued mission times out.
|
|
477
|
+
*
|
|
478
|
+
* @public
|
|
479
|
+
* @since 1.3.0
|
|
480
|
+
*/
|
|
481
|
+
declare class MissionQueueTimeout extends DomainEvent {
|
|
482
|
+
readonly missionId: string;
|
|
483
|
+
readonly waitTimeMs: number;
|
|
484
|
+
constructor(missionId: string, waitTimeMs: number);
|
|
485
|
+
}
|
|
486
|
+
|
|
244
487
|
/**
|
|
245
488
|
* LaunchpadOrbit provides automated deployment and preview capabilities for Gravito.
|
|
246
489
|
* It integrates with Docker and GitHub to provide "Preview Deployments" for Pull Requests.
|
|
@@ -276,4 +519,4 @@ declare function bootstrapLaunchpad(): Promise<{
|
|
|
276
519
|
fetch: (req: Request, server: any) => Response | Promise<Response> | undefined;
|
|
277
520
|
}>;
|
|
278
521
|
|
|
279
|
-
export { LaunchpadOrbit, Mission, MissionControl, PayloadInjector, PoolManager, RefurbishUnit, Rocket, RocketStatus, bootstrapLaunchpad };
|
|
522
|
+
export { DEFAULT_POOL_CONFIG, DEFAULT_REFURBISH_CONFIG, type IDockerAdapter, type IGitAdapter, type IGitHubAdapter, type IRocketRepository, type IRouterAdapter, LaunchpadOrbit, Mission, MissionAssigned, MissionControl, MissionQueue, MissionQueueTimeout, MissionQueued, PayloadInjector, type PoolConfig, PoolExhausted, PoolExhaustedException, PoolManager, QueueTimeoutException, type RefurbishConfig, RefurbishUnit, RefurbishmentCompleted, Rocket, RocketIgnited, RocketSplashedDown, RocketStatus, bootstrapLaunchpad };
|