Made daily uptime calculation be independent of epoch rewarding (#860)
* Made daily uptime calculation be independent of epoch rewarding It was moved into a separate timer * Don't lookup active gateways during rewarding
This commit is contained in:
committed by
GitHub
parent
bd4c18c723
commit
cdb21f418b
@@ -9,6 +9,7 @@ use std::time::Duration;
|
||||
pub(crate) mod local_guard;
|
||||
pub(crate) mod models;
|
||||
pub(crate) mod routes;
|
||||
pub(crate) mod uptime_updater;
|
||||
pub(crate) mod utils;
|
||||
|
||||
pub(crate) const FIFTEEN_MINUTES: Duration = Duration::from_secs(900);
|
||||
@@ -18,7 +19,7 @@ pub(crate) const ONE_DAY: Duration = Duration::from_secs(86400);
|
||||
pub(crate) fn stage(database_path: PathBuf) -> AdHoc {
|
||||
AdHoc::on_ignite("SQLx Stage", |rocket| async {
|
||||
rocket
|
||||
.attach(storage::NodeStatusStorage::stage(database_path))
|
||||
.attach(storage::ValidatorApiStorage::stage(database_path))
|
||||
.mount(
|
||||
"/v1/status",
|
||||
routes![
|
||||
|
||||
@@ -213,12 +213,12 @@ pub struct HistoricalUptime {
|
||||
}
|
||||
|
||||
pub(crate) struct ErrorResponse {
|
||||
error: NodeStatusApiError,
|
||||
error: ValidatorApiStorageError,
|
||||
status: Status,
|
||||
}
|
||||
|
||||
impl ErrorResponse {
|
||||
pub(crate) fn new(error: NodeStatusApiError, status: Status) -> Self {
|
||||
pub(crate) fn new(error: ValidatorApiStorageError, status: Status) -> Self {
|
||||
ErrorResponse { error, status }
|
||||
}
|
||||
}
|
||||
@@ -235,7 +235,7 @@ impl<'r, 'o: 'r> Responder<'r, 'o> for ErrorResponse {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum NodeStatusApiError {
|
||||
pub enum ValidatorApiStorageError {
|
||||
MixnodeReportNotFound(String),
|
||||
GatewayReportNotFound(String),
|
||||
MixnodeUptimeHistoryNotFound(String),
|
||||
@@ -245,30 +245,30 @@ pub enum NodeStatusApiError {
|
||||
InternalDatabaseError,
|
||||
}
|
||||
|
||||
impl Display for NodeStatusApiError {
|
||||
impl Display for ValidatorApiStorageError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
NodeStatusApiError::MixnodeReportNotFound(identity) => write!(
|
||||
ValidatorApiStorageError::MixnodeReportNotFound(identity) => write!(
|
||||
f,
|
||||
"Could not find status report associated with mixnode {}",
|
||||
identity
|
||||
),
|
||||
NodeStatusApiError::GatewayReportNotFound(identity) => write!(
|
||||
ValidatorApiStorageError::GatewayReportNotFound(identity) => write!(
|
||||
f,
|
||||
"Could not find status report associated with gateway {}",
|
||||
identity
|
||||
),
|
||||
NodeStatusApiError::MixnodeUptimeHistoryNotFound(identity) => write!(
|
||||
ValidatorApiStorageError::MixnodeUptimeHistoryNotFound(identity) => write!(
|
||||
f,
|
||||
"Could not find uptime history associated with mixnode {}",
|
||||
identity
|
||||
),
|
||||
NodeStatusApiError::GatewayUptimeHistoryNotFound(identity) => write!(
|
||||
ValidatorApiStorageError::GatewayUptimeHistoryNotFound(identity) => write!(
|
||||
f,
|
||||
"Could not find uptime history associated with gateway {}",
|
||||
identity
|
||||
),
|
||||
NodeStatusApiError::InternalDatabaseError => {
|
||||
ValidatorApiStorageError::InternalDatabaseError => {
|
||||
write!(f, "The internal database has experienced an issue")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,14 +5,14 @@ use crate::node_status_api::models::{
|
||||
ErrorResponse, GatewayStatusReport, GatewayUptimeHistory, MixnodeStatusReport,
|
||||
MixnodeUptimeHistory,
|
||||
};
|
||||
use crate::storage::NodeStatusStorage;
|
||||
use crate::storage::ValidatorApiStorage;
|
||||
use rocket::http::Status;
|
||||
use rocket::serde::json::Json;
|
||||
use rocket::State;
|
||||
|
||||
#[get("/mixnode/<pubkey>/report")]
|
||||
pub(crate) async fn mixnode_report(
|
||||
storage: &State<NodeStatusStorage>,
|
||||
storage: &State<ValidatorApiStorage>,
|
||||
pubkey: &str,
|
||||
) -> Result<Json<MixnodeStatusReport>, ErrorResponse> {
|
||||
storage
|
||||
@@ -24,7 +24,7 @@ pub(crate) async fn mixnode_report(
|
||||
|
||||
#[get("/gateway/<pubkey>/report")]
|
||||
pub(crate) async fn gateway_report(
|
||||
storage: &State<NodeStatusStorage>,
|
||||
storage: &State<ValidatorApiStorage>,
|
||||
pubkey: &str,
|
||||
) -> Result<Json<GatewayStatusReport>, ErrorResponse> {
|
||||
storage
|
||||
@@ -36,7 +36,7 @@ pub(crate) async fn gateway_report(
|
||||
|
||||
#[get("/mixnode/<pubkey>/history")]
|
||||
pub(crate) async fn mixnode_uptime_history(
|
||||
storage: &State<NodeStatusStorage>,
|
||||
storage: &State<ValidatorApiStorage>,
|
||||
pubkey: &str,
|
||||
) -> Result<Json<MixnodeUptimeHistory>, ErrorResponse> {
|
||||
storage
|
||||
@@ -48,7 +48,7 @@ pub(crate) async fn mixnode_uptime_history(
|
||||
|
||||
#[get("/gateway/<pubkey>/history")]
|
||||
pub(crate) async fn gateway_uptime_history(
|
||||
storage: &State<NodeStatusStorage>,
|
||||
storage: &State<ValidatorApiStorage>,
|
||||
pubkey: &str,
|
||||
) -> Result<Json<GatewayUptimeHistory>, ErrorResponse> {
|
||||
storage
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::node_status_api::models::{
|
||||
GatewayStatusReport, MixnodeStatusReport, ValidatorApiStorageError,
|
||||
};
|
||||
use crate::node_status_api::ONE_DAY;
|
||||
use crate::storage::ValidatorApiStorage;
|
||||
use log::error;
|
||||
use time::OffsetDateTime;
|
||||
use tokio::time::sleep;
|
||||
|
||||
pub(crate) struct HistoricalUptimeUpdater {
|
||||
storage: ValidatorApiStorage,
|
||||
}
|
||||
|
||||
impl HistoricalUptimeUpdater {
|
||||
pub(crate) fn new(storage: ValidatorApiStorage) -> Self {
|
||||
HistoricalUptimeUpdater { storage }
|
||||
}
|
||||
|
||||
/// Obtains the lists of all mixnodes and gateways that were tested at least a single time
|
||||
/// in the last 24h interval.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `now`: current time.
|
||||
async fn get_active_nodes(
|
||||
&self,
|
||||
now: OffsetDateTime,
|
||||
) -> Result<(Vec<MixnodeStatusReport>, Vec<GatewayStatusReport>), ValidatorApiStorageError>
|
||||
{
|
||||
let day_ago = (now - ONE_DAY).unix_timestamp();
|
||||
let active_mixnodes = self
|
||||
.storage
|
||||
.get_all_active_mixnode_reports_in_interval(day_ago, now.unix_timestamp())
|
||||
.await?;
|
||||
|
||||
let active_gateways = self
|
||||
.storage
|
||||
.get_all_active_gateway_reports_in_interval(day_ago, now.unix_timestamp())
|
||||
.await?;
|
||||
|
||||
Ok((active_mixnodes, active_gateways))
|
||||
}
|
||||
|
||||
async fn update_uptimes(&self) -> Result<(), ValidatorApiStorageError> {
|
||||
let now = OffsetDateTime::now_utc();
|
||||
let today_iso_8601 = now.date().to_string();
|
||||
|
||||
// get nodes that were active in last 24h
|
||||
let (active_mixnodes, active_gateways) = self.get_active_nodes(now).await?;
|
||||
|
||||
if self
|
||||
.storage
|
||||
.check_if_historical_uptimes_exist_for_date(&today_iso_8601)
|
||||
.await?
|
||||
{
|
||||
warn!("We have already updated uptimes for all nodes this day.")
|
||||
} else {
|
||||
info!("Updating historical daily uptimes of all nodes...");
|
||||
self.storage
|
||||
.update_historical_uptimes(&today_iso_8601, &active_mixnodes, &active_gateways)
|
||||
.await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn run(&self) {
|
||||
loop {
|
||||
// start any updates a day after starting the task so that we would have complete data
|
||||
sleep(ONE_DAY).await;
|
||||
if let Err(err) = self.update_uptimes().await {
|
||||
// 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
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user