feat: 初始化 bls-onoffline-backend 项目基础结构
添加 Kafka 消费者、数据库写入、Redis 集成等核心模块,实现设备上下线事件处理 - 创建项目基础目录结构与配置文件 - 实现 Kafka 消费逻辑与手动提交偏移量 - 添加 PostgreSQL 数据库连接与分区表管理 - 集成 Redis 用于错误队列和项目心跳 - 包含数据处理逻辑,区分重启与非重启数据 - 提供数据库初始化脚本与分区创建工具 - 添加单元测试与代码校验脚本
This commit is contained in:
85
bls-onoffline-backend/openspec/specs/onoffline/spec.md
Normal file
85
bls-onoffline-backend/openspec/specs/onoffline/spec.md
Normal 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 转换为毫秒
|
||||
|
||||
11
bls-onoffline-backend/openspec/specs/onoffline/status.md
Normal file
11
bls-onoffline-backend/openspec/specs/onoffline/status.md
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
## Implementation Status
|
||||
- **Date**: 2026-02-04
|
||||
- **Status**: Completed
|
||||
- **Notes**:
|
||||
- 已完成核心消费逻辑、分区管理、数据库幂等写入。
|
||||
- 已处理数据库连接泄露 (EADDRINUSE) 问题,增加了离线保护机制。
|
||||
- 已修复时间戳单位问题 (Seconds -> MS)。
|
||||
- 已将关键字段长度扩展至 VARCHAR(255) 并增加了代码层截断保护。
|
||||
- 验证了数据积压消费能力。
|
||||
- 本阶段开发任务已归档。
|
||||
Reference in New Issue
Block a user