@gravito/launchpad 1.2.2 → 1.3.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/CHANGELOG.md +66 -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 +392 -20
- package/dist/index.mjs +380 -20
- package/package.json +11 -9
- package/scripts/check-coverage.ts +64 -0
- package/src/Application/MissionQueue.ts +143 -0
- package/src/Application/PoolManager.ts +167 -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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,71 @@
|
|
|
1
1
|
# @gravito/launchpad
|
|
2
2
|
|
|
3
|
+
## 1.3.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Convert all workspace:\* dependencies to version numbers for npm publishing
|
|
8
|
+
|
|
9
|
+
- Fixed 144 workspace:\* dependencies across 58 packages
|
|
10
|
+
- Ensures all packages work properly when installed from npm
|
|
11
|
+
- Resolves issues with bunx and npm installation of CLI tools
|
|
12
|
+
- All internal dependencies now use explicit version constraints
|
|
13
|
+
|
|
14
|
+
- Updated dependencies
|
|
15
|
+
- @gravito/core@1.6.1
|
|
16
|
+
- @gravito/enterprise@1.0.4
|
|
17
|
+
- @gravito/ripple@4.0.1
|
|
18
|
+
- @gravito/stasis@3.1.1
|
|
19
|
+
|
|
20
|
+
## 1.3.1
|
|
21
|
+
|
|
22
|
+
### Patch Changes
|
|
23
|
+
|
|
24
|
+
- Updated dependencies [5a7f332]
|
|
25
|
+
- @gravito/ripple@4.0.0
|
|
26
|
+
|
|
27
|
+
## 1.3.0
|
|
28
|
+
|
|
29
|
+
### Minor Changes
|
|
30
|
+
|
|
31
|
+
- **P0 緊急修復:資源限制與隊列機制**
|
|
32
|
+
- 新增 `PoolConfig` 配置介面,支援 `maxRockets`、`maxQueueSize`、`queueTimeoutMs` 等參數
|
|
33
|
+
- 實現 `MissionQueue` 任務隊列管理,支援 FIFO 排程和超時處理
|
|
34
|
+
- 重構 `PoolManager.assignMission()`,加入三種資源耗盡策略:
|
|
35
|
+
- `queue`:任務進入等待隊列(預設)
|
|
36
|
+
- `reject`:立即拒絕新任務
|
|
37
|
+
- `dynamic`:有限度的動態建立容器
|
|
38
|
+
- 新增 Pool 狀態查詢 API:`getPoolStatus()`、`getQueueStats()`
|
|
39
|
+
- 新增領域事件:`PoolExhausted`、`MissionQueued`、`MissionQueueTimeout`
|
|
40
|
+
- 修改 `RefurbishConfig`,支援自訂清理命令和失敗處理策略
|
|
41
|
+
|
|
42
|
+
### Features
|
|
43
|
+
|
|
44
|
+
- **資源保護機制**:防止 Rocket 無限增長導致系統資源耗盡
|
|
45
|
+
- **任務隊列**:當 Pool 耗盡時,新任務自動進入隊列等待
|
|
46
|
+
- **可配置策略**:支援多種資源管理策略,適應不同使用場景
|
|
47
|
+
- **深度清理優化**:改進容器清理邏輯,減少髒污風險
|
|
48
|
+
|
|
49
|
+
### Breaking Changes
|
|
50
|
+
|
|
51
|
+
- `PoolManager` 構造函數新增可選的 `config` 參數
|
|
52
|
+
- `RefurbishUnit` 構造函數新增可選的 `config` 參數
|
|
53
|
+
- `warmup()` 方法的 `count` 參數改為可選,預設使用配置值
|
|
54
|
+
|
|
55
|
+
### Migration Guide
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
// 舊版(仍然有效)
|
|
59
|
+
const manager = new PoolManager(docker, repo);
|
|
60
|
+
|
|
61
|
+
// 新版(可選配置)
|
|
62
|
+
const manager = new PoolManager(docker, repo, refurbish, router, {
|
|
63
|
+
maxRockets: 10,
|
|
64
|
+
exhaustionStrategy: "queue",
|
|
65
|
+
maxQueueSize: 50,
|
|
66
|
+
});
|
|
67
|
+
```
|
|
68
|
+
|
|
3
69
|
## 1.2.2
|
|
4
70
|
|
|
5
71
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -12,26 +12,31 @@
|
|
|
12
12
|
- **♻️ Auto-Recycling**: Containers are automatically refurbished and returned to the pool after missions.
|
|
13
13
|
- **🤖 GitHub Integration**: Built-in webhook handler for PR previews and automated comments.
|
|
14
14
|
- **🛡️ Secure Isolation**: Each deployment runs in an isolated container environment.
|
|
15
|
+
- **📡 Real-time Telemetry**: Integrated with `@gravito/ripple` for live deployment progress updates via WebSockets.
|
|
16
|
+
- **🕸️ Dynamic Proxying**: High-performance routing to active deployments using Bun's native HTTP capabilities.
|
|
15
17
|
|
|
16
18
|
## 🏗️ Architecture Overview
|
|
17
19
|
|
|
18
|
-
Launchpad follows **Clean Architecture** principles
|
|
20
|
+
Launchpad follows **Clean Architecture** principles and is implemented as a **Gravito Orbit**:
|
|
19
21
|
|
|
20
|
-
### Domain Layer
|
|
21
|
-
- **Rocket**: The aggregate root representing a container instance.
|
|
22
|
-
- **Mission**: Represents a deployment task (
|
|
23
|
-
- **Status Machine**: Strictly manages transitions (Idle -> Assigned -> Deployed -> Recycling).
|
|
22
|
+
### Domain Layer (`src/Domain`)
|
|
23
|
+
- **Rocket**: The aggregate root representing a container instance and its lifecycle state.
|
|
24
|
+
- **Mission**: Represents a deployment task (repository URL, commit SHA, branch).
|
|
25
|
+
- **Status Machine**: Strictly manages transitions (`Idle` -> `Assigned` -> `Deployed` -> `Recycling`).
|
|
26
|
+
- **Events**: Domain events for tracking lifecycle changes.
|
|
24
27
|
|
|
25
|
-
### Application Layer
|
|
28
|
+
### Application Layer (`src/Application`)
|
|
26
29
|
- **PoolManager**: Orchestrates the lifecycle of Rockets (warmup, assignment, recycling).
|
|
27
|
-
- **
|
|
28
|
-
- **
|
|
29
|
-
- **RefurbishUnit**: Cleans up used containers for
|
|
30
|
+
- **MissionControl**: High-level facade for launching missions and coordinating injection.
|
|
31
|
+
- **PayloadInjector**: Handles the git operations and the physical injection of code into containers.
|
|
32
|
+
- **RefurbishUnit**: Cleans up and resets used containers for return to the pool.
|
|
30
33
|
|
|
31
|
-
### Infrastructure Layer
|
|
32
|
-
- **DockerAdapter**: Low-level communication with Docker daemon.
|
|
34
|
+
### Infrastructure Layer (`src/Infrastructure`)
|
|
35
|
+
- **DockerAdapter**: Low-level communication with the Docker daemon.
|
|
33
36
|
- **ShellGitAdapter**: Git operations via shell commands.
|
|
34
|
-
- **
|
|
37
|
+
- **OctokitGitHubAdapter**: Interaction with GitHub API for status updates and PR comments.
|
|
38
|
+
- **CachedRocketRepository**: Persistent storage for Rocket states using `@gravito/stasis`.
|
|
39
|
+
- **BunProxyAdapter**: Manages reverse proxying to active containers with sub-millisecond overhead.
|
|
35
40
|
|
|
36
41
|
## 🚀 Quick Start
|
|
37
42
|
|
|
@@ -41,55 +46,58 @@ Launchpad follows **Clean Architecture** principles:
|
|
|
41
46
|
bun add @gravito/launchpad
|
|
42
47
|
```
|
|
43
48
|
|
|
44
|
-
### Basic Usage
|
|
49
|
+
### Basic Usage (As an Orbit)
|
|
45
50
|
|
|
46
|
-
|
|
47
|
-
import { PoolManager, PayloadInjector, Mission } from '@gravito/launchpad'
|
|
48
|
-
import { DockerAdapter, ShellGitAdapter, InMemoryRocketRepository } from '@gravito/launchpad/infra'
|
|
49
|
-
|
|
50
|
-
// Initialize adapters
|
|
51
|
-
const docker = new DockerAdapter()
|
|
52
|
-
const repo = new InMemoryRocketRepository()
|
|
53
|
-
const manager = new PoolManager(docker, repo)
|
|
54
|
-
|
|
55
|
-
// 1. Warmup the pool (Create 3 idle containers)
|
|
56
|
-
await manager.warmup(3)
|
|
51
|
+
The most common way to use Launchpad is as part of a Gravito application:
|
|
57
52
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
53
|
+
```typescript
|
|
54
|
+
import { PlanetCore } from '@gravito/core'
|
|
55
|
+
import { OrbitCache } from '@gravito/stasis'
|
|
56
|
+
import { OrbitRipple } from '@gravito/ripple'
|
|
57
|
+
import { LaunchpadOrbit } from '@gravito/launchpad'
|
|
58
|
+
|
|
59
|
+
const ripple = new OrbitRipple({ path: '/ws' })
|
|
60
|
+
|
|
61
|
+
const core = await PlanetCore.boot({
|
|
62
|
+
orbits: [
|
|
63
|
+
new OrbitCache(),
|
|
64
|
+
ripple,
|
|
65
|
+
new LaunchpadOrbit(ripple)
|
|
66
|
+
],
|
|
63
67
|
})
|
|
64
68
|
|
|
65
|
-
|
|
66
|
-
const rocket = await manager.assignMission(mission)
|
|
67
|
-
const injector = new PayloadInjector(docker, new ShellGitAdapter())
|
|
68
|
-
await injector.deploy(rocket)
|
|
69
|
-
|
|
70
|
-
console.log(`Mission deployed to http://localhost:${rocket.port}`)
|
|
69
|
+
await core.bootstrap()
|
|
71
70
|
```
|
|
72
71
|
|
|
73
|
-
###
|
|
74
|
-
|
|
75
|
-
Launchpad can run as a Gravito Orbit, providing a REST API and Webhook support.
|
|
72
|
+
### Manual Mission Launch
|
|
76
73
|
|
|
77
74
|
```typescript
|
|
78
|
-
import {
|
|
75
|
+
import { MissionControl, Mission } from '@gravito/launchpad'
|
|
76
|
+
|
|
77
|
+
// Assuming container is available via Gravito Core
|
|
78
|
+
const ctrl = container.make<MissionControl>('launchpad.ctrl')
|
|
79
|
+
|
|
80
|
+
const mission = Mission.create({
|
|
81
|
+
id: 'mission-123',
|
|
82
|
+
repoUrl: 'https://github.com/example/repo.git',
|
|
83
|
+
branch: 'main'
|
|
84
|
+
})
|
|
79
85
|
|
|
80
|
-
const
|
|
81
|
-
console.log(`
|
|
86
|
+
const rocketId = await ctrl.launch(mission, (type, data) => {
|
|
87
|
+
console.log(`[Telemetry] ${type}:`, data)
|
|
88
|
+
})
|
|
82
89
|
```
|
|
83
90
|
|
|
84
91
|
## ⚙️ Configuration
|
|
85
92
|
|
|
86
|
-
Launchpad relies on
|
|
93
|
+
Launchpad relies on a working Docker environment.
|
|
87
94
|
|
|
88
95
|
| Environment Variable | Description | Default |
|
|
89
96
|
|----------------------|-------------|---------|
|
|
90
97
|
| `GITHUB_TOKEN` | Token for GitHub API access | (Required for PR comments) |
|
|
91
98
|
| `GITHUB_WEBHOOK_SECRET` | Secret for verifying webhooks | (Optional) |
|
|
92
99
|
| `POOL_SIZE` | Target number of pre-warmed containers | `3` |
|
|
100
|
+
| `CACHE_DRIVER` | Storage driver for Rocket states | `file` |
|
|
93
101
|
|
|
94
102
|
## 🧪 Testing
|
|
95
103
|
|
|
@@ -99,4 +107,4 @@ bun test
|
|
|
99
107
|
|
|
100
108
|
## 📄 License
|
|
101
109
|
|
|
102
|
-
MIT © Gravito Framework
|
|
110
|
+
MIT © Gravito Framework
|
package/README.zh-TW.md
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# @gravito/launchpad (繁體中文)
|
|
2
|
+
|
|
3
|
+
> 🚀 Bun 專用的即時部署系統。容器生命週期管理與零停機部署。
|
|
4
|
+
|
|
5
|
+
**Gravito Launchpad** 是專為 Bun 執行環境設計的協調系統。它採用獨特的「火箭池 (Rocket Pool)」架構來預熱容器,透過將程式碼直接注入已運行的實例而非重新構建映像檔,實現亞秒級 (sub-second) 的快速部署。
|
|
6
|
+
|
|
7
|
+
## ✨ 核心特性
|
|
8
|
+
|
|
9
|
+
- **🔥 火箭池 (Rocket Pool)**:預熱容器池,消除冷啟動時間。
|
|
10
|
+
- **💉 載荷注入 (Payload Injection)**:跳過 `docker build`。透過 `docker cp` 在毫秒內完成程式碼注入。
|
|
11
|
+
- **🏗️ DDD 架構**:基於 `@gravito/enterprise` 構建,具備嚴謹的狀態機管理。
|
|
12
|
+
- **♻️ 自動回收**:任務完成後,容器會自動翻新並返回池中供後續使用。
|
|
13
|
+
- **🤖 GitHub 整合**:內建 Webhook 處理程序,支持 PR 預覽部署與自動化評論。
|
|
14
|
+
- **🛡️ 安全隔離**:每個部署都在隔離的容器環境中運行。
|
|
15
|
+
- **📡 即時遙測**:整合 `@gravito/ripple`,透過 WebSockets 提供部署進度的即時更新。
|
|
16
|
+
- **🕸️ 動態代理**:利用 Bun 原生 HTTP 能力,為活動部署提供高性能路由。
|
|
17
|
+
|
|
18
|
+
## 🏗️ 架構概覽
|
|
19
|
+
|
|
20
|
+
Launchpad 遵循 **整潔架構 (Clean Architecture)** 原則,並作為一個 **Gravito Orbit** 實作:
|
|
21
|
+
|
|
22
|
+
### 領域層 (Domain Layer - `src/Domain`)
|
|
23
|
+
- **Rocket (火箭)**:代表容器實例及其生命週期狀態的聚合根 (Aggregate Root)。
|
|
24
|
+
- **Mission (任務)**:代表部署任務(儲存庫 URL、Commit SHA、分支)。
|
|
25
|
+
- **Status Machine (狀態機)**:嚴格管理狀態轉換 (`Idle` -> `Assigned` -> `Deployed` -> `Recycling`)。
|
|
26
|
+
- **Events (事件)**:用於追蹤生命週期變化的領域事件。
|
|
27
|
+
|
|
28
|
+
### 應用層 (Application Layer - `src/Application`)
|
|
29
|
+
- **PoolManager (池管理器)**:協調火箭的生命週期(預熱、分配、回收)。
|
|
30
|
+
- **MissionControl (任務控制中心)**:啟動任務並協調注入的高層外觀 (Facade)。
|
|
31
|
+
- **PayloadInjector (載荷注入器)**:處理 Git 操作及將程式碼物理注入容器。
|
|
32
|
+
- **RefurbishUnit (翻新單元)**:清理並重置已使用的容器以返回池中。
|
|
33
|
+
|
|
34
|
+
### 基礎設施層 (Infrastructure Layer - `src/Infrastructure`)
|
|
35
|
+
- **DockerAdapter**:與 Docker 守護進程的低階通訊。
|
|
36
|
+
- **ShellGitAdapter**:透過 Shell 指令進行 Git 操作。
|
|
37
|
+
- **OctokitGitHubAdapter**:與 GitHub API 互動以更新狀態及發佈 PR 評論。
|
|
38
|
+
- **CachedRocketRepository**:使用 `@gravito/stasis` 持久化火箭狀態。
|
|
39
|
+
- **BunProxyAdapter**:為活動容器提供亞毫秒級開銷的反向代理。
|
|
40
|
+
|
|
41
|
+
## 🚀 快速上手
|
|
42
|
+
|
|
43
|
+
### 安裝
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
bun add @gravito/launchpad
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### 基本用法 (作為 Orbit)
|
|
50
|
+
|
|
51
|
+
在 Gravito 應用中使用 Launchpad 的最常見方式:
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
import { PlanetCore } from '@gravito/core'
|
|
55
|
+
import { OrbitCache } from '@gravito/stasis'
|
|
56
|
+
import { OrbitRipple } from '@gravito/ripple'
|
|
57
|
+
import { LaunchpadOrbit } from '@gravito/launchpad'
|
|
58
|
+
|
|
59
|
+
const ripple = new OrbitRipple({ path: '/ws' })
|
|
60
|
+
|
|
61
|
+
const core = await PlanetCore.boot({
|
|
62
|
+
orbits: [
|
|
63
|
+
new OrbitCache(),
|
|
64
|
+
ripple,
|
|
65
|
+
new LaunchpadOrbit(ripple)
|
|
66
|
+
],
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
await core.bootstrap()
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### 手動啟動任務
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
import { MissionControl, Mission } from '@gravito/launchpad'
|
|
76
|
+
|
|
77
|
+
// 假設容器已透過 Gravito Core 提供
|
|
78
|
+
const ctrl = container.make<MissionControl>('launchpad.ctrl')
|
|
79
|
+
|
|
80
|
+
const mission = Mission.create({
|
|
81
|
+
id: 'mission-123',
|
|
82
|
+
repoUrl: 'https://github.com/example/repo.git',
|
|
83
|
+
branch: 'main'
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
const rocketId = await ctrl.launch(mission, (type, data) => {
|
|
87
|
+
console.log(`[遙測] ${type}:`, data)
|
|
88
|
+
})
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## ⚙️ 配置
|
|
92
|
+
|
|
93
|
+
Launchpad 依賴於運作正常的 Docker 環境。
|
|
94
|
+
|
|
95
|
+
| 環境變數 | 說明 | 預設值 |
|
|
96
|
+
|----------------------|-------------|---------|
|
|
97
|
+
| `GITHUB_TOKEN` | GitHub API 存取權杖 | (PR 評論必填) |
|
|
98
|
+
| `GITHUB_WEBHOOK_SECRET` | 驗證 Webhook 的密鑰 | (選填) |
|
|
99
|
+
| `POOL_SIZE` | 預熱容器的目標數量 | `3` |
|
|
100
|
+
| `CACHE_DRIVER` | 火箭狀態的儲存驅動 | `file` |
|
|
101
|
+
|
|
102
|
+
## 🧪 測試
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
bun test
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## 📄 授權
|
|
109
|
+
|
|
110
|
+
MIT © Gravito Framework
|
package/dist/index.d.mts
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 };
|