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
140
141
use std::collections::HashMap;
use std::fmt::Debug;
use std::sync::Arc;
use std::time::Duration;

use abstract_ns::{Name, Address, IpList};
use abstract_ns::{HostResolve, Resolve, HostSubscribe, Subscribe};
use internal_traits::{Resolver, Wrapper, NullResolver};


/// Configuration of the router
///
/// It has a builder interface. You can create a router from `Arc<Config>`
/// (made by `Config::done`) or a stream of configs.
#[derive(Clone, Debug)]
pub struct Config {
    pub(crate) restart_delay: Duration,
    pub(crate) convergence_delay: Duration,
    pub(crate) hosts: HashMap<Name, IpList>,
    pub(crate) services: HashMap<Name, Address>,
    pub(crate) suffixes: HashMap<String, Arc<Resolver>>,
    pub(crate) root: Arc<Resolver>,
}

impl Config {

    /// Create a new, empty config
    pub fn new() -> Config {
        Config {
            restart_delay: Duration::from_millis(100),
            convergence_delay: Duration::from_millis(100),
            hosts: HashMap::new(),
            services: HashMap::new(),
            suffixes: HashMap::new(),
            root: Arc::new(NullResolver),
        }
    }

    /// Sets delay after which router will restart any subscription stream
    ///
    /// This works both when stream yields end-of-stream and when stream
    /// has returned error. Default value is 100 milliseconds.
    pub fn restart_delay(&mut self, delay: Duration) -> &mut Self {
        self.restart_delay = delay;
        self
    }

    /// Sets delay used by [`subscribe_many`] family of functions
    ///
    /// The timeout is set when a new set of names arrives via stream or
    /// when configuration is updated. While the timer is active we don't
    /// send name updates to the application unless all (new) names are
    /// resolved.
    ///
    /// Good value is bigger than 90 or 99 percentile of name request
    /// latency, but small enough that delay of this long doesn't introduce
    /// any hiccups on the application.
    ///
    /// For example, if there are names [A, B, C] if C is resolved first
    /// we wait for the 100 millisecond (by default) timer to finish
    /// to let A and B also be resolved. If they aren't within the period
    /// only names in `C` are returned.
    ///
    /// Note if names are reloved later, they are added to the address set
    /// and update is delivered to the client. I.e. it's only important
    /// something depends on the first address value.
    ///
    /// The case where it's important is following: Client establishes
    /// few persistent connections by picking random IP Addresses from the
    /// set. Once new addresses arrive connections are still hold until
    /// one of them is broken. In this case, the first address (or the
    /// one that can be resolved faster for any reason) would have more
    /// connections received in most cases which might be a problem.
    ///
    /// [`subscribe_many`]: struct.Router.html#tymethod.subscribe_many
    pub fn convergence_delay(&mut self, delay: Duration) -> &mut Self {
        self.convergence_delay = delay;
        self
    }

    /// Add a host that will be resolved to list of addreses
    ///
    /// Hosts added by this host method overrides any other resolvers.
    pub fn add_host<A>(&mut self, name: &Name, addr: A)
        -> &mut Self
        where A: Into<IpList>
    {
        self.hosts.insert(name.clone(), addr.into());
        self
    }

    /// Add a service that will be resolved to an Address object
    ///
    /// Service names added by this host method overrides any other resolvers.
    pub fn add_service(&mut self, name: &Name, addr: Address) -> &mut Self {
        self.services.insert(name.clone(), addr);
        self
    }

    /// Add a resolver for suffix
    ///
    /// Note: you must supply a full resolver here,
    /// use `null_resolver`/`null_host_resolver` and
    /// [`interval_subscribe`] or `frozen_subscriber`
    /// and other combinators to fullfill needed type.
    ///
    /// [`interval_subscribe`]: trait.SubscribeExt.html#tymethod.interval_subscribe
    pub fn add_suffix<S, R>(&mut self, suffix: S, resolver: R)
        -> &mut Self
        where S: Into<String>,
              R: Resolve + HostResolve + Subscribe + HostSubscribe,
              R: Debug + 'static,
    {
        self.suffixes.insert(suffix.into(),
            Arc::new(Wrapper::new(resolver)));
        self
    }

    /// Removes already configured suffix
    pub fn remove_suffix<S>(&mut self, suffix: &str)
        -> &mut Self
    {
        self.suffixes.remove(suffix);
        self
    }

    /// Adds a host resolver used whenever no suffix matches
    pub fn set_fallthrough<R>(&mut self, resolver: R)
        -> &mut Self
        where R: Resolve + HostResolve + Subscribe + HostSubscribe,
              R: Debug + 'static,
    {
        self.root = Arc::new(Wrapper::new(resolver));
        self
    }

    /// A convenience method that returns Arc'd config
    pub fn done(&self) -> Arc<Config> {
        Arc::new(self.clone())
    }
}