# 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 retrieving project heartbeats. ## 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 - **AND** it SHALL use Redis database 15 ### 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 ### 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 ```json { "host": "string", "port": "number", "password": "string", "db": "number", "socket": { "reconnectStrategy": "function", "connectTimeout": "number", "keepAlive": "number" } } ``` ### Redis Connection Status ```json { "status": "string", // e.g., connecting, connected, disconnected, error "lastConnectedAt": "ISO-8601 string", "lastDisconnectedAt": "ISO-8601 string", "error": "string" // optional error message } ``` ## API Endpoints ### GET /api/redis/status - **Description**: Get Redis connection status - **Response**: ```json { "status": "string", "lastConnectedAt": "ISO-8601 string", "lastDisconnectedAt": "ISO-8601 string", "error": "string" } ``` ### POST /api/redis/reconnect - **Description**: Manually reconnect to Redis - **Response**: ```json { "success": true, "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 } ``` ## Redis Data Structures ### Key: 项目心跳 - **Type**: LIST - **Element**: JSON string `{"projectName":"...","apiBaseUrl":"...","lastActiveAt":1768566165572}`