Skip to content

Commit

Permalink
fix: Upgrade Status renders on data error (#1000)
Browse files Browse the repository at this point in the history
## High Level Overview of Change

<!--
Please include a summary/list of the changes.
If too broad, please consider splitting into multiple PRs.
-->

The VHS is experiencing an intermittent issue with CORS header that
causes occasional disruption in data fetching for the Upgrade Status
chart. This PR will add checks so to ensure the chart renders even when
there's a disruption.

<img width="1725" alt="Screenshot 2024-06-12 at 4 13 54 PM"
src="https://github.com/ripple/explorer/assets/71317875/f5120024-4954-4d26-8c77-5ede6326d265">


### Type of Change

<!--
Please check relevant options, delete irrelevant ones.
-->

- [x] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to not work as expected)
- [ ] Refactor (non-breaking change that only restructures code)
- [ ] Tests (You added tests for code that already exists, or your new
feature included in this PR)
- [ ] Documentation Updates
- [ ] Translation Updates
- [ ] Release
  • Loading branch information
pdp2121 authored Sep 4, 2024
1 parent 222a003 commit 1018f05
Show file tree
Hide file tree
Showing 9 changed files with 262 additions and 130 deletions.
4 changes: 2 additions & 2 deletions public/locales/ca-CA/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -445,8 +445,8 @@
"other_chain_destination": "Destinació a una altra xarxa",
"%_of_total_nodes_validators": "% total de nodes i validadors",
"version_display": "Versió: {{version}}",
"validators_count": "# de Validadors: {{vals_count}}",
"nodes_count": "# de Nodes: {{nodes_count}}",
"validator_count": "# de Validadors: {{val_count}}",
"node_count": "# de Nodes: {{node_count}}",
"current_stable_version": "Versió estable actual",
"stable_version": "{{stableVersion}}",
"nftoken_minter": "Encunyador NFT",
Expand Down
4 changes: 2 additions & 2 deletions public/locales/en-US/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -445,8 +445,8 @@
"other_chain_destination": "Other Chain Destination",
"%_of_total_nodes_validators": "% of Total Nodes & Validators",
"version_display": "Version: {{version}}",
"validators_count": "# of Validators: {{vals_count}}",
"nodes_count": "# of Nodes: {{nodes_count}}",
"validator_count": "# of Validators: {{val_count}}",
"node_count": "# of Nodes: {{node_count}}",
"current_stable_version": "Current Stable Version",
"stable_version": "{{stableVersion}}",
"nftoken_minter": "NFT Minter",
Expand Down
4 changes: 2 additions & 2 deletions public/locales/es-ES/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -441,8 +441,8 @@
"other_chain_destination": "Otro Destino de Cadena",
"%_of_total_nodes_validators": "% Total de Nodos y Validadores",
"version_display": "Versión: {{version}}",
"validators_count": "# de Validadores: {{vals_count}}",
"nodes_count": "# de Nodos: {{nodes_count}}",
"validator_count": "# de Validadores: {{val_count}}",
"node_count": "# de Nodos: {{node_count}}",
"current_stable_version": "Versión Estable Actual",
"stable_version": "{{stableVersion}}",
"nftoken_minter": "Acuñador NFT",
Expand Down
4 changes: 2 additions & 2 deletions public/locales/fr-FR/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -443,8 +443,8 @@
"other_chain_destination": "Autre destination de chaîne",
"%_of_total_nodes_validators": "% des nœuds et des validateurs",
"version_display": "Version: {{version}}",
"validators_count": "nb de Validateurs: {{vals_count}}",
"nodes_count": "nb de Nœuds: {{nodes_count}}",
"validator_count": "nb de Validateurs: {{val_count}}",
"node_count": "nb de Nœuds: {{node_count}}",
"current_stable_version": "Version Stable Actuelle",
"stable_version": "{{stableVersion}}",
"nftoken_minter": "Créateur du NFT",
Expand Down
4 changes: 2 additions & 2 deletions public/locales/ja-JP/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -443,8 +443,8 @@
"other_chain_destination": null,
"%_of_total_nodes_validators": null,
"version_display": "バージョン: {{version}}",
"validators_count": "バリデータの数: {{vals_count}}",
"nodes_count": "ノードの数: {{nodes_count}}",
"validator_count": "バリデータの数: {{val_count}}",
"node_count": "ノードの数: {{node_count}}",
"current_stable_version": "現在の安定バージョン",
"stable_version": null,
"nftoken_minter": "NFT発行者",
Expand Down
4 changes: 2 additions & 2 deletions public/locales/ko-KR/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -441,8 +441,8 @@
"other_chain_destination": "다른 체인의 목적지",
"%_of_total_nodes_validators": "노드와 검증자의 총 비율",
"version_display": "버전: {{version}}",
"validators_count": "검증자 수: {{vals_count}}",
"nodes_count": "노드 수: {{nodes_count}}",
"validator_count": "검증자 수: {{val_count}}",
"node_count": "노드 수: {{node_count}}",
"current_stable_version": "현재 안정적인 버전",
"stable_version": "{{stableVersion}}",
"nftoken_minter": "NFT 발행자",
Expand Down
12 changes: 6 additions & 6 deletions src/containers/Network/BarChartVersion.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,13 @@ const CustomTooltip = ({
<div className="custom-tooltip">
<p className="label">{t('version_display', { version: label })}</p>
<p className="value">
{t('validators_count', {
vals_count: payload ? payload[0].payload.validatorsCount : 0,
{t('validator_count', {
val_count: payload?.[0]?.payload?.validatorCount ?? 0,
})}
</p>
<p className="value">
{t('nodes_count', {
nodes_count: payload ? payload[0].payload.nodesCount : 0,
{t('node_count', {
node_count: payload?.[0]?.payload?.nodeCount ?? 0,
})}
</p>
</div>
Expand Down Expand Up @@ -162,7 +162,7 @@ const BarChartVersion = (props: Props) => {
/>
</YAxis>
<Bar
dataKey="validatorsPercent"
dataKey="validatorPercent"
barSize={30}
fill={PURPLE}
radius={[4, 4, 0, 0]}
Expand All @@ -183,7 +183,7 @@ const BarChartVersion = (props: Props) => {
))}
</Bar>
<Bar
dataKey="nodesPercent"
dataKey="nodePercent"
barSize={30}
fill={PURPLE}
radius={[4, 4, 0, 0]}
Expand Down
138 changes: 96 additions & 42 deletions src/containers/Network/UpgradeStatus.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,63 +22,108 @@ import {
} from '../shared/vhsTypes'
import NetworkContext from '../shared/NetworkContext'
import { ledgerCompare } from './Nodes'
import { Loader } from '../shared/components/Loader'

interface DataAggregation {
label: string
validatorsPercent: number
validatorsCount: number
nodesPercent: number
nodesCount: number
interface NodeStats {
nodePercent: number
nodeCount: number
}

export const aggregateData = (
validators: ValidatorResponse[],
nodes: NodeResponse[],
): DataAggregation[] => {
if (!validators) {
return []
}
interface ValidatorStats {
validatorPercent: number
validatorCount: number
}

let totalVals = 0
let totalNodes = 0
interface aggregationTypes {
validatorsCount: number
nodesCount: number
}
interface ValidatorAggregation {
[label: string]: ValidatorStats
}

const aggregation: Record<string, aggregationTypes> = {}
interface NodeAggregation {
[label: string]: NodeStats
}

interface DataAggregation extends ValidatorStats, NodeStats {
label: string
}

export const aggregateValidators = (validators: ValidatorResponse[]) => {
let totalVals = 0
const aggregation: ValidatorAggregation = {}
validators?.forEach((validator) => {
if (!validator.signing_key) return
const version = validator.server_version
totalVals += 1
if (version) {
if (!aggregation[version]) {
aggregation[version] = { validatorsCount: 0, nodesCount: 0 }
aggregation[version] = { validatorCount: 0, validatorPercent: 0 }
}
aggregation[version].validatorsCount += 1
aggregation[version].validatorCount += 1
}
})
for (const label of Object.keys(aggregation)) {
aggregation[label].validatorPercent =
totalVals > 0 ? (aggregation[label].validatorCount / totalVals) * 100 : 0
}

return aggregation
}

export const aggregateNodes = (nodes: NodeResponse[]) => {
let totalNodes = 0
const aggregation: NodeAggregation = {}
nodes?.forEach((node) => {
const { version } = node
if (!node.node_public_key) return
totalNodes += 1
if (version) {
if (!aggregation[version]) {
aggregation[version] = { validatorsCount: 0, nodesCount: 0 }
aggregation[version] = { nodeCount: 0, nodePercent: 0 }
}
aggregation[version].nodesCount += 1
aggregation[version].nodeCount += 1
}
})
for (const label of Object.keys(aggregation)) {
aggregation[label].nodePercent =
totalNodes > 0 ? (aggregation[label].nodeCount / totalNodes) * 100 : 0
}

return aggregation
}

return Object.entries(aggregation)
.map(([version, counts]) => ({
label: version ? version.trim() : 'N/A',
validatorsPercent:
totalVals > 0 ? (counts.validatorsCount * 100) / totalVals : 0,
validatorsCount: counts.validatorsCount,
nodesPercent: totalNodes > 0 ? (counts.nodesCount * 100) / totalNodes : 0,
nodesCount: counts.nodesCount,
export const aggregateData = (
validatorAggregation: ValidatorAggregation,
nodeAggregation: NodeAggregation,
): DataAggregation[] => {
const combinedAggregation: { [label: string]: ValidatorStats & NodeStats } =
{}
for (const label of Object.keys(validatorAggregation)) {
combinedAggregation[label] = {
validatorPercent: validatorAggregation[label].validatorPercent,
validatorCount: validatorAggregation[label].validatorCount,
nodePercent: 0,
nodeCount: 0,
}
}

for (const label of Object.keys(nodeAggregation)) {
if (!combinedAggregation[label]) {
combinedAggregation[label] = {
validatorPercent: 0,
validatorCount: 0,
nodePercent: nodeAggregation[label].nodePercent,
nodeCount: nodeAggregation[label].nodeCount,
}
} else {
combinedAggregation[label].nodePercent =
nodeAggregation[label].nodePercent
combinedAggregation[label].nodeCount = nodeAggregation[label].nodeCount
}
}

return Object.entries(combinedAggregation)
.map(([label, stats]) => ({
label,
...stats,
}))
.sort((a, b) => (isEarlierVersion(a.label, b.label) ? -1 : 1))
}
Expand Down Expand Up @@ -110,7 +155,9 @@ export const UpgradeStatus = () => {
const [vList, setVList] = useState<Record<string, ValidatorResponse>>({})
const [validations, setValidations] = useState<ValidatorResponse[]>([])
const [unlCount, setUnlCount] = useState(0)
const [aggregated, setAggregated] = useState<DataAggregation[]>([])
const [validatorAggregation, setValidatorAggregation] =
useState<ValidatorAggregation>({})
const [nodeAggregation, setNodeAggregation] = useState<NodeAggregation>({})
const { t } = useTranslation()
const language = useLanguage()
const network = useContext(NetworkContext)
Expand Down Expand Up @@ -145,24 +192,24 @@ export const UpgradeStatus = () => {
)

const fetchData = () => {
const validatorsReq = axios
axios
.get(`${process.env.VITE_DATA_URL}/validators/${network}`)
.then((resp) => resp.data.validators)
.then((validators: ValidatorResponse[]) => {
const newValidatorList: Record<string, ValidatorResponse> = {}
validators.forEach((validator) => {
newValidatorList[validator.signing_key] = validator
})

setVList(newValidatorList)
setUnlCount(
validators.filter((validator) => Boolean(validator.unl)).length,
)
setValidatorAggregation(aggregateValidators(validators))
return Object.values(newValidatorList)
})
.catch((e) => Log.error(e))

const nodesReq = axios
axios
.get(`${process.env.VITE_DATA_URL}/topology/nodes/${network}`)
.then((resp) => resp.data.nodes)
.then((allNodes) => {
Expand All @@ -188,12 +235,11 @@ export const UpgradeStatus = () => {
}
return 1
})

setNodeAggregation(aggregateNodes(nodes))
return nodes
})
.catch((e) => Log.error(e))
Promise.all([validatorsReq, nodesReq]).then(([validators, nodes]) => {
setAggregated(aggregateData(validators, nodes))
})
}

const fetchStableVersion = () => {
Expand Down Expand Up @@ -250,9 +296,17 @@ export const UpgradeStatus = () => {
</div>
<div className="wrap">
<NetworkTabs selected="upgrade-status" />
<div className="upgrade_status">
<BarChartVersion data={aggregated} stableVersion={stableVersion} />
</div>
{Object.keys(validatorAggregation).length > 0 ||
Object.keys(nodeAggregation).length > 0 ? (
<div className="upgrade_status">
<BarChartVersion
data={aggregateData(validatorAggregation, nodeAggregation)}
stableVersion={stableVersion}
/>
</div>
) : (
<Loader />
)}
</div>
</div>
)
Expand Down
Loading

0 comments on commit 1018f05

Please sign in to comment.