Files
Ayay/SHH.CameraSdk/Abstractions/Errors/RecoveryPolicy.cs

100 lines
4.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
namespace SHH.CameraSdk;
/// <summary>
/// [决策引擎] 故障自愈策略 (V3.3.1 修复版)
/// 核心职责:根据设备错误码特征,智能裁决系统应采取的恢复动作,实现故障自动化处理
/// 关键修复Bug R
/// <para>1. 致命错误防护:对 InvalidCredentials/AccountLocked 等错误禁止重试防止账号被锁、IP 拉黑</para>
/// <para>2. 未知错误保守策略:对 Unknown 错误采用 ManualIntervention避免未知风险扩散</para>
/// 设计原则:最小化风险、最大化自愈率,区分可重试/不可重试/需人工干预的错误类型
/// </summary>
public static class RecoveryPolicy
{
#region --- 1. ---
/// <summary>
/// 根据相机错误码判定对应的故障自愈动作
/// </summary>
/// <param name="code">设备上报的错误码</param>
/// <returns>标准化的自愈动作指令</returns>
public static RecoveryAction GetAction(CameraErrorCode code)
{
return code switch
{
// ========== 场景 A: 网络类故障 (可自愈) ==========
// 策略:指数退避重试
// 理由:网络波动、超时、闪断为暂时性故障,延迟重试大概率恢复
CameraErrorCode.NetworkUnreachable or
CameraErrorCode.NetworkSendError or
CameraErrorCode.NetworkRecvError or
CameraErrorCode.Timeout or
CameraErrorCode.SocketError or
CameraErrorCode.StreamInterrupted or
CameraErrorCode.DeviceRebooting => RecoveryAction.RetryWithBackoff,
// ========== 场景 B: 资源繁忙类故障 (可自愈) ==========
// 策略:指数退避重试
// 理由:设备连接数满、缓冲区溢出,等待资源释放后可恢复
CameraErrorCode.DeviceResourceBusy or
CameraErrorCode.DeviceBufferOverflow or
CameraErrorCode.DeviceBusy or
CameraErrorCode.OperationNotFinished or
CameraErrorCode.PortPoolExhausted or
CameraErrorCode.MaxConnectionsReached or
CameraErrorCode.MaxStreamExceeded => RecoveryAction.RetryWithBackoff,
// ========== 场景 C: 致命错误 (不可自愈,禁止重试) ==========
// 策略:立即停止
// 理由:密码错误、账号锁定、组件缺失等故障,重试无意义且会加剧风险(账号锁死、日志爆炸)
CameraErrorCode.InvalidCredentials or
CameraErrorCode.AccessDenied or
CameraErrorCode.UserNotExist or
CameraErrorCode.AccountLocked or
CameraErrorCode.SessionExpired or
CameraErrorCode.InvalidChannel or
CameraErrorCode.IpConflict or
CameraErrorCode.SdkNotInitialized or
CameraErrorCode.ComponentLoadFailed or
CameraErrorCode.EncryptionLibError => RecoveryAction.FatalStop,
// ========== 场景 D: 硬件故障 (需人工干预) ==========
// 策略:人工介入
// 理由:硬盘损坏、存储满等故障属于硬件层面,软件无法修复
CameraErrorCode.HardwareFault or
CameraErrorCode.StorageError or
CameraErrorCode.DiskFull or
CameraErrorCode.DiskReadOnly => RecoveryAction.ManualIntervention,
// ========== 场景 E: 正常状态 ==========
CameraErrorCode.Success => RecoveryAction.None,
// ========== 场景 F: 未知错误 (关键修复 Bug R) ==========
// 旧策略:盲目重试 → 新策略:人工干预
// 理由:未知错误可能包含 IP 拉黑、协议不兼容等严重问题,重试会扩大风险
_ => RecoveryAction.ManualIntervention
};
}
#endregion
#region --- 2. 退 ---
/// <summary>
/// 获取建议的指数退避延迟时间(毫秒)
/// 算法公式delay = min(2^n * 1000, 120000)n = 当前重试次数
/// 限流规则:第一次 2s → 第二次 4s → ... → 第六次 64s → 上限 120s2分钟
/// </summary>
/// <param name="retryCount">当前重试次数(从 1 开始计数)</param>
/// <returns>延迟毫秒数</returns>
public static int GetRetryDelay(int retryCount)
{
// 限制重试次数最大为 7防止指数爆炸导致数值溢出
int exponent = Math.Min(retryCount, 7);
// 计算指数退避秒数
int delaySeconds = (int)Math.Pow(2, exponent);
// 转换为毫秒并限制上限为 2 分钟120000ms
return Math.Min(delaySeconds * 1000, 120000);
}
#endregion
}