Skip to content

任务生命周期

本文档定义FDP-P2P的任务状态流转规则。

状态流转图

完整时序图

过期机制

exp字段规则

角色行为
发送方设置exp表示最晚等待结果的时间
接收方收到时检查exp < now,若过期则丢弃任务

过期处理

接收方收到已过期的任务时:

  • ❌ 不执行任务
  • ❌ 不回复ack
  • ❌ 不回复complete或failed
  • ✅ 静默丢弃

推荐过期时间

场景推荐值说明
常规任务time + 60s1分钟超时
低功耗设备配置下发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消息重排序

物联网设备通信协议文档