ns_router/
config.rs

1use std::collections::HashMap;
2use std::fmt::Debug;
3use std::sync::Arc;
4use std::time::Duration;
5
6use abstract_ns::{Name, Address, IpList};
7use abstract_ns::{HostResolve, Resolve, HostSubscribe, Subscribe};
8use internal_traits::{Resolver, Wrapper, NullResolver};
9
10
11/// Configuration of the router
12///
13/// It has a builder interface. You can create a router from `Arc<Config>`
14/// (made by `Config::done`) or a stream of configs.
15#[derive(Clone, Debug)]
16pub struct Config {
17    pub(crate) restart_delay: Duration,
18    pub(crate) convergence_delay: Duration,
19    pub(crate) hosts: HashMap<Name, IpList>,
20    pub(crate) services: HashMap<Name, Address>,
21    pub(crate) suffixes: HashMap<String, Arc<Resolver>>,
22    pub(crate) root: Arc<Resolver>,
23}
24
25impl Config {
26
27    /// Create a new, empty config
28    pub fn new() -> Config {
29        Config {
30            restart_delay: Duration::from_millis(100),
31            convergence_delay: Duration::from_millis(100),
32            hosts: HashMap::new(),
33            services: HashMap::new(),
34            suffixes: HashMap::new(),
35            root: Arc::new(NullResolver),
36        }
37    }
38
39    /// Sets delay after which router will restart any subscription stream
40    ///
41    /// This works both when stream yields end-of-stream and when stream
42    /// has returned error. Default value is 100 milliseconds.
43    pub fn restart_delay(&mut self, delay: Duration) -> &mut Self {
44        self.restart_delay = delay;
45        self
46    }
47
48    /// Sets delay used by [`subscribe_many`] family of functions
49    ///
50    /// The timeout is set when a new set of names arrives via stream or
51    /// when configuration is updated. While the timer is active we don't
52    /// send name updates to the application unless all (new) names are
53    /// resolved.
54    ///
55    /// Good value is bigger than 90 or 99 percentile of name request
56    /// latency, but small enough that delay of this long doesn't introduce
57    /// any hiccups on the application.
58    ///
59    /// For example, if there are names [A, B, C] if C is resolved first
60    /// we wait for the 100 millisecond (by default) timer to finish
61    /// to let A and B also be resolved. If they aren't within the period
62    /// only names in `C` are returned.
63    ///
64    /// Note if names are reloved later, they are added to the address set
65    /// and update is delivered to the client. I.e. it's only important
66    /// something depends on the first address value.
67    ///
68    /// The case where it's important is following: Client establishes
69    /// few persistent connections by picking random IP Addresses from the
70    /// set. Once new addresses arrive connections are still hold until
71    /// one of them is broken. In this case, the first address (or the
72    /// one that can be resolved faster for any reason) would have more
73    /// connections received in most cases which might be a problem.
74    ///
75    /// [`subscribe_many`]: struct.Router.html#tymethod.subscribe_many
76    pub fn convergence_delay(&mut self, delay: Duration) -> &mut Self {
77        self.convergence_delay = delay;
78        self
79    }
80
81    /// Add a host that will be resolved to list of addreses
82    ///
83    /// Hosts added by this host method overrides any other resolvers.
84    pub fn add_host<A>(&mut self, name: &Name, addr: A)
85        -> &mut Self
86        where A: Into<IpList>
87    {
88        self.hosts.insert(name.clone(), addr.into());
89        self
90    }
91
92    /// Add a service that will be resolved to an Address object
93    ///
94    /// Service names added by this host method overrides any other resolvers.
95    pub fn add_service(&mut self, name: &Name, addr: Address) -> &mut Self {
96        self.services.insert(name.clone(), addr);
97        self
98    }
99
100    /// Add a resolver for suffix
101    ///
102    /// Note: you must supply a full resolver here,
103    /// use `null_resolver`/`null_host_resolver` and
104    /// [`interval_subscribe`] or `frozen_subscriber`
105    /// and other combinators to fullfill needed type.
106    ///
107    /// [`interval_subscribe`]: trait.SubscribeExt.html#tymethod.interval_subscribe
108    pub fn add_suffix<S, R>(&mut self, suffix: S, resolver: R)
109        -> &mut Self
110        where S: Into<String>,
111              R: Resolve + HostResolve + Subscribe + HostSubscribe,
112              R: Debug + 'static,
113    {
114        self.suffixes.insert(suffix.into(),
115            Arc::new(Wrapper::new(resolver)));
116        self
117    }
118
119    /// Removes already configured suffix
120    pub fn remove_suffix<S>(&mut self, suffix: &str)
121        -> &mut Self
122    {
123        self.suffixes.remove(suffix);
124        self
125    }
126
127    /// Adds a host resolver used whenever no suffix matches
128    pub fn set_fallthrough<R>(&mut self, resolver: R)
129        -> &mut Self
130        where R: Resolve + HostResolve + Subscribe + HostSubscribe,
131              R: Debug + 'static,
132    {
133        self.root = Arc::new(Wrapper::new(resolver));
134        self
135    }
136
137    /// A convenience method that returns Arc'd config
138    pub fn done(&self) -> Arc<Config> {
139        Arc::new(self.clone())
140    }
141}