Pass through node details

This commit is contained in:
maciejhirsz
2018-06-27 16:52:32 +02:00
parent 5c9186670d
commit b57dc22c33
9 changed files with 104 additions and 51 deletions
+3 -2
View File
@@ -20,13 +20,14 @@ export default class Aggregator extends EventEmitter {
this.broadcast(Feed.addedNode(node));
node.once('disconnect', () => {
node.removeAllListeners('block');
node.removeAllListeners();
this.nodes.remove(node);
this.broadcast(Feed.removedNode(node));
});
node.on('block', () => this.updateBlock(node));
node.on('stats', () => this.broadcast(Feed.stats(node)));
}
public addFeed(feed: Feed) {
@@ -40,7 +41,7 @@ export default class Aggregator extends EventEmitter {
feed.once('disconnect', () => {
this.feeds.remove(feed);
})
});
}
public nodeList(): IterableIterator<Node> {
+8 -1
View File
@@ -41,7 +41,7 @@ export default class Feed extends EventEmitter {
public static addedNode(node: Node): FeedData {
return serialize({
action: 'added',
payload: [node.id, node.nodeDetails(), node.blockDetails()]
payload: [node.id, node.nodeDetails(), node.nodeStats(), node.blockDetails()]
})
}
@@ -59,6 +59,13 @@ export default class Feed extends EventEmitter {
});
}
public static stats(node: Node): FeedData {
return serialize({
action: 'stats',
payload: [node.id, node.nodeStats()]
});
}
public send(data: FeedData) {
this.socket.send(data);
}
+6 -6
View File
@@ -34,7 +34,7 @@ interface MessageBase {
}
export interface BestBlock {
best: string,
best: Types.BlockHash,
height: Types.BlockNumber,
ts: Date,
}
@@ -44,14 +44,14 @@ interface SystemConnected {
name: Types.NodeName,
chain: string,
config: string,
implementation: string,
version: string,
implementation: Types.NodeImplementation,
version: Types.NodeVersion,
}
interface SystemInterval extends BestBlock {
export interface SystemInterval extends BestBlock {
msg: 'system.interval',
txcount: number,
peers: number,
txcount: Types.TransactionCount,
peers: Types.PeerCount,
status: 'Idle' | string, // TODO: 'Idle' | ...?
}
+38 -17
View File
@@ -1,10 +1,10 @@
import * as WebSocket from 'ws';
import * as EventEmitter from 'events';
import { Maybe, Types, idGenerator } from '@dotstats/common';
import { parseMessage, getBestBlock, Message, BestBlock } from './message';
import { parseMessage, getBestBlock, Message, BestBlock, SystemInterval } from './message';
const BLOCK_TIME_HISTORY = 10;
const TIMEOUT = 1000 * 60 * 5; // 5 seconds
const TIMEOUT = 1000 * 60 * 1; // 1 minute
const nextId = idGenerator<Types.NodeId>();
@@ -12,18 +12,27 @@ export default class Node extends EventEmitter {
public lastMessage: number;
public id: Types.NodeId;
public name: Types.NodeName;
public implementation: string;
public version: string;
public implementation: Types.NodeImplementation;
public version: Types.NodeVersion;
public config: string;
public height = 0 as Types.BlockNumber;
public latency = 0 as Types.Milliseconds;
public blockTime = 0 as Types.Milliseconds;
private peers = 0 as Types.PeerCount;
private txcount = 0 as Types.TransactionCount;
private socket: WebSocket;
private blockTimes: Array<number> = new Array(BLOCK_TIME_HISTORY);
private lastBlockAt: Maybe<Date> = null;
constructor(socket: WebSocket, name: Types.NodeName, config: string, implentation: string, version: string) {
constructor(
socket: WebSocket,
name: Types.NodeName,
config: string,
implentation: Types.NodeImplementation,
version: Types.NodeVersion,
) {
super();
this.lastMessage = Date.now();
@@ -37,11 +46,11 @@ export default class Node extends EventEmitter {
console.log(`Listening to a new node: ${name}`);
socket.on('message', (data) => {
console.log(data);
const message = parseMessage(data);
if (!message) return;
if (!message) {
return;
}
this.lastMessage = Date.now();
this.updateLatency(message.ts);
@@ -51,6 +60,10 @@ export default class Node extends EventEmitter {
if (update) {
this.updateBestBlock(update);
}
if (message.msg === 'system.interval') {
this.onSystemInterval(message);
}
});
socket.on('close', () => {
@@ -74,8 +87,6 @@ export default class Node extends EventEmitter {
}
function handler(data: WebSocket.Data) {
console.log(data);
const message = parseMessage(data);
if (message && message.msg === "system.connected") {
@@ -106,16 +117,15 @@ export default class Node extends EventEmitter {
}
public nodeDetails(): Types.NodeDetails {
return {
name: this.name,
};
return [this.name, this.implementation, this.version];
}
public nodeStats(): Types.NodeStats {
return [this.peers, this.txcount];
}
public blockDetails(): Types.BlockDetails {
return {
height: this.height,
blockTime: this.blockTime,
};
return [this.height, this.blockTime];
}
public get average(): number {
@@ -143,6 +153,17 @@ export default class Node extends EventEmitter {
this.emit('disconnect');
}
private onSystemInterval(message: SystemInterval) {
const { peers, txcount } = message;
if (this.peers !== peers || this.txcount !== txcount) {
this.peers = peers;
this.txcount = txcount;
this.emit('stats');
}
}
private updateLatency(time: Date) {
this.latency = (this.lastMessage - +time) as Types.Milliseconds;
}
+1 -1
View File
@@ -4,6 +4,6 @@
"outDir": "build"
},
"include": [
"src/**/*.ts"
"./src/**/*.ts"
]
}
+15 -10
View File
@@ -4,17 +4,17 @@ import { Id } from './id';
export type FeedId = Id<'Feed'>;
export type NodeId = Id<'Node'>;
export type NodeName = Opaque<string, 'NodeName'>;
export type NodeImplementation = Opaque<string, 'NodeImplementation'>;
export type NodeVersion = Opaque<string, 'NodeVersion'>;
export type BlockNumber = Opaque<number, 'BlockNumber'>;
export type BlockHash = Opaque<string, 'BlockHash'>;
export type Milliseconds = Opaque<number, 'Milliseconds'>;
export type PeerCount = Opaque<number, 'PeerCount'>;
export type TransactionCount = Opaque<number, 'TransactionCount'>;
export interface BlockDetails {
height: BlockNumber;
blockTime: Milliseconds;
}
export interface NodeDetails {
name: NodeName;
}
export type BlockDetails = [BlockNumber, Milliseconds];
export type NodeDetails = [NodeName, NodeImplementation, NodeVersion];
export type NodeStats = [PeerCount, TransactionCount];
interface BestBlock {
action: 'best';
@@ -23,7 +23,7 @@ interface BestBlock {
interface AddedNode {
action: 'added';
payload: [NodeId, NodeDetails, BlockDetails];
payload: [NodeId, NodeDetails, NodeStats, BlockDetails];
}
interface RemovedNode {
@@ -36,4 +36,9 @@ interface Imported {
payload: [NodeId, BlockDetails];
}
export type FeedMessage = BestBlock | AddedNode | RemovedNode | Imported;
interface Stats {
action: 'stats';
payload: [NodeId, NodeStats];
}
export type FeedMessage = BestBlock | AddedNode | RemovedNode | Imported | Stats;
+32 -10
View File
@@ -4,6 +4,7 @@ import { Types } from '@dotstats/common';
interface Node {
nodeDetails: Types.NodeDetails,
nodeStats: Types.NodeStats,
blockDetails: Types.BlockDetails,
}
@@ -35,18 +36,27 @@ export default class App extends React.Component<{}, State> {
<table>
<thead>
<tr>
<th>Name</th><th>Block</th><th>Block time</th>
<th>Node Name</th><th>Node Type</th><th>Peers</th><th>Transactions</th><th>Block</th><th>Block time</th>
</tr>
</thead>
<tbody>
{
this.nodes().map(([ id, node ]) => (
<tr key={id}>
<td>{node.nodeDetails.name}</td>
<td>{node.blockDetails.height}</td>
<td>{node.blockDetails.blockTime / 1000}s</td>
</tr>
))
this.nodes().map(([ id, node ]) => {
const [name, implementation, version] = node.nodeDetails;
const [height, blockTime] = node.blockDetails;
const [peers, txcount] = node.nodeStats;
return (
<tr key={id}>
<td>{name}</td>
<td>{implementation} v{version}</td>
<td>{peers}</td>
<td>{txcount}</td>
<td>{height}</td>
<td>{blockTime / 1000}s</td>
</tr>
);
})
}
</tbody>
</table>
@@ -67,8 +77,8 @@ export default class App extends React.Component<{}, State> {
}
return;
case 'added': {
const [id, nodeDetails, blockDetails] = message.payload;
const node = { nodeDetails, blockDetails };
const [id, nodeDetails, nodeStats, blockDetails] = message.payload;
const node = { nodeDetails, nodeStats, blockDetails };
nodes.set(id, node);
}
@@ -89,6 +99,18 @@ export default class App extends React.Component<{}, State> {
node.blockDetails = blockDetails;
}
break;
case 'stats': {
const [id, nodeStats] = message.payload;
const node = nodes.get(id);
if (!node) {
return;
}
node.nodeStats = nodeStats;
}
break;
default:
return;
}
+1 -1
View File
@@ -1,3 +1,3 @@
scripts/build-common.sh
scripts/build-backend.sh
node packages/backend/build/index.js
node packages/backend/build/backend/src/index.js
-3
View File
@@ -22,9 +22,6 @@
"typeRoots": [
"./node_modules/@types"
],
"include": [
"src/**/*.ts"
],
"exclude": [
"node_modules"
]