# 804318 【Autoflow】对接沙箱和工具 —— 逻辑设计

---

## 一、需求分析

### 1.1 需求背景

#### 需求信息

| 字段     | 内容                       |
| -------- | -------------------------- |
| 需求号   | 804318                     |
| 类型     | Feature                    |
| 标题     | 【Autoflow】对接沙箱和工具 |
| 状态     | In Realizing               |
| 需求来源 | 产品规划                   |

#### 需求场景

随着数据处理流程的复杂化，用户需要在数据流中执行自定义代码逻辑，如数据转换、计算、分析等。当前系统缺乏安全、隔离的代码执行环境，无法满足用户对灵活数据处理的需求。

在数据处理流中，用户希望能够：

- 在流程节点中执行自定义代码（如 Python、JavaScript 等）
- 代码执行环境需要隔离，避免影响系统稳定性
- 支持异步执行，避免长时间阻塞流程
- 支持结果缓存，提升执行效率

#### 用户期望

本次需求目标包括：

1. **提供安全的代码执行环境**
   - 沙箱隔离执行
   - 资源限制保护
   - 支持多种编程语言

2. **支持异步执行和结果缓存**
   - 长时间任务异步执行
   - 相同输入结果可复用
   - 提升执行效率

3. **简化配置和管理**
   - 自动管理沙箱生命周期
   - 降低运维成本

4. **提升系统稳定性和可扩展性**
   - 资源隔离
   - 支持并发执行
   - 易于扩展和维护

5. **沙箱的流程运行环境**
   - 数据流（支持）
   - 工作流（不支持）
   - 算子（不支持）

---

### 1.2 用户故事

| 角色         | 痛点（Why）                      | 活动（What）                   | 价值（Value）              |
| ------------ | -------------------------------- | ------------------------------ | -------------------------- |
| 数据流设计者 | 无法在数据流中执行自定义代码逻辑 | 在数据流中添加沙箱节点执行代码 | 提升数据处理的灵活性和能力 |
| 数据流设计者 | 代码执行环境不安全，可能影响系统 | 使用沙箱隔离执行代码           | 保障系统安全稳定           |
| 数据流设计者 | 重复执行相同代码效率低           | 使用结果缓存复用执行结果       | 提升执行效率，降低成本     |

---

## 二、业务功能设计

### 2.1 概念与术语

| 中文     | 英文            | 定义                                       |
| -------- | --------------- | ------------------------------------------ |
| 沙箱     | Sandbox         | 隔离的代码执行环境，提供资源限制和安全保护 |
| 沙箱会话 | Sandbox Session | 沙箱的运行时实例，包含执行环境和上下文     |
| 沙箱节点 | Sandbox Action  | 数据流中用于执行代码的节点                 |

---

### 2.2 业务用例

#### 用例名称

**配置和执行沙箱节点**

#### 用例说明

| 项目     | 描述                                       |
| -------- | ------------------------------------------ |
| 参与者   | 数据流设计者                               |
| 前置条件 | 已创建数据流；用户有编辑权限；沙箱服务可用 |
| 后置条件 | 沙箱节点配置完成并成功执行                 |

---

### 2.3 业务功能定义

#### 沙箱会话管理

##### 会话配置存储

- sandbox节点保存沙箱会话配置（SandboxConfig），允许为空
- 配置为空时，默认从全局config读取配置
- 配置包括：template_id、cpu、memory、disk、timeout、dependencies等

##### 会话创建参数

创建沙箱会话时支持以下参数（存储在 `SandboxConfig` 中）：

| 参数名       | 类型   | 是否可选 | 描述                           |
| ------------ | ------ | -------- | ------------------------------ |
| template_id  | string | N        | 沙箱模板 ID，如 `python-basic` |
| cpu          | string | Y        | CPU 资源限制，如 `1`           |
| memory       | string | Y        | 内存限制，如 `512Mi`           |
| disk         | string | Y        | 磁盘限制，如 `1024Mi`          |
| timeout      | number | Y        | 会话超时时间（秒）             |
| dependencies | array  | Y        | 依赖包列表                     |

依赖包格式：

```json
{
  "name": "requests",
  "version": "=2.31.0"
}
```

##### 沙箱会话策略

1. **计算配置哈希**：根据沙箱会话配置计算唯一hash值
2. **获取分布式锁**：基于配置hash获取分布式锁，确保并发安全
3. **查询会话ID**：从redis读取hash对应的会话ID
4. **检查会话状态**：如果会话ID存在，则调用沙箱服务查询会话状态
5. **判断会话可用性**：
   - 如果会话ID不存在，或
   - 会话状态为 `completed`、`failed`，或
   - 会话不存在
   - 则根据配置重新创建会话
6. **释放分布式锁**：完成会话处理后释放锁
7. 会话创建后保持运行状态，由沙箱服务根据空闲状态自动回收

---

#### 沙箱节点参数设计

##### 节点配置

- `@sandbox/execute` (沙箱执行节点)

##### 输入参数

| 参数名         | 类型          | 支持变量 | 是否可选 | 描述                                                     |
| -------------- | ------------- | -------- | -------- | -------------------------------------------------------- |
| code           | string        | Y        | N        | 要执行的代码                                             |
| language       | string        | N        | N        | 编程语言，如 `python`、`javascript`，当前仅支持 `python` |
| event          | object        | Y        | Y        | 传递给代码的事件数据                                     |
| cache_result   | boolean       | N        | Y        | 是否缓存结果，默认 false                                 |
| interval_sec   | number        | N        | Y        | 轮询结果时间间隔（秒），默认 1                           |
| sandbox_config | SandboxConfig | N        | Y        | 沙箱配置                                                 |

##### 输出参数

| 参数名       | 类型 | 描述                                    |
| ------------ | ---- | --------------------------------------- |
| return_value | any  | 返回代码执行结果（`return_value` 字段） |


#### 接口设计

##### 节点调试接口

新增沙箱调试接口

```http
POST /api/v1/automation/v1/sandbox-execution

{
  "code": "",
  "language": "python",
  "event": {},
  "sandbox_config": {}
}
```

调试响应：

```json
{
  "id": "exec_20260123083647_8b3a951c",
  "session_id": "sess_20260123_71cab7c4",
  "status": "completed",
  "code": "def handler(event):\n    name = event.get('name', 'World')\n    return {\n        'statusCode': 200,\n        'body': f'Hello, {name}!'\n    }",
  "language": "python",
  "timeout": 30,
  "exit_code": 0,
  "error_message": null,
  "execution_time": null,
  "stdout": "",
  "stderr": "",
  "artifacts": [],
  "retry_count": 0,
  "created_at": "2026-01-23T08:36:47",
  "started_at": null,
  "completed_at": "2026-01-23T08:36:47",
  "return_value": {
    "statusCode": 200,
    "body": "Hello, Alice!"
  },
  "metrics": {
    "duration_ms": 47.19976894557476,
    "cpu_time_ms": 12.361333999999946,
    "peak_memory_mb": null,
    "io_read_bytes": null,
    "io_write_bytes": null
  }
}
```

---

#### 异步任务和结果缓存

##### 异步执行机制

- 任务提交后进入 `blocked` 状态，并启动协程轮询沙箱执行结果
- 轮询间隔由 `interval_sec` 参数控制，默认 1 秒
- 任务状态：`pending` → `running` → `success` / `failed`

##### 结果缓存机制

- 支持通过 `cache_result` 参数控制是否缓存结果
- 缓存键：基于代码内容、语言、事件数据生成 hash
- **开启缓存时**：
  - 先检查是否有缓存命中
  - 缓存命中且状态为 `success`：直接返回缓存结果
  - 缓存命中且状态为 `pending`：进入 `blocked` 状态等待
  - 缓存未命中或失败：提交任务并进入 `blocked` 状态
  - 任务完成后保存结果到缓存
- **未开启缓存时**：
  - 直接提交任务并进入 `blocked` 状态
  - 任务完成后不保存缓存
- 缓存过期时间：默认 24 小时

##### 轮询机制

- 任务提交成功后，按 `interval_sec` 间隔轮询任务状态
- 任务完成后，停止轮询，发送任务结果消息 `automation.async_task.result`
- `ContinueBlockInstances` 接收 `automation.async_task.result` 更新状态和结果

---

#### 沙箱服务集成

##### 接口说明

- **创建会话**：`POST /api/v1/sessions`
- **查询会话**：`GET /api/v1/sessions/{session_id}`
- **执行代码**：`POST /api/v1/executions/sessions/{session_id}/execute`
- **查询执行状态**：`GET /api/v1/executions/{execution_id}/status`
- **查询执行结果**：`GET /api/v1/executions/{execution_id}/result`

##### 错误处理

- 沙箱服务不可用时、会话创建失败、代码执行失败时，节点运行失败并终止流程

---

#### 2.4.1 沙箱节点执行流程

```
开始
  ↓
从sandbox节点获取SandboxConfig(为空则用全局配置)
  ↓
检查cache_result是否开启缓存
  ↓
缓存开启？
  ├─ 是 → 生成缓存hash并查询缓存结果
  │        ↓
  │      缓存命中且成功？
  │        ├─ 是 → 直接返回缓存结果并结束
  │        └─ 否 → 获取或创建沙箱会话 → 执行代码 → 保存结果到缓存 → 返回结果
  │
  └─ 否 → 获取或创建沙箱会话 → 执行代码 → 返回结果
  ↓
结束
```

#### 2.4.2 沙箱节点调试流程

```
开始
  ↓
从请求参数获取SandboxConfig(为空则用全局配置)
  ↓
根据SandboxConfig计算配置hash
  ↓
获取分布式锁(基于配置hash)
  ↓
从redis读取hash对应的会话ID
  ↓
有会话ID？
  ├─ 是 → 查询会话状态
  │        ↓
  │      会话状态不是completed或failed？
  │        ├─ 是 → 释放锁 → 执行代码
  │        └─ 否 → 创建新会话 → 保存会话ID到redis → 释放锁 → 执行代码
  │
  └─ 否 → 创建新会话 → 保存会话ID到redis → 释放锁 → 执行代码
  ↓
结束
```

#### 2.4.3 沙箱会话管理流程

```
开始
  ↓
根据SandboxConfig计算配置hash
  ↓
获取分布式锁(基于配置hash)
  ↓
从redis读取hash对应的会话ID
  ↓
会话ID存在？
  ├─ 是 → 查询会话状态
  │        ↓
  │      会话状态不是completed或failed？
  │        ├─ 是 → 释放锁 → 返回会话ID
  │        └─ 否 → 创建新会话 → 更新redis → 释放锁 → 返回会话ID
  │
  └─ 否 → 创建新会话 → 更新redis → 释放锁 → 返回会话ID
  ↓
结束
```

### 2.5 交互线框图
