# 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
指令创建时间
BM->>EH: 发起指令请求
Note over EH: ② sent_at
发送到MQTT时间
EH->>MQTT: Publish指令
Note over WD: ③ acked_at
Watchdog确认接收
MQTT->>WD: 推送指令
WD-->>EH: (可选) ACK确认
Note over WD: ④ started_at
开始执行时间
WD->>EX: 调用执行体
Note over EX: ⑤ start_time (ms)
执行体内部开始
EX->>EX: 执行指令...
Note over EX: ⑥ end_time (ms)
执行体内部结束
EX->>WD: 返回结果
Note over WD: ⑦ 消息上行
WD->>MQTT: ExecResult上行
Note over EH: ⑧ received_at
Exchange Hub接收
MQTT->>EH: 推送结果
Note over EH: ⑨ completed_at
指令完成时间
```
### 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本地时间生成,可能存在时钟偏差