8.4 KiB
2026-07-05 修改日志
本文记录本次代码审查后实际落地的修复、影响范围、验证结果和构建产物。
1. 本次目标
修复代码审查中确认的 1、2、4、5、8 号问题,并重新构建新的程序到 bin/fireleave_tool。
涉及的问题包括:
fire_check报警上传/上报失败时仍被当作成功处理- 心跳超时重启会扩大影响,可能同时重启两个推理进程
- 视频时间戳解析和合并异常处理不可靠
- WebSocket 重连可能并发启动多个重连循环
copyFile超时返回后后台 goroutine 仍可能继续写文件
2. 修改文件
主要修改:
main.goconnect/heartbeat.goconnect/ws_channel.goreporter/reporter.govideo_server/video_merge.gobin/fireleave_tool
构建/环境相关:
- 本机安装了 Go 编译器
- 当前构建使用
go1.26.4 - 新二进制目标为
linux/arm64
3. 详细修改内容
3.1 fire_check 上报成功语义修复
原问题:
fire_check 报警触发后,上传视频和 WebSocket 上报在异步流程中执行。调用方无法知道最终是否真正上传成功、是否真正写入 WebSocket,因此主流程可能提前清理 FireCheckCandidate 状态。这样会造成“报警没有报上去,但本地状态认为已经处理完成”的风险。
修改后:
reporter.UploadVideoAndReportFireCheck()改为同步执行。- 视频上传失败会返回 error。
- WebSocket 未初始化或未连接会返回 error。
- 事件上报失败会返回 error。
- 数据快照上报失败会返回 error。
- 只有视频上传、事件上报、快照上报都成功后才清理合并文件并返回成功。
reporter.TriggerFireCheckAlarm()改为返回bool:true表示报警已完整处理成功false表示合并、上传、上报或并发锁获取失败
main.go中只有当TriggerFireCheckAlarm()返回true时才清空FireCheckCandidate、FireCheckFirstSeen、FireCheckLastSeen。
影响:
fire_check报警处理会比原来更严格,调用路径会等待上传和 WebSocket 写入完成。- 如果平台或网络异常,本地候选状态不会被误清理,后续仍有机会重新触发。
- 失败场景下日志可能增加,但这是为了避免报警丢失。
3.2 fire_check 连续检测状态修复
原问题:
旧逻辑在收到推理结果的分支中立即判断持续时间并触发上报。如果上报失败,状态仍可能被重置。同时检测结果和上报处理耦合较重。
修改后:
deviceAlarmState中使用:FireCheckCandidateFireCheckFirstSeenFireCheckLastSeen
- 收到火焰推理结果时只更新候选状态和最近一次看到火焰的时间。
- 在
monitorTicker分支中统一判断是否达到fire_check持续时间。 - 增加
fireCheckLastSeenGrace,避免检测帧之间的短暂间隔导致候选状态过早失效。
影响:
- 火焰检测持续时间判断更稳定。
- 上报是否成功会影响候选状态是否清理。
- 短暂丢帧不一定立即打断候选状态。
3.3 心跳重启范围修复
原问题:
fire_leave 或 fire_check 某一个推理进程心跳超时时,旧逻辑会调用共享重启流程,可能把两个推理进程都重启。这样会扩大影响面,也可能造成重复重启。
修改后:
- 新增
connect.RestartInferenceProcess(deviceData, processUUID)。 - 该函数只重启指定的
processUUID:- 主模型:
deviceUUID - 火焰模型:
deviceUUID_fire_check
- 主模型:
connect.StartInferenceProcess()保留兼容行为,仍可重启两路推理。main.go心跳监控改为:fire_leave超时只重启deviceUUIDfire_check超时只重启deviceUUID_fire_check
- 重启后只刷新对应进程的心跳时间。
影响:
- 单路推理异常不会连带影响另一路推理。
- 保留旧的
StartInferenceProcess(),避免已有调用点失效。 - 重启逻辑仍使用
connect.GlobalPortManager获取原端口。
3.4 视频合并异常处理修复
原问题:
video_server.parseSimpleTimestamp() 直接按固定下标切片,遇到异常文件名可能 panic。MergeVideo() 虽然有 recover,但旧逻辑存在 panic 后没有明确错误返回的风险。
修改后:
MergeVideo()改为命名返回值:mergedPath stringerr error
recover捕获 panic 后会设置:mergedPath = ""err = fmt.Errorf("merge video panic: %v", recovered)
parseSimpleTimestamp()增加文件名长度校验。- 年、月、日、时、分、秒解析失败时都会返回明确 error。
getTimestampFromPath()改为返回(int64, error)。- 排序和时间戳匹配逻辑会处理解析失败,必要时回退到文件名排序。
影响:
- 异常文件名不会导致程序崩溃。
- 视频合并失败会更明确地返回错误,调用方可感知失败。
- 正常命名的 mp4 文件处理逻辑不变。
3.5 WebSocket 重连并发修复
原问题:
读循环、心跳循环、发送失败都可能触发 reconnect()。如果多个错误同时发生,可能启动多个重连 goroutine,并在重连成功后重复启动心跳循环。
修改后:
WSClient增加reconnecting bool。- 新增:
startReconnect()startReconnectLocked()
- 所有触发重连的地方都通过
startReconnect系列方法进入。 - 同一时间只允许一个重连循环运行。
- 重连完成后重置
reconnecting。 - 重连成功后只恢复
readLoop(),不再重复启动新的heartbeatLoop()。 - 重新订阅时先复制
subscribersmap,再遍历订阅,降低并发读写风险。 RegisterService()和SubscribeTopic()使用本地client := GetWSClient(),减少直接访问全局变量的竞态窗口。
影响:
- 断线时重连行为更可控。
- 减少 goroutine 堆积和重复 heartbeat 的风险。
- WebSocket 正常收发路径不变。
3.6 copyFile 超时写入修复
原问题:
旧 copyFile 使用 goroutine 执行复制,外层通过 context 超时返回。超时后后台 goroutine 仍可能继续写目标文件,导致函数已经失败但文件仍在被写入,甚至留下半成品。
修改后:
copyFile改为同步分块复制。- 每次循环检查 30 秒 deadline。
- 读取和写入使用 1MB buffer。
- 超时、读失败、写失败、短写或 sync 失败时都会删除目标文件。
- 函数返回后不再有后台 goroutine 继续写文件。
影响:
- 超时后不会继续写目标文件。
- 失败时不保留不完整目标文件。
- 大文件复制仍可能耗时,但行为更确定。
4. 构建与验证
已执行:
gofmt -w main.go connect/heartbeat.go connect/ws_channel.go reporter/reporter.go video_server/video_merge.go
go test ./...
go build -o bin/fireleave_tool.new .
验证结果:
go test ./... 通过
所有包均为 [no test files]
新构建产物:
bin/fireleave_tool
构建信息:
go version: go1.26.4
GOOS: linux
GOARCH: arm64
CGO_ENABLED: 0
binary size: 10011779 bytes
构建完成后已清理 bin 目录旧产物,当前 bin 目录只保留:
bin/fireleave_tool
5. 兼容性与风险说明
保持兼容的部分
connect.StartInferenceProcess()保留,已有调用仍可使用。fire_leave报警入口仍保持异步上报行为。- WebSocket 消息结构和 topic 订阅逻辑没有改协议。
- 视频文件命名规则未改变。
行为变化
fire_check上报变为同步确认成功。fire_check上报失败时不会清空候选报警状态。- 心跳超时只重启异常的单个推理进程。
- WebSocket 同一时间只允许一个重连流程。
- 文件复制超时会删除不完整目标文件。
仍需关注
- 当前部分历史中文注释已经存在编码损坏,后续维护时建议逐步替换成清晰 UTF-8 注释。
reporter中仍有旧的 event cycle 相关逻辑,当前未完全重构,只做了本次问题相关的收敛。- 如果现场网络长期异常,
fire_check候选状态可能持续重试,需要结合日志确认是否需要增加队列、退避或最大重试策略。
6. 本次结论
本次修复重点是避免误判成功、缩小重启影响、减少并发重连和后台写文件风险。新的 bin/fireleave_tool 已基于修复后的代码构建完成,可用于后续部署验证。