feat: 初始化 bls-onoffline-backend 项目基础结构

添加 Kafka 消费者、数据库写入、Redis 集成等核心模块,实现设备上下线事件处理
- 创建项目基础目录结构与配置文件
- 实现 Kafka 消费逻辑与手动提交偏移量
- 添加 PostgreSQL 数据库连接与分区表管理
- 集成 Redis 用于错误队列和项目心跳
- 包含数据处理逻辑,区分重启与非重启数据
- 提供数据库初始化脚本与分区创建工具
- 添加单元测试与代码校验脚本
This commit is contained in:
2026-02-04 17:51:50 +08:00
commit a8c7cf74e6
41 changed files with 6760 additions and 0 deletions

View File

@@ -0,0 +1,85 @@
# Spec: onoffline-backend
## Purpose
从 Kafka 消费设备上下线事件并按规则写入 PostgreSQL 分区表,确保高可靠性、幂等写入和错误恢复能力。
## Requirements
### Requirement: 消费并落库
系统 SHALL 从 blwlog4Nodejs-rcu-onoffline-topic-0 消费消息,并写入 log_platform.onoffline.onoffline_record。
#### Scenario: 非重启数据写入
- **GIVEN** RebootReason 为空或不存在
- **WHEN** 消息被处理
- **THEN** current_status 等于 CurrentStatus (截断至 255 字符)
### Requirement: 重启数据处理
系统 SHALL 在 RebootReason 非空时强制 current_status 为 on。
#### Scenario: 重启数据写入
- **GIVEN** RebootReason 为非空值
- **WHEN** 消息被处理
- **THEN** current_status 等于 on
### Requirement: 空值保留
系统 SHALL 保留上游空值,不对字段进行补 0。
#### Scenario: 空值写入
- **GIVEN** LauncherVersion 或 RebootReason 为空字符串
- **WHEN** 消息被处理
- **THEN** 数据库存储值为对应的空字符串
### Requirement: 数据库分区策略
系统 SHALL 使用 Range Partitioning 按天分区,并自动维护未来 30 天的分区表。
#### Scenario: 分区预创建
- **GIVEN** 系统启动或每日凌晨
- **WHEN** 运行分区维护任务
- **THEN** 确保数据库中存在未来 30 天的分区表
### Requirement: 消费可靠性 (At-Least-Once)
系统 SHALL 仅在数据成功写入数据库后,才向 Kafka 提交消费位点。
#### Scenario: 逐条确认与顺序提交
- **GIVEN** 并发处理多条消息 (Offset 1, 2, 3)
- **WHEN** Offset 2 先完成Offset 1 尚未完成
- **THEN** 系统不提交 Offset 2直到 Offset 1 也完成,才提交 Offset 3 (即 1, 2, 3 都完成)
### Requirement: 数据库离线保护
系统 SHALL 在数据库连接丢失时暂停消费,防止数据堆积或丢失。
#### Scenario: 数据库断连
- **GIVEN** 数据库连接失败 (ECONNREFUSED 等)
- **WHEN** 消费者尝试写入
- **THEN** 暂停 Kafka 消费 1 分钟,并进入轮询检测模式,直到数据库恢复
### Requirement: 幂等写入
系统 SHALL 处理重复消费的数据,防止主键冲突。
#### Scenario: 重复数据处理
- **GIVEN** Kafka 重新投递已处理过的消息
- **WHEN** 尝试写入数据库
- **THEN** 使用 `ON CONFLICT DO NOTHING` 忽略冲突,视为处理成功
### Requirement: 性能与日志
系统 SHALL 最小化正常运行时的日志输出。
#### Scenario: 正常运行日志
- **GIVEN** 数据正常处理
- **WHEN** 写入成功
- **THEN** 不输出单条日志,仅每分钟输出聚合统计 (Pulled/Inserted)
### Requirement: 字段长度限制与截断
系统 SHALL 将部分变长字段截断至数据库允许的最大长度 (VARCHAR(255)),防止写入失败。
#### Scenario: 超长字段处理
- **GIVEN** LauncherVersion, CurrentStatus 或 RebootReason 超过 255 字符
- **WHEN** 消息被处理
- **THEN** 字段被截断为前 255 个字符并入库
### Requirement: 时间戳单位自动识别
系统 SHALL 自动识别 UnixTime 字段是秒还是毫秒,并统一转换为毫秒。
#### Scenario: 秒级时间戳转换
- **GIVEN** UnixTime < 100000000000 (约 1973 年前)
- **WHEN** 解析时间戳
- **THEN** 自动乘以 1000 转换为毫秒

View File

@@ -0,0 +1,11 @@
## Implementation Status
- **Date**: 2026-02-04
- **Status**: Completed
- **Notes**:
- 已完成核心消费逻辑、分区管理、数据库幂等写入。
- 已处理数据库连接泄露 (EADDRINUSE) 问题,增加了离线保护机制。
- 已修复时间戳单位问题 (Seconds -> MS)。
- 已将关键字段长度扩展至 VARCHAR(255) 并增加了代码层截断保护。
- 验证了数据积压消费能力。
- 本阶段开发任务已归档。