use crate::BoxFuture;
use crate::error::SynwireError;
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum BatchStatus {
Pending,
InProgress,
Completed,
Failed {
message: String,
},
}
#[derive(Debug)]
pub struct BatchItemResult<T> {
pub index: usize,
pub result: Result<T, SynwireError>,
}
pub trait BatchProcessor<T: Send>: Send + Sync {
fn submit_batch(
&self,
inputs: Vec<serde_json::Value>,
) -> BoxFuture<'_, Result<String, SynwireError>>;
fn batch_status<'a>(
&'a self,
batch_id: &'a str,
) -> BoxFuture<'a, Result<BatchStatus, SynwireError>>;
fn get_batch_results<'a>(
&'a self,
batch_id: &'a str,
) -> BoxFuture<'a, Result<Vec<BatchItemResult<T>>, SynwireError>>;
fn cancel_batch<'a>(&'a self, batch_id: &'a str) -> BoxFuture<'a, Result<(), SynwireError>>;
}
#[cfg(test)]
#[allow(clippy::unwrap_used)]
mod tests {
use super::*;
struct FakeBatchProcessor;
impl BatchProcessor<String> for FakeBatchProcessor {
fn submit_batch(
&self,
_inputs: Vec<serde_json::Value>,
) -> BoxFuture<'_, Result<String, SynwireError>> {
Box::pin(async { Ok("batch-123".to_owned()) })
}
fn batch_status<'a>(
&'a self,
_batch_id: &'a str,
) -> BoxFuture<'a, Result<BatchStatus, SynwireError>> {
Box::pin(async { Ok(BatchStatus::Completed) })
}
fn get_batch_results<'a>(
&'a self,
_batch_id: &'a str,
) -> BoxFuture<'a, Result<Vec<BatchItemResult<String>>, SynwireError>> {
Box::pin(async {
Ok(vec![BatchItemResult {
index: 0,
result: Ok("result".to_owned()),
}])
})
}
fn cancel_batch<'a>(
&'a self,
_batch_id: &'a str,
) -> BoxFuture<'a, Result<(), SynwireError>> {
Box::pin(async { Ok(()) })
}
}
#[tokio::test]
async fn batch_processor_compiles_and_works() {
let processor = FakeBatchProcessor;
let batch_id = processor
.submit_batch(vec![serde_json::json!("test")])
.await
.unwrap();
assert_eq!(batch_id, "batch-123");
let status = processor.batch_status(&batch_id).await.unwrap();
assert_eq!(status, BatchStatus::Completed);
let results = processor.get_batch_results(&batch_id).await.unwrap();
assert_eq!(results.len(), 1);
assert_eq!(results[0].index, 0);
let cancel = processor.cancel_batch(&batch_id).await;
assert!(cancel.is_ok());
}
#[test]
fn batch_processor_is_object_safe() {
fn takes_processor(p: &dyn BatchProcessor<String>) {
let _ = p;
}
let p = FakeBatchProcessor;
takes_processor(&p);
}
}