feat: 重构项目心跳为Redis LIST并更新相关文档
重构项目心跳数据结构为Redis LIST,更新相关文档和OpenSpec规范。主要变更包括: - 将项目心跳从STRING改为LIST类型 - 更新后端服务以支持LIST操作 - 同步更新文档和OpenSpec规范 - 统一后端端口为3001 - 添加部署指南和Windows部署文档 修复前端API请求路径,移除硬编码的localhost地址。添加PM2和Nginx配置文件模板,完善部署流程文档。更新Redis集成协议文档,明确LIST数据结构和外部项目对接规范。
This commit is contained in:
28
openspec/changes/update-heartbeat-key-to-list/proposal.md
Normal file
28
openspec/changes/update-heartbeat-key-to-list/proposal.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# Change: Store project heartbeats as Redis LIST
|
||||
|
||||
## Why
|
||||
|
||||
当前项目将 `项目心跳` 存为 Redis STRING(JSON 数组),与外部项目的写入方式和并发更新场景不匹配;同时规范、文档与实现存在漂移(例如命令下发已改为 HTTP 调用,但规范仍描述 Redis 控制队列)。
|
||||
|
||||
## What Changes
|
||||
|
||||
- **BREAKING**:`项目心跳` 的 Redis 数据类型从 STRING 变更为 **LIST**。
|
||||
- 心跳记录以 JSON 字符串写入 LIST,每条元素表示一个项目的心跳记录:`{ projectName, apiBaseUrl, lastActiveAt }`。
|
||||
- 控制台后端按 `projectName` 去重,保留 `lastActiveAt` 最新的一条,作为项目列表/在线状态计算依据。
|
||||
- 对齐 OpenSpec 与文档:明确 DB 固定为 15;日志来自 `${projectName}_项目控制台`(LIST);命令下发通过 HTTP API 转发。
|
||||
|
||||
## Impact
|
||||
|
||||
- Affected specs: redis-connection, logging, command
|
||||
- Affected code:
|
||||
- src/backend/services/migrateHeartbeatData.js
|
||||
- src/backend/routes/projects.js
|
||||
- src/backend/routes/logs.js
|
||||
- src/backend/routes/commands.js
|
||||
- src/backend/server.js
|
||||
- Affected docs:
|
||||
- docs/redis-integration-protocol.md
|
||||
- docs/redis-data-structure.md
|
||||
- docs/openapi.yaml
|
||||
- README.md
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: Command Sending to Redis
|
||||
The system SHALL send commands to a target project's HTTP API.
|
||||
|
||||
#### Scenario: Sending a command to target project API
|
||||
- **WHEN** the user enters a command in the console
|
||||
- **AND** clicks the "Send" button
|
||||
- **THEN** the backend SHALL resolve `apiBaseUrl` from the project's heartbeat
|
||||
- **AND** it SHALL call `POST {apiBaseUrl}/{apiName}` with a structured payload
|
||||
- **AND** the user SHALL receive a success confirmation if upstream returns 2xx
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: Log Reading from Redis
|
||||
The system SHALL read log records from a Redis LIST `${projectName}_项目控制台`.
|
||||
|
||||
#### Scenario: Reading logs by polling
|
||||
- **WHEN** the user is viewing a project console
|
||||
- **THEN** the system SHALL read the latest log entries via `LRANGE`
|
||||
- **AND** it SHALL return logs in a user-friendly structure
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: Redis Connection Configuration
|
||||
The system SHALL allow configuration of Redis connection parameters.
|
||||
|
||||
#### Scenario: Configuring Redis connection via environment variables
|
||||
- **WHEN** the server starts with Redis environment variables set
|
||||
- **THEN** it SHALL use those variables to configure the Redis connection
|
||||
- **AND** it SHALL use Redis database 15
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Project Heartbeat List Retrieval
|
||||
The system SHALL read project heartbeats from Redis key `项目心跳` stored as a LIST.
|
||||
|
||||
#### Scenario: Reading projects list from Redis LIST
|
||||
- **WHEN** the client requests the projects list
|
||||
- **THEN** the system SHALL read `LRANGE 项目心跳 0 -1`
|
||||
- **AND** it SHALL parse each list element as JSON heartbeat record
|
||||
- **AND** it SHALL deduplicate by `projectName` and keep the latest `lastActiveAt`
|
||||
|
||||
9
openspec/changes/update-heartbeat-key-to-list/tasks.md
Normal file
9
openspec/changes/update-heartbeat-key-to-list/tasks.md
Normal file
@@ -0,0 +1,9 @@
|
||||
## 1. Implementation
|
||||
|
||||
- [ ] 1.1 Update OpenSpec specs for redis-connection/logging/command
|
||||
- [ ] 1.2 Update backend to read `项目心跳` as Redis LIST and dedupe projects
|
||||
- [ ] 1.3 Update backend to write migrated heartbeats into LIST
|
||||
- [ ] 1.4 Align backend port with Vite proxy/OpenAPI (default 3001)
|
||||
- [ ] 1.5 Update docs to match new Redis protocol and current behavior
|
||||
- [ ] 1.6 Update tests and validate with `npm test`
|
||||
|
||||
@@ -39,7 +39,7 @@ BLS Project Console是一个前后端分离的Node.js项目,用于从Redis队
|
||||
- **单元测试**: 对核心功能模块进行单元测试
|
||||
- **集成测试**: 测试API接口和Redis交互
|
||||
- **端到端测试**: 测试完整的用户流程
|
||||
- **测试框架**: Jest (后端), Vitest (前端)
|
||||
- **测试框架**: Vitest + Supertest
|
||||
|
||||
### Git Workflow
|
||||
|
||||
@@ -59,10 +59,10 @@ BLS Project Console是一个前后端分离的Node.js项目,用于从Redis队
|
||||
|
||||
## Domain Context
|
||||
|
||||
- **Redis队列**: 用于存储日志记录和控制台指令的消息队列
|
||||
- **日志记录**: 其他程序写入Redis队列的日志信息,包含时间戳、日志级别和消息内容
|
||||
- **控制台指令**: 从控制台发送到Redis队列的命令,供其他程序读取和执行
|
||||
- **实时更新**: 控制台需要实时从Redis队列获取新的日志记录
|
||||
- **Redis 数据结构**: DB15 中使用 `项目心跳`(LIST)与 `${projectName}_项目控制台`(LIST)
|
||||
- **日志记录**: 外部程序向 `${projectName}_项目控制台` 追加日志 JSON;控制台轮询读取并展示
|
||||
- **项目心跳**: 外部程序向 `项目心跳` 追加心跳 JSON;控制台按 projectName 去重并判定在线状态
|
||||
- **控制台指令**: 控制台通过 HTTP 调用目标项目 API(由心跳中的 `apiBaseUrl` 提供)
|
||||
|
||||
## Important Constraints
|
||||
|
||||
@@ -77,4 +77,4 @@ BLS Project Console是一个前后端分离的Node.js项目,用于从Redis队
|
||||
- **Redis**: 用于存储日志记录和控制台指令的消息队列服务
|
||||
- 版本: 6.x+
|
||||
- 连接方式: Redis客户端(redis@^4.6.10)
|
||||
- 主要用途: 日志队列和指令队列
|
||||
- 主要用途: 心跳列表与日志队列
|
||||
|
||||
@@ -1,34 +1,35 @@
|
||||
# Command Capability Specification
|
||||
|
||||
## Overview
|
||||
This specification defines the command capability for the BLS Project Console, which allows users to send console commands to Redis queues for other programs to read and execute.
|
||||
This specification defines the command capability for the BLS Project Console, which allows users to send console commands to target project HTTP APIs.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Command Sending to Redis
|
||||
The system SHALL send commands to a Redis queue.
|
||||
The system SHALL send commands to a target project's HTTP API.
|
||||
|
||||
#### Scenario: Sending a command to Redis queue
|
||||
#### Scenario: Sending a command to target project API
|
||||
- **WHEN** the user enters a command in the console
|
||||
- **AND** clicks the "Send" button
|
||||
- **THEN** the command SHALL be sent to the Redis queue
|
||||
- **AND** the user SHALL receive a success confirmation
|
||||
- **THEN** the backend SHALL resolve `apiBaseUrl` from the project's heartbeat
|
||||
- **AND** it SHALL call `POST {apiBaseUrl}/{apiName}` with a structured payload
|
||||
- **AND** the user SHALL receive a success confirmation if upstream returns 2xx
|
||||
|
||||
### Requirement: Command Validation
|
||||
The system SHALL validate commands before sending them to Redis.
|
||||
The system SHALL validate commands before sending them to target project API.
|
||||
|
||||
#### Scenario: Validating an empty command
|
||||
- **WHEN** the user tries to send an empty command
|
||||
- **THEN** the system SHALL display an error message
|
||||
- **AND** the command SHALL NOT be sent to Redis
|
||||
- **AND** the command SHALL NOT be sent
|
||||
|
||||
#### Scenario: Validating a command with invalid characters
|
||||
- **WHEN** the user tries to send a command with invalid characters
|
||||
- **THEN** the system SHALL display an error message
|
||||
- **AND** the command SHALL NOT be sent to Redis
|
||||
- **AND** the command SHALL NOT be sent
|
||||
|
||||
### Requirement: Command History
|
||||
The system SHALL maintain a history of sent commands.
|
||||
The system SHALL maintain a history of sent commands in the console UI.
|
||||
|
||||
#### Scenario: Viewing command history
|
||||
- **WHEN** the user opens the command history
|
||||
@@ -36,12 +37,11 @@ The system SHALL maintain a history of sent commands.
|
||||
- **AND** the user SHALL be able to select a command from the history to resend
|
||||
|
||||
### Requirement: Command Response Handling
|
||||
The system SHALL handle responses from commands sent to Redis.
|
||||
The system SHALL handle responses from commands sent to target project API.
|
||||
|
||||
#### Scenario: Receiving a command response
|
||||
- **WHEN** a command response is received from Redis
|
||||
- **THEN** the system SHALL display the response in the console
|
||||
- **AND** the response SHALL be associated with the original command
|
||||
- **WHEN** the target project API responds
|
||||
- **THEN** the system SHALL display the response status in the console
|
||||
|
||||
## Data Model
|
||||
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
# Logging Capability Specification
|
||||
|
||||
## Overview
|
||||
This specification defines the logging capability for the BLS Project Console, which allows the system to read log records from Redis queues and display them in the console interface.
|
||||
This specification defines the logging capability for the BLS Project Console, which allows the system to read log records from Redis lists and display them in the console interface.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Log Reading from Redis
|
||||
The system SHALL read log records from a Redis queue.
|
||||
The system SHALL read log records from a Redis LIST `${projectName}_项目控制台`.
|
||||
|
||||
#### Scenario: Reading logs from Redis queue
|
||||
- **WHEN** the server starts
|
||||
- **THEN** it SHALL establish a connection to the Redis queue
|
||||
- **AND** it SHALL begin listening for new log records
|
||||
- **AND** it SHALL store log records in memory for display
|
||||
#### Scenario: Reading logs by polling
|
||||
- **WHEN** the user is viewing a project console
|
||||
- **THEN** the system SHALL read the latest log entries via `LRANGE`
|
||||
- **AND** it SHALL return logs in a user-friendly structure
|
||||
|
||||
### Requirement: Log Display in Console
|
||||
The system SHALL display log records in a user-friendly format.
|
||||
@@ -83,7 +82,3 @@ The system SHALL automatically refresh logs in real-time.
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### GET /api/logs/live
|
||||
- **Description**: Establish a WebSocket connection for real-time log updates
|
||||
- **Response**: Continuous stream of log records
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Redis Connection Capability Specification
|
||||
|
||||
## Overview
|
||||
This specification defines the Redis connection capability for the BLS Project Console, which manages the connection between the system and the Redis server for reading logs and sending commands.
|
||||
This specification defines the Redis connection capability for the BLS Project Console, which manages the connection between the system and the Redis server for reading logs and retrieving project heartbeats.
|
||||
|
||||
## Requirements
|
||||
|
||||
@@ -20,6 +20,7 @@ The system SHALL allow configuration of Redis connection parameters.
|
||||
- **WHEN** the server starts with Redis environment variables set
|
||||
- **THEN** it SHALL use those variables to configure the Redis connection
|
||||
- **AND** it SHALL override default values
|
||||
- **AND** it SHALL use Redis database 15
|
||||
|
||||
### Requirement: Redis Connection Reconnection
|
||||
The system SHALL automatically reconnect to Redis if the connection is lost.
|
||||
@@ -47,6 +48,15 @@ The system SHALL monitor the Redis connection status.
|
||||
- **THEN** the system SHALL update the connection status in the UI
|
||||
- **AND** it SHALL log the status change
|
||||
|
||||
### Requirement: Project Heartbeat List Retrieval
|
||||
The system SHALL read project heartbeats from Redis key `项目心跳` stored as a LIST.
|
||||
|
||||
#### Scenario: Reading projects list from Redis LIST
|
||||
- **WHEN** the client requests the projects list
|
||||
- **THEN** the system SHALL read `LRANGE 项目心跳 0 -1`
|
||||
- **AND** it SHALL parse each list element as JSON heartbeat record
|
||||
- **AND** it SHALL deduplicate by `projectName` and keep the latest `lastActiveAt`
|
||||
|
||||
## Data Model
|
||||
|
||||
### Redis Connection Configuration
|
||||
@@ -139,3 +149,9 @@ The system SHALL monitor the Redis connection status.
|
||||
"deleteOldKeys": false
|
||||
}
|
||||
```
|
||||
|
||||
## Redis Data Structures
|
||||
|
||||
### Key: 项目心跳
|
||||
- **Type**: LIST
|
||||
- **Element**: JSON string `{"projectName":"...","apiBaseUrl":"...","lastActiveAt":1768566165572}`
|
||||
|
||||
Reference in New Issue
Block a user