From f590aad42c8e92ab5cb06aac9efc10bbe83ef517 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Mon, 27 Feb 2023 12:40:00 +0100 Subject: [PATCH] nym-api: uptime rework (#3053) * nym-api: cache updates as node performance * nym-api: update get mixnode avg_uptime endpoint * nym-api: mixnode report to use cached data * nym-api: annotate gateway bond with node performance * nym-api: gateway report to use cached data * wip * Add get_gateway_avg_uptime * Add comment * update NR gateways to include node_performance on frontend * use node_performance values on frontend * fixup select gateway from list * fix up lint errors --------- Co-authored-by: fmtabbara --- explorer/src/api/index.ts | 5 +- explorer/src/components/Gateways.ts | 7 +- .../src/components/Universal-DataGrid.tsx | 2 +- explorer/src/pages/GatewayDetail/index.tsx | 6 +- explorer/src/pages/Gateways/index.tsx | 19 +-- explorer/src/typeDefs/explorer-api.ts | 10 +- nym-api/nym-api-requests/src/models.rs | 41 ++++- .../src/node_status_api/cache/node_sets.rs | 31 +++- nym-api/src/node_status_api/helpers.rs | 152 +++++++++++++----- nym-api/src/node_status_api/mod.rs | 1 + nym-api/src/node_status_api/models.rs | 22 ++- nym-api/src/node_status_api/routes.rs | 68 ++++---- 12 files changed, 261 insertions(+), 103 deletions(-) diff --git a/explorer/src/api/index.ts b/explorer/src/api/index.ts index 49dcb04e85..894dd3e179 100644 --- a/explorer/src/api/index.ts +++ b/explorer/src/api/index.ts @@ -29,7 +29,6 @@ import { GatewayBondAnnotated, GatewayBond, } from '../typeDefs/explorer-api'; -import { toPercentIntegerString } from '../utils'; function getFromCache(key: string) { const ts = Number(localStorage.getItem('ts')); @@ -94,9 +93,9 @@ export class Api { static fetchGateways = async (): Promise => { const res = await fetch(GATEWAYS_API); const gatewaysAnnotated: GatewayBondAnnotated[] = await res.json(); - return gatewaysAnnotated.map(({ gateway_bond, performance }) => ({ + return gatewaysAnnotated.map(({ gateway_bond, node_performance }) => ({ ...gateway_bond, - performance: toPercentIntegerString(performance), + node_performance, })); }; diff --git a/explorer/src/components/Gateways.ts b/explorer/src/components/Gateways.ts index 6d8ff8ad6a..b78b1320da 100644 --- a/explorer/src/components/Gateways.ts +++ b/explorer/src/components/Gateways.ts @@ -1,4 +1,5 @@ import { GatewayResponse, GatewayBond, GatewayReportResponse } from '../typeDefs/explorer-api'; +import { toPercentIntegerString } from '../utils'; export type GatewayRowType = { id: string; @@ -8,7 +9,7 @@ export type GatewayRowType = { host: string; location: string; version: string; - performance: string; + node_performance: string; }; export type GatewayEnrichedRowType = GatewayRowType & { @@ -29,7 +30,7 @@ export function gatewayToGridRow(arrayOfGateways: GatewayResponse): GatewayRowTy bond: gw.pledge_amount.amount || 0, host: gw.gateway.host || '', version: gw.gateway.version || '', - performance: gw.performance, + node_performance: toPercentIntegerString(gw.node_performance.last_24h), })); } @@ -46,6 +47,6 @@ export function gatewayEnrichedToGridRow(gateway: GatewayBond, report: GatewayRe mixPort: gateway.gateway.mix_port || 0, routingScore: `${report.most_recent}%`, avgUptime: `${report.last_day || report.last_hour}%`, - performance: gateway.performance, + node_performance: toPercentIntegerString(gateway.node_performance.most_recent), }; } diff --git a/explorer/src/components/Universal-DataGrid.tsx b/explorer/src/components/Universal-DataGrid.tsx index 9dd1718112..928eb62e94 100644 --- a/explorer/src/components/Universal-DataGrid.tsx +++ b/explorer/src/components/Universal-DataGrid.tsx @@ -38,7 +38,7 @@ const CustomPagination = () => { color="primary" count={state.pagination.pageCount} page={state.pagination.page + 1} - onChange={(event, value) => apiRef.current.setPage(value - 1)} + onChange={(_, value) => apiRef.current.setPage(value - 1)} /> ); }; diff --git a/explorer/src/pages/GatewayDetail/index.tsx b/explorer/src/pages/GatewayDetail/index.tsx index 14aac28589..8995b1733f 100644 --- a/explorer/src/pages/GatewayDetail/index.tsx +++ b/explorer/src/pages/GatewayDetail/index.tsx @@ -26,7 +26,7 @@ const columns: ColumnsType[] = [ headerAlign: 'left', }, { - field: 'routingScore', + field: 'node_performance', title: 'Routing Score', flex: 1, headerAlign: 'left', @@ -130,13 +130,13 @@ const PageGatewayDetailsWithState = ({ selectedGateway }: { selectedGateway: Gat * Guard component to handle loading and not found states */ const PageGatewayDetailGuard: FCWithChildren = () => { - const [selectedGateway, setSelectedGateway] = React.useState(); + const [selectedGateway, setSelectedGateway] = React.useState(); const { gateways } = useMainContext(); const { id } = useParams<{ id: string | undefined }>(); React.useEffect(() => { if (gateways?.data) { - setSelectedGateway(gateways.data.find((gateway) => gateway.gateway.identity_key === id)); + setSelectedGateway(gateways.data.find((g) => g.gateway.identity_key === id)); } }, [gateways, id]); diff --git a/explorer/src/pages/Gateways/index.tsx b/explorer/src/pages/Gateways/index.tsx index c2a0ba1405..98e14be808 100644 --- a/explorer/src/pages/Gateways/index.tsx +++ b/explorer/src/pages/Gateways/index.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { Link as RRDLink } from 'react-router-dom'; -import { Box, Button, Card, Grid, Link as MuiLink } from '@mui/material'; +import { Box, Card, Grid, Link as MuiLink } from '@mui/material'; import { CopyToClipboard } from '@nymproject/react/clipboard/CopyToClipboard'; import { GridColDef, GridRenderCellParams } from '@mui/x-data-grid'; import { SelectChangeEvent } from '@mui/material/Select'; @@ -86,7 +86,6 @@ export const PageGateways: FCWithChildren = () => { const columns: GridColDef[] = [ { field: 'identity_key', - headerName: 'Identity Key', renderHeader: () => , headerClassName: 'MuiDataGrid-header-override', width: 380, @@ -119,7 +118,7 @@ export const PageGateways: FCWithChildren = () => { {unymToNym(params.value, 6)} @@ -127,8 +126,7 @@ export const PageGateways: FCWithChildren = () => { ), }, { - field: 'performance', - headerName: 'Routing Score', + field: 'node_performance', renderHeader: () => , width: 150, headerAlign: 'left', @@ -137,7 +135,7 @@ export const PageGateways: FCWithChildren = () => { {`${params.value}%`} @@ -154,7 +152,7 @@ export const PageGateways: FCWithChildren = () => { {params.value} @@ -168,9 +166,9 @@ export const PageGateways: FCWithChildren = () => { headerAlign: 'left', headerClassName: 'MuiDataGrid-header-override', renderCell: (params: GridRenderCellParams) => ( - + ), }, { @@ -207,7 +205,6 @@ export const PageGateways: FCWithChildren = () => { }, { field: 'version', - headerName: 'Version', renderHeader: () => , width: 150, headerAlign: 'left', diff --git a/explorer/src/typeDefs/explorer-api.ts b/explorer/src/typeDefs/explorer-api.ts index 48cf2091d9..e430427aff 100644 --- a/explorer/src/typeDefs/explorer-api.ts +++ b/explorer/src/typeDefs/explorer-api.ts @@ -114,6 +114,12 @@ export interface StatsResponse { packets_explicitly_dropped_since_last_update: number; } +export interface NodePerformance { + most_recent: string; + last_hour: string; + last_24h: string; +} + export type MixNodeHistoryResponse = StatsResponse; export interface GatewayBond { @@ -122,12 +128,12 @@ export interface GatewayBond { total_delegation: Amount; owner: string; gateway: Gateway; - performance: string; + node_performance: NodePerformance; } export interface GatewayBondAnnotated { gateway_bond: GatewayBond; - performance: string; + node_performance: NodePerformance; } export type GatewayResponse = GatewayBond[]; diff --git a/nym-api/nym-api-requests/src/models.rs b/nym-api/nym-api-requests/src/models.rs index 0954d4b9d6..daebc0b0ac 100644 --- a/nym-api/nym-api-requests/src/models.rs +++ b/nym-api/nym-api-requests/src/models.rs @@ -1,7 +1,7 @@ // Copyright 2022 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use cosmwasm_std::{Coin, Decimal}; +use cosmwasm_std::{Addr, Coin, Decimal}; use nym_mixnet_contract_common::families::FamilyHead; use nym_mixnet_contract_common::mixnode::MixNodeDetails; use nym_mixnet_contract_common::reward_params::{Performance, RewardingParams}; @@ -93,12 +93,21 @@ pub struct MixnodeStatusResponse { pub status: MixnodeStatus, } +#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema)] +pub struct NodePerformance { + pub most_recent: Performance, + pub last_hour: Performance, + pub last_24h: Performance, +} + #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] pub struct MixNodeBondAnnotated { pub mixnode_details: MixNodeDetails, pub stake_saturation: StakeSaturation, pub uncapped_stake_saturation: StakeSaturation, + // NOTE: the performance field is deprecated in favour of node_performance pub performance: Performance, + pub node_performance: NodePerformance, pub estimated_operator_apy: Decimal, pub estimated_delegators_apy: Decimal, pub family: Option, @@ -112,12 +121,32 @@ impl MixNodeBondAnnotated { pub fn mix_id(&self) -> MixId { self.mixnode_details.mix_id() } + + pub fn identity_key(&self) -> &str { + self.mixnode_details.bond_information.identity() + } + + pub fn owner(&self) -> &Addr { + self.mixnode_details.bond_information.owner() + } } #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] pub struct GatewayBondAnnotated { pub gateway_bond: GatewayBond, + // NOTE: the performance field is deprecated in favour of node_performance pub performance: Performance, + pub node_performance: NodePerformance, +} + +impl GatewayBondAnnotated { + pub fn identity(&self) -> &String { + self.gateway_bond.identity() + } + + pub fn owner(&self) -> &Addr { + self.gateway_bond.owner() + } } #[derive(Debug, Serialize, Deserialize, JsonSchema)] @@ -147,7 +176,17 @@ pub struct RewardEstimationResponse { #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] pub struct UptimeResponse { pub mix_id: MixId, + // The same as node_performance.last_24h. Legacy pub avg_uptime: u8, + pub node_performance: NodePerformance, +} + +#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +pub struct GatewayUptimeResponse { + pub identity: String, + // The same as node_performance.last_24h. Legacy + pub avg_uptime: u8, + pub node_performance: NodePerformance, } #[derive(Clone, Copy, Debug, Serialize, Deserialize, JsonSchema)] diff --git a/nym-api/src/node_status_api/cache/node_sets.rs b/nym-api/src/node_status_api/cache/node_sets.rs index 11e622052e..2d856bf9e7 100644 --- a/nym-api/src/node_status_api/cache/node_sets.rs +++ b/nym-api/src/node_status_api/cache/node_sets.rs @@ -1,6 +1,6 @@ use crate::node_status_api::reward_estimate::{compute_apy_from_reward, compute_reward_estimate}; use crate::support::storage::NymApiStorage; -use nym_api_requests::models::{GatewayBondAnnotated, MixNodeBondAnnotated}; +use nym_api_requests::models::{GatewayBondAnnotated, MixNodeBondAnnotated, NodePerformance}; use nym_mixnet_contract_common::families::FamilyHead; use nym_mixnet_contract_common::{reward_params::Performance, Interval, MixId}; use nym_mixnet_contract_common::{ @@ -99,16 +99,15 @@ pub(super) async fn annotate_nodes_with_details( .rewarding_details .uncapped_bond_saturation(&interval_reward_params); + let rewarded_set_status = rewarded_set.get(&mixnode.mix_id()).copied(); + // If the performance can't be obtained, because the nym-api was not started with // the monitoring (and hence, storage), then reward estimates will be all zero - let performance = get_mixnode_performance_from_storage(storage, mixnode.mix_id(), current_interval) .await .unwrap_or_default(); - let rewarded_set_status = rewarded_set.get(&mixnode.mix_id()).copied(); - let reward_estimate = compute_reward_estimate( &mixnode, performance, @@ -117,6 +116,17 @@ pub(super) async fn annotate_nodes_with_details( current_interval, ); + let node_performance = if let Some(storage) = storage { + storage + .construct_mixnode_report(mixnode.mix_id()) + .await + .map(NodePerformance::from) + .ok() + } else { + None + } + .unwrap_or_default(); + let (estimated_operator_apy, estimated_delegators_apy) = compute_apy_from_reward(&mixnode, reward_estimate, current_interval); @@ -129,6 +139,7 @@ pub(super) async fn annotate_nodes_with_details( stake_saturation, uncapped_stake_saturation, performance, + node_performance, estimated_operator_apy, estimated_delegators_apy, family, @@ -152,9 +163,21 @@ pub(crate) async fn annotate_gateways_with_details( .await .unwrap_or_default(); + let node_performance = if let Some(storage) = storage { + storage + .construct_gateway_report(gateway_bond.identity()) + .await + .map(NodePerformance::from) + .ok() + } else { + None + } + .unwrap_or_default(); + annotated.push(GatewayBondAnnotated { gateway_bond, performance, + node_performance, }); } annotated diff --git a/nym-api/src/node_status_api/helpers.rs b/nym-api/src/node_status_api/helpers.rs index 2c6a03b678..d131c6088e 100644 --- a/nym-api/src/node_status_api/helpers.rs +++ b/nym-api/src/node_status_api/helpers.rs @@ -8,26 +8,112 @@ use crate::{NodeStatusCache, NymContractCache}; use cosmwasm_std::Decimal; use nym_api_requests::models::{ AllInclusionProbabilitiesResponse, ComputeRewardEstParam, GatewayBondAnnotated, - InclusionProbabilityResponse, MixNodeBondAnnotated, MixnodeCoreStatusResponse, - MixnodeStatusReportResponse, MixnodeStatusResponse, MixnodeUptimeHistoryResponse, - RewardEstimationResponse, StakeSaturationResponse, UptimeResponse, + GatewayCoreStatusResponse, GatewayStatusReportResponse, GatewayUptimeHistoryResponse, + GatewayUptimeResponse, InclusionProbabilityResponse, MixNodeBondAnnotated, + MixnodeCoreStatusResponse, MixnodeStatusReportResponse, MixnodeStatusResponse, + MixnodeUptimeHistoryResponse, RewardEstimationResponse, StakeSaturationResponse, + UptimeResponse, }; -use nym_mixnet_contract_common::reward_params::Performance; -use nym_mixnet_contract_common::{Interval, MixId, RewardedSetNodeStatus}; +use nym_mixnet_contract_common::{MixId, RewardedSetNodeStatus}; use rocket::http::Status; use rocket::State; use super::reward_estimate::compute_reward_estimate; -pub(crate) async fn _mixnode_report( +async fn get_gateway_bond_annotated( + cache: &NodeStatusCache, + identity: &str, +) -> Result { + let gateways = cache.gateways_annotated().await.ok_or(ErrorResponse::new( + "no data available", + Status::ServiceUnavailable, + ))?; + + gateways + .into_inner() + .into_iter() + .find(|gateway| gateway.identity() == identity) + .ok_or(ErrorResponse::new( + "mixnode bond not found", + Status::NotFound, + )) +} + +async fn get_mixnode_bond_annotated( + cache: &NodeStatusCache, + mix_id: MixId, +) -> Result { + let mixnodes = cache.mixnodes_annotated().await.ok_or(ErrorResponse::new( + "no data available", + Status::ServiceUnavailable, + ))?; + + mixnodes + .into_inner() + .into_iter() + .find(|mixnode| mixnode.mix_id() == mix_id) + .ok_or(ErrorResponse::new( + "mixnode bond not found", + Status::NotFound, + )) +} + +pub(crate) async fn _gateway_report( + cache: &NodeStatusCache, + identity: &str, +) -> Result { + let gateway = get_gateway_bond_annotated(cache, identity).await?; + + Ok(GatewayStatusReportResponse { + identity: gateway.identity().to_owned(), + owner: gateway.owner().to_string(), + most_recent: gateway.node_performance.most_recent.round_to_integer(), + last_hour: gateway.node_performance.last_hour.round_to_integer(), + last_day: gateway.node_performance.last_24h.round_to_integer(), + }) +} + +pub(crate) async fn _gateway_uptime_history( storage: &NymApiStorage, + identity: &str, +) -> Result { + storage + .get_gateway_uptime_history(identity) + .await + .map(GatewayUptimeHistoryResponse::from) + .map_err(|err| ErrorResponse::new(err.to_string(), Status::NotFound)) +} + +pub(crate) async fn _gateway_core_status_count( + storage: &State, + identity: &str, + since: Option, +) -> Result { + let count = storage + .get_core_gateway_status_count(identity, since) + .await + .map_err(|err| ErrorResponse::new(err.to_string(), Status::NotFound))?; + + Ok(GatewayCoreStatusResponse { + identity: identity.to_string(), + count, + }) +} + +pub(crate) async fn _mixnode_report( + cache: &NodeStatusCache, mix_id: MixId, ) -> Result { - storage - .construct_mixnode_report(mix_id) - .await - .map(MixnodeStatusReportResponse::from) - .map_err(|err| ErrorResponse::new(err.to_string(), Status::NotFound)) + let mixnode = get_mixnode_bond_annotated(cache, mix_id).await?; + + Ok(MixnodeStatusReportResponse { + mix_id, + identity: mixnode.identity_key().to_owned(), + owner: mixnode.owner().to_string(), + most_recent: mixnode.node_performance.most_recent.round_to_integer(), + last_hour: mixnode.node_performance.last_hour.round_to_integer(), + last_day: mixnode.node_performance.last_24h.round_to_integer(), + }) } pub(crate) async fn _mixnode_uptime_history( @@ -103,21 +189,6 @@ pub(crate) async fn _get_mixnode_reward_estimation( } } -async fn average_mixnode_performance( - mix_id: MixId, - current_interval: Interval, - storage: &NymApiStorage, -) -> Result { - storage - .get_average_mixnode_uptime_in_the_last_24hrs( - mix_id, - current_interval.current_epoch_end_unix_timestamp(), - ) - .await - .map_err(|err| ErrorResponse::new(err.to_string(), Status::NotFound)) - .map(Into::into) -} - pub(crate) async fn _compute_mixnode_reward_estimation( user_reward_param: ComputeRewardEstParam, cache: &NodeStatusCache, @@ -254,21 +325,28 @@ pub(crate) async fn _get_mixnode_inclusion_probability( } pub(crate) async fn _get_mixnode_avg_uptime( - cache: &NymContractCache, - storage: &NymApiStorage, + cache: &NodeStatusCache, mix_id: MixId, ) -> Result { - let current_interval = cache - .current_interval() - .await - .into_inner() - .ok_or_else(|| ErrorResponse::new("server error", Status::InternalServerError))?; - - let performance = average_mixnode_performance(mix_id, current_interval, storage).await?; + let mixnode = get_mixnode_bond_annotated(cache, mix_id).await?; Ok(UptimeResponse { mix_id, - avg_uptime: performance.round_to_integer(), + avg_uptime: mixnode.node_performance.last_24h.round_to_integer(), + node_performance: mixnode.node_performance, + }) +} + +pub(crate) async fn _get_gateway_avg_uptime( + cache: &NodeStatusCache, + identity: &str, +) -> Result { + let gateway = get_gateway_bond_annotated(cache, identity).await?; + + Ok(GatewayUptimeResponse { + identity: identity.to_string(), + avg_uptime: gateway.node_performance.last_24h.round_to_integer(), + node_performance: gateway.node_performance, }) } @@ -288,7 +366,7 @@ pub(crate) async fn _get_mixnode_inclusion_probabilities( }) } else { Err(ErrorResponse::new( - "No data available".to_string(), + "No data available", Status::ServiceUnavailable, )) } diff --git a/nym-api/src/node_status_api/mod.rs b/nym-api/src/node_status_api/mod.rs index c8b3718fa6..1b05827e97 100644 --- a/nym-api/src/node_status_api/mod.rs +++ b/nym-api/src/node_status_api/mod.rs @@ -45,6 +45,7 @@ pub(crate) fn node_status_routes( routes::get_mixnode_stake_saturation, routes::get_mixnode_inclusion_probability, routes::get_mixnode_avg_uptime, + routes::get_gateway_avg_uptime, routes::get_mixnode_inclusion_probabilities, routes::get_mixnodes_detailed, routes::get_rewarded_set_detailed, diff --git a/nym-api/src/node_status_api/models.rs b/nym-api/src/node_status_api/models.rs index c65397a1f2..b1cb8cd79b 100644 --- a/nym-api/src/node_status_api/models.rs +++ b/nym-api/src/node_status_api/models.rs @@ -5,7 +5,7 @@ use crate::node_status_api::utils::NodeUptimes; use crate::storage::models::NodeStatus; use nym_api_requests::models::{ GatewayStatusReportResponse, GatewayUptimeHistoryResponse, HistoricalUptimeResponse, - MixnodeStatusReportResponse, MixnodeUptimeHistoryResponse, RequestError, + MixnodeStatusReportResponse, MixnodeUptimeHistoryResponse, NodePerformance, RequestError, }; use nym_mixnet_contract_common::reward_params::Performance; use nym_mixnet_contract_common::{IdentityKey, MixId}; @@ -179,6 +179,16 @@ impl From for MixnodeStatusReportResponse { } } +impl From for NodePerformance { + fn from(report: MixnodeStatusReport) -> Self { + NodePerformance { + most_recent: report.most_recent.into(), + last_hour: report.last_hour.into(), + last_24h: report.last_day.into(), + } + } +} + #[derive(Clone, Serialize, Deserialize, Debug, JsonSchema)] pub struct GatewayStatusReport { pub(crate) identity: String, @@ -228,6 +238,16 @@ impl From for GatewayStatusReportResponse { } } +impl From for NodePerformance { + fn from(report: GatewayStatusReport) -> Self { + NodePerformance { + most_recent: report.most_recent.into(), + last_hour: report.last_hour.into(), + last_24h: report.last_day.into(), + } + } +} + #[derive(Clone, Serialize, Deserialize, Debug, JsonSchema)] pub struct MixnodeUptimeHistory { pub(crate) mix_id: MixId, diff --git a/nym-api/src/node_status_api/routes.rs b/nym-api/src/node_status_api/routes.rs index a5bd3b7b6e..9d1f9d7dc0 100644 --- a/nym-api/src/node_status_api/routes.rs +++ b/nym-api/src/node_status_api/routes.rs @@ -4,11 +4,13 @@ use super::helpers::_get_gateways_detailed; use super::NodeStatusCache; use crate::node_status_api::helpers::{ - _compute_mixnode_reward_estimation, _get_active_set_detailed, _get_mixnode_avg_uptime, - _get_mixnode_inclusion_probabilities, _get_mixnode_inclusion_probability, - _get_mixnode_reward_estimation, _get_mixnode_stake_saturation, _get_mixnode_status, - _get_mixnodes_detailed, _get_rewarded_set_detailed, _mixnode_core_status_count, - _mixnode_report, _mixnode_uptime_history, + _compute_mixnode_reward_estimation, _gateway_core_status_count, _gateway_report, + _gateway_uptime_history, _get_active_set_detailed, _get_gateway_avg_uptime, + _get_mixnode_avg_uptime, _get_mixnode_inclusion_probabilities, + _get_mixnode_inclusion_probability, _get_mixnode_reward_estimation, + _get_mixnode_stake_saturation, _get_mixnode_status, _get_mixnodes_detailed, + _get_rewarded_set_detailed, _mixnode_core_status_count, _mixnode_report, + _mixnode_uptime_history, }; use crate::node_status_api::models::ErrorResponse; use crate::storage::NymApiStorage; @@ -16,12 +18,12 @@ use crate::NymContractCache; use nym_api_requests::models::{ AllInclusionProbabilitiesResponse, ComputeRewardEstParam, GatewayBondAnnotated, GatewayCoreStatusResponse, GatewayStatusReportResponse, GatewayUptimeHistoryResponse, - InclusionProbabilityResponse, MixNodeBondAnnotated, MixnodeCoreStatusResponse, - MixnodeStatusReportResponse, MixnodeStatusResponse, MixnodeUptimeHistoryResponse, - RewardEstimationResponse, StakeSaturationResponse, UptimeResponse, + GatewayUptimeResponse, InclusionProbabilityResponse, MixNodeBondAnnotated, + MixnodeCoreStatusResponse, MixnodeStatusReportResponse, MixnodeStatusResponse, + MixnodeUptimeHistoryResponse, RewardEstimationResponse, StakeSaturationResponse, + UptimeResponse, }; use nym_mixnet_contract_common::MixId; -use rocket::http::Status; use rocket::serde::json::Json; use rocket::State; use rocket_okapi::openapi; @@ -29,15 +31,10 @@ use rocket_okapi::openapi; #[openapi(tag = "status")] #[get("/gateway//report")] pub(crate) async fn gateway_report( - storage: &State, + cache: &State, identity: &str, ) -> Result, ErrorResponse> { - storage - .construct_gateway_report(identity) - .await - .map(GatewayStatusReportResponse::from) - .map(Json) - .map_err(|err| ErrorResponse::new(err.to_string(), Status::NotFound)) + Ok(Json(_gateway_report(cache, identity).await?)) } #[openapi(tag = "status")] @@ -46,12 +43,7 @@ pub(crate) async fn gateway_uptime_history( storage: &State, identity: &str, ) -> Result, ErrorResponse> { - storage - .get_gateway_uptime_history(identity) - .await - .map(GatewayUptimeHistoryResponse::from) - .map(Json) - .map_err(|err| ErrorResponse::new(err.to_string(), Status::NotFound)) + Ok(Json(_gateway_uptime_history(storage, identity).await?)) } #[openapi(tag = "status")] @@ -60,25 +52,19 @@ pub(crate) async fn gateway_core_status_count( storage: &State, identity: &str, since: Option, -) -> Json { - let count = storage - .get_core_gateway_status_count(identity, since) - .await - .unwrap_or_default(); - - Json(GatewayCoreStatusResponse { - identity: identity.to_string(), - count, - }) +) -> Result, ErrorResponse> { + Ok(Json( + _gateway_core_status_count(storage, identity, since).await?, + )) } #[openapi(tag = "status")] #[get("/mixnode//report")] pub(crate) async fn mixnode_report( - storage: &State, + cache: &State, mix_id: MixId, ) -> Result, ErrorResponse> { - Ok(Json(_mixnode_report(storage, mix_id).await?)) + Ok(Json(_mixnode_report(cache, mix_id).await?)) } #[openapi(tag = "status")] @@ -171,11 +157,19 @@ pub(crate) async fn get_mixnode_inclusion_probability( #[openapi(tag = "status")] #[get("/mixnode//avg_uptime")] pub(crate) async fn get_mixnode_avg_uptime( - cache: &State, - storage: &State, + cache: &State, mix_id: MixId, ) -> Result, ErrorResponse> { - Ok(Json(_get_mixnode_avg_uptime(cache, storage, mix_id).await?)) + Ok(Json(_get_mixnode_avg_uptime(cache, mix_id).await?)) +} + +#[openapi(tag = "status")] +#[get("/gateway//avg_uptime")] +pub(crate) async fn get_gateway_avg_uptime( + cache: &State, + identity: &str, +) -> Result, ErrorResponse> { + Ok(Json(_get_gateway_avg_uptime(cache, identity).await?)) } #[openapi(tag = "status")]