添加qiming-rcoder模块

This commit is contained in:
Codex
2026-06-01 13:54:52 +08:00
parent 8092c4b1f8
commit 4b1a580132
539 changed files with 151650 additions and 0 deletions

View File

@@ -0,0 +1,360 @@
# Design Document
## Overview
This design document outlines the unified container stopping module that will consolidate all container stopping logic into a single, reusable module within the `docker_manager` crate. The module will provide two distinct stopping strategies optimized for different scenarios: startup cleanup and runtime cleanup.
## Architecture
### Module Location
```
crates/docker_manager/src/
├── lib.rs (existing)
├── manager.rs (existing)
├── types.rs (existing)
├── utils.rs (existing)
└── container_stop.rs (new - unified stopping logic)
```
### High-Level Design
```mermaid
graph TD
A[main.rs startup] -->|startup cleanup| B[container_stop::startup_cleanup]
C[cleanup_task.rs] -->|runtime cleanup| D[container_stop::runtime_cleanup]
E[container_manager.rs] -->|runtime cleanup| D
B --> F[stop_with_409_filter]
D --> G[stop_with_quick_timeout]
F --> H[DockerManager::stop_container_by_id_with_timeout]
G --> H
H --> I[Docker API]
```
## Components and Interfaces
### 1. Container Stop Module (`container_stop.rs`)
#### Public API
```rust
/// 启动时容器清理策略
///
/// 特点:
/// - 使用5秒超时
/// - 过滤409冲突错误容器已在删除中
/// - 不阻塞服务启动
pub async fn startup_cleanup_containers(
docker_manager: &DockerManager,
pattern: &str,
) -> Result<CleanupResult, DockerError>
/// 运行时容器清理策略
///
/// 特点:
/// - 使用3秒优雅停止超时
/// - 立即强制停止
/// - 快速释放资源
pub async fn runtime_cleanup_container(
docker_manager: &DockerManager,
container_id: &str,
) -> Result<(), DockerError>
/// 运行时批量清理容器
pub async fn runtime_cleanup_containers(
docker_manager: &DockerManager,
container_ids: Vec<String>,
) -> Result<CleanupResult, DockerError>
```
#### Internal Helper Functions
```rust
/// 停止单个容器(启动场景)
async fn stop_container_startup_mode(
docker_manager: &DockerManager,
container_id: &str,
) -> Result<(), DockerError>
/// 停止单个容器(运行时场景)
async fn stop_container_runtime_mode(
docker_manager: &DockerManager,
container_id: &str,
) -> Result<(), DockerError>
/// 检查是否为409冲突错误
fn is_409_conflict_error(error: &DockerError) -> bool
/// 创建清理结果统计
fn create_cleanup_result(
total: usize,
successful: usize,
failed: usize,
removed_ids: Vec<String>,
failures: Vec<ContainerRemovalFailure>,
) -> CleanupResult
```
### 2. Configuration Constants
```rust
/// 启动清理超时时间(秒)
const STARTUP_CLEANUP_TIMEOUT_SECONDS: u64 = 5;
/// 运行时清理超时时间(秒)
const RUNTIME_CLEANUP_TIMEOUT_SECONDS: u64 = 3;
/// 容器停止后的等待时间(毫秒)
const POST_STOP_WAIT_MS: u64 = 100;
```
## Data Models
### CleanupResult (existing, reused)
```rust
pub struct CleanupResult {
pub total_found: usize,
pub successfully_removed: usize,
pub failed_removals: usize,
pub removed_container_ids: Vec<String>,
pub failed_removals_details: Vec<ContainerRemovalFailure>,
pub duration_ms: u64,
}
```
### ContainerRemovalFailure (existing, reused)
```rust
pub struct ContainerRemovalFailure {
pub container_id: String,
pub container_name: String,
pub error_message: String,
}
```
## Error Handling
### Startup Cleanup Error Handling
1. **409 Conflict Errors**
- Log at INFO level: "容器已在删除中,跳过"
- Do not count as failure
- Continue processing other containers
2. **Other Errors**
- Log at WARN level with error details
- Count as failure in statistics
- Continue processing other containers
- Do not block service startup
### Runtime Cleanup Error Handling
1. **All Errors**
- Log at WARN level with error details
- Return error to caller
- Caller decides whether to continue
2. **Timeout Handling**
- If graceful stop times out, force stop immediately
- Log timeout at WARN level
- Continue with force stop
## Testing Strategy
### Unit Tests
```rust
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_is_409_conflict_error() {
// Test 409 error detection
}
#[test]
fn test_cleanup_result_creation() {
// Test result statistics calculation
}
#[tokio::test]
async fn test_startup_cleanup_filters_409() {
// Test that 409 errors are filtered during startup
}
#[tokio::test]
async fn test_runtime_cleanup_quick_timeout() {
// Test that runtime cleanup uses 3-second timeout
}
}
```
### Integration Tests
1. **Startup Cleanup Integration**
- Create test containers
- Simulate 409 conflict scenario
- Verify service continues without error
2. **Runtime Cleanup Integration**
- Create running container
- Verify 3-second timeout behavior
- Verify force stop after timeout
## Implementation Details
### Startup Cleanup Flow
```
1. List all containers matching pattern
2. For each container:
a. Call stop_container_startup_mode
b. Use 5-second timeout
c. If 409 error: log INFO, skip to next
d. If other error: log WARN, count as failure
e. If success: count as success
3. Return CleanupResult with statistics
```
### Runtime Cleanup Flow
```
1. For given container_id:
a. Call stop_container_runtime_mode
b. Use 3-second graceful timeout
c. If timeout: force stop immediately
d. Remove container
e. Log result
2. Return success or error
```
### Integration Points
#### main.rs Changes
```rust
// Before
match startup_cleanup_orphaned_containers(&docker_manager).await {
Ok(cleaned_count) => { /* ... */ }
Err(e) => { /* ... */ }
}
// After
use docker_manager::container_stop;
match container_stop::startup_cleanup_containers(&docker_manager, "rcoder-agent-*").await {
Ok(result) => {
if result.successfully_removed > 0 {
info!("✅ 启动时清理完成,共清理了 {} 个遗留容器", result.successfully_removed);
}
}
Err(e) => {
warn!("⚠️ 启动时容器清理失败: {},但这不影响服务启动", e);
}
}
```
#### cleanup_task.rs Changes
```rust
// In destroy_docker_container method
use docker_manager::container_stop;
// Replace stop_container_by_id_with_timeout call
container_stop::runtime_cleanup_container(&docker_manager, &container_id).await?;
```
#### container_manager.rs Changes
```rust
// If needed for container cleanup
use docker_manager::container_stop;
container_stop::runtime_cleanup_container(&docker_manager, &container_id).await?;
```
## Performance Considerations
1. **Startup Cleanup**
- Parallel processing of containers (existing behavior maintained)
- 5-second timeout prevents long blocking
- 409 filtering reduces unnecessary retries
2. **Runtime Cleanup**
- 3-second timeout balances speed and graceful shutdown
- Immediate force stop after timeout
- Minimal resource holding time
## Security Considerations
1. **Container Isolation**
- Only stop containers matching specific patterns
- Validate container ownership before stopping
2. **Error Information**
- Do not expose sensitive container details in logs
- Use generic error messages for external errors
## Logging Strategy
### Log Levels
- **INFO**: Normal operations, 409 conflicts during startup
- **WARN**: Unexpected errors, timeouts
- **ERROR**: Critical failures (none expected in this module)
- **DEBUG**: Detailed operation flow (for development)
### Log Format
```rust
// Startup cleanup
info!("🧹 [STARTUP_CLEANUP] 开始清理容器: pattern={}", pattern);
info!("✅ [STARTUP_CLEANUP] 容器清理成功: container_id={}", container_id);
info!("🔄 [STARTUP_CLEANUP] 容器已在删除中,跳过: container_id={}", container_id);
warn!("⚠️ [STARTUP_CLEANUP] 容器清理失败: container_id={}, error={}", container_id, error);
// Runtime cleanup
info!("🔥 [RUNTIME_CLEANUP] 开始停止容器: container_id={}", container_id);
info!("✅ [RUNTIME_CLEANUP] 容器停止成功: container_id={}", container_id);
warn!("⏰ [RUNTIME_CLEANUP] 容器停止超时,强制停止: container_id={}", container_id);
warn!("⚠️ [RUNTIME_CLEANUP] 容器停止失败: container_id={}, error={}", container_id, error);
```
## Migration Strategy
### Phase 1: Create New Module
- Implement `container_stop.rs` in docker_manager crate
- Add unit tests
- Export public API from lib.rs
### Phase 2: Update main.rs
- Replace startup cleanup logic
- Test service startup with orphaned containers
- Verify 409 error filtering
### Phase 3: Update cleanup_task.rs
- Replace destroy_docker_container logic
- Test runtime cleanup behavior
- Verify 3-second timeout
### Phase 4: Update container_manager.rs (if needed)
- Replace any container stopping logic
- Test container lifecycle
### Phase 5: Cleanup
- Remove old duplicated code
- Update documentation
- Final integration testing
## Rollback Plan
If issues are discovered:
1. Revert changes to calling code (main.rs, cleanup_task.rs, etc.)
2. Keep new module for future use
3. Restore original inline implementations
4. Document issues for future redesign

View File

@@ -0,0 +1,78 @@
# Requirements Document
## Introduction
This document defines the requirements for unifying container stopping logic across the rcoder codebase. Currently, container stopping logic is scattered across multiple files with inconsistent implementations. We need to consolidate this into two well-defined scenarios with reusable functions.
## Glossary
- **Container**: Docker容器实例
- **Startup Cleanup**: 服务启动时的容器清理流程
- **Runtime Cleanup**: 运行时的容器清理流程
- **409 Conflict Error**: Docker API返回的容器已在删除中的错误
- **Graceful Stop**: 给容器优雅退出时间的停止方式
- **Force Stop**: 立即强制停止容器的方式
- **docker_manager**: 负责Docker容器管理的crate模块
## Requirements
### Requirement 1: 启动时容器清理场景
**User Story:** As a system administrator, I want the rcoder service to clean up orphaned containers during startup without blocking the service initialization, so that the system can start reliably even when containers are already being deleted.
#### Acceptance Criteria
1. WHEN the rcoder service starts, THE Container Stop Module SHALL identify all rcoder-agent-* containers
2. WHEN a container is found during startup cleanup, THE Container Stop Module SHALL attempt to stop it with a 5-second timeout
3. IF a 409 conflict error occurs indicating the container is already being deleted, THEN THE Container Stop Module SHALL log this as informational and continue without error
4. WHEN all containers are processed, THE Container Stop Module SHALL return the count of successfully cleaned containers
5. THE Container Stop Module SHALL NOT block service startup if container cleanup encounters non-409 errors
### Requirement 2: 运行时容器清理场景
**User Story:** As a system operator, I want containers to be stopped quickly during runtime cleanup operations, so that resources are freed promptly without waiting for long graceful shutdown periods.
#### Acceptance Criteria
1. WHEN a container needs to be stopped during runtime, THE Container Stop Module SHALL give the container 3 seconds for graceful shutdown
2. WHEN the 3-second grace period expires, THE Container Stop Module SHALL immediately force-stop the container
3. THE Container Stop Module SHALL remove the container after stopping it
4. THE Container Stop Module SHALL log all stop operations with appropriate detail levels
5. THE Container Stop Module SHALL handle errors gracefully and continue cleanup operations
### Requirement 3: 统一的容器停止接口
**User Story:** As a developer, I want a unified API for stopping containers in different scenarios, so that I can easily invoke the appropriate stopping strategy without duplicating code.
#### Acceptance Criteria
1. THE Container Stop Module SHALL provide a function for startup cleanup scenario
2. THE Container Stop Module SHALL provide a function for runtime cleanup scenario
3. WHEN called from main.rs startup logic, THE Container Stop Module SHALL use the startup cleanup strategy
4. WHEN called from cleanup_task.rs, THE Container Stop Module SHALL use the runtime cleanup strategy
5. WHEN called from container_manager.rs, THE Container Stop Module SHALL use the runtime cleanup strategy
6. THE Container Stop Module SHALL be located in the docker_manager crate for reusability
### Requirement 4: 错误处理和日志记录
**User Story:** As a system operator, I want clear logging of container stop operations, so that I can diagnose issues and understand what happened during cleanup.
#### Acceptance Criteria
1. THE Container Stop Module SHALL log container stop attempts at INFO level
2. THE Container Stop Module SHALL log 409 conflict errors at INFO level during startup cleanup
3. THE Container Stop Module SHALL log other errors at WARN level
4. THE Container Stop Module SHALL log successful stops at INFO level
5. THE Container Stop Module SHALL include container_id and project_id in all log messages
### Requirement 5: 代码复用和维护性
**User Story:** As a developer, I want the container stopping logic centralized in one module, so that future changes only need to be made in one place.
#### Acceptance Criteria
1. THE Container Stop Module SHALL be implemented in a new file under crates/docker_manager/src/
2. WHEN container stopping is needed in main.rs, THE code SHALL call the Container Stop Module
3. WHEN container stopping is needed in cleanup_task.rs, THE code SHALL call the Container Stop Module
4. WHEN container stopping is needed in container_manager.rs, THE code SHALL call the Container Stop Module
5. THE Container Stop Module SHALL eliminate all duplicated container stopping logic across the codebase

View File

@@ -0,0 +1,135 @@
# Implementation Plan
## 任务概述
将分散在多个文件中的容器停止逻辑统一到 docker_manager crate 的新模块中,提供两种清理策略:启动时清理和运行时清理。
## 任务列表
- [x] 1. 创建 container_stop 模块基础结构
-`crates/docker_manager/src/` 创建 `container_stop.rs` 文件
- 定义模块常量(超时时间等)
-`lib.rs` 中导出新模块
- _Requirements: 3.6, 5.1_
- [x] 2. 实现启动时清理功能
- [x] 2.1 实现 startup_cleanup_containers 函数
- 实现容器模式匹配查找
- 实现 5 秒超时停止逻辑
- 实现 409 错误过滤
- 返回 CleanupResult 统计信息
- _Requirements: 1.1, 1.2, 1.3, 1.4_
- [x] 2.2 实现 stop_container_startup_mode 辅助函数
- 调用 DockerManager::stop_container_by_id_with_timeout
- 使用 STARTUP_CLEANUP_TIMEOUT_SECONDS 常量
- 实现错误处理和日志记录
- _Requirements: 1.2, 4.1, 4.2_
- [x] 2.3 实现 is_409_conflict_error 辅助函数
- 检查 DockerError 是否包含 "409" 和 "already in progress"
- 返回布尔值
- _Requirements: 1.3_
- [x] 3. 实现运行时清理功能
- [x] 3.1 实现 runtime_cleanup_container 函数
- 实现单个容器停止逻辑
- 使用 3 秒优雅停止超时
- 超时后立即强制停止
- _Requirements: 2.1, 2.2, 2.3_
- [x] 3.2 实现 runtime_cleanup_containers 批量清理函数
- 批量处理多个容器 ID
- 返回 CleanupResult 统计信息
- _Requirements: 2.4, 2.5_
- [x] 3.3 实现 stop_container_runtime_mode 辅助函数
- 调用 DockerManager::stop_container_by_id_with_timeout
- 使用 RUNTIME_CLEANUP_TIMEOUT_SECONDS 常量
- 实现错误处理和日志记录
- _Requirements: 2.2, 4.1, 4.4_
- [x] 4. 更新 main.rs 使用新的启动清理接口
- [x] 4.1 导入 container_stop 模块
- 添加 `use docker_manager::container_stop;`
- _Requirements: 3.3, 5.2_
- [x] 4.2 替换 startup_cleanup_orphaned_containers 函数
- 调用 `container_stop::startup_cleanup_containers`
- 更新错误处理逻辑
- 更新日志输出
- _Requirements: 3.3, 4.2, 4.3_
- [x] 4.3 删除旧的 startup_cleanup_orphaned_containers 实现
- 删除 `startup_cleanup_orphaned_containers` 函数
- 删除 `find_and_cleanup_orphaned_containers` 函数(如果不再使用)
- _Requirements: 5.5_
- [x] 5. 更新 cleanup_task.rs 使用新的运行时清理接口
- [x] 5.1 导入 container_stop 模块
-`destroy_docker_container` 方法中添加导入
- _Requirements: 3.4, 5.3_
- [x] 5.2 替换容器停止逻辑
-`stop_container_by_id_with_timeout` 调用替换为 `container_stop::runtime_cleanup_container`
- 简化错误处理逻辑
- 更新日志输出
- _Requirements: 3.4, 4.4_
- [x] 5.3 清理 cleanup_single_orphaned_container 方法
- 使用新的 runtime_cleanup_container 接口
- 删除重复的停止逻辑
- _Requirements: 5.5_
- [x] 6. 更新 container_manager.rs如需要
- [x] 6.1 检查是否有容器停止逻辑
- 搜索 `stop_container` 相关调用
- 确定是否需要更新
- _Requirements: 3.5, 5.4_
- [x] 6.2 如有需要,替换为新接口
- 导入 container_stop 模块
- 替换停止逻辑
- _Requirements: 3.5, 5.4_
- [x] 7. 添加文档和注释
- [x] 7.1 为 container_stop.rs 添加模块级文档
- 说明两种清理策略的区别
- 提供使用示例
- _Requirements: 5.5_
- [x] 7.2 为公共函数添加详细文档注释
- 包含参数说明
- 包含返回值说明
- 包含使用示例
- _Requirements: 4.5_
- [x] 8. 验证和测试
- [x] 8.1 编译检查
- 运行 `cargo check` 确保无编译错误
- 运行 `cargo clippy` 检查代码质量
- _Requirements: 5.5_
- [x] 8.2 功能测试
- 测试启动时清理(模拟 409 错误场景)
- 测试运行时清理(验证 3 秒超时)
- 验证日志输出正确
- _Requirements: 1.5, 2.5, 4.1-4.5_