feat: 重构项目心跳数据结构并实现项目列表API

- 新增统一项目列表Redis键和迁移工具
- 实现GET /api/projects端点获取项目列表
- 实现POST /api/projects/migrate端点支持数据迁移
- 更新前端ProjectSelector组件使用真实项目数据
- 扩展projectStore状态管理
- 更新相关文档和OpenSpec规范
- 添加测试用例验证新功能
This commit is contained in:
2026-01-13 19:45:05 +08:00
parent 19e65d78dc
commit 282f7268ed
66 changed files with 4378 additions and 456 deletions

View File

@@ -1,11 +1,13 @@
# Redis Connection Capability Design
## Context
This design document describes the technical implementation of 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.
## Goals / Non-Goals
### Goals
- Establish and manage connection to Redis server
- Provide configuration options for Redis connection
- Implement automatic reconnection mechanism
@@ -13,6 +15,7 @@ This design document describes the technical implementation of the Redis connect
- Monitor and report connection status
### Non-Goals
- Redis server administration
- Redis cluster management
- Advanced Redis features (e.g., pub/sub, streams) beyond basic queue operations
@@ -20,29 +23,33 @@ This design document describes the technical implementation of the Redis connect
## Decisions
### Decision: Redis Client Library
- **What**: Use the official `redis` npm package
- **Why**: It's the official Redis client for Node.js, well-maintained, and supports all Redis commands
- **Alternatives considered**:
- **Alternatives considered**:
- `ioredis`: More features but more complex
- `node-redis`: Older, less maintained
### Decision: Connection Configuration
- **What**: Use environment variables for Redis connection configuration
- **Why**: Environment variables are a standard way to configure services in containerized environments, and they allow easy configuration without code changes
- **Alternatives considered**:
- **Alternatives considered**:
- Configuration files: Less flexible for containerized environments
- Hardcoded values: Not suitable for production use
### Decision: Reconnection Strategy
- **What**: Use exponential backoff for reconnection attempts
- **Why**: Exponential backoff prevents overwhelming the Redis server with reconnection attempts, while still ensuring timely reconnection
- **Alternatives considered**:
- **Alternatives considered**:
- Fixed interval reconnection: Less efficient, could overwhelm the server
- No reconnection: Not suitable for production use
## Architecture
### Redis Connection Architecture
```
Redis Connection Manager
├── Redis Client
@@ -54,25 +61,28 @@ Redis Connection Manager
## Implementation Details
### Redis Client Initialization
1. Server reads Redis configuration from environment variables
2. Server creates a Redis client instance with the configuration
3. Server attaches event listeners for connection events (connect, error, end, reconnecting)
4. Server attempts to connect to Redis
### Configuration Parameters
| Parameter | Default Value | Environment Variable | Description |
|-----------|---------------|----------------------|-------------|
| host | localhost | REDIS_HOST | Redis server hostname |
| port | 6379 | REDIS_PORT | Redis server port |
| password | null | REDIS_PASSWORD | Redis server password |
| db | 0 | REDIS_DB | Redis database index |
| connectTimeout | 10000 | REDIS_CONNECT_TIMEOUT | Connection timeout in milliseconds |
| maxRetriesPerRequest | 3 | REDIS_MAX_RETRIES | Maximum retries per request |
| reconnectStrategy | exponential | REDIS_RECONNECT_STRATEGY | Reconnection strategy (exponential, fixed) |
| reconnectInterval | 1000 | REDIS_RECONNECT_INTERVAL | Base reconnection interval in milliseconds |
| maxReconnectInterval | 30000 | REDIS_MAX_RECONNECT_INTERVAL | Maximum reconnection interval in milliseconds |
| Parameter | Default Value | Environment Variable | Description |
| -------------------- | ------------- | ---------------------------- | --------------------------------------------- |
| host | localhost | REDIS_HOST | Redis server hostname |
| port | 6379 | REDIS_PORT | Redis server port |
| password | null | REDIS_PASSWORD | Redis server password |
| db | 0 | REDIS_DB | Redis database index |
| connectTimeout | 10000 | REDIS_CONNECT_TIMEOUT | Connection timeout in milliseconds |
| maxRetriesPerRequest | 3 | REDIS_MAX_RETRIES | Maximum retries per request |
| reconnectStrategy | exponential | REDIS_RECONNECT_STRATEGY | Reconnection strategy (exponential, fixed) |
| reconnectInterval | 1000 | REDIS_RECONNECT_INTERVAL | Base reconnection interval in milliseconds |
| maxReconnectInterval | 30000 | REDIS_MAX_RECONNECT_INTERVAL | Maximum reconnection interval in milliseconds |
### Reconnection Implementation
- Use the built-in reconnection feature of the `redis` package
- Configure exponential backoff with:
- Initial delay: 1 second
@@ -81,11 +91,13 @@ Redis Connection Manager
- Log each reconnection attempt with timestamp and delay
### Error Handling
- **Connection errors**: Log the error, update connection status, and attempt to reconnect
- **Command errors**: Log the error, update the command status, and notify the user
- **Timeout errors**: Log the error, update connection status, and attempt to reconnect
### Connection Monitoring
- Track connection status (connecting, connected, disconnected, error)
- Log status changes with timestamps
- Expose connection status via API endpoint
@@ -94,21 +106,26 @@ Redis Connection Manager
## Risks / Trade-offs
### Risk: Redis Server Unavailability
- **Risk**: If the Redis server is unavailable for an extended period, the system won't be able to read logs or send commands
- **Mitigation**: Implement proper error handling and reconnection logic, and notify users of the issue
### Risk: Misconfiguration of Redis Connection
- **Risk**: Incorrect Redis configuration could lead to connection failures
- **Mitigation**: Validate configuration on startup, log configuration values (excluding passwords), and provide clear error messages
### Risk: Performance Impact of Reconnection Attempts
- **Risk**: Frequent reconnection attempts could impact system performance
- **Mitigation**: Use exponential backoff to reduce the frequency of reconnection attempts, and limit the maximum reconnection delay
## Migration Plan
No migration is required as this is a new feature.
## Open Questions
- What is the expected Redis server availability?
- Should we implement connection pooling for better performance?
- Should we support Redis Sentinel or Cluster for high availability?
- Should we support Redis Sentinel or Cluster for high availability?

View File

@@ -1,48 +1,59 @@
# 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.
## Requirements
### Requirement: Redis Connection Establishment
The system SHALL establish a connection to the Redis server.
#### Scenario: Establishing Redis connection on server start
- **WHEN** the server starts
- **THEN** it SHALL attempt to connect to the Redis server
- **AND** it SHALL log the connection status
### 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 override default values
### Requirement: Redis Connection Reconnection
The system SHALL automatically reconnect to Redis if the connection is lost.
#### Scenario: Reconnecting to Redis after connection loss
- **WHEN** the Redis connection is lost
- **THEN** the system SHALL attempt to reconnect with exponential backoff
- **AND** it SHALL log each reconnection attempt
- **AND** it SHALL notify the user when connection is restored
### Requirement: Redis Connection Error Handling
The system SHALL handle Redis connection errors gracefully.
#### Scenario: Handling Redis connection failure
- **WHEN** the system fails to connect to Redis
- **THEN** it SHALL log the error
- **AND** it SHALL display an error message to the user
- **AND** it SHALL continue attempting to reconnect
### Requirement: Redis Connection Monitoring
The system SHALL monitor the Redis connection status.
#### Scenario: Monitoring Redis connection status
- **WHEN** the Redis connection status changes
- **THEN** the system SHALL update the connection status in the UI
- **AND** it SHALL log the status change
@@ -50,6 +61,7 @@ The system SHALL monitor the Redis connection status.
## Data Model
### Redis Connection Configuration
```json
{
"host": "string",
@@ -65,6 +77,7 @@ The system SHALL monitor the Redis connection status.
```
### Redis Connection Status
```json
{
"status": "string", // e.g., connecting, connected, disconnected, error
@@ -77,6 +90,7 @@ The system SHALL monitor the Redis connection status.
## API Endpoints
### GET /api/redis/status
- **Description**: Get Redis connection status
- **Response**:
```json
@@ -84,11 +98,12 @@ The system SHALL monitor the Redis connection status.
"status": "string",
"lastConnectedAt": "ISO-8601 string",
"lastDisconnectedAt": "ISO-8601 string",
"error": "string" // optional
"error": "string"
}
```
### POST /api/redis/reconnect
- **Description**: Manually reconnect to Redis
- **Response**:
```json
@@ -97,3 +112,47 @@ The system SHALL monitor the Redis connection status.
"message": "Reconnection attempt initiated"
}
```
### GET /api/projects
- **Description**: Get list of all projects from Redis
- **Response**:
```json
{
"success": true,
"projects": [
{
"id": "string",
"name": "string",
"apiBaseUrl": "string",
"lastActiveAt": "number",
"status": "online|offline|unknown",
"isOnline": "boolean",
"ageMs": "number"
}
],
"count": 10
}
```
### POST /api/projects/migrate
- **Description**: Migrate heartbeat data from old structure to new unified structure
- **Request Body**:
```json
{
"deleteOldKeys": false,
"dryRun": false
}
```
- **Response**:
```json
{
"success": true,
"message": "数据迁移完成",
"migrated": 5,
"projects": [...],
"listKey": "项目心跳",
"deleteOldKeys": false
}
```