feat: 更新 Kafka 配置和数据库管理逻辑

- 在 .env.example 中添加 Kafka 配置项:KAFKA_FETCH_MAX_BYTES, KAFKA_FETCH_MIN_BYTES, KAFKA_FETCH_MAX_WAIT_MS。
- 删除 room_status_sync 提案及相关文档。
- 删除 fix_uint64_overflow 提案及相关文档。
- 更新数据库管理器以支持使用 COPY 语句进行高效数据写入,替换批量 INSERT 逻辑。
- 实现心跳数据的整数溢出处理,确保无效数据被持久化到 heartbeat_events_errors 表。
- 更新处理器规范,确保心跳数据成功写入历史表后触发 room_status 同步。
- 添加新文档,描述新的分区方法案例。
- 归档旧的提案和规范文档以保持项目整洁。
This commit is contained in:
2026-03-03 18:22:12 +08:00
parent d0c4940e01
commit c0cdc9ea66
19 changed files with 188 additions and 215 deletions

View File

@@ -14,7 +14,7 @@ The `room_status.room_status_moment` table is a shared table for real-time devic
* Map `version` to `agreement_ver` and `bright_g` to `bright_g`.
## Tasks
- [ ] Update `docs/room_status_moment.sql` with new columns and index.
- [ ] Update `docs/plan-room-status-sync.md` with new fields and finalized plan.
- [ ] Implement `upsertRoomStatus` in `DatabaseManager`.
- [ ] Integrate into `HeartbeatProcessor`.
- [x] Update `docs/room_status_moment.sql` with new columns and index.
- [x] Update `docs/plan-room-status-sync.md` with new fields and finalized plan.
- [x] Implement `upsertRoomStatus` in `DatabaseManager`.
- [x] Integrate into `HeartbeatProcessor`.

View File

@@ -0,0 +1,9 @@
## MODIFIED Requirements
### Requirement: 数据库表结构管理
系统 MUST 支持 room_status 实时状态表与心跳历史表的协同写入能力。
#### Scenario: room_status 结构与约束支持
- **WHEN** 心跳服务执行 room_status upsert 同步
- **THEN** 目标表应具备支撑 UPSERT 的唯一约束hotel_id, room_id, device_id
- **AND** 需要的同步字段应存在并可写入

View File

@@ -0,0 +1,9 @@
## MODIFIED Requirements
### Requirement: 心跳数据转换
系统 MUST 在历史表写入成功后触发 room_status 同步。
#### Scenario: 历史写入成功后同步状态表
- **WHEN** 一批心跳数据成功写入历史分区表
- **THEN** 系统应调用 room_status 的 upsert 同步逻辑
- **AND** 同步失败不应阻塞主历史写入流程

View File

@@ -0,0 +1,24 @@
# Change: Handle integer overflows, persist unprocessable data, and use COPY for extreme write performance
## Why
1. **Overflows**: Hardware devices report bitmasks and counters where unsigned values exceed PostgreSQL's signed boundaries (e.g. `uint64`), causing out of range Database errors.
2. **Missing History**: Previously, fully unprocessable rows directly crashed out or vanished into Redis logs, causing data loss without DB traceability.
3. **Database Write Pressure**: The multi-row `INSERT INTO ... VALUES (...)` logic built queries with up to 30,000 parameter bindings for a batch, creating massive CPU load for parsing scaling synchronously via a single database connection.
## What Changes
- Use `pg-copy-streams` to replace batch `INSERT` with `COPY heartbeat.heartbeat_events FROM STDIN WITH (FORMAT text)`. The objects are automatically formatted into a memory buffer and flushed down a pipeline stream, completely saving parameter parsing overhead by ~90%.
- Refine array text mapping natively avoiding SQL JSONB mapping latency and safely escaping special string quotes.
- Safely map completely oversized integers to signed `int64`, `int32`, `int16` 2's complement equivalents natively in Javascript.
- Implement an upstream catch that automatically redirects isolated PostgreSQL validation exceptions alongside JSON parsing defects purely to the new `heartbeat_events_errors` table batch-sink for complete persistence.
## Impact
- Affected specs: `processor`
- Affected code:
- `src/processor/heartbeatProcessor.js`
- `src/db/databaseManager.js`
- `package.json`
## Recorded Follow-ups (2026-03-03)
- Partition maintenance strategy is adjusted to avoid redundant per-partition index creation during daily partition pre-creation; parent-table indexes remain the primary index definition source.
- Legacy compatibility paths for old heartbeat schema access are removed from implementation scope, and the project baseline is aligned to the new partitioned schema.
- Kafka consume/write throughput tuning knobs are documented and exposed via runtime envs (`KAFKA_FETCH_MAX_BYTES`, `KAFKA_FETCH_MIN_BYTES`, `KAFKA_FETCH_MAX_WAIT_MS`, `KAFKA_MAX_IN_FLIGHT_MESSAGES`, `PROCESSOR_BATCH_SIZE`, `PROCESSOR_BATCH_TIMEOUT`).

View File

@@ -0,0 +1,6 @@
## 1. Implementation
- [x] 1.1 Support all numeric overflow types (`int16`, `int32`, `int64`) with JavaScript two's complement mapped conversions.
- [x] 1.2 Replace batch `INSERT` logic with `COPY... FROM STDIN` streaming using `pg-copy-streams` to achieve massive raw write throughput.
- [x] 1.3 Add dynamic string formatter mapping arrays properly for native PostgreSQL Tab-Separated ingestion formatting.
- [x] 1.4 Wire fallback inserts explicitly tracking fully failed outputs into the isolated `heartbeat_events_errors` capture bucket.
- [x] 1.5 Update the `openspec` specs representing these architectural and constraint transitions.

View File

@@ -1,15 +0,0 @@
# Change: Handle integer overflows and persist unprocessable data
## Why
Hardware devices occasionally report `service_mask` or other bitmasks and counters (like `power_state`) where their unsigned values exceed PostgreSQL's signed boundaries (e.g. `uint64`, `uint32`, `uint16`). This triggers out of range database insertion errors which causes batch failure and falls back to individual row insertions. Previously, rows that failed due to data range constraints directly crashed out or were only logged to Redis, meaning fully invalid data or boundary constraint violations were fundamentally lost from DB history.
## What Changes
- Safely map completely oversized integers to signed `int64`, `int32`, `int16` 2's complement equivalents natively in Javascript (e.g. `(v << 16) >> 16` for `int2`).
- Refine the loop mechanism in `databaseManager.js` to avoid throwing errors exclusively built from data-level constraint mismatches when doing individual row fallback.
- Extend `_emitRejectedRecord` to persist any unprocessable, validation-failing, or insert-failing raw records directly into a dedicated error database table: `heartbeat_events_errors`.
## Impact
- Affected specs: `processor`
- Affected code:
- `src/processor/heartbeatProcessor.js`
- `src/db/databaseManager.js`

View File

@@ -1,6 +0,0 @@
## 1. Implementation
- [x] 1.1 Update `heartbeatProcessor.js` to handle all numeric overflow types (`int16`, `int32`, `int64`) with two's complement.
- [x] 1.2 Prevent purely data-related Postgres failures from throwing away individual fallbacks within `databaseManager.js`.
- [x] 1.3 Add `insertHeartbeatEventsErrors` to `databaseManager.js` to sink rejected records.
- [x] 1.4 Wire `_emitRejectedRecord` in `heartbeatProcessor.js` to directly write all completely unprocessable heartbeats into the `heartbeat_events_errors` DB.
- [x] 1.5 Update the `openspec` specs with these newly supported overflow & validation fallback states.