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}