From ea8d7ad77d708a9ceaaf997967b3178d902bffdc Mon Sep 17 00:00:00 2001 From: maciejhirsz Date: Thu, 12 Jul 2018 16:04:04 +0200 Subject: [PATCH] Sort chains by node count --- packages/backend/src/Aggregator.ts | 6 ++-- packages/backend/src/Chain.ts | 4 +-- packages/backend/src/Feed.ts | 5 ++-- packages/common/src/feed.ts | 13 +++++++-- packages/common/src/types.ts | 1 + packages/frontend/src/App.tsx | 4 +-- .../src/{message.ts => Connection.ts} | 22 ++++++++++---- packages/frontend/src/components/Chain.css | 2 +- packages/frontend/src/components/Chains.tsx | 29 ++++++++++++++----- packages/frontend/src/state.ts | 2 +- 10 files changed, 63 insertions(+), 25 deletions(-) rename packages/frontend/src/{message.ts => Connection.ts} (92%) diff --git a/packages/backend/src/Aggregator.ts b/packages/backend/src/Aggregator.ts index 048dd89..41d0897 100644 --- a/packages/backend/src/Aggregator.ts +++ b/packages/backend/src/Aggregator.ts @@ -16,13 +16,15 @@ export default class Aggregator { let chain = this.getChain(node.chain); chain.addNode(node); + + this.feeds.broadcast(Feed.addedChain(chain)); } public addFeed(feed: Feed) { this.feeds.add(feed); 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) => { @@ -68,7 +70,7 @@ export default class Aggregator { this.chains.set(label, chain); console.log(`New chain: ${label}`); - this.feeds.broadcast(Feed.addedChain(label)); + this.feeds.broadcast(Feed.addedChain(chain)); return chain; } diff --git a/packages/backend/src/Chain.ts b/packages/backend/src/Chain.ts index e86a5cf..d2b81e8 100644 --- a/packages/backend/src/Chain.ts +++ b/packages/backend/src/Chain.ts @@ -18,8 +18,8 @@ export default class Chain { this.label = label; } - public get nodeCount(): number { - return this.nodes.size; + public get nodeCount(): Types.NodeCount { + return this.nodes.size as Types.NodeCount; } public addNode(node: Node) { diff --git a/packages/backend/src/Feed.ts b/packages/backend/src/Feed.ts index bd6848d..ede3542 100644 --- a/packages/backend/src/Feed.ts +++ b/packages/backend/src/Feed.ts @@ -1,6 +1,7 @@ import * as WebSocket from 'ws'; import * as EventEmitter from 'events'; import Node from './Node'; +import Chain from './Chain'; import { timestamp, Maybe, FeedMessage, Types, idGenerator } from '@dotstats/common'; const nextId = idGenerator(); @@ -66,10 +67,10 @@ export default class Feed { }; } - public static addedChain(label: Types.ChainLabel): FeedMessage.Message { + public static addedChain(chain: Chain): FeedMessage.Message { return { action: Actions.AddedChain, - payload: label + payload: [chain.label, chain.nodeCount] }; } diff --git a/packages/common/src/feed.ts b/packages/common/src/feed.ts index 32d37a7..008753c 100644 --- a/packages/common/src/feed.ts +++ b/packages/common/src/feed.ts @@ -1,5 +1,14 @@ 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 = { BestBlock: 0 as 0, @@ -54,7 +63,7 @@ export namespace Variants { export interface AddedChainMessage extends MessageBase { action: typeof Actions.AddedChain; - payload: ChainLabel; + payload: [ChainLabel, NodeCount]; } export interface RemovedChainMessage extends MessageBase { diff --git a/packages/common/src/types.ts b/packages/common/src/types.ts index 1879379..15ae916 100644 --- a/packages/common/src/types.ts +++ b/packages/common/src/types.ts @@ -12,6 +12,7 @@ export type BlockHash = Opaque; export type Milliseconds = Opaque; export type Timestamp = Opaque; export type PropagationTime = Opaque; +export type NodeCount = Opaque; export type PeerCount = Opaque; export type TransactionCount = Opaque; diff --git a/packages/frontend/src/App.tsx b/packages/frontend/src/App.tsx index 0195d02..1fda33a 100644 --- a/packages/frontend/src/App.tsx +++ b/packages/frontend/src/App.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { Types } from '@dotstats/common'; import { Chains, Chain, Ago } from './components'; -import { Connection } from './message'; +import { Connection } from './Connection'; import { State } from './state'; import './App.css'; @@ -12,7 +12,7 @@ export default class App extends React.Component<{}, State> { blockTimestamp: 0 as Types.Timestamp, timeDiff: 0 as Types.Milliseconds, subscribed: null, - chains: new Set(), + chains: new Map(), nodes: new Map() }; diff --git a/packages/frontend/src/message.ts b/packages/frontend/src/Connection.ts similarity index 92% rename from packages/frontend/src/message.ts rename to packages/frontend/src/Connection.ts index df82c91..3a7c6b3 100644 --- a/packages/frontend/src/message.ts +++ b/packages/frontend/src/Connection.ts @@ -146,8 +146,8 @@ export class Connection { } case Actions.AddedChain: { - chains.add(message.payload); - + const [label, nodeCount] = message.payload; + chains.set(label, nodeCount); this.autoSubscribe(); break; @@ -195,10 +195,22 @@ export class Connection { private autoSubscribe() { const { subscribed, chains } = this.state; - if (subscribed == null && chains.size) { - const first = chains.values().next().value; + if (subscribed) { + return; + } - this.subscribe(first); + let topLabel: Maybe = 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); } } diff --git a/packages/frontend/src/components/Chain.css b/packages/frontend/src/components/Chain.css index 39a6c68..fc42992 100644 --- a/packages/frontend/src/components/Chain.css +++ b/packages/frontend/src/components/Chain.css @@ -6,7 +6,7 @@ .Chain-content { position: absolute; - left: 80px; + left: 0; /*80px;*/ right: 0; min-height: 50vh; background: #222; diff --git a/packages/frontend/src/components/Chains.tsx b/packages/frontend/src/components/Chains.tsx index b1e950e..53498ad 100644 --- a/packages/frontend/src/components/Chains.tsx +++ b/packages/frontend/src/components/Chains.tsx @@ -1,14 +1,19 @@ import * as React from 'react'; -import { Connection } from '../message'; +import { Connection } from '../Connection'; import { Icon } from './Icon'; import { Types, Maybe } from '@dotstats/common'; import chainIcon from '../icons/link.svg'; import './Chains.css'; +interface ChainData { + label: Types.ChainLabel; + nodeCount: Types.NodeCount; +} + export namespace Chains { export interface Props { - chains: Set, + chains: Map, subscribed: Maybe, connection: Promise } @@ -26,20 +31,28 @@ export class Chains extends React.Component { ); } - private renderChain(chain: Types.ChainLabel): React.ReactNode { - const className = chain === this.props.subscribed + private renderChain(chain: ChainData): React.ReactNode { + const { label, nodeCount } = chain; + + const className = label === this.props.subscribed ? 'Chains-chain Chains-chain-selected' : 'Chains-chain'; + return ( - - {chain} + + {label} ({nodeCount}) ) } - private get chains(): Types.ChainLabel[] { - return Array.from(this.props.chains); + private get chains(): ChainData[] { + 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) { diff --git a/packages/frontend/src/state.ts b/packages/frontend/src/state.ts index 32df319..e552437 100644 --- a/packages/frontend/src/state.ts +++ b/packages/frontend/src/state.ts @@ -6,7 +6,7 @@ export interface State { blockTimestamp: Types.Timestamp, timeDiff: Types.Milliseconds, subscribed: Maybe, - chains: Set, + chains: Map, nodes: Map, }