use std::{sync::Arc, time::Duration};
use apibara_dna_protocol::dna::stream::dna_stream_client::DnaStreamClient;
use snafu::{ResultExt, Snafu};
use tonic::{
metadata::MetadataMap,
transport::{Channel, ClientTlsConfig, Uri},
};
use crate::{auth::BearerTokenProvider, client::StreamClient, interceptor::MetadataInterceptor};
pub struct StreamClientBuilder {
token_provider: Option<Arc<dyn BearerTokenProvider>>,
max_message_size: Option<usize>,
metadata: MetadataMap,
timeout: Duration,
tls_config: Option<ClientTlsConfig>,
}
#[derive(Debug, Snafu)]
pub enum StreamClientBuilderError {
#[snafu(display("Failed to connect to the server"))]
Connection { source: tonic::transport::Error },
#[snafu(display("Failed to get bearer token"))]
BearerToken {
source: crate::auth::BearerTokenError,
},
}
impl StreamClientBuilder {
pub fn new() -> Self {
Default::default()
}
pub fn with_bearer_token_provider(mut self, provider: Arc<dyn BearerTokenProvider>) -> Self {
self.token_provider = Some(provider);
self
}
pub fn with_metadata(mut self, metadata: MetadataMap) -> Self {
self.metadata = metadata;
self
}
pub fn with_timeout(mut self, timeout: Duration) -> Self {
self.timeout = timeout;
self
}
pub fn with_max_message_size_bytes(mut self, message_size: usize) -> Self {
self.max_message_size = Some(message_size);
self
}
pub async fn connect(self, url: Uri) -> Result<StreamClient, StreamClientBuilderError> {
let tls = self
.tls_config
.unwrap_or_else(|| ClientTlsConfig::default().with_native_roots());
let channel = Channel::builder(url)
.tls_config(tls)
.context(ConnectionSnafu {})?
.connect()
.await
.context(ConnectionSnafu {})?;
let mut interceptor = MetadataInterceptor::with_metadata(self.metadata);
if let Some(token_provider) = self.token_provider {
let token = token_provider.get_token().context(BearerTokenSnafu {})?;
interceptor
.insert_bearer_token(token)
.map_err(Into::into)
.context(BearerTokenSnafu {})?;
}
let mut default_client = DnaStreamClient::with_interceptor(channel, interceptor);
default_client = if let Some(max_message_size) = self.max_message_size {
default_client.max_decoding_message_size(max_message_size)
} else {
default_client
};
Ok(StreamClient::new(default_client, self.timeout))
}
}
impl Default for StreamClientBuilder {
fn default() -> Self {
Self {
token_provider: None,
max_message_size: None,
metadata: MetadataMap::new(),
timeout: Duration::from_secs(60),
tls_config: None,
}
}
}