Skip to content

Commit b402599

Browse files
committed
Handle peer deletion better and UI fixes
1 parent 6fea5f1 commit b402599

File tree

9 files changed

+147
-94
lines changed

9 files changed

+147
-94
lines changed

frontend/src/components/search-peer-item.tsx

+12-6
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,27 @@ import React from "react";
22
import { Tag, Slider } from "antd";
33
import { Peer } from "../types";
44
import { BlockNum } from "../atoms/block-num";
5-
import { formatNumberWithCommas, formatTime } from "../utils/format";
5+
import { formatNumberWithCommas } from "../utils/format";
66
import Moment from "react-moment";
77
import "moment-timezone";
88

99
export function SearchPeerItem(props: {
1010
peer: Peer;
1111
headBlockNum: number;
1212
visualize: boolean;
13+
showKey: boolean;
1314
}): React.ReactElement {
1415
const { peer, headBlockNum } = props;
1516

1617
let adjustedLowBlockNum = peer.tailBlockNum;
1718
if (!peer.tailBlockNum) {
1819
adjustedLowBlockNum = 0;
1920
}
20-
const highBlockRatio = (peer.headBlockNum / headBlockNum) * 100;
21+
2122
return (
2223
<>
23-
<tr>
24-
<td>{peer.host}</td>
24+
<tr className={peer.deleted ? "peer-deleted" : ""}>
25+
<td>{props.showKey ? peer.key : peer.host}</td>
2526
<td>
2627
<Tag>{peer.tier}</Tag>
2728
</td>
@@ -40,8 +41,13 @@ export function SearchPeerItem(props: {
4041
{formatNumberWithCommas(peer.shardSize)}
4142
</td>
4243
<td style={{ textAlign: "center" }}>
43-
{peer.ready && <Tag color="#87d068">ready</Tag>}
44-
{!peer.ready && <Tag color="#f50">not ready</Tag>}
44+
{peer.ready && <Tag color="green">ready</Tag>}
45+
{!peer.ready && peer.deleted && (
46+
<Tag color="volcano">deleted</Tag>
47+
)}
48+
{!peer.ready && !peer.deleted && (
49+
<Tag color="magenta">not ready</Tag>
50+
)}
4551
</td>
4652
<td style={{ textAlign: "center" }}>
4753
<Moment format="YYYY-MM-DD HH:mm Z">{peer.boot}</Moment>

frontend/src/components/search-peer-list.tsx

+16-19
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,40 @@
11
import React, { useState } from "react";
2-
import { Icon, Tag, Slider } from "antd";
2+
import { Icon, Button } from "antd";
33
import { Peer } from "../types";
44
import { SearchPeerItem } from "./search-peer-item";
55

66
export function SearchPeerList(props: {
77
peers: Peer[];
8+
visualize: boolean;
89
headBlockNum: number;
910
}): React.ReactElement {
10-
const [visualize, setVisualize] = useState(false);
11+
const [showKey, setShowKey] = useState(false);
12+
1113
const peerItem = props.peers
1214
.sort((a: Peer, b: Peer) => {
1315
return a.tier < b.tier ? -1 : 1;
1416
})
1517
.map((peer: Peer) => (
1618
<SearchPeerItem
19+
key={`${peer.host}-${peer.key}`}
1720
peer={peer}
1821
headBlockNum={props.headBlockNum}
19-
visualize={visualize}
22+
visualize={props.visualize}
23+
showKey={showKey}
2024
/>
2125
));
2226

2327
return (
2428
<div>
2529
<div className="ant-table-body">
26-
<button
27-
style={{ float: "right" }}
28-
onClick={() => {
29-
setVisualize(!visualize);
30-
}}
31-
>
32-
<Icon type="radar-chart" />
33-
</button>
3430
<table style={{ width: "100%" }}>
3531
<thead className="ant-table-thead">
3632
<tr>
37-
<th>Host</th>
33+
<th>
34+
<Icon type="key" onClick={() => setShowKey(!showKey)} /> Host
35+
</th>
3836
<th>Tier</th>
39-
{!visualize && (
37+
{!props.visualize && (
4038
<>
4139
<th style={{ textAlign: "right" }}>Tail Block</th>
4240
<th style={{ textAlign: "right" }}>IRR Block</th>
@@ -46,12 +44,11 @@ export function SearchPeerList(props: {
4644
<th style={{ textAlign: "center" }}>Boot Time</th>
4745
</>
4846
)}
49-
{visualize && (
50-
<>
51-
<th style={{ width: "100%" }}></th>
52-
</>
53-
)}
54-
<th style={{ textAlign: "center" }}>Features</th>
47+
{props.visualize && <th style={{ width: "100%" }}></th>}
48+
<>
49+
<th style={{ textAlign: "center" }}>Features</th>
50+
<th></th>
51+
</>
5552
</tr>
5653
</thead>
5754
<tbody className="ant-table-tbody">{peerItem}</tbody>

frontend/src/index.scss

+9-3
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ code {
1818
margin-right: 10px;
1919
}
2020
span.black-range-num {
21-
padding-right: 10px
21+
padding-right: 10px;
2222
}
2323
}
2424
button.btn {
@@ -27,8 +27,14 @@ button.btn {
2727
span.svg {
2828
line-height: 1;
2929
svg {
30-
height:22px;
30+
height: 22px;
3131
}
3232
}
33+
}
3334

34-
}
35+
.peer-deleted {
36+
td {
37+
//background-color: #e8e8e8;
38+
text-decoration: line-through;
39+
}
40+
}

frontend/src/index.tsx

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import React from "react"
2-
import ReactDOM from 'react-dom';
1+
import React from "react";
2+
import ReactDOM from "react-dom";
33

4-
import 'antd/dist/antd.css';
5-
import './index.scss';
4+
import "antd/dist/antd.css";
5+
import "./index.scss";
66

7-
import App from './App';
7+
import App from "./App";
88

9-
ReactDOM.render(<App />, document.getElementById('root'));
9+
ReactDOM.render(<App />, document.getElementById("root"));

frontend/src/pages/dmesh.tsx

+92-59
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,60 @@
11
import React, { useEffect, useState } from "react";
22
import { withRouter, RouteComponentProps } from "react-router";
3-
import { Row, Col, Typography, PageHeader, Descriptions } from "antd";
3+
import {
4+
Row,
5+
Col,
6+
Typography,
7+
PageHeader,
8+
Descriptions,
9+
Tag,
10+
Icon,
11+
Button
12+
} from "antd";
413
import { Peer } from "../types";
514
import { ApiService } from "../utils/api";
615
import { useAppConfig } from "../hooks/dignose";
716
import { SearchPeerList } from "../components/search-peer-list";
817
import { MainLayout } from "../components/main-layout";
9-
import { Btn } from "../atoms/buttons";
1018

1119
const { Text } = Typography;
1220

1321
function BaseDmeshPage(props: RouteComponentProps): React.ReactElement {
14-
const [track, setTrack] = useState(false);
22+
const [visualize, setVisualize] = useState(false);
23+
const [connected, setConnected] = useState(false);
1524
const [peers, setPeers] = useState<Peer[]>([]);
1625
const [headBlockNum, setHeadBlockNum] = useState(0);
1726

1827
const appConfig = useAppConfig();
1928

20-
const peerIndex = (peerHost: string): number => {
21-
return peers.findIndex(peer => peer.host === peerHost);
22-
};
23-
2429
const deletePeer = (peer: Peer) => {
25-
const index = peerIndex(peer.host);
26-
if (index >= 0) {
27-
setPeers(currentPeers => {
28-
return [...currentPeers.slice(index, 1)];
30+
setPeers(currentPeers => {
31+
const newCurrentPeers = currentPeers.map(peerItem => {
32+
if (peerItem.key === peer.key) {
33+
return { ...peerItem, deleted: true, ready: false };
34+
}
35+
return peerItem;
2936
});
30-
}
37+
return newCurrentPeers;
38+
});
3139
};
3240

3341
const updatePeer = (peer: Peer) => {
3442
if (peer.headBlockNum > headBlockNum) {
3543
setHeadBlockNum(peer.headBlockNum);
3644
}
3745
setPeers(currentPeers => {
38-
const newCUrrentPeers = currentPeers.map(peerItem => {
39-
if (peerItem.host === peer.host) {
46+
let foundPeer = false;
47+
let newCurrentPeers = currentPeers.map(peerItem => {
48+
if (peerItem.key === peer.key) {
49+
foundPeer = true;
4050
return peer;
4151
}
4252
return peerItem;
4353
});
44-
return newCUrrentPeers;
54+
if (!foundPeer) {
55+
newCurrentPeers = [...newCurrentPeers, peer];
56+
}
57+
return newCurrentPeers;
4558
});
4659
};
4760

@@ -55,63 +68,79 @@ function BaseDmeshPage(props: RouteComponentProps): React.ReactElement {
5568
};
5669

5770
useEffect(() => {
58-
let stream: WebSocket;
59-
if (track) {
60-
setPeers([]);
61-
stream = ApiService.stream({
62-
route: "search_peers",
63-
onComplete: () => {
64-
setTrack(false);
65-
},
66-
onData: resp => {
67-
switch (resp.type) {
68-
case "Transaction":
69-
break;
70-
case "BlockRange":
71-
break;
72-
case "Message":
73-
break;
74-
case "PeerEvent":
75-
if (resp.payload.EventName === "sync") {
76-
addPeer(resp.payload.Peer);
77-
} else if (resp.payload.EventName === "update") {
78-
updatePeer(resp.payload.Peer);
79-
} else if (resp.payload.EventName === "delete") {
80-
deletePeer(resp.payload.Peer);
81-
}
82-
break;
83-
}
71+
setPeers([]);
72+
setConnected(true);
73+
const stream = ApiService.stream({
74+
route: "search_peers",
75+
onError: () => {
76+
setConnected(false);
77+
},
78+
onComplete: () => {
79+
setConnected(false);
80+
},
81+
onData: resp => {
82+
let localPeer;
83+
switch (resp.type) {
84+
case "Transaction":
85+
break;
86+
case "BlockRange":
87+
break;
88+
case "Message":
89+
break;
90+
case "PeerEvent":
91+
localPeer = resp.payload.Peer;
92+
localPeer.key = resp.payload.PeerKey;
93+
if (resp.payload.EventName === "sync") {
94+
console.log(
95+
`[SYNC] for peer ${resp.payload.PeerKey} - ${resp.payload.Peer.host}`
96+
);
97+
addPeer(localPeer);
98+
} else if (resp.payload.EventName === "update") {
99+
updatePeer(localPeer);
100+
} else if (resp.payload.EventName === "delete") {
101+
console.log(
102+
`[DELETED] for peer ${resp.payload.PeerKey} - ${resp.payload.Peer.host}`
103+
);
104+
deletePeer(localPeer);
105+
}
106+
break;
84107
}
85-
});
86-
}
87-
108+
}
109+
});
88110
return () => {
89111
if (stream) {
90-
console.log("closing stream");
91112
stream.close();
92113
}
93114
};
94-
}, [track]);
115+
}, []);
95116

96117
return (
97118
<MainLayout config={appConfig} {...props}>
98119
<PageHeader
99120
title="Dmesh Peers"
121+
tags={
122+
connected ? (
123+
<Tag color="geekblue">
124+
<Icon type="sync" spin /> connected
125+
</Tag>
126+
) : (
127+
<Tag color="red">
128+
<Icon type="disconnect" /> disconnected
129+
</Tag>
130+
)
131+
}
100132
extra={[
101-
<Btn
102-
key={1}
103-
stopText="Stop Tracking Dmesh"
104-
startText="Track Dmesh"
105-
loading={track}
106-
onStart={e => {
107-
e.preventDefault();
108-
setTrack(true);
109-
}}
110-
onStop={e => {
133+
<Button
134+
key="1"
135+
onClick={e => {
111136
e.preventDefault();
112-
setTrack(false);
137+
setVisualize(!visualize);
113138
}}
114-
/>
139+
size="small"
140+
type="ghost"
141+
>
142+
<Icon type="sliders" />
143+
</Button>
115144
]}
116145
>
117146
<Descriptions size="small" column={3}>
@@ -127,7 +156,11 @@ function BaseDmeshPage(props: RouteComponentProps): React.ReactElement {
127156
<Row>
128157
<Col>
129158
<div style={{ marginTop: "10px" }}>
130-
<SearchPeerList peers={peers} headBlockNum={headBlockNum} />
159+
<SearchPeerList
160+
peers={peers}
161+
headBlockNum={headBlockNum}
162+
visualize={visualize}
163+
/>
131164
</div>
132165
</Col>
133166
</Row>

frontend/src/types.ts

+2
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ export interface PeerEventSocketMessage {
5252
type: "PeerEvent";
5353
payload: {
5454
EventName: string;
55+
PeerKey: string;
5556
Peer: Peer;
5657
};
5758
}
@@ -71,6 +72,7 @@ export interface Peer {
7172
tailMoves: boolean;
7273
tier: number;
7374
deleted: boolean;
75+
key: string;
7476
}
7577

7678
export type SocketMessage =

0 commit comments

Comments
 (0)