This commit is contained in:
imeepos 2025-08-08 13:52:49 +08:00
parent 5f6a302dfd
commit 3c247b2d3b
3 changed files with 381 additions and 0 deletions

View File

@ -0,0 +1,328 @@
use anyhow::{Result, anyhow};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::collections::HashMap;
use std::sync::Arc;
use std::time::Duration;
use tracing::{info, warn, error, debug};
use crate::config::ComfyUISettings;
use crate::business::services::comfyui_service::ComfyUIService;
use crate::business::services::comfyui_sdk_service::{ComfyUISDKService, WorkflowExecutionResult, SDKExecutionConfig};
use crate::data::models::outfit_photo_generation::{WorkflowProgress, WorkflowNodeReplacement};
/// ComfyUI 集成服务
/// 提供统一的接口,可以选择使用原生实现或 SDK 实现
pub struct ComfyUIIntegrationService {
legacy_service: Arc<ComfyUIService>,
sdk_service: Option<Arc<ComfyUISDKService>>,
use_sdk: bool,
settings: ComfyUISettings,
}
/// 集成服务配置
#[derive(Debug, Clone)]
pub struct IntegrationConfig {
pub prefer_sdk: bool,
pub fallback_to_legacy: bool,
pub timeout: Duration,
pub retry_attempts: u32,
}
impl Default for IntegrationConfig {
fn default() -> Self {
Self {
prefer_sdk: true,
fallback_to_legacy: true,
timeout: Duration::from_secs(300),
retry_attempts: 3,
}
}
}
/// 统一的工作流执行结果
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UnifiedWorkflowResult {
pub prompt_id: String,
pub outputs: HashMap<String, Vec<String>>,
pub execution_time: Duration,
pub node_outputs: HashMap<String, Value>,
pub used_sdk: bool,
}
impl ComfyUIIntegrationService {
/// 创建新的集成服务实例
pub async fn new(settings: ComfyUISettings, config: IntegrationConfig) -> Result<Self> {
// 创建传统服务
let legacy_service = Arc::new(ComfyUIService::new(settings.clone()).await?);
// 尝试创建 SDK 服务
let sdk_service = if config.prefer_sdk {
match ComfyUISDKService::new(settings.clone()) {
Ok(service) => {
info!("ComfyUI SDK 服务初始化成功");
Some(Arc::new(service))
}
Err(e) => {
warn!("ComfyUI SDK 服务初始化失败: {}, 将使用传统服务", e);
None
}
}
} else {
None
};
let use_sdk = sdk_service.is_some() && config.prefer_sdk;
Ok(Self {
legacy_service,
sdk_service,
use_sdk,
settings,
})
}
/// 检查服务健康状态
pub async fn check_health(&self) -> Result<bool> {
if self.use_sdk {
if let Some(sdk_service) = &self.sdk_service {
match sdk_service.check_health().await {
Ok(healthy) => return Ok(healthy),
Err(e) => {
warn!("SDK 健康检查失败,尝试传统服务: {}", e);
}
}
}
}
// 回退到传统服务
self.legacy_service.check_health().await
}
/// 执行工作流(统一接口)
pub async fn execute_workflow(
&self,
workflow: Value,
replacements: Vec<WorkflowNodeReplacement>,
config: IntegrationConfig,
) -> Result<UnifiedWorkflowResult> {
// 应用节点替换
let processed_workflow = self.apply_replacements(workflow, replacements)?;
// 优先使用 SDK
if self.use_sdk {
if let Some(sdk_service) = &self.sdk_service {
match self.execute_with_sdk(sdk_service.clone(), processed_workflow.clone(), &config).await {
Ok(result) => {
info!("使用 SDK 成功执行工作流");
return Ok(UnifiedWorkflowResult {
prompt_id: result.prompt_id,
outputs: result.outputs,
execution_time: result.execution_time,
node_outputs: result.node_outputs,
used_sdk: true,
});
}
Err(e) => {
warn!("SDK 执行失败: {}", e);
if !config.fallback_to_legacy {
return Err(e);
}
}
}
}
}
// 回退到传统服务
info!("使用传统服务执行工作流");
let result = self.execute_with_legacy(processed_workflow, &config).await?;
Ok(UnifiedWorkflowResult {
prompt_id: result.prompt_id,
outputs: result.outputs,
execution_time: result.execution_time,
node_outputs: result.node_outputs,
used_sdk: false,
})
}
/// 使用 SDK 执行工作流
async fn execute_with_sdk(
&self,
sdk_service: Arc<ComfyUISDKService>,
workflow: Value,
config: &IntegrationConfig,
) -> Result<WorkflowExecutionResult> {
let sdk_config = SDKExecutionConfig {
timeout: config.timeout,
retry_attempts: config.retry_attempts,
progress_callback: None, // 可以根据需要添加进度回调
};
sdk_service.execute_workflow(workflow, sdk_config).await
}
/// 使用传统服务执行工作流
async fn execute_with_legacy(
&self,
workflow: Value,
config: &IntegrationConfig,
) -> Result<LegacyWorkflowResult> {
// 这里需要调用传统服务的执行方法
// 由于原始的 ComfyUIService 可能没有统一的执行接口,我们需要适配
let start_time = std::time::Instant::now();
// 提交工作流
let prompt_id = self.legacy_service.submit_workflow(workflow).await?;
// 等待完成(这里需要根据实际的传统服务接口来实现)
let outputs = self.legacy_service.wait_for_completion(&prompt_id, config.timeout).await?;
let execution_time = start_time.elapsed();
Ok(LegacyWorkflowResult {
prompt_id,
outputs,
execution_time,
node_outputs: HashMap::new(), // 传统服务可能不提供详细的节点输出
})
}
/// 应用节点替换
fn apply_replacements(
&self,
mut workflow: Value,
replacements: Vec<WorkflowNodeReplacement>,
) -> Result<Value> {
for replacement in replacements {
if let Some(node) = workflow.get_mut(&replacement.node_id) {
if let Some(inputs) = node.get_mut("inputs") {
if let Some(inputs_obj) = inputs.as_object_mut() {
inputs_obj.insert(replacement.field_name, replacement.new_value);
}
}
}
}
Ok(workflow)
}
/// 获取队列状态
pub async fn get_queue_status(&self) -> Result<QueueStatusInfo> {
if self.use_sdk {
if let Some(sdk_service) = &self.sdk_service {
match sdk_service.get_queue_status().await {
Ok(status) => {
return Ok(QueueStatusInfo {
running: status.running,
pending: status.pending,
from_sdk: true,
});
}
Err(e) => {
warn!("SDK 获取队列状态失败: {}", e);
}
}
}
}
// 回退到传统服务
let status = self.legacy_service.get_queue_status().await?;
Ok(QueueStatusInfo {
running: status.running,
pending: status.pending,
from_sdk: false,
})
}
/// 取消工作流执行
pub async fn cancel_workflow(&self, prompt_id: &str) -> Result<()> {
if self.use_sdk {
if let Some(sdk_service) = &self.sdk_service {
if let Ok(_) = sdk_service.cancel_workflow(prompt_id).await {
return Ok(());
}
}
}
// 回退到传统服务
self.legacy_service.cancel_workflow(prompt_id).await
}
/// 切换到 SDK 模式
pub async fn switch_to_sdk(&mut self) -> Result<()> {
if self.sdk_service.is_none() {
let sdk_service = ComfyUISDKService::new(self.settings.clone())?;
self.sdk_service = Some(Arc::new(sdk_service));
}
self.use_sdk = true;
info!("已切换到 SDK 模式");
Ok(())
}
/// 切换到传统模式
pub fn switch_to_legacy(&mut self) {
self.use_sdk = false;
info!("已切换到传统模式");
}
/// 获取当前使用的服务类型
pub fn get_current_service_type(&self) -> &'static str {
if self.use_sdk && self.sdk_service.is_some() {
"SDK"
} else {
"Legacy"
}
}
}
/// 传统服务工作流结果
#[derive(Debug)]
struct LegacyWorkflowResult {
prompt_id: String,
outputs: HashMap<String, Vec<String>>,
execution_time: Duration,
node_outputs: HashMap<String, Value>,
}
/// 队列状态信息
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct QueueStatusInfo {
pub running: usize,
pub pending: usize,
pub from_sdk: bool,
}
// 为了编译通过,我们需要为传统服务添加一些方法的扩展
// 这些方法需要在实际的 ComfyUIService 中实现
impl ComfyUIService {
/// 提交工作流(需要在实际服务中实现)
pub async fn submit_workflow(&self, _workflow: Value) -> Result<String> {
// 这里需要调用实际的提交方法
todo!("需要在 ComfyUIService 中实现 submit_workflow 方法")
}
/// 等待完成(需要在实际服务中实现)
pub async fn wait_for_completion(&self, _prompt_id: &str, _timeout: Duration) -> Result<HashMap<String, Vec<String>>> {
// 这里需要调用实际的等待方法
todo!("需要在 ComfyUIService 中实现 wait_for_completion 方法")
}
/// 获取队列状态(需要在实际服务中实现)
pub async fn get_queue_status(&self) -> Result<QueueStatusInfo> {
// 这里需要调用实际的队列状态方法
todo!("需要在 ComfyUIService 中实现 get_queue_status 方法")
}
/// 取消工作流(需要在实际服务中实现)
pub async fn cancel_workflow(&self, _prompt_id: &str) -> Result<()> {
// 这里需要调用实际的取消方法
todo!("需要在 ComfyUIService 中实现 cancel_workflow 方法")
}
/// 检查健康状态(需要在实际服务中实现)
pub async fn check_health(&self) -> Result<bool> {
// 这里需要调用实际的健康检查方法
todo!("需要在 ComfyUIService 中实现 check_health 方法")
}
}

View File

@ -36,6 +36,8 @@ pub mod jianying_export;
pub mod template_segment_weight_service;
pub mod directory_settings_service;
pub mod comfyui_service;
pub mod comfyui_sdk_service;
pub mod comfyui_integration_service;
pub mod outfit_photo_generation_service;
pub mod workflow_management_service;
pub mod error_handling_service;

View File

@ -51,6 +51,26 @@ pub struct ComfyUISettings {
pub workflow_directory: Option<String>,
/// 输出文件存储目录
pub output_directory: Option<String>,
/// SDK 配置
pub sdk_config: ComfyUISDKConfig,
}
/// ComfyUI SDK 配置
/// 控制 SDK 的使用和行为
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ComfyUISDKConfig {
/// 是否优先使用 SDK
pub prefer_sdk: bool,
/// 当 SDK 失败时是否回退到传统实现
pub fallback_to_legacy: bool,
/// SDK 执行超时时间(秒)
pub sdk_timeout_seconds: u64,
/// SDK 重试次数
pub sdk_retry_attempts: u32,
/// 是否启用详细日志
pub enable_verbose_logging: bool,
/// 是否启用进度回调
pub enable_progress_callback: bool,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
@ -72,6 +92,19 @@ impl Default for DirectorySettings {
}
}
impl Default for ComfyUISDKConfig {
fn default() -> Self {
ComfyUISDKConfig {
prefer_sdk: true,
fallback_to_legacy: true,
sdk_timeout_seconds: 300,
sdk_retry_attempts: 3,
enable_verbose_logging: false,
enable_progress_callback: true,
}
}
}
impl Default for ComfyUISettings {
fn default() -> Self {
ComfyUISettings {
@ -82,10 +115,28 @@ impl Default for ComfyUISettings {
enabled: false,
workflow_directory: None,
output_directory: None,
sdk_config: ComfyUISDKConfig::default(),
}
}
}
impl ComfyUISettings {
/// 获取完整的 ComfyUI 服务 URL
pub fn base_url(&self) -> String {
format!("http://{}:{}", self.server_address, self.server_port)
}
/// 检查是否启用了 SDK
pub fn is_sdk_enabled(&self) -> bool {
self.enabled && self.sdk_config.prefer_sdk
}
/// 获取 SDK 超时时间
pub fn get_sdk_timeout(&self) -> std::time::Duration {
std::time::Duration::from_secs(self.sdk_config.sdk_timeout_seconds)
}
}
impl Default for AppConfig {
fn default() -> Self {
AppConfig {