use async_trait::async_trait;
use cognate_core::{Chunk, Provider, Request, Response, Result};
use futures::stream::BoxStream;
use std::sync::Arc;
pub struct FallbackProvider {
primary: Arc<dyn Provider>,
fallback: Arc<dyn Provider>,
}
impl FallbackProvider {
pub fn new(primary: Arc<dyn Provider>, fallback: Arc<dyn Provider>) -> Self {
Self { primary, fallback }
}
}
#[async_trait]
impl Provider for FallbackProvider {
async fn complete(&self, req: Request) -> Result<Response> {
match self.primary.complete(req.clone()).await {
Ok(resp) => Ok(resp),
Err(e) if e.is_retryable() => {
tracing::warn!(error = %e, "cognate: primary provider failed, trying fallback");
self.fallback.complete(req).await
}
Err(e) => Err(e),
}
}
async fn stream(&self, req: Request) -> Result<BoxStream<'static, Result<Chunk>>> {
match self.primary.stream(req.clone()).await {
Ok(s) => Ok(s),
Err(e) if e.is_retryable() => {
tracing::warn!(error = %e, "cognate: primary provider failed on stream, trying fallback");
self.fallback.stream(req).await
}
Err(e) => Err(e),
}
}
}