mirror of
https://github.com/pezkuwichain/pezkuwi-telemetry.git
synced 2026-06-17 16:11:03 +00:00
feat: Instead of delisting, push stale nodes to bottom (#161)
This commit is contained in:
@@ -29,13 +29,12 @@ export default class Chain {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public get nodeCount(): Types.NodeCount {
|
public get nodeCount(): Types.NodeCount {
|
||||||
return this.count as Types.NodeCount;
|
return this.nodes.size as Types.NodeCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public addNode(node: Node) {
|
public addNode(node: Node) {
|
||||||
console.log(`[${this.label}] new node: ${node.name}`);
|
console.log(`[${this.label}] new node: ${node.name}`);
|
||||||
|
|
||||||
this.count += 1;
|
|
||||||
this.nodes.add(node);
|
this.nodes.add(node);
|
||||||
this.feeds.broadcast(Feed.addedNode(node));
|
this.feeds.broadcast(Feed.addedNode(node));
|
||||||
|
|
||||||
@@ -83,12 +82,7 @@ export default class Chain {
|
|||||||
node.events.removeAllListeners();
|
node.events.removeAllListeners();
|
||||||
|
|
||||||
this.nodes.delete(node);
|
this.nodes.delete(node);
|
||||||
|
this.feeds.broadcast(Feed.removedNode(node));
|
||||||
if (!node.isStale) {
|
|
||||||
this.count -= 1;
|
|
||||||
this.feeds.broadcast(Feed.removedNode(node));
|
|
||||||
}
|
|
||||||
|
|
||||||
this.events.emit('disconnect', this.nodeCount);
|
this.events.emit('disconnect', this.nodeCount);
|
||||||
|
|
||||||
if (this.height === node.best.number) {
|
if (this.height === node.best.number) {
|
||||||
@@ -97,8 +91,7 @@ export default class Chain {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public staleNode(node: Node) {
|
public staleNode(node: Node) {
|
||||||
this.count -= 1;
|
this.feeds.broadcast(Feed.staleNode(node));
|
||||||
this.feeds.broadcast(Feed.removedNode(node));
|
|
||||||
|
|
||||||
if (this.height === node.best.number) {
|
if (this.height === node.best.number) {
|
||||||
this.downgradeBlock();
|
this.downgradeBlock();
|
||||||
@@ -174,8 +167,6 @@ export default class Chain {
|
|||||||
|
|
||||||
if (node.isStale) {
|
if (node.isStale) {
|
||||||
node.isStale = false;
|
node.isStale = false;
|
||||||
this.feeds.broadcast(Feed.addedNode(node));
|
|
||||||
this.count += 1;
|
|
||||||
} else {
|
} else {
|
||||||
this.feeds.broadcast(Feed.imported(node));
|
this.feeds.broadcast(Feed.imported(node));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,6 +65,13 @@ export default class Feed {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static staleNode(node: Node): FeedMessage.Message {
|
||||||
|
return {
|
||||||
|
action: Actions.StaleNode,
|
||||||
|
payload: node.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static locatedNode(node: Node, location: Location): FeedMessage.Message {
|
public static locatedNode(node: Node, location: Location): FeedMessage.Message {
|
||||||
return {
|
return {
|
||||||
action: Actions.LocatedNode,
|
action: Actions.LocatedNode,
|
||||||
|
|||||||
+23
-16
@@ -22,26 +22,27 @@ import {
|
|||||||
} from './types';
|
} from './types';
|
||||||
|
|
||||||
export const Actions = {
|
export const Actions = {
|
||||||
FeedVersion : 0x00 as 0x00,
|
FeedVersion : 0x00 as 0x00,
|
||||||
BestBlock : 0x01 as 0x01,
|
BestBlock : 0x01 as 0x01,
|
||||||
BestFinalized : 0x02 as 0x02,
|
BestFinalized : 0x02 as 0x02,
|
||||||
AddedNode : 0x03 as 0x03,
|
AddedNode : 0x03 as 0x03,
|
||||||
RemovedNode : 0x04 as 0x04,
|
RemovedNode : 0x04 as 0x04,
|
||||||
LocatedNode : 0x05 as 0x05,
|
LocatedNode : 0x05 as 0x05,
|
||||||
ImportedBlock : 0x06 as 0x06,
|
ImportedBlock : 0x06 as 0x06,
|
||||||
FinalizedBlock : 0x07 as 0x07,
|
FinalizedBlock : 0x07 as 0x07,
|
||||||
NodeStats : 0x08 as 0x08,
|
NodeStats : 0x08 as 0x08,
|
||||||
NodeHardware : 0x09 as 0x09,
|
NodeHardware : 0x09 as 0x09,
|
||||||
TimeSync : 0x0A as 0x0A,
|
TimeSync : 0x0A as 0x0A,
|
||||||
AddedChain : 0x0B as 0x0B,
|
AddedChain : 0x0B as 0x0B,
|
||||||
RemovedChain : 0x0C as 0x0C,
|
RemovedChain : 0x0C as 0x0C,
|
||||||
SubscribedTo : 0x0D as 0x0D,
|
SubscribedTo : 0x0D as 0x0D,
|
||||||
UnsubscribedFrom : 0x0E as 0x0E,
|
UnsubscribedFrom : 0x0E as 0x0E,
|
||||||
Pong : 0x0F as 0x0F,
|
Pong : 0x0F as 0x0F,
|
||||||
AfgFinalized : 0x10 as 0x10,
|
AfgFinalized : 0x10 as 0x10,
|
||||||
AfgReceivedPrevote : 0x11 as 0x11,
|
AfgReceivedPrevote : 0x11 as 0x11,
|
||||||
AfgReceivedPrecommit : 0x12 as 0x12,
|
AfgReceivedPrecommit : 0x12 as 0x12,
|
||||||
AfgAuthoritySet : 0x13 as 0x13,
|
AfgAuthoritySet : 0x13 as 0x13,
|
||||||
|
StaleNode : 0x14 as 0x14,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Action = typeof Actions[keyof typeof Actions];
|
export type Action = typeof Actions[keyof typeof Actions];
|
||||||
@@ -151,6 +152,11 @@ export namespace Variants {
|
|||||||
action: typeof Actions.AfgReceivedPrevote;
|
action: typeof Actions.AfgReceivedPrevote;
|
||||||
payload: [Address, BlockNumber, BlockHash, Address];
|
payload: [Address, BlockNumber, BlockHash, Address];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface StaleNodeMessage extends MessageBase {
|
||||||
|
action: typeof Actions.StaleNode;
|
||||||
|
payload: NodeId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Message =
|
export type Message =
|
||||||
@@ -173,6 +179,7 @@ export type Message =
|
|||||||
| Variants.AfgReceivedPrevote
|
| Variants.AfgReceivedPrevote
|
||||||
| Variants.AfgReceivedPrecommit
|
| Variants.AfgReceivedPrecommit
|
||||||
| Variants.AfgAuthoritySet
|
| Variants.AfgAuthoritySet
|
||||||
|
| Variants.StaleNodeMessage
|
||||||
| Variants.PongMessage;
|
| Variants.PongMessage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -9,4 +9,4 @@ import * as FeedMessage from './feed';
|
|||||||
export { Types, FeedMessage };
|
export { Types, FeedMessage };
|
||||||
|
|
||||||
// Increment this if breaking changes were made to types in `feed.ts`
|
// Increment this if breaking changes were made to types in `feed.ts`
|
||||||
export const VERSION: Types.FeedVersion = 22 as Types.FeedVersion;
|
export const VERSION: Types.FeedVersion = 25 as Types.FeedVersion;
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ export class Connection {
|
|||||||
return new Connection(await Connection.socket(), update, pins);
|
return new Connection(await Connection.socket(), update, pins);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static readonly utf8decoder = new TextDecoder('utf-8');
|
||||||
|
|
||||||
private static readonly address = window.location.protocol === 'https:'
|
private static readonly address = window.location.protocol === 'https:'
|
||||||
? `wss://${window.location.hostname}/feed/`
|
? `wss://${window.location.hostname}/feed/`
|
||||||
: `ws://${window.location.hostname}:8080`;
|
: `ws://${window.location.hostname}:8080`;
|
||||||
@@ -55,6 +57,7 @@ export class Connection {
|
|||||||
|
|
||||||
const socket = new WebSocket(Connection.address);
|
const socket = new WebSocket(Connection.address);
|
||||||
|
|
||||||
|
socket.binaryType = "arraybuffer";
|
||||||
socket.addEventListener('open', onSuccess);
|
socket.addEventListener('open', onSuccess);
|
||||||
socket.addEventListener('error', onFailure);
|
socket.addEventListener('error', onFailure);
|
||||||
socket.addEventListener('close', onFailure);
|
socket.addEventListener('close', onFailure);
|
||||||
@@ -173,6 +176,14 @@ export class Connection {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Actions.StaleNode: {
|
||||||
|
const id = message.payload;
|
||||||
|
|
||||||
|
nodes.mutAndSort(id, (node) => node.setStale(true));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case Actions.LocatedNode: {
|
case Actions.LocatedNode: {
|
||||||
const [id, lat, lon, city] = message.payload;
|
const [id, lat, lon, city] = message.payload;
|
||||||
|
|
||||||
@@ -376,7 +387,9 @@ export class Connection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private handleFeedData = (event: MessageEvent) => {
|
private handleFeedData = (event: MessageEvent) => {
|
||||||
const data = event.data as FeedMessage.Data;
|
const data = typeof event.data === 'string'
|
||||||
|
? event.data as any as FeedMessage.Data
|
||||||
|
: Connection.utf8decoder.decode(event.data) as any as FeedMessage.Data;
|
||||||
|
|
||||||
this.handleMessages(FeedMessage.deserialize(data));
|
this.handleMessages(FeedMessage.deserialize(data));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,6 +60,10 @@
|
|||||||
color: #E6007A;
|
color: #E6007A;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.Row-stale {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
.Row:hover {
|
.Row:hover {
|
||||||
background-color: #1E1E1E;
|
background-color: #1E1E1E;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -374,6 +374,10 @@ export class Row extends React.Component<Row.Props, Row.State> {
|
|||||||
className += ' Row-pinned';
|
className += ' Row-pinned';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (node.stale) {
|
||||||
|
className += ' Row-stale';
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<tr className={className} onClick={this.toggle}>
|
<tr className={className} onClick={this.toggle}>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { Types, Maybe, SortedCollection } from '@dotstats/common';
|
|||||||
|
|
||||||
export class Node {
|
export class Node {
|
||||||
public static compare(a: Node, b: Node): number {
|
public static compare(a: Node, b: Node): number {
|
||||||
if (a.pinned === b.pinned) {
|
if (a.pinned === b.pinned && a.stale === b.stale) {
|
||||||
if (a.height === b.height) {
|
if (a.height === b.height) {
|
||||||
const aPropagation = a.propagationTime == null ? Infinity : a.propagationTime as number;
|
const aPropagation = a.propagationTime == null ? Infinity : a.propagationTime as number;
|
||||||
const bPropagation = b.propagationTime == null ? Infinity : b.propagationTime as number;
|
const bPropagation = b.propagationTime == null ? Infinity : b.propagationTime as number;
|
||||||
@@ -11,7 +11,10 @@ export class Node {
|
|||||||
return aPropagation - bPropagation;
|
return aPropagation - bPropagation;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return +b.pinned - +a.pinned;
|
const bSort = (b.pinned ? -2 : 0) + +b.stale;
|
||||||
|
const aSort = (a.pinned ? -2 : 0) + +a.stale;
|
||||||
|
|
||||||
|
return aSort - bSort;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Descending sort by block number
|
// Descending sort by block number
|
||||||
@@ -26,6 +29,7 @@ export class Node {
|
|||||||
public readonly validator: Maybe<Types.Address>;
|
public readonly validator: Maybe<Types.Address>;
|
||||||
public readonly networkId: Maybe<Types.NetworkId>;
|
public readonly networkId: Maybe<Types.NetworkId>;
|
||||||
|
|
||||||
|
public stale: boolean;
|
||||||
public pinned: boolean;
|
public pinned: boolean;
|
||||||
public peers: Types.PeerCount;
|
public peers: Types.PeerCount;
|
||||||
public txs: Types.TransactionCount;
|
public txs: Types.TransactionCount;
|
||||||
@@ -110,6 +114,7 @@ export class Node {
|
|||||||
this.blockTime = blockTime;
|
this.blockTime = blockTime;
|
||||||
this.blockTimestamp = blockTimestamp;
|
this.blockTimestamp = blockTimestamp;
|
||||||
this.propagationTime = propagationTime;
|
this.propagationTime = propagationTime;
|
||||||
|
this.stale = false;
|
||||||
|
|
||||||
this.trigger();
|
this.trigger();
|
||||||
}
|
}
|
||||||
@@ -143,6 +148,13 @@ export class Node {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public setStale(stale: boolean) {
|
||||||
|
if (this.stale !== stale) {
|
||||||
|
this.stale = stale;
|
||||||
|
this.trigger();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public subscribe(handler: (node: Node) => void) {
|
public subscribe(handler: (node: Node) => void) {
|
||||||
this.subscriptions.add(handler);
|
this.subscriptions.add(handler);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user