feat: 添加 G5 状态表同步开关,默认关闭写入功能并更新相关配置和文档
This commit is contained in:
@@ -49,3 +49,7 @@ REDIS_PASSWORD=
|
|||||||
REDIS_DB=15
|
REDIS_DB=15
|
||||||
REDIS_CONNECT_TIMEOUT_MS=5000
|
REDIS_CONNECT_TIMEOUT_MS=5000
|
||||||
REDIS_PROJECT_NAME=bls-onoffline
|
REDIS_PROJECT_NAME=bls-onoffline
|
||||||
|
|
||||||
|
# G5 room_status.moment sync
|
||||||
|
# false: do not write room_status.room_status_moment_g5
|
||||||
|
G5_ROOM_STATUS_MOMENT_SYNC_ENABLED=false
|
||||||
|
|||||||
@@ -29,3 +29,7 @@ REDIS_PASSWORD=
|
|||||||
REDIS_DB=0
|
REDIS_DB=0
|
||||||
REDIS_PROJECT_NAME=bls-onoffline
|
REDIS_PROJECT_NAME=bls-onoffline
|
||||||
REDIS_API_BASE_URL=http://localhost:3001
|
REDIS_API_BASE_URL=http://localhost:3001
|
||||||
|
|
||||||
|
# G5 room_status.moment sync
|
||||||
|
# false: do not write room_status.room_status_moment_g5
|
||||||
|
G5_ROOM_STATUS_MOMENT_SYNC_ENABLED=false
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
# Change: add g5 room status sync toggle
|
||||||
|
|
||||||
|
## Why
|
||||||
|
当前 G5 `room_status.room_status_moment_g5` 同步是默认启用的,但新的运行要求需要默认关闭,避免未经确认就写入状态表。
|
||||||
|
|
||||||
|
## What Changes
|
||||||
|
- 新增一个环境变量开关,控制是否同步写入 G5 `room_status.room_status_moment_g5`。
|
||||||
|
- 默认值为 `false`,即不写入该表。
|
||||||
|
- 当开关开启时,保留现有按 `hotel_id + room_id` upsert 更新 `ip` 的行为。
|
||||||
|
|
||||||
|
## Impact
|
||||||
|
- Affected specs: `openspec/specs/onoffline/spec.md`
|
||||||
|
- Affected code: `src/config/config.js`, `src/index.js`, `.env`, `.env.example`
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
## ADDED Requirements
|
||||||
|
|
||||||
|
### Requirement: G5 状态表同步开关
|
||||||
|
系统 SHALL 提供一个环境变量开关,用于控制是否向 G5 状态表 `room_status.room_status_moment_g5` 写入数据;该开关默认值 SHALL 为 `false`。
|
||||||
|
|
||||||
|
#### Scenario: 默认关闭
|
||||||
|
- **GIVEN** 未设置 G5 状态表同步开关
|
||||||
|
- **WHEN** 服务启动并处理 Kafka 消息
|
||||||
|
- **THEN** 系统不向 `room_status.room_status_moment_g5` 写入数据
|
||||||
|
|
||||||
|
#### Scenario: 显式开启
|
||||||
|
- **GIVEN** G5 状态表同步开关被设置为 `true`
|
||||||
|
- **WHEN** 服务处理 Kafka 消息
|
||||||
|
- **THEN** 系统恢复向 `room_status.room_status_moment_g5` 写入数据
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
## 1. Implementation
|
||||||
|
- [x] 1.1 Add a config flag for G5 room_status synchronization.
|
||||||
|
- [x] 1.2 Disable `room_status.room_status_moment_g5` writes by default.
|
||||||
|
- [x] 1.3 Keep the existing upsert behavior when the flag is enabled.
|
||||||
|
- [x] 1.4 Update environment samples to set the flag to `false`.
|
||||||
|
|
||||||
|
## 2. Validation
|
||||||
|
- [x] 2.1 Run `npm run lint`.
|
||||||
|
- [x] 2.2 Run `npm run test`.
|
||||||
|
- [x] 2.3 Run `npm run build`.
|
||||||
|
- [x] 2.4 Run `openspec validate add-g5-room-status-sync-toggle --strict`.
|
||||||
@@ -106,3 +106,16 @@
|
|||||||
- **WHEN** 服务处理该错误
|
- **WHEN** 服务处理该错误
|
||||||
- **THEN** 服务记录错误并按既有错误处理机制处理,不在运行时执行分区创建
|
- **THEN** 服务记录错误并按既有错误处理机制处理,不在运行时执行分区创建
|
||||||
|
|
||||||
|
### Requirement: G5 状态表同步开关
|
||||||
|
系统 SHALL 提供一个环境变量开关,用于控制是否向 G5 状态表 `room_status.room_status_moment_g5` 写入数据;该开关默认值 SHALL 为 `false`。
|
||||||
|
|
||||||
|
#### Scenario: 默认关闭
|
||||||
|
- **GIVEN** 未设置 G5 状态表同步开关
|
||||||
|
- **WHEN** 服务启动并处理 Kafka 消息
|
||||||
|
- **THEN** 系统不向 `room_status.room_status_moment_g5` 写入数据
|
||||||
|
|
||||||
|
#### Scenario: 显式开启
|
||||||
|
- **GIVEN** G5 状态表同步开关被设置为 `true`
|
||||||
|
- **WHEN** 服务处理 Kafka 消息
|
||||||
|
- **THEN** 系统恢复向 `room_status.room_status_moment_g5` 写入数据
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,12 @@ const parseList = (value) =>
|
|||||||
.map((item) => item.trim())
|
.map((item) => item.trim())
|
||||||
.filter(Boolean);
|
.filter(Boolean);
|
||||||
|
|
||||||
|
const parseBoolean = (value, defaultValue) => {
|
||||||
|
if (value === undefined || value === null || value === '') return defaultValue;
|
||||||
|
if (typeof value === 'boolean') return value;
|
||||||
|
return value === 'true' || value === '1';
|
||||||
|
};
|
||||||
|
|
||||||
export const config = {
|
export const config = {
|
||||||
env: process.env.NODE_ENV || 'development',
|
env: process.env.NODE_ENV || 'development',
|
||||||
port: parseNumber(process.env.PORT, 3001),
|
port: parseNumber(process.env.PORT, 3001),
|
||||||
@@ -51,6 +57,7 @@ export const config = {
|
|||||||
},
|
},
|
||||||
g5db: {
|
g5db: {
|
||||||
enabled: !!process.env.POSTGRES_HOST_G5,
|
enabled: !!process.env.POSTGRES_HOST_G5,
|
||||||
|
roomStatusMomentSyncEnabled: parseBoolean(process.env.G5_ROOM_STATUS_MOMENT_SYNC_ENABLED, false),
|
||||||
host: process.env.POSTGRES_HOST_G5,
|
host: process.env.POSTGRES_HOST_G5,
|
||||||
port: parseNumber(process.env.POSTGRES_PORT_G5, 5434),
|
port: parseNumber(process.env.POSTGRES_PORT_G5, 5434),
|
||||||
user: process.env.POSTGRES_USER_G5,
|
user: process.env.POSTGRES_USER_G5,
|
||||||
|
|||||||
@@ -21,6 +21,10 @@ const bootstrap = async () => {
|
|||||||
database: config.db.database,
|
database: config.db.database,
|
||||||
schema: config.db.schema
|
schema: config.db.schema
|
||||||
},
|
},
|
||||||
|
g5db: {
|
||||||
|
enabled: config.g5db.enabled,
|
||||||
|
roomStatusMomentSyncEnabled: config.g5db.roomStatusMomentSyncEnabled
|
||||||
|
},
|
||||||
kafka: {
|
kafka: {
|
||||||
brokers: config.kafka.brokers,
|
brokers: config.kafka.brokers,
|
||||||
topic: config.kafka.topic,
|
topic: config.kafka.topic,
|
||||||
@@ -183,10 +187,12 @@ const bootstrap = async () => {
|
|||||||
promises.push(g5DbManager.insertRows({ schema: config.g5db.schema, table: config.g5db.table, rows }).catch(e => {
|
promises.push(g5DbManager.insertRows({ schema: config.g5db.schema, table: config.g5db.table, rows }).catch(e => {
|
||||||
logger.error('G5 Database insert failed but non-blocking', { error: e.message });
|
logger.error('G5 Database insert failed but non-blocking', { error: e.message });
|
||||||
}));
|
}));
|
||||||
|
if (config.g5db.roomStatusMomentSyncEnabled) {
|
||||||
promises.push(g5DbManager.upsertRoomStatusMomentIp(rows).catch(e => {
|
promises.push(g5DbManager.upsertRoomStatusMomentIp(rows).catch(e => {
|
||||||
logger.error('G5 room_status_moment_g5 upsert failed but non-blocking', { error: e.message });
|
logger.error('G5 room_status_moment_g5 upsert failed but non-blocking', { error: e.message });
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
await Promise.all(promises);
|
await Promise.all(promises);
|
||||||
|
|
||||||
metricCollector.increment('db_insert_count', 1);
|
metricCollector.increment('db_insert_count', 1);
|
||||||
@@ -216,10 +222,12 @@ const bootstrap = async () => {
|
|||||||
promises.push(g5DbManager.insertRows({ schema: config.g5db.schema, table: config.g5db.table, rows }).catch(e => {
|
promises.push(g5DbManager.insertRows({ schema: config.g5db.schema, table: config.g5db.table, rows }).catch(e => {
|
||||||
logger.error('G5 Database insert failed in insertOnce', { error: e.message });
|
logger.error('G5 Database insert failed in insertOnce', { error: e.message });
|
||||||
}));
|
}));
|
||||||
|
if (config.g5db.roomStatusMomentSyncEnabled) {
|
||||||
promises.push(g5DbManager.upsertRoomStatusMomentIp(rows).catch(e => {
|
promises.push(g5DbManager.upsertRoomStatusMomentIp(rows).catch(e => {
|
||||||
logger.error('G5 room_status_moment_g5 upsert failed in insertOnce', { error: e.message });
|
logger.error('G5 room_status_moment_g5 upsert failed in insertOnce', { error: e.message });
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
await Promise.all(promises);
|
await Promise.all(promises);
|
||||||
metricCollector.increment('db_insert_count', 1);
|
metricCollector.increment('db_insert_count', 1);
|
||||||
metricCollector.increment('db_insert_ms_sum', Date.now() - startedAt);
|
metricCollector.increment('db_insert_ms_sum', Date.now() - startedAt);
|
||||||
|
|||||||
Reference in New Issue
Block a user