1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
//! `ginepro` offers an enriched tonic [`Channel`](tonic::transport::Channel) using a pluggable service discovery
//! to periodcally update the active set of `gRPC` servers.
//!
//! # Simple example
//!
//! ```rust
//! #[tokio::main]
//! async fn main() {
//! use ginepro::LoadBalancedChannel;
//! use shared_proto::pb::tester_client::TesterClient;
//! use std::convert::TryInto;
//!
//! // Create a load balanced channel with the default lookup implementation.
//! let load_balanced_channel = LoadBalancedChannel::builder(("my.hostname", 5000))
//! .channel()
//! .await
//! .expect("failed to construct LoadBalancedChannel");
//!
//! let tester_client = TesterClient::new(load_balanced_channel);
//! }
//! ```
//!
//! [`LoadBalancedChannel`] also allows plugging in a different implementation of [`LookupService`].
//!
//! ```rust
//! use ginepro::{LookupService, ServiceDefinition};
//! use std::collections::HashSet;
//! use std::net::SocketAddr;
//!
//! // This does nothing
//! struct DummyLookupService;
//!
//! #[async_trait::async_trait]
//! impl LookupService for DummyLookupService {
//! async fn resolve_service_endpoints(
//! &self,
//! _definition: &ServiceDefinition,
//! ) -> Result<HashSet<SocketAddr>, anyhow::Error> {
//! Ok(HashSet::new())
//! }
//! }
//!
//! #[tokio::main]
//! async fn main() {
//! use ginepro::LoadBalancedChannel;
//! use shared_proto::pb::tester_client::TesterClient;
//! use std::convert::TryInto;
//!
//! // Create a load balanced channel with the default lookup implementation.
//! let load_balanced_channel = LoadBalancedChannel::builder(("my.hostname", 5000))
//! .lookup_service(DummyLookupService)
//! .channel()
//! .await
//! .expect("failed to construct LoadBalancedChannel");
//!
//! let tester_client = TesterClient::new(load_balanced_channel);
//! }
//! ```
//! For systems with lower churn, the probe interval can be lowered.
//!
//! ```rust
//! #[tokio::main]
//! async fn main() {
//! use ginepro::{LoadBalancedChannel, LoadBalancedChannelBuilder};
//! use shared_proto::pb::tester_client::TesterClient;
//! use std::convert::TryInto;
//!
//! let load_balanced_channel = LoadBalancedChannelBuilder::new_with_service(("my.hostname", 5000))
//! .dns_probe_interval(std::time::Duration::from_secs(3))
//! .channel()
//! .await
//! .expect("failed to construct LoadBalancedChannel");
//!
//! let tester_client = TesterClient::new(load_balanced_channel);
//! }
//! ```
//!
//! It's also possible to associate a timeout for every new endpoint that the
//! [`LoadBalancedChannel`] tries to connect to.
//! .
//!
//! ```rust
//! #[tokio::main]
//! async fn main() {
//! use ginepro::LoadBalancedChannel;
//! use shared_proto::pb::tester_client::TesterClient;
//! use std::convert::TryInto;
//!
//! let load_balanced_channel = LoadBalancedChannel::builder(("my.hostname", 5000))
//! .timeout(std::time::Duration::from_secs(10))
//! .channel()
//! .await
//! .expect("failed to construct LoadBalancedChannel");
//!
//! let tester_client = TesterClient::new(load_balanced_channel);
//! }
//! ```
//!
//! It's also possible to eagerly resolve the service endpoints once before
//! [`LoadBalancedChannel`] is constructed.
//! .
//!
//! ```rust,no_run
//! #[tokio::main]
//! async fn main() {
//! use ginepro::{LoadBalancedChannel, ResolutionStrategy};
//! use shared_proto::pb::tester_client::TesterClient;
//! use std::time::Duration;
//! use std::convert::TryInto;
//!
//! let load_balanced_channel = LoadBalancedChannel::builder(("my.hostname", 5000))
//! .timeout(std::time::Duration::from_secs(10))
//! .resolution_strategy(ginepro::ResolutionStrategy::Eager {
//! timeout: Duration::from_secs(20),
//! })
//! .channel()
//! .await
//! .expect("failed to construct LoadBalancedChannel");
//!
//! let tester_client = TesterClient::new(load_balanced_channel);
//! }
//! ```
//!
//! # Internals
//! The tonic [`Channel`](tonic::transport::Channel) exposes the function
//! [`balance_channel`](tonic::transport::Channel::balance_channel) which returnes a bounded channel through which
//! endpoint changes can be sent.
//! `ginepro` uses this message passing mechanism to report when servers are added and removed.
mod balanced_channel;
mod dns_resolver;
mod lookup_service;
mod service_definition;
mod service_probe;
pub use balanced_channel::*;
pub use dns_resolver::*;
pub use lookup_service::*;
pub use service_definition::*;