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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
use std::sync::Arc;

use futures::Future;
use futures::stream::Stream;
use error::Error;

use combinators::{FrozenSubscriber, NullResolver, NullHostResolver};
use {Name, Address, IpList};


/// Resolves a hostname into a list of IpAddresses
///
/// This is usually equivalent of the resolving A or AAAA record. This
/// kind of resolution is used in two cases:
///
/// 1. If user specified port of the service explicitly (`example.org:1234`)
/// 2. When there is known default port like `80` for http
///
/// Note: akin to A records this method returns plain list of addresses so
/// it can't use a backup addresses and weights. So this should be used for
/// simple cases and full blown `Resolve` trait (i.e. SRV records) for
/// more complex ones.
pub trait HostResolve {

    /// A future returned from `resolve()`
    type HostFuture: Future<Item=IpList, Error=Error>;

    /// Resolve a name to an address once
    fn resolve_host(&self, name: &Name) -> Self::HostFuture;

    /// Create a subscriber that resolves once using this resolver
    /// and never updates a stream
    ///
    /// This is mostly useful for tests
    fn frozen_host_subscriber(self) -> FrozenSubscriber<Self>
        where Self: Sized
    {
        FrozenSubscriber { resolver: self }
    }

    /// Create a thing that implements Resolve+HostResolve but returns
    /// `NameNotFound` on `resolve`
    ///
    /// This is needed to add resolver that can only resolve hostnames to
    /// the router.
    fn null_service_resolver(self) -> NullResolver<Self>
        where Self: Sized
    {
        NullResolver { resolver: self }
    }
}

/// Resolves a name of the service in to a set of addresses
///
/// This is commonly done using SRV records, but can also be done
/// as a wrapper around resolver by resolving a host and adding a
/// default value (see `HostResolve::with_default_port`.
pub trait Resolve {
    /// A future returned from `resolve()`
    type Future: Future<Item=Address, Error=Error>;

    /// Resolve a name to an address once
    fn resolve(&self, name: &Name) -> Self::Future;

    /// Create a subscriber that resolves once using this resolver
    /// and never updates a stream
    ///
    /// This is mostly useful for tests
    fn frozen_subscriber(self) -> FrozenSubscriber<Self>
        where Self: Resolve + Sized
    {
        FrozenSubscriber { resolver: self }
    }

    /// Create a subscriber that resolves once using this resolver
    /// and never updates a stream
    ///
    /// This is mostly useful for tests
    fn frozen_service_subscriber(self) -> FrozenSubscriber<Self>
        where Self: Sized
    {
        FrozenSubscriber { resolver: self }
    }

    /// Create a thing that implements Resolve+HostResolve but returns
    /// `NameNotFound` on `resolve_host`
    ///
    /// This is needed to add resolver that can only resolve services to
    /// the router.
    fn null_host_resolver(self) -> NullHostResolver<Self>
        where Self: Sized
    {
        NullHostResolver { resolver: self }
    }
}

/// A resolver that allows to subscribe on the host name and receive updates
///
pub trait HostSubscribe {

    /// An error type returned by a stream
    ///
    /// This is usually either ``abstract_ns::Error`` or ``Void``, showing
    /// whether error can actually occur, but can be any other error at your
    /// convenience.
    ///
    /// Note: this is an associated type so that connection pool
    /// implementations could accept `SubscribeHost<Error=Void>` as there are
    /// no reason to shutdown pool if there is a temporary error in name
    /// resolution (and all errors should be considered temporary as
    /// user can even fix invalid name by fixing configuration file while
    /// connection pool is operating).
    type HostError: Into<Error>;

    /// A stream returned from `subscribe()`
    type HostStream: Stream<Item=IpList, Error=Self::HostError>;

    /// Resolve a name and subscribe to the updates
    ///
    /// Note: errors returned by a stream are considered fatal but temporary.
    /// I.e. stream can't be used after an error, but user might subscribe
    /// again after a short interval.
    ///
    /// For efficiency it might be useful to attempt name resolution few
    /// times if the error is temporary before returning an error, but
    /// on network resolver fatal errors (or subsequent temporary ones)
    /// should be returned so middleware and routers can failover to other
    /// sources and put errors to log.
    fn subscribe_host(&self, name: &Name) -> Self::HostStream;
}

/// A resolver that allows to subscribe on the service name
/// and receive updates
pub trait Subscribe {

    /// An error type returned by a stream
    ///
    /// This is usually either ``abstract_ns::Error`` or ``Void``, showing
    /// whether error can actually occur, but can be any other error at your
    /// convenience.
    ///
    /// Note: this is an associated type so that connection pool
    /// implementations could accept `SubscribeHost<Error=Void>` as there are
    /// no reason to shutdown pool if there is a temporary error in name
    /// resolution (and all errors should be considered temporary as
    /// user can even fix invalid name by fixing configuration file while
    /// connection pool is operating).
    type Error: Into<Error>;

    /// A stream returned from `subscribe()`
    type Stream: Stream<Item=Address, Error=Self::Error>;

    /// Resolve a name and subscribe to the updates
    ///
    /// Note: errors returned by a stream are considered fatal but temporary.
    /// I.e. stream can't be used after an error, but user might subscribe
    /// again after a short interval.
    ///
    /// For efficiency it might be useful to attempt name resolution few
    /// times if the error is temporary before returning an error, but
    /// on network resolver fatal errors (or subsequent temporary ones)
    /// should be returned so middleware and routers can failover to other
    /// sources and put errors to log.
    fn subscribe(&self, name: &Name) -> Self::Stream;
}

impl<T: Resolve> Resolve for Arc<T> {
    type Future = T::Future;
    fn resolve(&self, name: &Name) -> Self::Future {
        (**self).resolve(name)
    }
}

impl<T: HostResolve> HostResolve for Arc<T> {
    type HostFuture = T::HostFuture;
    fn resolve_host(&self, name: &Name) -> Self::HostFuture {
        (**self).resolve_host(name)
    }
}

impl<T: Subscribe> Subscribe for Arc<T> {
    type Error = T::Error;
    type Stream = T::Stream;
    fn subscribe(&self, name: &Name) -> Self::Stream {
        (**self).subscribe(name)
    }
}

impl<T: HostSubscribe> HostSubscribe for Arc<T> {
    type HostError = T::HostError;
    type HostStream = T::HostStream;
    fn subscribe_host(&self, name: &Name) -> Self::HostStream {
        (**self).subscribe_host(name)
    }
}