This commit is contained in:
maciejhirsz
2018-06-27 15:56:32 +02:00
parent 0580e25380
commit 4812a5ddce
53 changed files with 152 additions and 1002 deletions
+8 -8
View File
@@ -1,13 +1,13 @@
import * as EventEmitter from 'events';
import Node from './node';
import Feed, { FeedData } from './feed';
import { Id, IdSet } from '@dotstats/common';
import { Types, IdSet } from '@dotstats/common';
export default class Aggregator extends EventEmitter {
private nodes: IdSet<Node> = new IdSet<Node>();
private feeds: IdSet<Feed> = new IdSet<Feed>();
private nodes = new IdSet<Types.NodeId, Node>();
private feeds = new IdSet<Types.FeedId, Feed>();
public height: number = 0;
public height = 0 as Types.BlockNumber;
constructor() {
super();
@@ -34,7 +34,7 @@ export default class Aggregator extends EventEmitter {
feed.send(Feed.bestBlock(this.height));
for (const node of this.nodes.entries) {
for (const node of this.nodes.values()) {
feed.send(Feed.addedNode(node));
}
@@ -44,11 +44,11 @@ export default class Aggregator extends EventEmitter {
}
public nodeList(): IterableIterator<Node> {
return this.nodes.entries;
return this.nodes.values();
}
private broadcast(data: FeedData) {
for (const feed of this.feeds.entries) {
for (const feed of this.feeds.values()) {
feed.send(data);
}
}
@@ -56,7 +56,7 @@ export default class Aggregator extends EventEmitter {
private timeoutCheck() {
const now = Date.now();
for (const node of this.nodes.entries) {
for (const node of this.nodes.values()) {
node.timeoutCheck(now);
}
}
+9 -36
View File
@@ -1,50 +1,23 @@
import * as WebSocket from 'ws';
import * as EventEmitter from 'events';
import Node, { NodeInfo, BlockInfo } from './node';
import { Opaque, Id, idGenerator } from '@dotstats/common';
import Node from './node';
import { Opaque, Types, idGenerator } from '@dotstats/common';
const nextId = idGenerator<Feed>();
export interface BlockInfo {
height: number;
blockTime: number;
}
interface BestBlock {
action: 'best';
payload: number;
}
interface AddedNode {
action: 'added';
payload: [Id<Node>, NodeInfo, BlockInfo];
}
interface RemovedNode {
action: 'removed';
payload: Id<Node>;
}
interface Imported {
action: 'imported';
payload: [Id<Node>, BlockInfo];
}
type Message = BestBlock | AddedNode | RemovedNode | Imported;
const nextId = idGenerator<Types.FeedId>();
/**
* Opaque data type to be sent to the feed. Passing through
* strings means we can only serialize once, no matter how
* many feed clients are listening in.
*/
export type FeedData = Opaque<string, Message>;
export type FeedData = Opaque<string, Types.FeedMessage>;
function serialize(msg: Message): FeedData {
function serialize(msg: Types.FeedMessage): FeedData {
return JSON.stringify(msg) as FeedData;
}
export default class Feed extends EventEmitter {
public id: Id<Feed>;
public id: Types.FeedId;
private socket: WebSocket;
@@ -58,7 +31,7 @@ export default class Feed extends EventEmitter {
socket.on('close', () => this.disconnect());
}
public static bestBlock(height: number): FeedData {
public static bestBlock(height: Types.BlockNumber): FeedData {
return serialize({
action: 'best',
payload: height
@@ -68,7 +41,7 @@ export default class Feed extends EventEmitter {
public static addedNode(node: Node): FeedData {
return serialize({
action: 'added',
payload: [node.id, node.nodeInfo(), node.blockInfo()]
payload: [node.id, node.nodeDetails(), node.blockDetails()]
})
}
@@ -82,7 +55,7 @@ export default class Feed extends EventEmitter {
public static imported(node: Node): FeedData {
return serialize({
action: 'imported',
payload: [node.id, node.blockInfo()]
payload: [node.id, node.blockDetails()]
});
}
+3 -3
View File
@@ -1,5 +1,5 @@
import { Data } from 'ws';
import { Maybe, Opaque } from '@dotstats/common';
import { Maybe, Types } from '@dotstats/common';
export function parseMessage(data: Data): Maybe<Message> {
try {
@@ -35,13 +35,13 @@ interface MessageBase {
export interface BestBlock {
best: string,
height: number,
height: Types.BlockNumber,
ts: Date,
}
interface SystemConnected {
msg: 'system.connected',
name: string,
name: Types.NodeName,
chain: string,
config: string,
implementation: string,
+18 -25
View File
@@ -1,38 +1,29 @@
import * as WebSocket from 'ws';
import * as EventEmitter from 'events';
import { Maybe, Id, idGenerator } from '@dotstats/common';
import { Maybe, Types, idGenerator } from '@dotstats/common';
import { parseMessage, getBestBlock, Message, BestBlock } from './message';
const BLOCK_TIME_HISTORY = 10;
const TIMEOUT = 1000 * 60 * 5; // 5 seconds
const nextId = idGenerator<Node>();
export interface NodeInfo {
name: string;
}
export interface BlockInfo {
height: number;
blockTime: number;
}
const nextId = idGenerator<Types.NodeId>();
export default class Node extends EventEmitter {
public lastMessage: number;
public id: Id<Node>;
public name: string;
public id: Types.NodeId;
public name: Types.NodeName;
public implementation: string;
public version: string;
public height: number = 0;
public config: string;
public latency: number = 0;
public blockTime: number = 0;
public height = 0 as Types.BlockNumber;
public latency = 0 as Types.Milliseconds;
public blockTime = 0 as Types.Milliseconds;
private socket: WebSocket;
private blockTimes: Array<number> = new Array(BLOCK_TIME_HISTORY);
private lastBlockAt: Maybe<Date> = null;
constructor(socket: WebSocket, name: string, config: string, implentation: string, version: string) {
constructor(socket: WebSocket, name: Types.NodeName, config: string, implentation: string, version: string) {
super();
this.lastMessage = Date.now();
@@ -46,6 +37,8 @@ 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;
@@ -81,6 +74,8 @@ export default class Node extends EventEmitter {
}
function handler(data: WebSocket.Data) {
console.log(data);
const message = parseMessage(data);
if (message && message.msg === "system.connected") {
@@ -110,13 +105,13 @@ export default class Node extends EventEmitter {
}
}
public nodeInfo(): NodeInfo {
public nodeDetails(): Types.NodeDetails {
return {
name: this.name,
};
}
public blockInfo(): BlockInfo {
public blockDetails(): Types.BlockDetails {
return {
height: this.height,
blockTime: this.blockTime,
@@ -141,8 +136,6 @@ export default class Node extends EventEmitter {
return sum / accounted;
}
private disconnect() {
this.socket.removeAllListeners();
this.socket.close();
@@ -151,7 +144,7 @@ export default class Node extends EventEmitter {
}
private updateLatency(time: Date) {
this.latency = this.lastMessage - +time;
this.latency = (this.lastMessage - +time) as Types.Milliseconds;
}
private updateBestBlock(update: BestBlock) {
@@ -169,11 +162,11 @@ export default class Node extends EventEmitter {
}
}
private getBlockTime(time: Date): number {
private getBlockTime(time: Date): Types.Milliseconds {
if (!this.lastBlockAt) {
return 0;
return 0 as Types.Milliseconds;
}
return +time - +this.lastBlockAt;
return (+time - +this.lastBlockAt) as Types.Milliseconds;
}
}