comfyui_api/api/
history.rs

1use reqwest::Url;
2
3use crate::models::{History, Task};
4
5/// Errors that can occur when interacting with `HistoryApi`.
6#[derive(thiserror::Error, Debug)]
7#[non_exhaustive]
8pub enum HistoryApiError {
9    /// Error parsing endpoint URL
10    #[error("Failed to parse endpoint URL")]
11    ParseError(#[from] url::ParseError),
12    /// Error sending request
13    #[error("Failed to send request")]
14    RequestFailed(#[from] reqwest::Error),
15    /// An error occurred while parsing the response from the API.
16    #[error("Parsing response failed")]
17    InvalidResponse(#[source] reqwest::Error),
18    /// An error occurred getting response data.
19    #[error("Failed to get response data")]
20    GetDataFailed(#[source] reqwest::Error),
21    /// Server returned an error getting history
22    #[error("Failed to get history: {status}: {error}")]
23    GetHistoryFailed {
24        status: reqwest::StatusCode,
25        error: String,
26    },
27    /// Task was not found
28    #[error("Task not found: {0}")]
29    TaskNotFound(uuid::Uuid),
30    /// Server returned an error getting task
31    #[error("Failed to get task {task}: {status}: {error}")]
32    GetTaskFailed {
33        task: uuid::Uuid,
34        status: reqwest::StatusCode,
35        error: String,
36    },
37}
38
39type Result<T> = std::result::Result<T, HistoryApiError>;
40
41/// Struct representing a connection to the ComfyUI API `history` endpoint.
42#[derive(Clone, Debug)]
43pub struct HistoryApi {
44    client: reqwest::Client,
45    endpoint: Url,
46}
47
48impl HistoryApi {
49    /// Constructs a new `HistoryApi` client with a given `reqwest::Client` and ComfyUI API
50    /// endpoint.
51    ///
52    /// # Arguments
53    ///
54    /// * `client` - A `reqwest::Client` used to send requests.
55    /// * `endpoint` - A `str` representation of the endpoint url.
56    ///
57    /// # Returns
58    ///
59    /// A `Result` containing a new `HistoryApi` instance on success, or an error if url parsing failed.
60    pub fn new<S>(client: reqwest::Client, endpoint: S) -> Result<Self>
61    where
62        S: AsRef<str>,
63    {
64        Ok(Self::new_with_url(client, Url::parse(endpoint.as_ref())?))
65    }
66
67    /// Constructs a new `HistoryApi` client with a given `reqwest::Client` and endpoint `Url`.
68    ///
69    /// # Arguments
70    ///
71    /// * `client` - A `reqwest::Client` used to send requests.
72    /// * `endpoint` - A `Url` representing the endpoint url.
73    ///
74    /// # Returns
75    ///
76    /// A new `HistoryApi` instance.
77    pub fn new_with_url(client: reqwest::Client, endpoint: Url) -> Self {
78        Self { client, endpoint }
79    }
80
81    /// Sends a history request using the HistoryApi client.
82    ///
83    /// # Returns
84    ///
85    /// A `Result` containing a `History` on success, or an error if the request failed.
86    pub async fn get(&self) -> Result<History> {
87        let response = self.client.get(self.endpoint.clone()).send().await?;
88        if response.status().is_success() {
89            return response
90                .json()
91                .await
92                .map_err(HistoryApiError::InvalidResponse);
93        }
94        let status = response.status();
95        let text = response
96            .text()
97            .await
98            .map_err(HistoryApiError::GetDataFailed)?;
99        Err(HistoryApiError::GetHistoryFailed {
100            status,
101            error: text,
102        })
103    }
104
105    /// Sends a history request using the HistoryApi client.
106    ///
107    /// # Arguments
108    ///
109    /// * `prompt_id` - A `uuid::Uuid` representing the prompt id.
110    ///
111    /// # Returns
112    ///
113    /// A `Result` containing a `Task` on success, or an error if the request failed.
114    pub async fn get_prompt(&self, prompt_id: &uuid::Uuid) -> Result<Task> {
115        let response = self
116            .client
117            .get(self.endpoint.clone().join(prompt_id.to_string().as_str())?)
118            .send()
119            .await?;
120        if response.status().is_success() {
121            let mut history: History = response
122                .json()
123                .await
124                .map_err(HistoryApiError::InvalidResponse)?;
125            return history
126                .tasks
127                .remove(prompt_id)
128                .ok_or_else(|| HistoryApiError::TaskNotFound(*prompt_id));
129        }
130        let status = response.status();
131        let text = response
132            .text()
133            .await
134            .map_err(HistoryApiError::GetDataFailed)?;
135        Err(HistoryApiError::GetTaskFailed {
136            task: *prompt_id,
137            status,
138            error: text,
139        })
140    }
141}