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 <fmtabbara@hotmail.co.uk>
This commit is contained in:
Jon Häggblad
2023-02-27 12:40:00 +01:00
committed by GitHub
parent d684f6d7ae
commit f590aad42c
12 changed files with 261 additions and 103 deletions
+2 -3
View File
@@ -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<GatewayBond[]> => {
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,
}));
};
+4 -3
View File
@@ -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),
};
}
@@ -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)}
/>
);
};
+3 -3
View File
@@ -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<GatewayBond | undefined>();
const [selectedGateway, setSelectedGateway] = React.useState<GatewayBond>();
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]);
+8 -11
View File
@@ -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: () => <CustomColumnHeading headingTitle="Identity Key" />,
headerClassName: 'MuiDataGrid-header-override',
width: 380,
@@ -119,7 +118,7 @@ export const PageGateways: FCWithChildren = () => {
<MuiLink
sx={{ ...cellStyles }}
component={RRDLink}
to={`/network-components/gateway/${params.row.identityKey}`}
to={`/network-components/gateway/${params.row.identity_key}`}
data-testid="pledge-amount"
>
{unymToNym(params.value, 6)}
@@ -127,8 +126,7 @@ export const PageGateways: FCWithChildren = () => {
),
},
{
field: 'performance',
headerName: 'Routing Score',
field: 'node_performance',
renderHeader: () => <CustomColumnHeading headingTitle="Routing Score" />,
width: 150,
headerAlign: 'left',
@@ -137,7 +135,7 @@ export const PageGateways: FCWithChildren = () => {
<MuiLink
sx={{ ...cellStyles }}
component={RRDLink}
to={`/network-components/gateway/${params.row.identityKey}`}
to={`/network-components/gateway/${params.row.identity_key}`}
data-testid="pledge-amount"
>
{`${params.value}%`}
@@ -154,7 +152,7 @@ export const PageGateways: FCWithChildren = () => {
<MuiLink
sx={{ ...cellStyles }}
component={RRDLink}
to={`/network-components/gateway/${params.row.identityKey}`}
to={`/network-components/gateway/${params.row.identity_key}`}
data-testid="host"
>
{params.value}
@@ -168,9 +166,9 @@ export const PageGateways: FCWithChildren = () => {
headerAlign: 'left',
headerClassName: 'MuiDataGrid-header-override',
renderCell: (params: GridRenderCellParams) => (
<Button
<Box
onClick={() => handleSearch(params.value as string)}
sx={{ ...cellStyles, justifyContent: 'flex-start' }}
sx={{ ...cellStyles, justifyContent: 'flex-start', cursor: 'pointer' }}
data-testid="location-button"
>
<Tooltip text={params.value} id="gateway-location-text">
@@ -184,7 +182,7 @@ export const PageGateways: FCWithChildren = () => {
{params.value}
</Box>
</Tooltip>
</Button>
</Box>
),
},
{
@@ -207,7 +205,6 @@ export const PageGateways: FCWithChildren = () => {
},
{
field: 'version',
headerName: 'Version',
renderHeader: () => <CustomColumnHeading headingTitle="Version" />,
width: 150,
headerAlign: 'left',
+8 -2
View File
@@ -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[];
+40 -1
View File
@@ -1,7 +1,7 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// 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<FamilyHead>,
@@ -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)]
+27 -4
View File
@@ -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
+115 -37
View File
@@ -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<GatewayBondAnnotated, ErrorResponse> {
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<MixNodeBondAnnotated, ErrorResponse> {
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<GatewayStatusReportResponse, ErrorResponse> {
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<GatewayUptimeHistoryResponse, ErrorResponse> {
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<NymApiStorage>,
identity: &str,
since: Option<i64>,
) -> Result<GatewayCoreStatusResponse, ErrorResponse> {
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<MixnodeStatusReportResponse, ErrorResponse> {
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<Performance, ErrorResponse> {
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<UptimeResponse, ErrorResponse> {
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<GatewayUptimeResponse, ErrorResponse> {
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,
))
}
+1
View File
@@ -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,
+21 -1
View File
@@ -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<MixnodeStatusReport> for MixnodeStatusReportResponse {
}
}
impl From<MixnodeStatusReport> 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<GatewayStatusReport> for GatewayStatusReportResponse {
}
}
impl From<GatewayStatusReport> 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,
+31 -37
View File
@@ -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/<identity>/report")]
pub(crate) async fn gateway_report(
storage: &State<NymApiStorage>,
cache: &State<NodeStatusCache>,
identity: &str,
) -> Result<Json<GatewayStatusReportResponse>, 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<NymApiStorage>,
identity: &str,
) -> Result<Json<GatewayUptimeHistoryResponse>, 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<NymApiStorage>,
identity: &str,
since: Option<i64>,
) -> Json<GatewayCoreStatusResponse> {
let count = storage
.get_core_gateway_status_count(identity, since)
.await
.unwrap_or_default();
Json(GatewayCoreStatusResponse {
identity: identity.to_string(),
count,
})
) -> Result<Json<GatewayCoreStatusResponse>, ErrorResponse> {
Ok(Json(
_gateway_core_status_count(storage, identity, since).await?,
))
}
#[openapi(tag = "status")]
#[get("/mixnode/<mix_id>/report")]
pub(crate) async fn mixnode_report(
storage: &State<NymApiStorage>,
cache: &State<NodeStatusCache>,
mix_id: MixId,
) -> Result<Json<MixnodeStatusReportResponse>, 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/<mix_id>/avg_uptime")]
pub(crate) async fn get_mixnode_avg_uptime(
cache: &State<NymContractCache>,
storage: &State<NymApiStorage>,
cache: &State<NodeStatusCache>,
mix_id: MixId,
) -> Result<Json<UptimeResponse>, 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/<identity>/avg_uptime")]
pub(crate) async fn get_gateway_avg_uptime(
cache: &State<NodeStatusCache>,
identity: &str,
) -> Result<Json<GatewayUptimeResponse>, ErrorResponse> {
Ok(Json(_get_gateway_avg_uptime(cache, identity).await?))
}
#[openapi(tag = "status")]