fix: 修复ComfyUI队列API响应格式解析问题
- 修复WebSocket错误消息解析失败问题,支持更多错误字段格式 - 改进执行错误处理,收到错误时立即中断而不是等待超时 - 修复ComfyUI队列API响应格式不匹配问题,支持数组格式的队列数据 - 添加灵活的队列项解析逻辑,支持整数和字符串类型的prompt_id - 在EventEmitter中添加错误存储功能,支持实时错误状态检查 - 更新所有相关的队列状态转换代码 解决的问题: 1. WebSocket消息解析错误:missing field 'message' 2. 执行错误后仍等待超时的问题 3. 队列API响应解析错误:invalid type integer/string expected 4. 批量处理中错误统计不准确的问题
This commit is contained in:
@@ -6,18 +6,59 @@ use std::collections::HashMap;
|
||||
/// Queue status response
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct QueueStatus {
|
||||
pub queue_running: Vec<QueueItem>,
|
||||
pub queue_pending: Vec<QueueItem>,
|
||||
pub queue_running: Vec<serde_json::Value>,
|
||||
pub queue_pending: Vec<serde_json::Value>,
|
||||
}
|
||||
|
||||
/// Queue item
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
/// Queue item (parsed from array format)
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct QueueItem {
|
||||
pub prompt_id: String,
|
||||
pub number: u32,
|
||||
pub outputs: HashMap<String, serde_json::Value>,
|
||||
}
|
||||
|
||||
impl QueueStatus {
|
||||
/// Parse running queue items from raw JSON values
|
||||
pub fn get_running_items(&self) -> Vec<QueueItem> {
|
||||
self.queue_running.iter()
|
||||
.filter_map(|item| Self::parse_queue_item(item))
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Parse pending queue items from raw JSON values
|
||||
pub fn get_pending_items(&self) -> Vec<QueueItem> {
|
||||
self.queue_pending.iter()
|
||||
.filter_map(|item| Self::parse_queue_item(item))
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Parse a single queue item from JSON value
|
||||
fn parse_queue_item(value: &serde_json::Value) -> Option<QueueItem> {
|
||||
if let serde_json::Value::Array(arr) = value {
|
||||
if arr.len() >= 2 {
|
||||
let number = match &arr[0] {
|
||||
serde_json::Value::Number(n) => n.as_u64()? as u32,
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
let prompt_id = match &arr[1] {
|
||||
serde_json::Value::String(s) => s.clone(),
|
||||
serde_json::Value::Number(n) => n.to_string(),
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
return Some(QueueItem {
|
||||
prompt_id,
|
||||
number,
|
||||
outputs: HashMap::new(), // ComfyUI queue format doesn't include outputs
|
||||
});
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Prompt request
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct PromptRequest {
|
||||
@@ -137,3 +178,59 @@ pub struct ViewMetadata {
|
||||
#[serde(flatten)]
|
||||
pub metadata: HashMap<String, serde_json::Value>,
|
||||
}
|
||||
|
||||
/// Custom deserializer that can handle both string and number types
|
||||
fn deserialize_string_or_number<'de, D>(deserializer: D) -> Result<String, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
use serde::de::{self, Visitor};
|
||||
use std::fmt;
|
||||
|
||||
struct StringOrNumberVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for StringOrNumberVisitor {
|
||||
type Value = String;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("a string or number")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, value: &str) -> Result<String, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
Ok(value.to_string())
|
||||
}
|
||||
|
||||
fn visit_string<E>(self, value: String) -> Result<String, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
fn visit_i64<E>(self, value: i64) -> Result<String, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
Ok(value.to_string())
|
||||
}
|
||||
|
||||
fn visit_u64<E>(self, value: u64) -> Result<String, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
Ok(value.to_string())
|
||||
}
|
||||
|
||||
fn visit_f64<E>(self, value: f64) -> Result<String, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
Ok(value.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_any(StringOrNumberVisitor)
|
||||
}
|
||||
|
||||
@@ -97,8 +97,17 @@ pub struct WSExecutedData {
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct WSErrorData {
|
||||
pub node_id: Option<String>,
|
||||
pub message: String,
|
||||
pub node: Option<String>,
|
||||
pub message: Option<String>,
|
||||
pub details: Option<serde_json::Value>,
|
||||
pub error: Option<String>,
|
||||
pub exception_message: Option<String>,
|
||||
pub exception_type: Option<String>,
|
||||
pub traceback: Option<Vec<String>>,
|
||||
pub prompt_id: Option<String>,
|
||||
// 使用 flatten 来捕获任何其他字段
|
||||
#[serde(flatten)]
|
||||
pub extra: HashMap<String, serde_json::Value>,
|
||||
}
|
||||
|
||||
/// Execution options
|
||||
|
||||
Reference in New Issue
Block a user