abstract_ns/
resolver.rs

1use std::sync::Arc;
2
3use futures::Future;
4use futures::stream::Stream;
5use error::Error;
6
7use combinators::{FrozenSubscriber, NullResolver, NullHostResolver};
8use {Name, Address, IpList};
9
10
11/// Resolves a hostname into a list of IpAddresses
12///
13/// This is usually equivalent of the resolving A or AAAA record. This
14/// kind of resolution is used in two cases:
15///
16/// 1. If user specified port of the service explicitly (`example.org:1234`)
17/// 2. When there is known default port like `80` for http
18///
19/// Note: akin to A records this method returns plain list of addresses so
20/// it can't use a backup addresses and weights. So this should be used for
21/// simple cases and full blown `Resolve` trait (i.e. SRV records) for
22/// more complex ones.
23pub trait HostResolve {
24
25    /// A future returned from `resolve()`
26    type HostFuture: Future<Item=IpList, Error=Error>;
27
28    /// Resolve a name to an address once
29    fn resolve_host(&self, name: &Name) -> Self::HostFuture;
30
31    /// Create a subscriber that resolves once using this resolver
32    /// and never updates a stream
33    ///
34    /// This is mostly useful for tests
35    fn frozen_host_subscriber(self) -> FrozenSubscriber<Self>
36        where Self: Sized
37    {
38        FrozenSubscriber { resolver: self }
39    }
40
41    /// Create a thing that implements Resolve+HostResolve but returns
42    /// `NameNotFound` on `resolve`
43    ///
44    /// This is needed to add resolver that can only resolve hostnames to
45    /// the router.
46    fn null_service_resolver(self) -> NullResolver<Self>
47        where Self: Sized
48    {
49        NullResolver { resolver: self }
50    }
51}
52
53/// Resolves a name of the service in to a set of addresses
54///
55/// This is commonly done using SRV records, but can also be done
56/// as a wrapper around resolver by resolving a host and adding a
57/// default value (see `HostResolve::with_default_port`.
58pub trait Resolve {
59    /// A future returned from `resolve()`
60    type Future: Future<Item=Address, Error=Error>;
61
62    /// Resolve a name to an address once
63    fn resolve(&self, name: &Name) -> Self::Future;
64
65    /// Create a subscriber that resolves once using this resolver
66    /// and never updates a stream
67    ///
68    /// This is mostly useful for tests
69    fn frozen_subscriber(self) -> FrozenSubscriber<Self>
70        where Self: Resolve + Sized
71    {
72        FrozenSubscriber { resolver: self }
73    }
74
75    /// Create a subscriber that resolves once using this resolver
76    /// and never updates a stream
77    ///
78    /// This is mostly useful for tests
79    fn frozen_service_subscriber(self) -> FrozenSubscriber<Self>
80        where Self: Sized
81    {
82        FrozenSubscriber { resolver: self }
83    }
84
85    /// Create a thing that implements Resolve+HostResolve but returns
86    /// `NameNotFound` on `resolve_host`
87    ///
88    /// This is needed to add resolver that can only resolve services to
89    /// the router.
90    fn null_host_resolver(self) -> NullHostResolver<Self>
91        where Self: Sized
92    {
93        NullHostResolver { resolver: self }
94    }
95}
96
97/// A resolver that allows to subscribe on the host name and receive updates
98///
99pub trait HostSubscribe {
100
101    /// An error type returned by a stream
102    ///
103    /// This is usually either ``abstract_ns::Error`` or ``Void``, showing
104    /// whether error can actually occur, but can be any other error at your
105    /// convenience.
106    ///
107    /// Note: this is an associated type so that connection pool
108    /// implementations could accept `SubscribeHost<Error=Void>` as there are
109    /// no reason to shutdown pool if there is a temporary error in name
110    /// resolution (and all errors should be considered temporary as
111    /// user can even fix invalid name by fixing configuration file while
112    /// connection pool is operating).
113    type HostError: Into<Error>;
114
115    /// A stream returned from `subscribe()`
116    type HostStream: Stream<Item=IpList, Error=Self::HostError>;
117
118    /// Resolve a name and subscribe to the updates
119    ///
120    /// Note: errors returned by a stream are considered fatal but temporary.
121    /// I.e. stream can't be used after an error, but user might subscribe
122    /// again after a short interval.
123    ///
124    /// For efficiency it might be useful to attempt name resolution few
125    /// times if the error is temporary before returning an error, but
126    /// on network resolver fatal errors (or subsequent temporary ones)
127    /// should be returned so middleware and routers can failover to other
128    /// sources and put errors to log.
129    fn subscribe_host(&self, name: &Name) -> Self::HostStream;
130}
131
132/// A resolver that allows to subscribe on the service name
133/// and receive updates
134pub trait Subscribe {
135
136    /// An error type returned by a stream
137    ///
138    /// This is usually either ``abstract_ns::Error`` or ``Void``, showing
139    /// whether error can actually occur, but can be any other error at your
140    /// convenience.
141    ///
142    /// Note: this is an associated type so that connection pool
143    /// implementations could accept `SubscribeHost<Error=Void>` as there are
144    /// no reason to shutdown pool if there is a temporary error in name
145    /// resolution (and all errors should be considered temporary as
146    /// user can even fix invalid name by fixing configuration file while
147    /// connection pool is operating).
148    type Error: Into<Error>;
149
150    /// A stream returned from `subscribe()`
151    type Stream: Stream<Item=Address, Error=Self::Error>;
152
153    /// Resolve a name and subscribe to the updates
154    ///
155    /// Note: errors returned by a stream are considered fatal but temporary.
156    /// I.e. stream can't be used after an error, but user might subscribe
157    /// again after a short interval.
158    ///
159    /// For efficiency it might be useful to attempt name resolution few
160    /// times if the error is temporary before returning an error, but
161    /// on network resolver fatal errors (or subsequent temporary ones)
162    /// should be returned so middleware and routers can failover to other
163    /// sources and put errors to log.
164    fn subscribe(&self, name: &Name) -> Self::Stream;
165}
166
167impl<T: Resolve> Resolve for Arc<T> {
168    type Future = T::Future;
169    fn resolve(&self, name: &Name) -> Self::Future {
170        (**self).resolve(name)
171    }
172}
173
174impl<T: HostResolve> HostResolve for Arc<T> {
175    type HostFuture = T::HostFuture;
176    fn resolve_host(&self, name: &Name) -> Self::HostFuture {
177        (**self).resolve_host(name)
178    }
179}
180
181impl<T: Subscribe> Subscribe for Arc<T> {
182    type Error = T::Error;
183    type Stream = T::Stream;
184    fn subscribe(&self, name: &Name) -> Self::Stream {
185        (**self).subscribe(name)
186    }
187}
188
189impl<T: HostSubscribe> HostSubscribe for Arc<T> {
190    type HostError = T::HostError;
191    type HostStream = T::HostStream;
192    fn subscribe_host(&self, name: &Name) -> Self::HostStream {
193        (**self).subscribe_host(name)
194    }
195}