添加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,8 @@
//! Container Runtime API
//!
//! This crate provides the `ContainerRuntime` trait abstraction for different
//! container runtimes (Docker, Kubernetes, etc.).
pub mod runtime_trait;
pub use runtime_trait::*;

View File

@@ -0,0 +1,305 @@
//! Container runtime abstraction trait
use async_trait::async_trait;
use chrono::{DateTime, Utc};
use shared_types::{ContainerBasicInfo, ServiceResourceLimits, ServiceType};
use thiserror::Error;
/// Container runtime errors
#[derive(Error, Debug)]
pub enum ContainerRuntimeError {
#[error("Connection error: {0}")]
ConnectionError(String),
#[error("Container creation failed: {0}")]
ContainerCreationError(String),
#[error("Container start failed: {0}")]
ContainerStartError(String),
#[error("Container stop failed: {0}")]
ContainerStopError(String),
#[error("Container not found: {0}")]
ContainerNotFound(String),
#[error("Configuration error: {0}")]
ConfigurationError(String),
#[error("Timeout: {0}")]
Timeout(String),
#[error("Kubernetes error: {0}")]
K8sError(String),
#[error("Docker error: {0}")]
DockerError(String),
}
/// Result type for container operations
pub type ContainerRuntimeResult<T> = Result<T, ContainerRuntimeError>;
/// Container runtime status
#[derive(Debug, Clone, PartialEq)]
pub enum ContainerRuntimeStatus {
Pending,
Running,
Succeeded,
Failed,
Unknown(String),
}
/// Basic container info returned by runtime
#[derive(Debug, Clone)]
pub struct RuntimeContainerInfo {
pub container_id: String,
pub container_name: String,
pub container_ip: String,
pub status: ContainerRuntimeStatus,
pub created_at: DateTime<Utc>,
}
/// 已被移除的容器信息(用于清理关联资源)
#[derive(Debug, Clone)]
pub struct RemovedContainerInfo {
/// 容器名称(稳定标识符)
pub container_name: String,
/// 容器 IP
pub container_ip: String,
/// 容器标识符project_id 或 user_id
pub identifier: String,
/// 服务类型
pub service_type: ServiceType,
}
impl From<ContainerRuntimeStatus> for String {
fn from(status: ContainerRuntimeStatus) -> Self {
match status {
ContainerRuntimeStatus::Pending => "pending".to_string(),
ContainerRuntimeStatus::Running => "running".to_string(),
ContainerRuntimeStatus::Succeeded => "succeeded".to_string(),
ContainerRuntimeStatus::Failed => "failed".to_string(),
ContainerRuntimeStatus::Unknown(s) => s,
}
}
}
/// Parameters for creating a container
///
/// Bundles all parameters needed for container creation to avoid
/// long parameter lists that hurt code readability and maintainability.
#[derive(Debug, Clone)]
pub struct ContainerCreateParams {
/// Project identifier (used as container name base for RCoder service)
pub project_id: Option<String>,
/// User identifier (used as container name base for ComputerAgentRunner)
pub user_id: Option<String>,
/// Workspace path on host
pub host_workspace_path: String,
/// Service type determining container purpose
pub service_type: ServiceType,
/// Optional resource constraints
pub resource_limits: Option<ServiceResourceLimits>,
/// Pod identifier for container reuse (for multi-tenant scenarios)
pub pod_id: Option<String>,
/// Isolation type: tenant|space|project (for multi-tenant scenarios)
pub isolation_type: Option<String>,
/// Tenant identifier (for multi-tenant scenarios)
pub tenant_id: Option<String>,
/// Space identifier (for multi-tenant scenarios)
pub space_id: Option<String>,
}
impl ContainerCreateParams {
/// Create a new builder for container create params
pub fn builder() -> ContainerCreateParamsBuilder {
ContainerCreateParamsBuilder::default()
}
}
#[derive(Debug, Clone, Default)]
pub struct ContainerCreateParamsBuilder {
project_id: Option<String>,
user_id: Option<String>,
host_workspace_path: Option<String>,
service_type: Option<ServiceType>,
resource_limits: Option<ServiceResourceLimits>,
pod_id: Option<String>,
isolation_type: Option<String>,
tenant_id: Option<String>,
space_id: Option<String>,
}
impl ContainerCreateParamsBuilder {
pub fn project_id(mut self, project_id: impl Into<String>) -> Self {
self.project_id = Some(project_id.into());
self
}
pub fn user_id(mut self, user_id: impl Into<String>) -> Self {
self.user_id = Some(user_id.into());
self
}
pub fn host_workspace_path(mut self, host_workspace_path: impl Into<String>) -> Self {
self.host_workspace_path = Some(host_workspace_path.into());
self
}
pub fn service_type(mut self, service_type: ServiceType) -> Self {
self.service_type = Some(service_type);
self
}
pub fn resource_limits(mut self, resource_limits: ServiceResourceLimits) -> Self {
self.resource_limits = Some(resource_limits);
self
}
pub fn pod_id(mut self, pod_id: impl Into<String>) -> Self {
self.pod_id = Some(pod_id.into());
self
}
pub fn isolation_type(mut self, isolation_type: impl Into<String>) -> Self {
self.isolation_type = Some(isolation_type.into());
self
}
pub fn tenant_id(mut self, tenant_id: impl Into<String>) -> Self {
self.tenant_id = Some(tenant_id.into());
self
}
pub fn space_id(mut self, space_id: impl Into<String>) -> Self {
self.space_id = Some(space_id.into());
self
}
pub fn build(self) -> ContainerCreateParams {
ContainerCreateParams {
project_id: self.project_id,
user_id: self.user_id,
host_workspace_path: self
.host_workspace_path
.unwrap_or_else(|| String::new()),
service_type: self.service_type.unwrap_or(ServiceType::RCoder),
resource_limits: self.resource_limits,
pod_id: self.pod_id,
isolation_type: self.isolation_type,
tenant_id: self.tenant_id,
space_id: self.space_id,
}
}
}
/// Abstraction trait for container runtimes (Docker, Kubernetes, etc.)
///
/// This trait follows the Interface Segregation Principle - it provides
/// a lean interface with only the methods that callers actually need.
#[async_trait]
pub trait ContainerRuntime: Send + Sync {
/// Create and start a container
async fn create_container(
&self,
params: ContainerCreateParams,
) -> ContainerRuntimeResult<ContainerBasicInfo>;
/// Get container information by project_id
async fn get_container_info(
&self,
project_id: &str,
) -> ContainerRuntimeResult<Option<ContainerBasicInfo>>;
/// Get container information by identifier + service type.
///
/// `identifier` means:
/// - RCoder: `project_id`
/// - ComputerAgentRunner: `user_id`
async fn get_container_info_by_identifier(
&self,
identifier: &str,
service_type: &ServiceType,
) -> ContainerRuntimeResult<Option<ContainerBasicInfo>> {
if matches!(service_type, ServiceType::RCoder) {
return self.get_container_info(identifier).await;
}
let info = self.find_container(identifier, service_type).await?;
Ok(info.map(|pod| ContainerBasicInfo {
container_id: pod.container_id,
container_name: pod.container_name,
container_ip: pod.container_ip.clone(),
internal_port: shared_types::GRPC_DEFAULT_PORT,
external_port: 0,
project_id: identifier.to_string(),
status: String::from(pod.status),
created_at: pod.created_at,
service_url: format!(
"http://{}:{}",
pod.container_ip,
shared_types::GRPC_DEFAULT_PORT
),
}))
}
/// Find container by project_id (returns None if not running)
async fn find_container(
&self,
project_id: &str,
service_type: &ServiceType,
) -> ContainerRuntimeResult<Option<RuntimeContainerInfo>>;
/// Stop and remove container
async fn stop_container(&self, project_id: &str) -> ContainerRuntimeResult<()>;
/// Stop and remove container by identifier + service type.
///
/// `identifier` means:
/// - RCoder: `project_id`
/// - ComputerAgentRunner: `user_id`
async fn stop_container_by_identifier(
&self,
identifier: &str,
_service_type: &ServiceType,
) -> ContainerRuntimeResult<()> {
self.stop_container(identifier).await
}
/// Get container status
async fn is_container_running(&self, project_id: &str) -> ContainerRuntimeResult<bool>;
/// Get container status by identifier + service type.
async fn is_container_running_by_identifier(
&self,
identifier: &str,
service_type: &ServiceType,
) -> ContainerRuntimeResult<bool> {
Ok(self
.find_container(identifier, service_type)
.await?
.map(|c| c.status == ContainerRuntimeStatus::Running)
.unwrap_or(false))
}
/// List all containers managed by this runtime
async fn list_containers(&self) -> ContainerRuntimeResult<Vec<RuntimeContainerInfo>>;
/// 同步缓存状态,清理失效的容器记录
///
/// 对于 Docker遍历 ContainerStateActor 缓存,通过 Docker API 验证容器是否仍存在
/// 对于 K8s遍历 pod_cache通过 K8s API 验证 Pod 是否仍存在
///
/// # Returns
/// 返回元组 (已检查数量, 已移除容器信息列表)
async fn sync_states(&self) -> ContainerRuntimeResult<(u32, Vec<RemovedContainerInfo>)> {
// 默认实现:不做任何事(向后兼容)
Ok((0, Vec::new()))
}
/// Cleanup all containers (used on shutdown)
async fn cleanup_all(&self) -> ContainerRuntimeResult<()>;
/// Health check - verify runtime is accessible
async fn health_check(&self) -> ContainerRuntimeResult<()>;
}