use std::sync::Arc;
use tonic::transport::Endpoint;
use crate::tonic::connector::TargetConnectorBuilder;
use crate::tonic::middleware::ResolveStatusMiddleware;
use crate::tonic::naming::TargetResolver;
use super::swap::SwapChannel;
pub type TargetChannel = ResolveStatusMiddleware<SwapChannel>;
pub struct TargetChannelBuilder {
resolver: Option<Arc<dyn TargetResolver>>,
endpoint_template: Option<Endpoint>,
trailer_header: Option<http::HeaderName>,
}
impl TargetChannelBuilder {
pub fn new() -> Self {
Self {
resolver: None,
endpoint_template: None,
trailer_header: None,
}
}
pub fn resolver(mut self, r: Arc<dyn TargetResolver>) -> Self {
self.resolver = Some(r);
self
}
pub fn trailer_header(mut self, name: impl AsRef<str>) -> Self {
let parsed = http::HeaderName::try_from(name.as_ref())
.expect("TargetChannelBuilder::trailer_header: invalid header name");
self.trailer_header = Some(parsed);
self
}
pub fn endpoint_template(mut self, ep: Endpoint) -> Self {
self.endpoint_template = Some(ep);
self
}
pub fn build(self) -> TargetChannel {
let resolver = self
.resolver
.expect("TargetChannelBuilder::resolver is required");
let trailer_header = self
.trailer_header
.expect("TargetChannelBuilder::trailer_header is required");
let connector = TargetConnectorBuilder::new().resolver(resolver).build();
let ep = self.endpoint_template.unwrap_or_else(default_endpoint);
let swap = SwapChannel::new(ep, connector);
ResolveStatusMiddleware::new(swap.clone(), trailer_header, move || swap.rebuild())
}
}
impl Default for TargetChannelBuilder {
fn default() -> Self {
Self::new()
}
}
fn default_endpoint() -> Endpoint {
Endpoint::from_static("http://fabric.invalid")
}