use std::pin::Pin;
use eventsource_stream::Eventsource;
use futures_util::StreamExt;
use futures_util::stream::Stream;
use reqwest::Response;
use uuid::Uuid;
use crate::error::Error;
#[derive(Debug, Clone)]
pub struct SseEvent {
pub event_type: String,
pub data: String,
}
impl SseEvent {
pub fn deserialize<T: serde::de::DeserializeOwned>(&self) -> Result<T, Error> {
serde_json::from_str(&self.data)
.map_err(|e| Error::Deserialize(format!("{e}: {}", self.data)))
}
}
pub type EventStream = Pin<Box<dyn Stream<Item = Result<SseEvent, Error>> + Send>>;
pub(crate) fn parse_sse_stream(response: Response) -> EventStream {
let stream = response.bytes_stream().eventsource().map(|result| {
result
.map(|event| SseEvent {
event_type: event.event,
data: event.data,
})
.map_err(|e| Error::Sse(e.to_string()))
});
Box::pin(stream)
}
impl crate::IronflowClient {
pub async fn events(
&self,
run_id: Option<Uuid>,
types: Option<&[&str]>,
) -> Result<EventStream, Error> {
let mut request = self.get("/api/v1/events");
if let Some(rid) = run_id {
request = request.query(&[("run_id", rid.to_string())]);
}
if let Some(ts) = types {
request = request.query(&[("types", ts.join(","))]);
}
let response = request.send().await?;
if !response.status().is_success() {
return Err(Self::into_api_error(response).await);
}
Ok(parse_sse_stream(response))
}
pub async fn subscribe_run_events(&self, run_id: Uuid) -> Result<EventStream, Error> {
self.rate_limiter.wait().await;
let path = format!("/api/v1/runs/{run_id}/events");
let response = self.get(&path).send().await?;
if !response.status().is_success() {
return Err(Self::into_api_error(response).await);
}
Ok(parse_sse_stream(response))
}
pub async fn subscribe_global_events(&self) -> Result<EventStream, Error> {
self.rate_limiter.wait().await;
self.events(None, None).await
}
}