# RMDC-Exchange-Hub 指令执行时间计算规范

## 1. 概述

本文档定义了 RMDC-Exchange-Hub 模块中指令执行全生命周期的时间追踪与计算规范。

---

## 2. 时间点定义

### 2.1 指令生命周期时间点

```mermaid
sequenceDiagram
    participant BM as 业务模块
    participant EH as Exchange Hub
    participant MQTT as MQTT Broker
    participant WD as Watchdog
    participant EX as 执行体

    Note over EH: ① created_at<br/>指令创建时间
    BM->>EH: 发起指令请求
    
    Note over EH: ② sent_at<br/>发送到MQTT时间
    EH->>MQTT: Publish指令
    
    Note over WD: ③ acked_at<br/>Watchdog确认接收
    MQTT->>WD: 推送指令
    WD-->>EH: (可选) ACK确认
    
    Note over WD: ④ started_at<br/>开始执行时间
    WD->>EX: 调用执行体
    
    Note over EX: ⑤ start_time (ms)<br/>执行体内部开始
    EX->>EX: 执行指令...
    Note over EX: ⑥ end_time (ms)<br/>执行体内部结束
    
    EX->>WD: 返回结果
    
    Note over WD: ⑦ 消息上行
    WD->>MQTT: ExecResult上行
    
    Note over EH: ⑧ received_at<br/>Exchange Hub接收
    MQTT->>EH: 推送结果
    
    Note over EH: ⑨ completed_at<br/>指令完成时间
```

### 2.2 时间点存储位置

| 时间点 | 字段名 | 存储表 | 类型 | 说明 |
|-------|-------|-------|------|------|
| 指令创建 | `created_at` | command_trackers | TIMESTAMP | 自动记录 |
| 发送到MQTT | `sent_at` | command_trackers | TIMESTAMP | 调用MQTT Publish时记录 |
| Watchdog确认 | `acked_at` | command_trackers | TIMESTAMP | 收到ACK消息时记录 |
| 开始执行 | `started_at` | command_trackers | TIMESTAMP | 收到running状态时记录 |
| 执行开始(内部) | `start_time` | command_results | INT64 (ms) | Watchdog侧记录 |
| 执行结束(内部) | `end_time` | command_results | INT64 (ms) | Watchdog侧记录 |
| 结果接收 | `received_at` | command_results | TIMESTAMP | Exchange Hub接收结果时记录 |
| 指令完成 | `completed_at` | command_trackers | TIMESTAMP | 更新为终态时记录 |

---

## 3. 时间耗时计算公式

### 3.1 核心耗时指标

| 指标名称 | 计算公式 | 单位 | 含义 |
|---------|---------|------|------|
| **指令下发耗时** | `acked_at - sent_at` | ms | 指令从Exchange Hub到达Watchdog的网络耗时 |
| **指令执行耗时** | `end_time - start_time` (或 `duration`) | ms | 指令在执行体内的实际执行时间 |
| **指令上行耗时** | `received_at - end_time` | ms | 执行结果从Watchdog返回Exchange Hub的耗时 |
| **总体耗时** | `completed_at - sent_at` | ms | 从发送到完成的总时间 |

### 3.2 扩展耗时指标

| 指标名称 | 计算公式 | 单位 | 含义 |
|---------|---------|------|------|
| 排队耗时 | `sent_at - created_at` | ms | 指令在Exchange Hub等待发送的时间 |
| 处理准备耗时 | `started_at - acked_at` | ms | Watchdog接收到开始执行的准备时间 |

---

## 4. 数据结构定义

### 4.1 CommandTracker 时间字段

```go
type CommandTracker struct {
    // ... 其他字段 ...
    
    // 时间追踪字段
    SentAt      *time.Time // 发送到MQTT时间戳
    AckedAt     *time.Time // Watchdog确认接收时间戳  
    StartedAt   *time.Time // 开始执行时间戳
    CompletedAt *time.Time // 完成时间戳
    CreatedAt   time.Time  // 创建时间
    TimeoutAt   *time.Time // 超时时间
}
```

### 4.2 CommandResult 时间字段

```go
type CommandResult struct {
    // ... 其他字段 ...
    
    // 执行时间字段 (来自Watchdog)
    StartTime  int64     // 执行开始时间戳(ms)
    EndTime    int64     // 执行结束时间戳(ms)
    Duration   int64     // 执行时长(ms)
    
    // 上行时间字段 (Exchange Hub记录)
    ReceivedAt     time.Time // 结果接收时间
    UploadDuration int64     // 上行耗时(ms) = ReceivedAt - EndTime
}
```

### 4.3 时间详情DTO

```go
// CommandTimeDurations 指令时间耗时详情
type CommandTimeDurations struct {
    DeliveryDuration      int64  `json:"delivery_duration"`       // 下发耗时(ms)
    ExecDuration          int64  `json:"exec_duration"`           // 执行耗时(ms)
    UploadDuration        int64  `json:"upload_duration"`         // 上行耗时(ms)
    TotalDuration         int64  `json:"total_duration"`          // 总体耗时(ms)
    QueueDuration         int64  `json:"queue_duration,omitempty"` // 排队耗时(ms)
}
```

---

## 5. API响应格式

### 5.1 查询指令响应增强

```json
{
    "code": 0,
    "message": "success",
    "data": {
        "command_id": "k8s_exec-proj_001-241222114530",
        "project_id": "proj_001",
        "status": "success",
        "created_at": "2024-12-22 11:45:30",
        "completed_at": "2024-12-22 11:45:35",
        "time_durations": {
            "delivery_duration": 150,
            "exec_duration": 4500,
            "upload_duration": 120,
            "total_duration": 4850
        },
        "result": { ... }
    }
}
```

### 5.2 同步指令响应

```json
{
    "code": 0,
    "message": "success",
    "data": {
        "command_id": "k8s_exec-proj_001-241222114530",
        "status": "success",
        "exit_code": 0,
        "output": "...",
        "duration": 4500,
        "time_durations": {
            "delivery_duration": 150,
            "exec_duration": 4500,
            "upload_duration": 120,
            "total_duration": 4850
        }
    }
}
```

---

## 6. 计算实现伪代码

```go
// CalculateCommandDurations 计算指令时间耗时
func CalculateCommandDurations(
    tracker *entity.CommandTracker,
    result *entity.CommandResult,
) *dto.CommandTimeDurations {
    durations := &dto.CommandTimeDurations{}
    
    // 1. 下发耗时
    if tracker.SentAt != nil && tracker.AckedAt != nil {
        durations.DeliveryDuration = tracker.AckedAt.Sub(*tracker.SentAt).Milliseconds()
    }
    
    // 2. 执行耗时 (优先使用Watchdog计算值)
    if result != nil && result.Duration > 0 {
        durations.ExecDuration = result.Duration
    } else if result != nil && result.StartTime > 0 && result.EndTime > 0 {
        durations.ExecDuration = result.EndTime - result.StartTime
    }
    
    // 3. 上行耗时
    if result != nil && result.EndTime > 0 {
        receivedAtMs := result.ReceivedAt.UnixMilli()
        durations.UploadDuration = receivedAtMs - result.EndTime
    }
    
    // 4. 总体耗时
    if tracker.SentAt != nil && tracker.CompletedAt != nil {
        durations.TotalDuration = tracker.CompletedAt.Sub(*tracker.SentAt).Milliseconds()
    }
    
    // 5. 排队耗时 (可选)
    if tracker.SentAt != nil {
        durations.QueueDuration = tracker.SentAt.Sub(tracker.CreatedAt).Milliseconds()
    }
    
    return durations
}
```

---

## 7. 注意事项

1. **时区统一**: 所有时间必须使用统一时区 (Asia/Shanghai, UTC+8)
2. **精度要求**: 毫秒级精度，int64存储
3. **空值处理**: 计算时需检查时间字段是否为nil
4. **Watchdog时间**: `start_time`/`end_time` 由Watchdog本地时间生成，可能存在时钟偏差
