dcs2/
coordination.rs

1use crate::communication::messages::{Package, UpdateClusterVec};
2use crate::communication::service::CommunicationService;
3use core::fmt::Debug;
4
5use crate::nodes::SystemNodeId;
6use crate::rules::measurements::{Measurement, SystemState};
7use crate::rules::strategy::Rule;
8
9pub type CoordinationPackage<CoordMessage> = Package<SystemNodeId, CoordMessage>;
10
11/// Stopwatches are used when you need to know when time is up. This is when you need to assert
12/// a certain ammount of time has passed
13pub trait Stopwatch {
14    /// Creates a new instance with the target time as now + `millis`
15    fn from_millis(millis: u64) -> Self;
16    /// Returns the delta time in secs.
17    fn as_secs(&self) -> u64;
18    /// Restarts the clock.
19    fn restart(&mut self);
20    /// Returns true if the time set in [`Stopwatch::from_millis`] has passed
21    fn is_timeout(&self) -> bool;
22    /// Returns the current stopwatch time expressed as seconds.
23    fn current_time_as_secs(&mut self) -> u64;
24    /// This is used in case a manual update of the clock is required after each tick or cycle of
25    /// the main event loop.
26    fn update(&mut self) {}
27}
28
29/// Timer gives the current time in seconds
30pub trait Timer {
31    /// Creates a new instance with the delta set as `millis`
32    fn from_millis(millis: u64) -> Self;
33    /// Returns the delta time in secs.
34    fn as_secs(&self) -> u64;
35    /// Waits for the given delta time.
36    fn wait(&self);
37}
38
39/// This is the main abstraction to be implemented by any coordination algorithm.
40pub trait CoordinationService<Clock: Stopwatch, Message: Clone + Debug, Members, Metadata> {
41    fn new(id: SystemNodeId, metadata: Metadata) -> Self;
42
43    /// Returns the ID of the cluster leader, or None if it is not set.
44    fn leader(&self) -> Option<SystemNodeId>;
45
46    /// Returns the coordinated state of the system
47    fn get_state(&self) -> SystemState;
48
49    /// Returns the current rule coordinated by the system
50    fn get_current_rule(&self) -> Option<Rule>;
51
52    /// Updates the nodes in the cluster based on [`new_config`].
53    fn update_rule(
54        &mut self,
55        communication_service: &mut dyn CommunicationService<Package<SystemNodeId, Message>>,
56        new_rule: Rule,
57    );
58
59    /// Updates the nodes in the cluster based on [`new_config`].
60    fn update_members(
61        &mut self,
62        communication_service: &mut dyn CommunicationService<Package<SystemNodeId, Message>>,
63        new_config: UpdateClusterVec,
64    );
65
66    /// Updates the coordinated state of the system based on `measurement`
67    fn update_state(
68        &mut self,
69        communication_service: &mut dyn CommunicationService<Package<SystemNodeId, Message>>,
70        measurement: Measurement,
71    );
72
73    /// Receives a message from another node so that the coordination can occur.
74    fn process(
75        &mut self,
76        communication_service: &mut dyn CommunicationService<Package<SystemNodeId, Message>>,
77        package: Option<CoordinationPackage<Message>>,
78        members: Members,
79    );
80}