From 52344b3dc517464df5f35f7a254e354d7b7c74fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Fri, 28 Oct 2022 11:20:22 +0100 Subject: [PATCH 1/5] Removed commented out type alias --- validator-api/src/epoch_operations/mod.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/validator-api/src/epoch_operations/mod.rs b/validator-api/src/epoch_operations/mod.rs index 1273ac4310..2419e2363e 100644 --- a/validator-api/src/epoch_operations/mod.rs +++ b/validator-api/src/epoch_operations/mod.rs @@ -50,9 +50,6 @@ impl From for ExecuteMsg { } } -// // Epoch has all the same semantics as interval, but has a lower set duration -// type Epoch = Interval; - pub struct RewardedSetUpdater { nymd_client: Client, validator_cache: ValidatorCache, From 00d1c9caf238ad97776e9720ebc9a035934b4491 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Fri, 28 Oct 2022 11:20:50 +0100 Subject: [PATCH 2/5] typos --- validator-api/src/epoch_operations/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/validator-api/src/epoch_operations/mod.rs b/validator-api/src/epoch_operations/mod.rs index 2419e2363e..832781afa1 100644 --- a/validator-api/src/epoch_operations/mod.rs +++ b/validator-api/src/epoch_operations/mod.rs @@ -265,7 +265,7 @@ impl RewardedSetUpdater { log::info!("Advanced the epoch and updated the rewarded set... SUCCESS"); } - log::info!("Puring all node statuses from the storage..."); + log::info!("Purging old node statuses from the storage..."); let cutoff = (epoch_end - Duration::from_secs(86400)).unix_timestamp(); self.storage.purge_old_statuses(cutoff).await?; From 2e7b028aa598151e4e031259d2b2342ba018c802 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Fri, 28 Oct 2022 11:39:36 +0100 Subject: [PATCH 3/5] Using the same underlying timer for uptime updater --- .../src/node_status_api/uptime_updater.rs | 32 ++++++++----------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/validator-api/src/node_status_api/uptime_updater.rs b/validator-api/src/node_status_api/uptime_updater.rs index 0e60650f65..5b6d5c1a65 100644 --- a/validator-api/src/node_status_api/uptime_updater.rs +++ b/validator-api/src/node_status_api/uptime_updater.rs @@ -7,9 +7,10 @@ use crate::node_status_api::models::{ use crate::node_status_api::ONE_DAY; use crate::storage::ValidatorApiStorage; use log::error; +use std::time::Duration; use task::ShutdownListener; -use time::OffsetDateTime; -use tokio::time::sleep; +use time::{OffsetDateTime, PrimitiveDateTime, Time}; +use tokio::time::{interval, sleep}; pub(crate) struct HistoricalUptimeUpdater { storage: ValidatorApiStorage, @@ -69,28 +70,21 @@ impl HistoricalUptimeUpdater { } pub(crate) async fn run(&self, mut shutdown: ShutdownListener) { + + let mut interval = interval(ONE_DAY); while !shutdown.is_shutdown() { tokio::select! { - _ = sleep(ONE_DAY) => { - tokio::select! { - biased; - _ = shutdown.recv() => { - trace!("UpdateHandler: Received shutdown"); - } - Err(err) = self.update_uptimes() => { - // normally that would have been a warning rather than an error, - // however, in this case it implies some underlying issues with our database - // that might affect the entire program - error!( - "We failed to update daily uptimes of active nodes - {}", - err - ); - } - } - } + biased; _ = shutdown.recv() => { trace!("UpdateHandler: Received shutdown"); } + _ = interval.tick() => { + // we don't want to have another select here; uptime update is relatively speedy + // and we don't want to exit while we're in the middle of database update + if let Err(err) = self.update_uptimes().await { + error!("We failed to update daily uptimes of active nodes - {err}"); + } + } } } } From 009be4e44c115f8584324e550762978ad1286d4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Fri, 28 Oct 2022 11:40:09 +0100 Subject: [PATCH 4/5] Updating uptimes at 23:00 UTC each day --- validator-api/src/epoch_operations/mod.rs | 3 +- .../src/node_status_api/uptime_updater.rs | 30 +++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/validator-api/src/epoch_operations/mod.rs b/validator-api/src/epoch_operations/mod.rs index 832781afa1..cb33962890 100644 --- a/validator-api/src/epoch_operations/mod.rs +++ b/validator-api/src/epoch_operations/mod.rs @@ -30,6 +30,7 @@ pub(crate) mod error; mod helpers; use crate::epoch_operations::helpers::stake_to_f64; +use crate::node_status_api::ONE_DAY; use error::RewardingError; use mixnet_contract_common::mixnode::MixNodeDetails; use task::ShutdownListener; @@ -266,7 +267,7 @@ impl RewardedSetUpdater { } log::info!("Purging old node statuses from the storage..."); - let cutoff = (epoch_end - Duration::from_secs(86400)).unix_timestamp(); + let cutoff = (epoch_end - 2 * ONE_DAY).unix_timestamp(); self.storage.purge_old_statuses(cutoff).await?; Ok(()) diff --git a/validator-api/src/node_status_api/uptime_updater.rs b/validator-api/src/node_status_api/uptime_updater.rs index 5b6d5c1a65..dcb4f6424c 100644 --- a/validator-api/src/node_status_api/uptime_updater.rs +++ b/validator-api/src/node_status_api/uptime_updater.rs @@ -70,6 +70,36 @@ impl HistoricalUptimeUpdater { } pub(crate) async fn run(&self, mut shutdown: ShutdownListener) { + // update uptimes at 23:00 UTC each day so that we'd have data from the actual [almost] whole day + // and so that we would avoid the edge case of starting validator API at 23:59 and having some + // nodes update for different days + + // the unwrap is fine as 23:00:00 is a valid time + let update_time = Time::from_hms(23, 0, 0).unwrap(); + let now = OffsetDateTime::now_utc(); + // is the current time within 0:00 - 22:59:59 or 23:00 - 23:59:59 ? + let update_date = if now.hour() < 23 { + now.date() + } else { + // the unwrap is fine as (**PRESUMABLY**) we're not running this code in the year 9999 + now.date().next_day().unwrap() + }; + let update_datetime = PrimitiveDateTime::new(update_date, update_time).assume_utc(); + // the unwrap here is fine as we're certain `update_datetime` is in the future and thus the + // resultant Duration is positive + let time_left: Duration = (update_datetime - now).try_into().unwrap(); + + log::info!( + "waiting until {update_datetime} to update the historical uptimes for the first time ({} seconds left)", time_left.as_secs() + ); + + tokio::select! { + biased; + _ = shutdown.recv() => { + trace!("UpdateHandler: Received shutdown"); + } + _ = sleep(time_left) => {} + } let mut interval = interval(ONE_DAY); while !shutdown.is_shutdown() { From 43d8eecf9268c0235aec257866d716e783703df7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Mon, 31 Oct 2022 11:00:13 +0000 Subject: [PATCH 5/5] Changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d867b8bb6e..4e843a33f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https:// ### Fixed - validator-api, mixnode, gateway should now prefer values in config.toml over mainnet defaults ([#1645]) +- validator-api should now correctly update historical uptimes for all mixnodes and gateways every 24h ([#1721]) - socks5-client: fix bug where in some cases packet reordering could trigger a connection being closed too early ([#1702],[#1724]) ### Changed @@ -47,6 +48,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https:// [#1687]: https://github.com/nymtech/nym/pull/1687 [#1702]: https://github.com/nymtech/nym/pull/1702 [#1703]: https://github.com/nymtech/nym/pull/1703 +[#1721]: https://github.com/nymtech/nym/pull/1721 [#1724]: https://github.com/nymtech/nym/pull/1724 [#1725]: https://github.com/nymtech/nym/pull/1725