Feature/node status api (#680)

* Basic storage stub

* New models for new node status api

* Route handling

* Mounting new routes

* Missing selective commit

* Moved network monitor related files to separate package

* Starting to see some sqlx action

* Schema updates

* Log statement upon finished migration

* Removed old diesel related imports

* Converted mixnode cache initialisation into a fairing

* Moved cache related functionalities to separate package

Also defined staging there

* Created run method for validator cache + removed unwrap

* Removed old node-status-api types and left bunch of todo placeholders in their place

* Fixed managing validatorcache

* Status reports are starting to get constructed

* Submitting some dummy results to the database

* Removing duplicate code for generating reports

* Removed statuses older than 48h

* Initial attempt at trying to obtain reports for all active nodes

* Removed duplicates from the full report

* Grabbing uptime history

* Updating historical uptimes of active nodes

* Updated sqlx-data.json

* Removed all placeholder foomp owner values

* Changed Layer serde behaviour for easier usage

* Extended validator api config

* Initial (seems working !) integration with network monitor

* Added database path configuration to config

* Using ValidatorCache in NetworkMonitor

* Flag indicating whether validator cache has been initialised

* Introduced a locla-only route for reward script to perform daily chores

* Flag to save config to a file

* Moved spawning of receiving future to run method rather than new

* Removed arguments that dont make sense to be configured via CLI

* Removed dead code from config file

* More dead code removal

* Added validator API to CI

* Corrected manifest-path arguments

* Constructing network monitor by passing config

* Combined validator API CI with the main CI file

* Using query_as for NodeStatus

* Checking if historical uptimes were already calculated on particular day

* Making id field NOT NULL

* More query_as! action

* Updated sqlx-data.json

* Removed unused chrono feature

* Renamed the migration file

* Changed default validator endpoint to point to local validator

* Removing unnecessary clone

* More appropriate naming

* Removed dead code

* Lock file updates

* Updated network monitor address in contract code

* Don't stage node status api if network monitor is disabled

* cargo fmt

* Updated all license notices to SPDX
This commit is contained in:
Jędrzej Stuczyński
2021-07-19 14:02:47 +01:00
committed by GitHub
parent 25d2af3b04
commit e5afd54ce0
159 changed files with 6857 additions and 2487 deletions
@@ -0,0 +1,99 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::node_status_api::models::Uptime;
use crate::node_status_api::{FIFTEEN_MINUTES, ONE_HOUR};
use sqlx::types::time::OffsetDateTime;
// Internally used struct to catch results from the database to calculate uptimes for given mixnode/gateway
pub(crate) struct NodeStatus {
pub(crate) timestamp: i64,
pub(crate) up: bool,
}
// Internally used struct to catch results from the database to find active mixnodes/gateways
pub(crate) struct ActiveNode {
pub(crate) id: i64,
pub(crate) pub_key: String,
pub(crate) owner: String,
}
// A temporary helper struct used to produce reports for active nodes.
pub(crate) struct ActiveNodeDayStatuses {
pub(crate) pub_key: String,
pub(crate) owner: String,
pub(crate) node_id: i64,
pub(crate) ipv4_statuses: Vec<NodeStatus>,
pub(crate) ipv6_statuses: Vec<NodeStatus>,
}
// A helper intermediate struct to remove duplicate code for construction of mixnode and gateway reports
pub(crate) struct NodeUptimes {
pub(crate) most_recent_ipv4: bool,
pub(crate) most_recent_ipv6: bool,
pub(crate) last_hour_ipv4: Uptime,
pub(crate) last_hour_ipv6: Uptime,
pub(crate) last_day_ipv4: Uptime,
pub(crate) last_day_ipv6: Uptime,
}
impl NodeUptimes {
pub(crate) fn calculate_from_last_day_reports(
last_day_ipv4: Vec<NodeStatus>,
last_day_ipv6: Vec<NodeStatus>,
) -> Self {
let now = OffsetDateTime::now_utc();
let hour_ago = (now - ONE_HOUR).unix_timestamp();
let fifteen_minutes_ago = (now - FIFTEEN_MINUTES).unix_timestamp();
let ipv4_day_total = last_day_ipv4.len();
let ipv6_day_total = last_day_ipv6.len();
let ipv4_day_up = last_day_ipv4.iter().filter(|report| report.up).count();
let ipv6_day_up = last_day_ipv6.iter().filter(|report| report.up).count();
let ipv4_hour_total = last_day_ipv4
.iter()
.filter(|report| report.timestamp >= hour_ago)
.count();
let ipv6_hour_total = last_day_ipv6
.iter()
.filter(|report| report.timestamp >= hour_ago)
.count();
let ipv4_hour_up = last_day_ipv4
.iter()
.filter(|report| report.up && report.timestamp >= hour_ago)
.count();
let ipv6_hour_up = last_day_ipv6
.iter()
.filter(|report| report.up && report.timestamp >= hour_ago)
.count();
// most recent status MUST BE within last 15min
let most_recent_ipv4 = last_day_ipv4
.iter()
.max_by_key(|report| report.timestamp) // find the most recent
.map(|status| status.timestamp >= fifteen_minutes_ago && status.up) // make sure its within last 15min
.unwrap_or_default();
let most_recent_ipv6 = last_day_ipv6
.iter()
.max_by_key(|report| report.timestamp) // find the most recent
.map(|status| status.timestamp >= fifteen_minutes_ago && status.up) // make sure its within last 15min
.unwrap_or_default();
// the unwraps in Uptime::from_ratio are fine because it's impossible for us to have more "up" results than all results in total
// because both of those values originate from the same vector
NodeUptimes {
most_recent_ipv4,
most_recent_ipv6,
last_hour_ipv4: Uptime::from_ratio(ipv4_hour_up, ipv4_hour_total).unwrap(),
last_hour_ipv6: Uptime::from_ratio(ipv6_hour_up, ipv6_hour_total).unwrap(),
last_day_ipv4: Uptime::from_ratio(ipv4_day_up, ipv4_day_total).unwrap(),
last_day_ipv6: Uptime::from_ratio(ipv6_day_up, ipv6_day_total).unwrap(),
}
}
}