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
//! Where you have services, you need managers use crate::service::Service; use crate::utils; /// Manages an internal collection of Services /// /// This implements a simple [Composite Pattern](https://en.wikipedia.org/wiki/Composite_pattern) /// that allows to manages a group of Service in a coordinated fashion. /// /// Services are `start()`ed in the order they are registered, and `stop()`ped in the reverse /// order. Also, a `ServiceManager` is also a `Service`, so further composition is possible. /// /// The design implies that in your application, you would hand over all the instances of `Service` /// to a `ServiceManager`, that will then orchestrate their starting and stopping. /// /// Thanks to the use of Composite Pattern, it can contain further instances of `ServiceManager`, /// allowing for the creation of complex /// [DAG diagrams](https://en.wikipedia.org/wiki/Directed_acyclic_graph) of services, /// with expressive relationship between them. pub struct ServiceManager { services: Vec<Box<Service>> } impl ServiceManager { /// Constructor pub fn new() -> Self { ServiceManager { services: Vec::new(), } } /// Register an instance of `Service`. /// /// The order of registration is important: `Service`s are started in order, and stopped /// in reverse order. /// /// # Parameters /// /// * `service_box`: a `Box` containing an instance of implementation of the `Service` trait pub fn register(&mut self, service_box: Box<Service>) { self.services.push(service_box); } /// Wait for the Process to receive a termination signal, then stop this `ServiceManager`. /// /// It's strongly advised to use this method only onces, for the _root_ `ServiceManager`, /// at the end of the `main()` thread. pub fn wait_termination_signal_then_stop(&mut self) { // Block until the process is terminated by a signal... utils::wait_for_process_termination_signal(); // ... then gracefully shut every service down self.stop_and_await(); } /// Apply the same closure to all contained `Service`s, in order fn apply_ordered<F>(&mut self, closure: F) where F: Fn(&mut Box<Service>) -> () { self.services .iter_mut() .for_each(closure); } /// Apply the same closure to all contained `Service`s, in reverse order fn apply_reversed<F>(&mut self, closure: F) where F: FnMut(&mut Box<Service>) -> () { self.services .iter_mut() .rev() .for_each(closure); } } impl Service for ServiceManager { /// Start all registered `Service`s, in order of registration fn start(&mut self) { self.apply_ordered(|s: &mut Box<Service>| s.start()); } /// Wait for all registered `Service`s to be started, in order of registration fn await_started(&mut self) { self.apply_ordered(|s: &mut Box<Service>| s.await_started()); } /// Start and then wait for all registered `Service`, in order of registration /// /// This is different then calling `start()` and then `await_started()`, because this method /// will wait for a `Service` to be started, before moving to the next one. /// /// This can be used to implement a _gracefull start_. fn start_and_await(&mut self) { self.apply_ordered(|s: &mut Box<Service>| s.start_and_await()); } /// Stop all registered `Service`s, in reverse order of registration fn stop(&mut self) { self.apply_reversed(|s: &mut Box<Service>| s.stop()); } /// Wait for all registered `Service`s to be stopped, in reverse order of registration fn await_stopped(&mut self) { self.apply_reversed(|s: &mut Box<Service>| s.await_stopped()); } /// Stop and then wait for all registered `Service`, in reverse order of registration /// /// This is different then calling `stop()` and then `await_stopped()`, because this method /// will wait for a `Service` to be stopped, before moving to the next one. /// /// This can be used to implement a _gracefull stop_. fn stop_and_await(&mut self) { self.apply_reversed(|s: &mut Box<Service>| s.stop_and_await()); } }