Appearance
任务生命周期
本文档定义FDP-P2P的任务状态流转规则。
状态流转图
完整时序图
过期机制
exp字段规则
| 角色 | 行为 |
|---|---|
| 发送方 | 设置exp表示最晚等待结果的时间 |
| 接收方 | 收到时检查exp < now,若过期则丢弃任务 |
过期处理
接收方收到已过期的任务时:
- ❌ 不执行任务
- ❌ 不回复ack
- ❌ 不回复complete或failed
- ✅ 静默丢弃
推荐过期时间
| 场景 | 推荐值 | 说明 |
|---|---|---|
| 常规任务 | time + 60s | 1分钟超时 |
| 低功耗设备配置下发 | time + 24h | 设备可能长时间离线 |
| 实时控制 | time + 10s | 快速失败 |
消息流模式
模式1:仅发送(Fire-and-Forget)
最简单的模式,不关心执行结果。
适用场景:日志上报、状态通知
模式2:确认送达
确保任务被接收。
适用场景:重要通知、配置下发
模式3:完整生命周期
追踪完整的任务执行过程。
适用场景:固件升级、大文件传输
模式4:请求-响应
同步等待执行结果。
适用场景:开锁、状态查询
幂等性要求
由于网络原因,消息可能重复送达。实现时应确保:
幂等设计原则
| 原则 | 说明 | 示例 |
|---|---|---|
| 使用绝对值 | 设置目标状态而非增量 | "设置温度25度" 而非 "增加温度1度" |
| 消息去重 | 记录已处理的msg_id | 忽略重复的msg_id |
| 时间戳检查 | 丢弃过时消息 | 只处理最新的配置 |
去重实现参考
go
type MessageHandler struct {
processed map[string]bool // msg_id -> 是否已处理
mu sync.Mutex
}
func (h *MessageHandler) Handle(msg MessagePending) {
h.mu.Lock()
defer h.mu.Unlock()
// 检查是否已处理
if h.processed[msg.MsgId] {
return // 忽略重复消息
}
// 标记为已处理
h.processed[msg.MsgId] = true
// 执行业务逻辑...
}错误处理
发送方超时处理
go
func SendWithTimeout(msg MessagePending, timeout time.Duration) (*MessageComplete, error) {
// 发送任务
publish(msg)
// 等待结果
select {
case result := <-completeChan:
return result, nil
case err := <-failedChan:
return nil, err
case <-time.After(timeout):
return nil, ErrTimeout
}
}接收方错误回复
任务执行失败时,应明确回复Failed消息:
json
{
"msg_id": "...",
"error": "door_jammed"
}常见错误码建议:
| 错误码 | 说明 |
|---|---|
invalid_action | 不支持的操作类型 |
invalid_value | 参数格式错误 |
permission_denied | 权限不足 |
device_busy | 设备忙 |
timeout | 执行超时 |
internal_error | 内部错误 |
顺序性说明
重要
FDP-P2P 不保证消息顺序,在以下情况可能发生乱序:
- 网络抖动导致重传
- QoS 1消息重排序
