mirror of
https://github.com/pezkuwichain/pezkuwi-telemetry.git
synced 2026-07-20 15:05:43 +00:00
Sort chains by node count
This commit is contained in:
@@ -16,13 +16,15 @@ export default class Aggregator {
|
|||||||
let chain = this.getChain(node.chain);
|
let chain = this.getChain(node.chain);
|
||||||
|
|
||||||
chain.addNode(node);
|
chain.addNode(node);
|
||||||
|
|
||||||
|
this.feeds.broadcast(Feed.addedChain(chain));
|
||||||
}
|
}
|
||||||
|
|
||||||
public addFeed(feed: Feed) {
|
public addFeed(feed: Feed) {
|
||||||
this.feeds.add(feed);
|
this.feeds.add(feed);
|
||||||
|
|
||||||
for (const chain of this.chains.values()) {
|
for (const chain of this.chains.values()) {
|
||||||
feed.sendMessage(Feed.addedChain(chain.label));
|
feed.sendMessage(Feed.addedChain(chain));
|
||||||
}
|
}
|
||||||
|
|
||||||
feed.events.on('subscribe', (label: Types.ChainLabel) => {
|
feed.events.on('subscribe', (label: Types.ChainLabel) => {
|
||||||
@@ -68,7 +70,7 @@ export default class Aggregator {
|
|||||||
this.chains.set(label, chain);
|
this.chains.set(label, chain);
|
||||||
|
|
||||||
console.log(`New chain: ${label}`);
|
console.log(`New chain: ${label}`);
|
||||||
this.feeds.broadcast(Feed.addedChain(label));
|
this.feeds.broadcast(Feed.addedChain(chain));
|
||||||
|
|
||||||
return chain;
|
return chain;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ export default class Chain {
|
|||||||
this.label = label;
|
this.label = label;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get nodeCount(): number {
|
public get nodeCount(): Types.NodeCount {
|
||||||
return this.nodes.size;
|
return this.nodes.size as Types.NodeCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public addNode(node: Node) {
|
public addNode(node: Node) {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import * as WebSocket from 'ws';
|
import * as WebSocket from 'ws';
|
||||||
import * as EventEmitter from 'events';
|
import * as EventEmitter from 'events';
|
||||||
import Node from './Node';
|
import Node from './Node';
|
||||||
|
import Chain from './Chain';
|
||||||
import { timestamp, Maybe, FeedMessage, Types, idGenerator } from '@dotstats/common';
|
import { timestamp, Maybe, FeedMessage, Types, idGenerator } from '@dotstats/common';
|
||||||
|
|
||||||
const nextId = idGenerator<Types.FeedId>();
|
const nextId = idGenerator<Types.FeedId>();
|
||||||
@@ -66,10 +67,10 @@ export default class Feed {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static addedChain(label: Types.ChainLabel): FeedMessage.Message {
|
public static addedChain(chain: Chain): FeedMessage.Message {
|
||||||
return {
|
return {
|
||||||
action: Actions.AddedChain,
|
action: Actions.AddedChain,
|
||||||
payload: label
|
payload: [chain.label, chain.nodeCount]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,14 @@
|
|||||||
import { Opaque } from './helpers';
|
import { Opaque } from './helpers';
|
||||||
import { NodeId, NodeDetails, NodeStats, BlockNumber, BlockDetails, Timestamp, ChainLabel } from './types';
|
import {
|
||||||
|
NodeId,
|
||||||
|
NodeCount,
|
||||||
|
NodeDetails,
|
||||||
|
NodeStats,
|
||||||
|
BlockNumber,
|
||||||
|
BlockDetails,
|
||||||
|
Timestamp,
|
||||||
|
ChainLabel
|
||||||
|
} from './types';
|
||||||
|
|
||||||
export const Actions = {
|
export const Actions = {
|
||||||
BestBlock: 0 as 0,
|
BestBlock: 0 as 0,
|
||||||
@@ -54,7 +63,7 @@ export namespace Variants {
|
|||||||
|
|
||||||
export interface AddedChainMessage extends MessageBase {
|
export interface AddedChainMessage extends MessageBase {
|
||||||
action: typeof Actions.AddedChain;
|
action: typeof Actions.AddedChain;
|
||||||
payload: ChainLabel;
|
payload: [ChainLabel, NodeCount];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RemovedChainMessage extends MessageBase {
|
export interface RemovedChainMessage extends MessageBase {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ export type BlockHash = Opaque<string, 'BlockHash'>;
|
|||||||
export type Milliseconds = Opaque<number, 'Milliseconds'>;
|
export type Milliseconds = Opaque<number, 'Milliseconds'>;
|
||||||
export type Timestamp = Opaque<Milliseconds, 'Timestamp'>;
|
export type Timestamp = Opaque<Milliseconds, 'Timestamp'>;
|
||||||
export type PropagationTime = Opaque<Milliseconds, 'PropagationTime'>;
|
export type PropagationTime = Opaque<Milliseconds, 'PropagationTime'>;
|
||||||
|
export type NodeCount = Opaque<number, 'NodeCount'>;
|
||||||
export type PeerCount = Opaque<number, 'PeerCount'>;
|
export type PeerCount = Opaque<number, 'PeerCount'>;
|
||||||
export type TransactionCount = Opaque<number, 'TransactionCount'>;
|
export type TransactionCount = Opaque<number, 'TransactionCount'>;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { Types } from '@dotstats/common';
|
import { Types } from '@dotstats/common';
|
||||||
import { Chains, Chain, Ago } from './components';
|
import { Chains, Chain, Ago } from './components';
|
||||||
import { Connection } from './message';
|
import { Connection } from './Connection';
|
||||||
import { State } from './state';
|
import { State } from './state';
|
||||||
|
|
||||||
import './App.css';
|
import './App.css';
|
||||||
@@ -12,7 +12,7 @@ export default class App extends React.Component<{}, State> {
|
|||||||
blockTimestamp: 0 as Types.Timestamp,
|
blockTimestamp: 0 as Types.Timestamp,
|
||||||
timeDiff: 0 as Types.Milliseconds,
|
timeDiff: 0 as Types.Milliseconds,
|
||||||
subscribed: null,
|
subscribed: null,
|
||||||
chains: new Set(),
|
chains: new Map(),
|
||||||
nodes: new Map()
|
nodes: new Map()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -146,8 +146,8 @@ export class Connection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case Actions.AddedChain: {
|
case Actions.AddedChain: {
|
||||||
chains.add(message.payload);
|
const [label, nodeCount] = message.payload;
|
||||||
|
chains.set(label, nodeCount);
|
||||||
this.autoSubscribe();
|
this.autoSubscribe();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -195,10 +195,22 @@ export class Connection {
|
|||||||
private autoSubscribe() {
|
private autoSubscribe() {
|
||||||
const { subscribed, chains } = this.state;
|
const { subscribed, chains } = this.state;
|
||||||
|
|
||||||
if (subscribed == null && chains.size) {
|
if (subscribed) {
|
||||||
const first = chains.values().next().value;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.subscribe(first);
|
let topLabel: Maybe<Types.ChainLabel> = null;
|
||||||
|
let topCount: Types.NodeCount = 0 as Types.NodeCount;
|
||||||
|
|
||||||
|
for (const [label, count] of chains.entries()) {
|
||||||
|
if (count > topCount) {
|
||||||
|
topLabel = label;
|
||||||
|
topCount = topCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (topLabel) {
|
||||||
|
this.subscribe(topLabel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
.Chain-content {
|
.Chain-content {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 80px;
|
left: 0; /*80px;*/
|
||||||
right: 0;
|
right: 0;
|
||||||
min-height: 50vh;
|
min-height: 50vh;
|
||||||
background: #222;
|
background: #222;
|
||||||
|
|||||||
@@ -1,14 +1,19 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { Connection } from '../message';
|
import { Connection } from '../Connection';
|
||||||
import { Icon } from './Icon';
|
import { Icon } from './Icon';
|
||||||
import { Types, Maybe } from '@dotstats/common';
|
import { Types, Maybe } from '@dotstats/common';
|
||||||
|
|
||||||
import chainIcon from '../icons/link.svg';
|
import chainIcon from '../icons/link.svg';
|
||||||
import './Chains.css';
|
import './Chains.css';
|
||||||
|
|
||||||
|
interface ChainData {
|
||||||
|
label: Types.ChainLabel;
|
||||||
|
nodeCount: Types.NodeCount;
|
||||||
|
}
|
||||||
|
|
||||||
export namespace Chains {
|
export namespace Chains {
|
||||||
export interface Props {
|
export interface Props {
|
||||||
chains: Set<Types.ChainLabel>,
|
chains: Map<Types.ChainLabel, Types.NodeCount>,
|
||||||
subscribed: Maybe<Types.ChainLabel>,
|
subscribed: Maybe<Types.ChainLabel>,
|
||||||
connection: Promise<Connection>
|
connection: Promise<Connection>
|
||||||
}
|
}
|
||||||
@@ -26,20 +31,28 @@ export class Chains extends React.Component<Chains.Props, {}> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderChain(chain: Types.ChainLabel): React.ReactNode {
|
private renderChain(chain: ChainData): React.ReactNode {
|
||||||
const className = chain === this.props.subscribed
|
const { label, nodeCount } = chain;
|
||||||
|
|
||||||
|
const className = label === this.props.subscribed
|
||||||
? 'Chains-chain Chains-chain-selected'
|
? 'Chains-chain Chains-chain-selected'
|
||||||
: 'Chains-chain';
|
: 'Chains-chain';
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<a key={chain} className={className} onClick={this.subscribe.bind(this, chain)}>
|
<a key={label} className={className} onClick={this.subscribe.bind(this, label)}>
|
||||||
{chain}
|
{label} ({nodeCount})
|
||||||
</a>
|
</a>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private get chains(): Types.ChainLabel[] {
|
private get chains(): ChainData[] {
|
||||||
return Array.from(this.props.chains);
|
return Array
|
||||||
|
.from(this.props.chains.entries())
|
||||||
|
.sort((a, b) => {
|
||||||
|
return b[1] - a[1];
|
||||||
|
})
|
||||||
|
.map(([label, nodeCount]) => ({ label, nodeCount }));
|
||||||
}
|
}
|
||||||
|
|
||||||
private async subscribe(chain: Types.ChainLabel) {
|
private async subscribe(chain: Types.ChainLabel) {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ export interface State {
|
|||||||
blockTimestamp: Types.Timestamp,
|
blockTimestamp: Types.Timestamp,
|
||||||
timeDiff: Types.Milliseconds,
|
timeDiff: Types.Milliseconds,
|
||||||
subscribed: Maybe<Types.ChainLabel>,
|
subscribed: Maybe<Types.ChainLabel>,
|
||||||
chains: Set<Types.ChainLabel>,
|
chains: Map<Types.ChainLabel, Types.NodeCount>,
|
||||||
nodes: Map<Types.NodeId, Node.Props>,
|
nodes: Map<Types.NodeId, Node.Props>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user