From b4809b3f33e0069480edef07185f9dd71a9af063 Mon Sep 17 00:00:00 2001 From: maciejnems Date: Wed, 28 Dec 2022 13:30:18 +0100 Subject: [PATCH 01/12] add justification broadcast ticker --- finality-aleph/src/lib.rs | 1 + finality-aleph/src/sync/mod.rs | 3 + finality-aleph/src/sync/ticker.rs | 102 ++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+) create mode 100644 finality-aleph/src/sync/mod.rs create mode 100644 finality-aleph/src/sync/ticker.rs diff --git a/finality-aleph/src/lib.rs b/finality-aleph/src/lib.rs index 9de90b43de..12f4567466 100644 --- a/finality-aleph/src/lib.rs +++ b/finality-aleph/src/lib.rs @@ -44,6 +44,7 @@ mod nodes; mod party; mod session; mod session_map; +mod sync; #[cfg(test)] pub mod testing; diff --git a/finality-aleph/src/sync/mod.rs b/finality-aleph/src/sync/mod.rs new file mode 100644 index 0000000000..0f9efc7832 --- /dev/null +++ b/finality-aleph/src/sync/mod.rs @@ -0,0 +1,3 @@ +// TODO: remove when ticker is used +#[allow(dead_code)] +mod ticker; diff --git a/finality-aleph/src/sync/ticker.rs b/finality-aleph/src/sync/ticker.rs new file mode 100644 index 0000000000..94edb25d5a --- /dev/null +++ b/finality-aleph/src/sync/ticker.rs @@ -0,0 +1,102 @@ +use tokio::time::{sleep, Duration, Instant}; + +/// This struct is used for determining when we should broadcast justification so that it does not happen too often. +pub struct BroadcastTicker { + last_broadcast: Instant, + last_periodic_broadcast: Instant, + current_periodic_timeout: Duration, + max_timeout: Duration, + min_timeout: Duration, +} + +impl BroadcastTicker { + pub fn new(max_timeout: Duration, min_timeout: Duration) -> Self { + Self { + last_broadcast: Instant::now(), + last_periodic_broadcast: Instant::now(), + current_periodic_timeout: max_timeout, + max_timeout, + min_timeout, + } + } + + /// Returns whether we should broadcast right now if we just imported a justification. + /// If min_timeout elapsed since last broadcast, returns true, sets last broadcast to now and will + /// return true again if called after `self.min_timeout`. + /// If not, returns false and sets periodic broadcast timeout to `self.min_timeout`. + /// This is to prevent from sending every justification when importing a batch of them. This way, + /// when receiving batch of justifications we will broadcast the first justification and the highest known + /// after `self.min_timeout` using periodic broadcast. + pub fn try_broadcast(&mut self) -> bool { + let now = Instant::now(); + if now.saturating_duration_since(self.last_broadcast) >= self.min_timeout { + self.last_broadcast = now; + true + } else { + self.current_periodic_timeout = self.min_timeout; + false + } + } + + /// Sleeps until next periodic broadcast should happen. + /// In case time elapsed, sets last periodic broadcast to now and periodic timeout to `self.max_timeout`. + pub async fn wait_for_periodic_broadcast(&mut self) { + let since_last = Instant::now().saturating_duration_since(self.last_periodic_broadcast); + sleep(self.current_periodic_timeout.saturating_sub(since_last)).await; + self.current_periodic_timeout = self.max_timeout; + self.last_periodic_broadcast = Instant::now(); + } +} + +#[cfg(test)] +mod tests { + use tokio::time::{sleep, timeout, Duration}; + + use super::BroadcastTicker; + + #[tokio::test] + async fn try_broadcast() { + let max_timeout = Duration::from_millis(700); + let min_timeout = Duration::from_millis(100); + let mut ticker = BroadcastTicker::new(max_timeout, min_timeout); + assert!(!ticker.try_broadcast()); + sleep(min_timeout).await; + assert!(ticker.try_broadcast()); + assert!(!ticker.try_broadcast()); + } + + #[tokio::test] + async fn wait_for_periodic_broadcast() { + let max_timeout = Duration::from_millis(700); + let min_timeout = Duration::from_millis(100); + let mut ticker = BroadcastTicker::new(max_timeout, min_timeout); + assert_ne!( + timeout(2 * min_timeout, ticker.wait_for_periodic_broadcast()).await, + Ok(()) + ); + assert_eq!( + timeout(max_timeout, ticker.wait_for_periodic_broadcast()).await, + Ok(()) + ); + } + + #[tokio::test] + async fn wait_for_periodic_broadcast_after_try_broadcast() { + let max_timeout = Duration::from_millis(700); + let min_timeout = Duration::from_millis(100); + let mut ticker = BroadcastTicker::new(max_timeout, min_timeout); + assert!(!ticker.try_broadcast()); + assert_eq!( + timeout(2 * min_timeout, ticker.wait_for_periodic_broadcast()).await, + Ok(()) + ); + assert_ne!( + timeout(2 * min_timeout, ticker.wait_for_periodic_broadcast()).await, + Ok(()) + ); + assert_eq!( + timeout(max_timeout, ticker.wait_for_periodic_broadcast()).await, + Ok(()) + ); + } +} From c989c8e754206c682f197bc521e2a3e62c679c13 Mon Sep 17 00:00:00 2001 From: maciejnems Date: Wed, 28 Dec 2022 14:17:07 +0100 Subject: [PATCH 02/12] Join periodic and normal broadcast last Instant --- finality-aleph/src/sync/ticker.rs | 53 +++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 6 deletions(-) diff --git a/finality-aleph/src/sync/ticker.rs b/finality-aleph/src/sync/ticker.rs index 94edb25d5a..fc67ef8414 100644 --- a/finality-aleph/src/sync/ticker.rs +++ b/finality-aleph/src/sync/ticker.rs @@ -3,7 +3,6 @@ use tokio::time::{sleep, Duration, Instant}; /// This struct is used for determining when we should broadcast justification so that it does not happen too often. pub struct BroadcastTicker { last_broadcast: Instant, - last_periodic_broadcast: Instant, current_periodic_timeout: Duration, max_timeout: Duration, min_timeout: Duration, @@ -13,7 +12,6 @@ impl BroadcastTicker { pub fn new(max_timeout: Duration, min_timeout: Duration) -> Self { Self { last_broadcast: Instant::now(), - last_periodic_broadcast: Instant::now(), current_periodic_timeout: max_timeout, max_timeout, min_timeout, @@ -39,12 +37,12 @@ impl BroadcastTicker { } /// Sleeps until next periodic broadcast should happen. - /// In case time elapsed, sets last periodic broadcast to now and periodic timeout to `self.max_timeout`. + /// In case enough time elapsed, sets last broadcast to now and periodic timeout to `self.max_timeout`. pub async fn wait_for_periodic_broadcast(&mut self) { - let since_last = Instant::now().saturating_duration_since(self.last_periodic_broadcast); + let since_last = Instant::now().saturating_duration_since(self.last_broadcast); sleep(self.current_periodic_timeout.saturating_sub(since_last)).await; self.current_periodic_timeout = self.max_timeout; - self.last_periodic_broadcast = Instant::now(); + self.last_broadcast = Instant::now(); } } @@ -59,6 +57,7 @@ mod tests { let max_timeout = Duration::from_millis(700); let min_timeout = Duration::from_millis(100); let mut ticker = BroadcastTicker::new(max_timeout, min_timeout); + assert!(!ticker.try_broadcast()); sleep(min_timeout).await; assert!(ticker.try_broadcast()); @@ -70,6 +69,26 @@ mod tests { let max_timeout = Duration::from_millis(700); let min_timeout = Duration::from_millis(100); let mut ticker = BroadcastTicker::new(max_timeout, min_timeout); + + assert_ne!( + timeout(2 * min_timeout, ticker.wait_for_periodic_broadcast()).await, + Ok(()) + ); + assert_eq!( + timeout(max_timeout, ticker.wait_for_periodic_broadcast()).await, + Ok(()) + ); + } + + #[tokio::test] + async fn wait_for_periodic_broadcast_after_try_broadcast_true() { + let max_timeout = Duration::from_millis(700); + let min_timeout = Duration::from_millis(100); + let mut ticker = BroadcastTicker::new(max_timeout, min_timeout); + + sleep(min_timeout).await; + assert!(ticker.try_broadcast()); + assert_ne!( timeout(2 * min_timeout, ticker.wait_for_periodic_broadcast()).await, Ok(()) @@ -81,11 +100,13 @@ mod tests { } #[tokio::test] - async fn wait_for_periodic_broadcast_after_try_broadcast() { + async fn wait_for_periodic_broadcast_after_try_broadcast_false() { let max_timeout = Duration::from_millis(700); let min_timeout = Duration::from_millis(100); let mut ticker = BroadcastTicker::new(max_timeout, min_timeout); + assert!(!ticker.try_broadcast()); + assert_eq!( timeout(2 * min_timeout, ticker.wait_for_periodic_broadcast()).await, Ok(()) @@ -99,4 +120,24 @@ mod tests { Ok(()) ); } + + #[tokio::test] + async fn try_broadcast_after_wait_for_periodic_broadcast() { + let max_timeout = Duration::from_millis(700); + let min_timeout = Duration::from_millis(100); + let mut ticker = BroadcastTicker::new(max_timeout, min_timeout); + + assert_eq!( + timeout( + max_timeout + min_timeout, + ticker.wait_for_periodic_broadcast() + ) + .await, + Ok(()) + ); + + assert!(!ticker.try_broadcast()); + sleep(min_timeout).await; + assert!(ticker.try_broadcast()); + } } From 78c5068e343e7c4878d7f4aceb612383c86acecd Mon Sep 17 00:00:00 2001 From: maciejnems Date: Wed, 28 Dec 2022 19:18:49 +0100 Subject: [PATCH 03/12] move clippy dead code --- finality-aleph/src/lib.rs | 2 ++ finality-aleph/src/sync/mod.rs | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/finality-aleph/src/lib.rs b/finality-aleph/src/lib.rs index 12f4567466..b2a6f7aae0 100644 --- a/finality-aleph/src/lib.rs +++ b/finality-aleph/src/lib.rs @@ -44,6 +44,8 @@ mod nodes; mod party; mod session; mod session_map; +// TODO: remove when module is used +#[allow(dead_code)] mod sync; #[cfg(test)] pub mod testing; diff --git a/finality-aleph/src/sync/mod.rs b/finality-aleph/src/sync/mod.rs index 0f9efc7832..54f03c743e 100644 --- a/finality-aleph/src/sync/mod.rs +++ b/finality-aleph/src/sync/mod.rs @@ -1,3 +1 @@ -// TODO: remove when ticker is used -#[allow(dead_code)] mod ticker; From d5a908b1bb196283aaf7e40fc68686eff568b90d Mon Sep 17 00:00:00 2001 From: maciejnems Date: Wed, 28 Dec 2022 19:20:47 +0100 Subject: [PATCH 04/12] rename to ticker --- finality-aleph/src/sync/ticker.rs | 52 +++++++++++++++---------------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/finality-aleph/src/sync/ticker.rs b/finality-aleph/src/sync/ticker.rs index fc67ef8414..1815ad0e53 100644 --- a/finality-aleph/src/sync/ticker.rs +++ b/finality-aleph/src/sync/ticker.rs @@ -1,48 +1,46 @@ use tokio::time::{sleep, Duration, Instant}; -/// This struct is used for determining when we should broadcast justification so that it does not happen too often. -pub struct BroadcastTicker { - last_broadcast: Instant, - current_periodic_timeout: Duration, +/// This struct is used for rate limiting as an on-demand ticker. It can be used for ticking +/// at least once `max_timeout` but not more than once every `min_timeout`. +pub struct Ticker { + last_tick: Instant, + current_timeout: Duration, max_timeout: Duration, min_timeout: Duration, } -impl BroadcastTicker { +impl Ticker { pub fn new(max_timeout: Duration, min_timeout: Duration) -> Self { Self { - last_broadcast: Instant::now(), - current_periodic_timeout: max_timeout, + last_tick: Instant::now(), + current_timeout: max_timeout, max_timeout, min_timeout, } } - /// Returns whether we should broadcast right now if we just imported a justification. - /// If min_timeout elapsed since last broadcast, returns true, sets last broadcast to now and will - /// return true again if called after `self.min_timeout`. - /// If not, returns false and sets periodic broadcast timeout to `self.min_timeout`. - /// This is to prevent from sending every justification when importing a batch of them. This way, - /// when receiving batch of justifications we will broadcast the first justification and the highest known - /// after `self.min_timeout` using periodic broadcast. - pub fn try_broadcast(&mut self) -> bool { + /// Returns whether at least `min_timeout` time elapsed since last tick. + /// If `min_timeout` elapsed since last tick, returns true, sets last tick to now, + /// current timout to `max_timeout` and will Return true again if called after `min_timeout`. + /// If not, returns false and sets current timeout to `min_timeout`. + pub fn try_tick(&mut self) -> bool { let now = Instant::now(); - if now.saturating_duration_since(self.last_broadcast) >= self.min_timeout { - self.last_broadcast = now; + if now.saturating_duration_since(self.last_tick) >= self.min_timeout { + self.last_tick = now; true } else { - self.current_periodic_timeout = self.min_timeout; + self.current_timeout = self.min_timeout; false } } - /// Sleeps until next periodic broadcast should happen. - /// In case enough time elapsed, sets last broadcast to now and periodic timeout to `self.max_timeout`. - pub async fn wait_for_periodic_broadcast(&mut self) { - let since_last = Instant::now().saturating_duration_since(self.last_broadcast); - sleep(self.current_periodic_timeout.saturating_sub(since_last)).await; - self.current_periodic_timeout = self.max_timeout; - self.last_broadcast = Instant::now(); + /// Sleeps until next tick should happen. In case enough time elapsed, + /// sets last tick to now and current timeout to `max_timeout`. + pub async fn wait(&mut self) { + let since_last = Instant::now().saturating_duration_since(self.last_tick); + sleep(self.current_timeout.saturating_sub(since_last)).await; + self.current_timeout = self.max_timeout; + self.last_tick = Instant::now(); } } @@ -136,8 +134,8 @@ mod tests { Ok(()) ); - assert!(!ticker.try_broadcast()); + assert!(!ticker.try_tick()); sleep(min_timeout).await; - assert!(ticker.try_broadcast()); + assert!(ticker.try_tick()); } } From bf0011c35ab6766e5e8806364a72ccc100e79bea Mon Sep 17 00:00:00 2001 From: maciejnems Date: Wed, 28 Dec 2022 19:22:49 +0100 Subject: [PATCH 05/12] restructure tests --- finality-aleph/src/sync/ticker.rs | 116 ++++++++++++------------------ 1 file changed, 44 insertions(+), 72 deletions(-) diff --git a/finality-aleph/src/sync/ticker.rs b/finality-aleph/src/sync/ticker.rs index 1815ad0e53..164358a7d7 100644 --- a/finality-aleph/src/sync/ticker.rs +++ b/finality-aleph/src/sync/ticker.rs @@ -48,94 +48,66 @@ impl Ticker { mod tests { use tokio::time::{sleep, timeout, Duration}; - use super::BroadcastTicker; + use super::Ticker; + + const MAX_TIMEOUT: Duration = Duration::from_millis(700); + const MIN_TIMEOUT: Duration = Duration::from_millis(100); + + const MAX_TIMEOUT_PLUS: Duration = Duration::from_millis(800); + const MIN_TIMEOUT_PLUS: Duration = Duration::from_millis(200); + + fn setup_ticker() -> Ticker { + Ticker::new(MAX_TIMEOUT, MIN_TIMEOUT) + } #[tokio::test] - async fn try_broadcast() { - let max_timeout = Duration::from_millis(700); - let min_timeout = Duration::from_millis(100); - let mut ticker = BroadcastTicker::new(max_timeout, min_timeout); - - assert!(!ticker.try_broadcast()); - sleep(min_timeout).await; - assert!(ticker.try_broadcast()); - assert!(!ticker.try_broadcast()); + async fn try_tick() { + let mut ticker = setup_ticker(); + + assert!(!ticker.try_tick()); + sleep(MIN_TIMEOUT).await; + assert!(ticker.try_tick()); + assert!(!ticker.try_tick()); } #[tokio::test] - async fn wait_for_periodic_broadcast() { - let max_timeout = Duration::from_millis(700); - let min_timeout = Duration::from_millis(100); - let mut ticker = BroadcastTicker::new(max_timeout, min_timeout); - - assert_ne!( - timeout(2 * min_timeout, ticker.wait_for_periodic_broadcast()).await, - Ok(()) - ); - assert_eq!( - timeout(max_timeout, ticker.wait_for_periodic_broadcast()).await, - Ok(()) - ); + async fn wait() { + let mut ticker = setup_ticker(); + + assert_ne!(timeout(MIN_TIMEOUT_PLUS, ticker.wait()).await, Ok(())); + assert_eq!(timeout(MAX_TIMEOUT, ticker.wait()).await, Ok(())); } #[tokio::test] - async fn wait_for_periodic_broadcast_after_try_broadcast_true() { - let max_timeout = Duration::from_millis(700); - let min_timeout = Duration::from_millis(100); - let mut ticker = BroadcastTicker::new(max_timeout, min_timeout); - - sleep(min_timeout).await; - assert!(ticker.try_broadcast()); - - assert_ne!( - timeout(2 * min_timeout, ticker.wait_for_periodic_broadcast()).await, - Ok(()) - ); - assert_eq!( - timeout(max_timeout, ticker.wait_for_periodic_broadcast()).await, - Ok(()) - ); + async fn wait_after_try_tick_true() { + let mut ticker = setup_ticker(); + + sleep(MIN_TIMEOUT).await; + assert!(ticker.try_tick()); + + assert_ne!(timeout(MIN_TIMEOUT_PLUS, ticker.wait()).await, Ok(())); + assert_eq!(timeout(MAX_TIMEOUT, ticker.wait()).await, Ok(())); } #[tokio::test] - async fn wait_for_periodic_broadcast_after_try_broadcast_false() { - let max_timeout = Duration::from_millis(700); - let min_timeout = Duration::from_millis(100); - let mut ticker = BroadcastTicker::new(max_timeout, min_timeout); - - assert!(!ticker.try_broadcast()); - - assert_eq!( - timeout(2 * min_timeout, ticker.wait_for_periodic_broadcast()).await, - Ok(()) - ); - assert_ne!( - timeout(2 * min_timeout, ticker.wait_for_periodic_broadcast()).await, - Ok(()) - ); - assert_eq!( - timeout(max_timeout, ticker.wait_for_periodic_broadcast()).await, - Ok(()) - ); + async fn wait_after_try_tick_false() { + let mut ticker = setup_ticker(); + + assert!(!ticker.try_tick()); + + assert_eq!(timeout(MIN_TIMEOUT_PLUS, ticker.wait()).await, Ok(())); + assert_ne!(timeout(MIN_TIMEOUT_PLUS, ticker.wait()).await, Ok(())); + assert_eq!(timeout(MAX_TIMEOUT, ticker.wait()).await, Ok(())); } #[tokio::test] - async fn try_broadcast_after_wait_for_periodic_broadcast() { - let max_timeout = Duration::from_millis(700); - let min_timeout = Duration::from_millis(100); - let mut ticker = BroadcastTicker::new(max_timeout, min_timeout); - - assert_eq!( - timeout( - max_timeout + min_timeout, - ticker.wait_for_periodic_broadcast() - ) - .await, - Ok(()) - ); + async fn try_tick_after_wait() { + let mut ticker = setup_ticker(); + + assert_eq!(timeout(MAX_TIMEOUT_PLUS, ticker.wait()).await, Ok(())); assert!(!ticker.try_tick()); - sleep(min_timeout).await; + sleep(MIN_TIMEOUT).await; assert!(ticker.try_tick()); } } From ab8954c2604ad01b9c1b88f5c7ede614ea486bf6 Mon Sep 17 00:00:00 2001 From: maciejnems Date: Wed, 28 Dec 2022 19:23:25 +0100 Subject: [PATCH 06/12] change timeout after try tick true --- finality-aleph/src/sync/ticker.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/finality-aleph/src/sync/ticker.rs b/finality-aleph/src/sync/ticker.rs index 164358a7d7..8b32d16a8b 100644 --- a/finality-aleph/src/sync/ticker.rs +++ b/finality-aleph/src/sync/ticker.rs @@ -27,6 +27,7 @@ impl Ticker { let now = Instant::now(); if now.saturating_duration_since(self.last_tick) >= self.min_timeout { self.last_tick = now; + self.current_timeout = self.min_timeout; true } else { self.current_timeout = self.min_timeout; @@ -82,6 +83,7 @@ mod tests { async fn wait_after_try_tick_true() { let mut ticker = setup_ticker(); + assert!(!ticker.try_tick()); sleep(MIN_TIMEOUT).await; assert!(ticker.try_tick()); From 0d138ab90696c9ea4348bd8cca171a8d6985457e Mon Sep 17 00:00:00 2001 From: maciejnems Date: Wed, 28 Dec 2022 20:03:09 +0100 Subject: [PATCH 07/12] hmmmmmm --- finality-aleph/src/sync/ticker.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/finality-aleph/src/sync/ticker.rs b/finality-aleph/src/sync/ticker.rs index 8b32d16a8b..aebb442e97 100644 --- a/finality-aleph/src/sync/ticker.rs +++ b/finality-aleph/src/sync/ticker.rs @@ -27,7 +27,7 @@ impl Ticker { let now = Instant::now(); if now.saturating_duration_since(self.last_tick) >= self.min_timeout { self.last_tick = now; - self.current_timeout = self.min_timeout; + self.current_timeout = self.max_timeout; true } else { self.current_timeout = self.min_timeout; From 4a0d9ad1c9320de9a0f5f298a0cc3f2516e90467 Mon Sep 17 00:00:00 2001 From: maciejnems Date: Thu, 29 Dec 2022 11:01:25 +0100 Subject: [PATCH 08/12] apply suggested changes to docs --- finality-aleph/src/sync/ticker.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/finality-aleph/src/sync/ticker.rs b/finality-aleph/src/sync/ticker.rs index aebb442e97..1f034388ad 100644 --- a/finality-aleph/src/sync/ticker.rs +++ b/finality-aleph/src/sync/ticker.rs @@ -2,6 +2,8 @@ use tokio::time::{sleep, Duration, Instant}; /// This struct is used for rate limiting as an on-demand ticker. It can be used for ticking /// at least once `max_timeout` but not more than once every `min_timeout`. +/// Example usage would be to use `wait` method in main select loop and `try_tick` whenever +/// you would like to tick sooner in another branch of select. pub struct Ticker { last_tick: Instant, current_timeout: Duration, @@ -10,6 +12,8 @@ pub struct Ticker { } impl Ticker { + /// Retruns new Ticker struct. Behaves as if last tick happened during creation of TIcker. + /// Requires `max_timeout` >= `min_timeout`. pub fn new(max_timeout: Duration, min_timeout: Duration) -> Self { Self { last_tick: Instant::now(), @@ -20,9 +24,9 @@ impl Ticker { } /// Returns whether at least `min_timeout` time elapsed since last tick. - /// If `min_timeout` elapsed since last tick, returns true, sets last tick to now, - /// current timout to `max_timeout` and will Return true again if called after `min_timeout`. - /// If not, returns false and sets current timeout to `min_timeout`. + /// If `min_timeout` elapsed since last tick, returns true and records a tick. + /// If not, returns false and calls to `wait` will return when `min_timeout` + /// elapses until the next tick. pub fn try_tick(&mut self) -> bool { let now = Instant::now(); if now.saturating_duration_since(self.last_tick) >= self.min_timeout { @@ -35,8 +39,8 @@ impl Ticker { } } - /// Sleeps until next tick should happen. In case enough time elapsed, - /// sets last tick to now and current timeout to `max_timeout`. + /// Sleeps until next tick should happen. + /// When enough time elapsed, returns and records a tick. pub async fn wait(&mut self) { let since_last = Instant::now().saturating_duration_since(self.last_tick); sleep(self.current_timeout.saturating_sub(since_last)).await; From 699b9650df443dcb83a5b975ceaede9b359874d8 Mon Sep 17 00:00:00 2001 From: maciejnems Date: Thu, 29 Dec 2022 11:32:44 +0100 Subject: [PATCH 09/12] add assert to constructor --- finality-aleph/src/sync/ticker.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/finality-aleph/src/sync/ticker.rs b/finality-aleph/src/sync/ticker.rs index 1f034388ad..8e216372ef 100644 --- a/finality-aleph/src/sync/ticker.rs +++ b/finality-aleph/src/sync/ticker.rs @@ -15,6 +15,12 @@ impl Ticker { /// Retruns new Ticker struct. Behaves as if last tick happened during creation of TIcker. /// Requires `max_timeout` >= `min_timeout`. pub fn new(max_timeout: Duration, min_timeout: Duration) -> Self { + assert!( + max_timeout >= min_timeout, + "Max timoeut ({:?}) must be bigger then min timeout ({:?}) in Ticker", + max_timeout, + min_timeout + ); Self { last_tick: Instant::now(), current_timeout: max_timeout, From d5a351c263e2b8106d471939de940253634cbddb Mon Sep 17 00:00:00 2001 From: maciejnems Date: Thu, 29 Dec 2022 14:17:10 +0100 Subject: [PATCH 10/12] or maybe no assert --- finality-aleph/src/sync/ticker.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/finality-aleph/src/sync/ticker.rs b/finality-aleph/src/sync/ticker.rs index 8e216372ef..b30cd699b2 100644 --- a/finality-aleph/src/sync/ticker.rs +++ b/finality-aleph/src/sync/ticker.rs @@ -14,13 +14,10 @@ pub struct Ticker { impl Ticker { /// Retruns new Ticker struct. Behaves as if last tick happened during creation of TIcker. /// Requires `max_timeout` >= `min_timeout`. - pub fn new(max_timeout: Duration, min_timeout: Duration) -> Self { - assert!( - max_timeout >= min_timeout, - "Max timoeut ({:?}) must be bigger then min timeout ({:?}) in Ticker", - max_timeout, - min_timeout - ); + pub fn new(mut max_timeout: Duration, min_timeout: Duration) -> Self { + if max_timeout < min_timeout { + max_timeout = min_timeout; + }; Self { last_tick: Instant::now(), current_timeout: max_timeout, From 2d645e35f863f18f5d4f60819f1d261fc82209d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Nem=C5=9B?= Date: Thu, 29 Dec 2022 16:08:02 +0100 Subject: [PATCH 11/12] the in docs Co-authored-by: kostekIV <27210860+kostekIV@users.noreply.github.com> --- finality-aleph/src/sync/ticker.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/finality-aleph/src/sync/ticker.rs b/finality-aleph/src/sync/ticker.rs index b30cd699b2..5919af2ce8 100644 --- a/finality-aleph/src/sync/ticker.rs +++ b/finality-aleph/src/sync/ticker.rs @@ -26,8 +26,8 @@ impl Ticker { } } - /// Returns whether at least `min_timeout` time elapsed since last tick. - /// If `min_timeout` elapsed since last tick, returns true and records a tick. + /// Returns whether at least `min_timeout` time elapsed since the last tick. + /// If `min_timeout` elapsed since the last tick, returns true and records a tick. /// If not, returns false and calls to `wait` will return when `min_timeout` /// elapses until the next tick. pub fn try_tick(&mut self) -> bool { From 3cc1a9e43825a8d94760da683677569f83058cc7 Mon Sep 17 00:00:00 2001 From: maciejnems Date: Thu, 29 Dec 2022 16:13:48 +0100 Subject: [PATCH 12/12] wait_and_tick --- finality-aleph/src/sync/ticker.rs | 33 ++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/finality-aleph/src/sync/ticker.rs b/finality-aleph/src/sync/ticker.rs index 5919af2ce8..3120a0f13a 100644 --- a/finality-aleph/src/sync/ticker.rs +++ b/finality-aleph/src/sync/ticker.rs @@ -44,7 +44,7 @@ impl Ticker { /// Sleeps until next tick should happen. /// When enough time elapsed, returns and records a tick. - pub async fn wait(&mut self) { + pub async fn wait_and_tick(&mut self) { let since_last = Instant::now().saturating_duration_since(self.last_tick); sleep(self.current_timeout.saturating_sub(since_last)).await; self.current_timeout = self.max_timeout; @@ -82,8 +82,11 @@ mod tests { async fn wait() { let mut ticker = setup_ticker(); - assert_ne!(timeout(MIN_TIMEOUT_PLUS, ticker.wait()).await, Ok(())); - assert_eq!(timeout(MAX_TIMEOUT, ticker.wait()).await, Ok(())); + assert_ne!( + timeout(MIN_TIMEOUT_PLUS, ticker.wait_and_tick()).await, + Ok(()) + ); + assert_eq!(timeout(MAX_TIMEOUT, ticker.wait_and_tick()).await, Ok(())); } #[tokio::test] @@ -94,8 +97,11 @@ mod tests { sleep(MIN_TIMEOUT).await; assert!(ticker.try_tick()); - assert_ne!(timeout(MIN_TIMEOUT_PLUS, ticker.wait()).await, Ok(())); - assert_eq!(timeout(MAX_TIMEOUT, ticker.wait()).await, Ok(())); + assert_ne!( + timeout(MIN_TIMEOUT_PLUS, ticker.wait_and_tick()).await, + Ok(()) + ); + assert_eq!(timeout(MAX_TIMEOUT, ticker.wait_and_tick()).await, Ok(())); } #[tokio::test] @@ -104,16 +110,25 @@ mod tests { assert!(!ticker.try_tick()); - assert_eq!(timeout(MIN_TIMEOUT_PLUS, ticker.wait()).await, Ok(())); - assert_ne!(timeout(MIN_TIMEOUT_PLUS, ticker.wait()).await, Ok(())); - assert_eq!(timeout(MAX_TIMEOUT, ticker.wait()).await, Ok(())); + assert_eq!( + timeout(MIN_TIMEOUT_PLUS, ticker.wait_and_tick()).await, + Ok(()) + ); + assert_ne!( + timeout(MIN_TIMEOUT_PLUS, ticker.wait_and_tick()).await, + Ok(()) + ); + assert_eq!(timeout(MAX_TIMEOUT, ticker.wait_and_tick()).await, Ok(())); } #[tokio::test] async fn try_tick_after_wait() { let mut ticker = setup_ticker(); - assert_eq!(timeout(MAX_TIMEOUT_PLUS, ticker.wait()).await, Ok(())); + assert_eq!( + timeout(MAX_TIMEOUT_PLUS, ticker.wait_and_tick()).await, + Ok(()) + ); assert!(!ticker.try_tick()); sleep(MIN_TIMEOUT).await;