3x-ui/docs/Tasktracking/2026-04-24-fix-traffic-flush-blocked-by-stale-delta.md
root eca9b219cf docs: add missing task tracking records for multi-node and traffic fixes
Add task tracking records for commits that were missing documentation:
- 2026-04-10: multi-node backend foundation (7 commits)
- 2026-04-15: improve mariadb flow and traffic flush
- 2026-04-23: install cron before acme.sh
- 2026-04-24: resolve client traffic InboundId from DB
- 2026-04-24: fix traffic flush blocked by stale inboundId=0 delta
2026-04-24 03:04:15 +08:00

2.3 KiB
Raw Blame History

Task Record: Resolve shared-mode traffic flush blocked by stale inboundId=0 delta

Date: 2026-04-24 Related Module: web/service/traffic_flush.go, web/web.go, web/job/xray_traffic_job.go — 流量刷盘 Change Type: Fix

Background

共享模式下流量统计始终为 0MariaDB 的 client_traffics 表从未被写入。排查发现 traffic-pending.json 中存在一个残留的 inboundId: 0 客户端流量 delta在 InboundId 解析修复前产生)。flushToDatabase() 尝试将其写入 client_traffics 时,违反外键约束 fk_inbounds_client_statsinbounds 表不存在 id=0),导致整个事务回滚,所有流量永远无法写入。

此外,NewXrayTrafficJob()startTrafficFlushLoop() 各自创建了独立的 TrafficPendingStore 实例,指向同一个 traffic-pending.json 文件但使用独立的 sync.Mutex,存在数据竞争风险。

Changes

  • web/service/traffic_flush.go:
    • flushToDatabase() 循环开头新增 InboundID == 0 检查,跳过无效 delta 并记录 warning 日志
  • web/job/xray_traffic_job.go:
    • NewXrayTrafficJob() 改为接受 *service.TrafficPendingStore 参数,不再自行创建 store
    • 移除 config 包依赖
  • web/web.go:
    • Server struct 新增 trafficStore *service.TrafficPendingStore 字段
    • Start() 中统一创建一个 TrafficPendingStore 实例
    • startTask()startTrafficFlushLoop() 共享同一个 store 实例,消除双实例竞争
  • web/service/traffic_flush_test.go:
    • 新增 TestFlushOnceSkipsZeroInboundIdDelta 测试

Impact

  • web/service/traffic_flush.go: flushToDatabase() 跳过无效 delta
  • web/web.go: Server 启动流程变更store 统一创建
  • web/job/xray_traffic_job.go: 构造函数签名变更
  • 修复后需要删除残留的 traffic-pending.json 文件才能生效

Verification

  • go test ./web/service/ -run TestTraffic -v — PASS
  • go test ./web/service/ -run TestFlushOnceSkipsZeroInboundIdDelta -v — PASS

Risks And Follow-Up

  • 部署时必须删除 /etc/x-ui/traffic-pending.json,否则残留的 inboundId: 0 delta 仍会被跳过(不影响功能,但会产生 warning 日志)
  • TrafficPendingStore 的文件级锁已通过共享实例解决,但如果未来有多个进程访问同一文件,仍需考虑进程级锁