@@ -11,6 +11,11 @@ use std::{
1111} ;
1212use tokio:: sync:: Mutex ;
1313
14+ pub type PinnedBoxedFuture < ' a , T > = Pin < Box < dyn Future < Output = T > + ' a > > ;
15+
16+ pub type PinnedBoxedFutureResult < ' a , T > =
17+ PinnedBoxedFuture < ' a , Result < T , Box < dyn Error + Send + Sync > > > ;
18+
1419#[ derive( Debug ) ]
1520pub enum Status {
1621 Started ,
@@ -102,24 +107,52 @@ impl ServiceInfo {
102107 }
103108 }
104109
110+ pub fn is_available ( & self ) -> Pin < Box < dyn Future < Output = bool > + ' _ > > {
111+ Box :: pin ( async move {
112+ let lock = self . status . lock ( ) . await ;
113+ matches ! ( & * lock, Status :: Started )
114+ } )
115+ }
116+
105117 pub async fn set_status ( & self , status : Status ) {
106118 let mut lock = self . status . lock ( ) . await ;
107119 * lock = status;
108120 }
109121}
110122
111- pub type PinnedBoxedFuture < ' a , T > = Pin < Box < dyn Future < Output = T > + ' a > > ;
123+ impl PartialEq for ServiceInfo {
124+ fn eq ( & self , other : & Self ) -> bool {
125+ self . id == other. id
126+ }
127+ }
112128
113- pub type PinnedBoxedFutureResult < ' a , T > =
114- PinnedBoxedFuture < ' a , Result < T , Box < dyn Error + Send + Sync > > > ;
129+ impl Eq for ServiceInfo { }
115130
116- //TODO: When Rust allows async trait methods to be object-safe, refactor this to use async instead of returning a future
131+ impl Ord for ServiceInfo {
132+ fn cmp ( & self , other : & Self ) -> Ordering {
133+ self . name . cmp ( & other. name )
134+ }
135+ }
136+
137+ impl PartialOrd for ServiceInfo {
138+ fn partial_cmp ( & self , other : & Self ) -> Option < Ordering > {
139+ Some ( self . cmp ( other) )
140+ }
141+ }
142+
143+ impl Hash for ServiceInfo {
144+ fn hash < H : Hasher > ( & self , state : & mut H ) {
145+ self . id . hash ( state) ;
146+ }
147+ }
148+
149+ //TODO: When Rust allows async trait methods to be object-safe, refactor this to use async instead of returning a PinnedBoxedFutureResult
117150pub trait ServiceInternals {
118151 fn start ( & mut self ) -> PinnedBoxedFutureResult < ' _ , ( ) > ;
119152 fn stop ( & mut self ) -> PinnedBoxedFutureResult < ' _ , ( ) > ;
120153}
121154
122- //TODO: When Rust allows async trait methods to be object-safe, refactor this to use async instead of returning a future
155+ //TODO: When Rust allows async trait methods to be object-safe, refactor this to use async instead of returning a PinnedBoxedFutureResult
123156pub trait Service : ServiceInternals {
124157 fn info ( & self ) -> & ServiceInfo ;
125158
@@ -171,33 +204,28 @@ pub trait Service: ServiceInternals {
171204 match ServiceInternals :: stop ( self ) . await {
172205 Ok ( ( ) ) => {
173206 self . info ( ) . set_status ( Status :: Stopped ) . await ;
207+ info ! ( "Stopped service: {}" , self . info( ) . name) ;
174208 }
175209 Err ( error) => {
176210 self . info ( ) . set_status ( Status :: FailedStopping ( error) ) . await ;
211+ error ! ( "Failed to stop service: {}" , self . info( ) . name) ;
177212 }
178213 }
179214 } )
180215 }
181-
182- fn is_available ( & self ) -> Pin < Box < dyn Future < Output = bool > + ' _ > > {
183- Box :: pin ( async move {
184- let lock = self . info ( ) . status . lock ( ) . await ;
185- matches ! ( & * lock, Status :: Started )
186- } )
187- }
188216}
189217
190218impl Eq for dyn Service { }
191219
192220impl PartialEq for dyn Service {
193221 fn eq ( & self , other : & Self ) -> bool {
194- self . info ( ) . name == other. info ( ) . name
222+ self . info ( ) == other. info ( )
195223 }
196224}
197225
198226impl Ord for dyn Service {
199227 fn cmp ( & self , other : & Self ) -> Ordering {
200- self . info ( ) . name . cmp ( & other. info ( ) . name )
228+ self . info ( ) . cmp ( other. info ( ) )
201229 }
202230}
203231
@@ -209,7 +237,7 @@ impl PartialOrd for dyn Service {
209237
210238impl Hash for dyn Service {
211239 fn hash < H : Hasher > ( & self , state : & mut H ) {
212- self . info ( ) . name . hash ( state) ;
240+ self . info ( ) . hash ( state) ;
213241 }
214242}
215243
@@ -224,15 +252,12 @@ impl ServiceManagerBuilder {
224252 }
225253
226254 pub fn with_service ( mut self , service : Box < dyn Service > ) -> Self {
227- let service_exists = self
228- . services
229- . iter ( )
230- . any ( |s| s. info ( ) . name == service. info ( ) . name ) ; // Can't use *s == service here because value would be moved
255+ let service_exists = self . services . iter ( ) . any ( |s| s. info ( ) == service. info ( ) ) ;
231256
232257 if service_exists {
233258 warn ! (
234- "Tried to add service {} multiple times . Ignoring." ,
235- service. info( ) . name
259+ "Tried to add service {} ({}), but a service with that ID already exists . Ignoring." ,
260+ service. info( ) . name, service . info ( ) . id
236261 ) ;
237262
238263 return self ;
@@ -260,7 +285,6 @@ impl ServiceManager {
260285 pub fn start_services ( & mut self ) -> PinnedBoxedFuture < ' _ , ( ) > {
261286 Box :: pin ( async move {
262287 for service in & mut self . services {
263- info ! ( "Starting service: {}" , service. info( ) . name) ;
264288 service. wrapped_start ( ) . await ;
265289 }
266290 } )
@@ -269,7 +293,6 @@ impl ServiceManager {
269293 pub fn stop_services ( & mut self ) -> PinnedBoxedFuture < ' _ , ( ) > {
270294 Box :: pin ( async move {
271295 for service in & mut self . services {
272- info ! ( "Stopping service: {}" , service. info( ) . name) ;
273296 service. wrapped_stop ( ) . await ;
274297 }
275298 } )
@@ -423,7 +446,7 @@ impl Display for ServiceManager {
423446
424447 let mut services = self . services . iter ( ) . peekable ( ) ;
425448 while let Some ( service) = services. next ( ) {
426- write ! ( f, "{}" , service. info( ) . name) ?;
449+ write ! ( f, "{} ({}) " , service. info( ) . name, service . info ( ) . id ) ?;
427450 if services. peek ( ) . is_some ( ) {
428451 write ! ( f, ", " ) ?;
429452 }
0 commit comments