第2章 状态定义与状态转移图设计

本章定义崩溃上报系统的六种核心状态,并设计完整的状态转移图。状态机是重试机制的基础,清晰的状态定义和转移规则能够防止上报死循环、丢失上报、资源泄漏等问题。我们将先以表格形式逐一说明每个状态的含义与生命周期,再给出状态转移图,最后提供状态机骨架代码和关键设计约束。

2.1 六种状态定义

状态含义生命周期与备注
初始崩溃记录已写入队列,尚未发起网络上报入口状态,可接收取消信号
上报中正在向远程服务器发送崩溃数据不可重复触发,超时或网络异常导致转移
成功服务端返回200 OK,上报数据已被接收终态前置,后续必须进入终止
失败网络错误、服务端拒绝或业务校验不通过触发重试逻辑,进入重试等待
重试等待按退避策略等待下一次重试必须设置最大重试次数,超限后进入终止
终止上报流程结束,释放所有资源终态,不可再转移出去

2.2 状态转移图

下图展示了六个状态之间的合法转移路径。箭头方向表示事件触发后的目标状态。关键转移包括:初始→上报中(发起上报)、上报中→成功/失败(上报结果)、失败→重试等待(进入退避)、重试等待→上报中(重试触发)、重试等待→终止(重试次数耗尽或手动取消)、成功→终止(正常结束)。

崩溃上报状态转移图 初始 上报中 成功 失败 重试等待 终止

2.3 转移规则与重试触发条件

状态转移由事件驱动,本系统定义以下关键事件:

  • Start:从初始进入上报中,触发崩溃数据打包和网络请求。
  • Success:服务端响应 2xx,上报中 → 成功。
  • Fail:网络超时、连接断开或服务端返回错误码,上报中 → 失败。
  • RetryScheduled:失败后自动发生,失败 → 重试等待,并启动退避定时器。
  • RetryFire:退避定时器到期,重试等待 → 上报中。
  • Abort:重试次数耗尽、用户手动取消或系统关闭,重试等待 → 终止。
  • Complete:成功上报后清理资源,成功 → 终止。

重试等待状态必须与退避算法绑定,常用策略包括固定间隔、指数退避(Exponential Backoff)或加入随机抖动(Jitter)。示例配置:

retry:
  max_attempts: 5
  base_delay_ms: 1000
  multiplier: 2
  jitter: true

2.4 状态机代码骨架

以下 C++ 代码展示了状态枚举与基于事件的状态转移核心逻辑。实际工程中应使用锁保护并发访问,并配合回调通知上层。

enum class CrashState {
    Initial,
    Reporting,
    Success,
    Failed,
    RetryWaiting,
    Terminated
};

enum class Event {
    Start,
    Success,
    Fail,
    RetryScheduled,
    RetryFire,
    Abort,
    Complete
};

CrashState transition(CrashState current, Event event) {
    switch (current) {
        case CrashState::Initial:
            if (event == Event::Start) return CrashState::Reporting;
            break;
        case CrashState::Reporting:
            if (event == Event::Success) return CrashState::Success;
            if (event == Event::Fail)    return CrashState::Failed;
            break;
        case CrashState::Failed:
            if (event == Event::RetryScheduled) return CrashState::RetryWaiting;
            break;
        case CrashState::RetryWaiting:
            if (event == Event::RetryFire) return CrashState::Reporting;
            if (event == Event::Abort)     return CrashState::Terminated;
            break;
        case CrashState::Success:
            if (event == Event::Complete)  return CrashState::Terminated;
            break;
        default:
            break;
    }
    // 非法转移保持原状态,并记录告警
    return current;
}
设计约束:禁止从终止状态向外转移,否则会导致资源无法回收。重试等待必须配合 max_attempts 和超时,防止无限重试耗尽电量与带宽。上报中状态应设置全局超时(例如 30 秒),超时后按失败处理。

2.5 状态机边界与模块职责

状态机位于“上报调度器”(Reporter Scheduler)模块内部,对外只暴露以下接口:

  • void Start():将状态从初始推进至上报中。
  • void OnResponse(bool success):由网络层回调,触发成功/失败转移。
  • void Cancel():用户请求终止,允许从初始或重试等待直接进入终止。

重试定时器不属于状态机内部,而是由调度器持有。状态机只负责“什么事件发生时切换到什么状态”,不负责控制退避延迟时间。

对比:若将退避逻辑嵌入状态机,会导致状态数目膨胀(例如“重试等待-第1次”“重试等待-第2次”)。推荐分离为“状态机+外部退避策略”,使状态图保持简洁,便于测试和持久化。