feat: 重构项目心跳数据结构并实现项目列表API
- 新增统一项目列表Redis键和迁移工具 - 实现GET /api/projects端点获取项目列表 - 实现POST /api/projects/migrate端点支持数据迁移 - 更新前端ProjectSelector组件使用真实项目数据 - 扩展projectStore状态管理 - 更新相关文档和OpenSpec规范 - 添加测试用例验证新功能
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
# Command Capability Design
|
||||
|
||||
## Context
|
||||
|
||||
This design document describes the technical implementation of 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.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
### Goals
|
||||
|
||||
- Implement command sending to Redis queues
|
||||
- Provide command validation and error handling
|
||||
- Maintain a history of sent commands
|
||||
@@ -13,6 +15,7 @@ This design document describes the technical implementation of the command capab
|
||||
- Ensure high performance and reliability
|
||||
|
||||
### Non-Goals
|
||||
|
||||
- Command execution or processing
|
||||
- Complex command syntax highlighting
|
||||
- Advanced command editing capabilities
|
||||
@@ -20,29 +23,33 @@ This design document describes the technical implementation of the command capab
|
||||
## Decisions
|
||||
|
||||
### Decision: Redis Queue Implementation
|
||||
|
||||
- **What**: Use Redis List as the queue data structure
|
||||
- **Why**: Redis Lists provide efficient push/pop operations with O(1) time complexity, making them ideal for message queues
|
||||
- **Alternatives considered**:
|
||||
- **Alternatives considered**:
|
||||
- Redis Streams: More advanced but overkill for our use case
|
||||
- Redis Pub/Sub: No persistence, so commands would be lost if the receiving program is down
|
||||
|
||||
### Decision: Command History Storage
|
||||
|
||||
- **What**: Store command history in memory with a configurable maximum size
|
||||
- **Why**: In-memory storage provides fast access times and avoids the complexity of database management
|
||||
- **Alternatives considered**:
|
||||
- **Alternatives considered**:
|
||||
- Database storage: Adds complexity and latency
|
||||
- File system: Not suitable for real-time access
|
||||
|
||||
### Decision: Command Validation
|
||||
|
||||
- **What**: Implement basic command validation on both frontend and backend
|
||||
- **Why**: Frontend validation provides immediate feedback to users, while backend validation ensures data integrity
|
||||
- **Alternatives considered**:
|
||||
- **Alternatives considered**:
|
||||
- Only frontend validation: Less secure, as users could bypass it
|
||||
- Only backend validation: Less responsive, as users would have to wait for server response
|
||||
|
||||
## Architecture
|
||||
|
||||
### Frontend Architecture
|
||||
|
||||
```
|
||||
CommandView Component
|
||||
├── CommandForm Component
|
||||
@@ -51,6 +58,7 @@ CommandView Component
|
||||
```
|
||||
|
||||
### Backend Architecture
|
||||
|
||||
```
|
||||
Command Routes
|
||||
├── Command Service
|
||||
@@ -62,11 +70,13 @@ Command Routes
|
||||
## Implementation Details
|
||||
|
||||
### Redis Connection
|
||||
|
||||
- Use the `redis` npm package to connect to Redis
|
||||
- Implement automatic reconnection with exponential backoff
|
||||
- Handle connection errors gracefully
|
||||
|
||||
### Command Sending
|
||||
|
||||
1. User enters a command in the frontend form
|
||||
2. Frontend validates the command (not empty, no invalid characters)
|
||||
3. Frontend sends a POST request to `/api/commands` with the command content
|
||||
@@ -77,6 +87,7 @@ Command Routes
|
||||
8. Backend sends a success response to the frontend
|
||||
|
||||
### Command Validation
|
||||
|
||||
- **Frontend validation**:
|
||||
- Check that the command is not empty
|
||||
- Check that the command does not contain invalid characters (e.g., null bytes)
|
||||
@@ -86,6 +97,7 @@ Command Routes
|
||||
- Additional server-side validation if needed
|
||||
|
||||
### Command History
|
||||
|
||||
- Store command history in an array in memory
|
||||
- Implement a circular buffer to limit memory usage
|
||||
- Default maximum command count: 1000
|
||||
@@ -93,6 +105,7 @@ Command Routes
|
||||
- Include command ID, content, timestamp, and status
|
||||
|
||||
### Command Response Handling
|
||||
|
||||
1. Receiving program reads the command from the Redis queue
|
||||
2. Receiving program executes the command
|
||||
3. Receiving program writes the response to a separate Redis queue
|
||||
@@ -103,21 +116,26 @@ Command Routes
|
||||
## Risks / Trade-offs
|
||||
|
||||
### Risk: Redis Connection Failure
|
||||
|
||||
- **Risk**: If Redis connection is lost, commands won't be sent
|
||||
- **Mitigation**: Implement automatic reconnection with exponential backoff, and notify users when connection is lost
|
||||
|
||||
### Risk: Command Loss
|
||||
|
||||
- **Risk**: Commands could be lost if Redis goes down
|
||||
- **Mitigation**: Implement Redis persistence (RDB or AOF) to ensure commands are not lost
|
||||
|
||||
### Risk: Command Response Timeout
|
||||
|
||||
- **Risk**: Commands could take too long to execute, causing the UI to hang
|
||||
- **Mitigation**: Implement a timeout mechanism for command responses, and show a loading indicator to users
|
||||
|
||||
## Migration Plan
|
||||
|
||||
No migration is required as this is a new feature.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- What is the expected maximum command frequency per minute?
|
||||
- Should we add support for command templates or macros?
|
||||
- Should we implement command scheduling for future execution?
|
||||
- Should we implement command scheduling for future execution?
|
||||
|
||||
@@ -1,44 +1,54 @@
|
||||
# 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.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Command Sending to Redis
|
||||
|
||||
The system SHALL send commands to a Redis queue.
|
||||
|
||||
#### Scenario: Sending a command to Redis queue
|
||||
|
||||
- **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
|
||||
|
||||
### Requirement: Command Validation
|
||||
|
||||
The system SHALL validate commands before sending them to Redis.
|
||||
|
||||
#### 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
|
||||
|
||||
#### 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
|
||||
|
||||
### Requirement: Command History
|
||||
|
||||
The system SHALL maintain a history of sent commands.
|
||||
|
||||
#### Scenario: Viewing command history
|
||||
|
||||
- **WHEN** the user opens the command history
|
||||
- **THEN** the system SHALL display a list of previously 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.
|
||||
|
||||
#### 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
|
||||
@@ -46,6 +56,7 @@ The system SHALL handle responses from commands sent to Redis.
|
||||
## Data Model
|
||||
|
||||
### Command
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "string",
|
||||
@@ -56,6 +67,7 @@ The system SHALL handle responses from commands sent to Redis.
|
||||
```
|
||||
|
||||
### Command Response
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "string",
|
||||
@@ -69,29 +81,80 @@ The system SHALL handle responses from commands sent to Redis.
|
||||
## API Endpoints
|
||||
|
||||
### POST /api/commands
|
||||
- **Description**: Send a command to the Redis queue
|
||||
|
||||
- **Description**: Send a command to a project's API endpoint
|
||||
- **Request Body**:
|
||||
```json
|
||||
{
|
||||
"content": "string" // the command to send
|
||||
"targetProjectName": "string",
|
||||
"command": "string"
|
||||
}
|
||||
```
|
||||
- **Response**:
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Command sent successfully",
|
||||
"commandId": "string"
|
||||
"message": "已调用目标项目 API",
|
||||
"commandId": "string",
|
||||
"targetUrl": "string",
|
||||
"upstreamStatus": 200,
|
||||
"upstreamData": "object"
|
||||
}
|
||||
```
|
||||
|
||||
### GET /api/projects
|
||||
|
||||
- **Description**: Get list of all projects with their heartbeat status
|
||||
- **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
|
||||
}
|
||||
```
|
||||
|
||||
### GET /api/commands/history
|
||||
- **Description**: Get command history
|
||||
|
||||
- **Description**: Get command history (deprecated - use project logs instead)
|
||||
- **Query Parameters**:
|
||||
- `limit`: Maximum number of commands to return (default: 50)
|
||||
- `offset`: Offset for pagination (default: 0)
|
||||
- **Response**: Array of command objects
|
||||
|
||||
### GET /api/commands/:id/response
|
||||
- **Description**: Get response for a specific command
|
||||
|
||||
- **Description**: Get response for a specific command (deprecated - use project logs instead)
|
||||
- **Response**: Command response object
|
||||
|
||||
Reference in New Issue
Block a user