Files
qiming/qiming-rcoder/crates/rcoder/src/cleanup_task/strategies/mod.rs
2026-06-01 13:54:52 +08:00

124 lines
3.6 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! 清理策略模块
//!
//! 定义不同服务类型的清理策略 trait
use anyhow::Result;
use async_trait::async_trait;
use chrono::{DateTime, Utc};
use serde::Serialize;
use std::sync::Arc;
/// 容器销毁原因
///
/// 记录容器被销毁的具体原因,便于日志追踪和问题排查
#[derive(Debug, Clone, Serialize)]
pub enum DestroyReason {
/// 闲置超时 - 所有项目都超过闲置时间限制
/// - RCoder: 项目闲置超时
/// - ComputerAgentRunner: 容器下所有项目都闲置
IdleTimeout {
/// 闲置时长(秒)
idle_duration_secs: i64,
/// 超时阈值(秒)
timeout_secs: u64,
},
/// 孤立容器 - DuckDB 中没有对应记录
/// - 容器存在但状态管理系统中没有记录
/// - 可能是由于系统重启、异常退出等原因导致
Orphaned {
/// 容器创建时间
created_at: DateTime<Utc>,
/// 是否在保护期内
was_protected: bool,
},
/// 手动停止 - 用户主动停止或重启
/// - 通过 API 调用停止
/// - 通过 Agent 生命周期管理停止
ManualStop {
/// 触发来源
source: String,
},
}
impl DestroyReason {
/// 获取销毁原因的简短描述(用于日志)
pub fn as_str(&self) -> &str {
match self {
DestroyReason::IdleTimeout { .. } => "Idle timeout",
DestroyReason::Orphaned { .. } => "Orphaned container",
DestroyReason::ManualStop { .. } => "Manual stop",
}
}
/// 获取销毁原因的详细描述
pub fn description(&self) -> String {
match self {
DestroyReason::IdleTimeout {
idle_duration_secs,
timeout_secs,
} => {
format!(
"Idle timeout (idle {}s / timeout {}s)",
idle_duration_secs, timeout_secs
)
}
DestroyReason::Orphaned {
created_at,
was_protected,
} => {
format!(
"Orphaned container (created at {}, protected:{})",
created_at.format("%Y-%m-%d %H:%M:%S"),
was_protected
)
}
DestroyReason::ManualStop { source } => {
format!("manual stop (source:{})", source)
}
}
}
}
/// 清理策略 trait
///
/// 不同服务类型有不同的容器管理策略:
/// - RCoder: 1容器 = 1项目直接销毁
/// - ComputerAgentRunner: 1容器 = N项目需要引用计数检查
#[async_trait]
pub trait CleanupStrategy: Send + Sync {
/// 检查容器是否应该被销毁
///
/// 返回 `Some(DestroyReason)` 表示应该销毁容器,并附带原因
/// 返回 `None` 表示不应该销毁容器
async fn should_destroy_container(
&self,
project_id: &str,
context: &CleanupContext,
) -> Result<Option<DestroyReason>>;
/// 获取容器的唯一标识符(用于查找容器)
///
/// RCoder 返回 project_id
/// ComputerAgentRunner 返回 user_id
fn get_container_identifier(&self, project_info: &ProjectInfo) -> Result<String>;
}
/// 清理上下文
pub struct CleanupContext {
pub state: Arc<crate::router::AppState>,
pub config: super::config::CleanupConfig,
}
/// 项目信息摘要
pub struct ProjectInfo {
pub project_id: String,
pub user_id: Option<String>,
pub pod_id: Option<String>,
pub last_activity: DateTime<Utc>,
}
pub mod computer_runner;
pub mod rcoder;