mirror of
https://github.com/pezkuwichain/pezkuwi-telemetry.git
synced 2026-06-13 18:31:02 +00:00
Reworking interfaces a bit
This commit is contained in:
+2
-70
@@ -1,76 +1,8 @@
|
|||||||
import * as WebSocket from 'ws';
|
import * as WebSocket from 'ws';
|
||||||
|
import Node from './node';
|
||||||
|
|
||||||
const wss = new WebSocket.Server({ port: 1024 });
|
const wss = new WebSocket.Server({ port: 1024 });
|
||||||
|
|
||||||
wss.on('connection', async (socket: WebSocket) => {
|
wss.on('connection', async (socket: WebSocket) => {
|
||||||
await Node.fromSocket(socket);
|
await Node.fromSocket(socket);
|
||||||
});
|
});
|
||||||
|
|
||||||
type Level = "INFO" | "WARN";
|
|
||||||
|
|
||||||
interface SystemConnected {
|
|
||||||
msg: "system.connected",
|
|
||||||
name: string,
|
|
||||||
ts: string,
|
|
||||||
chain: string,
|
|
||||||
config: string,
|
|
||||||
implementation: string,
|
|
||||||
version: string,
|
|
||||||
}
|
|
||||||
|
|
||||||
type Message = SystemConnected;
|
|
||||||
|
|
||||||
class Node {
|
|
||||||
private socket: WebSocket;
|
|
||||||
private name: string;
|
|
||||||
private config: string;
|
|
||||||
private implementation: string;
|
|
||||||
private version: string;
|
|
||||||
|
|
||||||
constructor(socket: WebSocket, name: string, config: string, implentation: string, version: string) {
|
|
||||||
this.socket = socket;
|
|
||||||
this.name = name;
|
|
||||||
this.config = config;
|
|
||||||
this.implementation = implentation;
|
|
||||||
this.version = version;
|
|
||||||
|
|
||||||
console.log(`Started listening to a new node: ${name}`);
|
|
||||||
|
|
||||||
socket.on('message', (message: WebSocket.Data) => {
|
|
||||||
console.log('received: %s', message);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static fromSocket(socket: WebSocket): Promise<Node> {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
function handler(msg: WebSocket.Data) {
|
|
||||||
let message: Message;
|
|
||||||
|
|
||||||
try {
|
|
||||||
message = JSON.parse(msg.toString());
|
|
||||||
} catch (err) {
|
|
||||||
socket.removeEventListener('message');
|
|
||||||
|
|
||||||
return reject(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (message.msg === "system.connected") {
|
|
||||||
socket.removeEventListener('message');
|
|
||||||
|
|
||||||
const { name, config, implementation, version } = message;
|
|
||||||
|
|
||||||
resolve(new Node(socket, name, config, implementation, version));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
socket.on('message', handler);
|
|
||||||
|
|
||||||
// TODO: timeout
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// received: {"msg":"block.import","level":"INFO","ts":"2018-06-18T17:30:35.285406538+02:00","best":"3d4fdc7960078ddc9be87dddc48324a6d64afdf1f65fffe89529ce9965cd5f29","height":526}
|
|
||||||
// received: {"msg":"node.start","level":"INFO","ts":"2018-06-18T17:30:40.038731057+02:00","best":"3d4fdc7960078ddc9be87dddc48324a6d64afdf1f65fffe89529ce9965cd5f29","height":526}
|
|
||||||
// received: {"msg":"system.connected","level":"INFO","ts":"2018-06-18T17:30:40.038975471+02:00","chain":"dev","config":"","version":"0.2.0","implementation":"parity-polkadot","name":"Majestic Widget"}
|
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
export type Maybe<T> = T | null | undefined;
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
import { Data } from 'ws';
|
||||||
|
import { Maybe } from './maybe';
|
||||||
|
|
||||||
|
export function parseMessage(data: Data): Maybe<Message> {
|
||||||
|
try {
|
||||||
|
const message = JSON.parse(data.toString());
|
||||||
|
|
||||||
|
if (message && typeof message.msg === 'string') {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
} catch (_) {
|
||||||
|
console.warn('Error parsing message JSON');
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getBestBlock(message: Message): Maybe<BestBlock> {
|
||||||
|
switch (message.msg) {
|
||||||
|
case 'node.start':
|
||||||
|
case 'system.interval':
|
||||||
|
case 'block.import':
|
||||||
|
return message;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MessageBase {
|
||||||
|
ts: string, // Timestamp
|
||||||
|
level: 'INFO' | 'WARN',
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BestBlock {
|
||||||
|
best: string,
|
||||||
|
height: number,
|
||||||
|
ts: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SystemConnected {
|
||||||
|
msg: 'system.connected',
|
||||||
|
name: string,
|
||||||
|
chain: string,
|
||||||
|
config: string,
|
||||||
|
implementation: string,
|
||||||
|
version: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SystemInterval extends BestBlock {
|
||||||
|
msg: 'system.interval',
|
||||||
|
txcount: number,
|
||||||
|
peers: number,
|
||||||
|
status: 'Idle' | string, // TODO: 'Idle' | ...?
|
||||||
|
}
|
||||||
|
|
||||||
|
interface NodeStart extends BestBlock {
|
||||||
|
msg: 'node.start',
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BlockImport extends BestBlock {
|
||||||
|
msg: 'block.import',
|
||||||
|
}
|
||||||
|
|
||||||
|
// Union type
|
||||||
|
export type Message = MessageBase & (
|
||||||
|
SystemConnected |
|
||||||
|
SystemInterval |
|
||||||
|
NodeStart |
|
||||||
|
BlockImport
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// received: {"msg":"block.import","level":"INFO","ts":"2018-06-18T17:30:35.285406538+02:00","best":"3d4fdc7960078ddc9be87dddc48324a6d64afdf1f65fffe89529ce9965cd5f29","height":526}
|
||||||
|
// received: {"msg":"node.start","level":"INFO","ts":"2018-06-18T17:30:40.038731057+02:00","best":"3d4fdc7960078ddc9be87dddc48324a6d64afdf1f65fffe89529ce9965cd5f29","height":526}
|
||||||
|
// received: {"msg":"system.connected","level":"INFO","ts":"2018-06-18T17:30:40.038975471+02:00","chain":"dev","config":"","version":"0.2.0","implementation":"parity-polkadot","name":"Majestic Widget"}
|
||||||
|
// received: {"msg":"system.interval","level":"INFO","ts":"2018-06-19T14:00:05.091355364+02:00","txcount":0,"best":"360c9563857308703398f637932b7ffe884e5c7b09692600ff09a4d753c9d948","height":7559,"peers":0,"status":"Idle"}
|
||||||
+78
@@ -0,0 +1,78 @@
|
|||||||
|
import * as WebSocket from 'ws';
|
||||||
|
import { parseMessage, getBestBlock, Message, BestBlock } from './message';
|
||||||
|
|
||||||
|
export default class Node {
|
||||||
|
private socket: WebSocket;
|
||||||
|
private name: string;
|
||||||
|
private config: string;
|
||||||
|
private implementation: string;
|
||||||
|
private version: string;
|
||||||
|
private height: number = 0;
|
||||||
|
|
||||||
|
constructor(socket: WebSocket, name: string, config: string, implentation: string, version: string) {
|
||||||
|
this.socket = socket;
|
||||||
|
this.name = name;
|
||||||
|
this.config = config;
|
||||||
|
this.implementation = implentation;
|
||||||
|
this.version = version;
|
||||||
|
|
||||||
|
console.log(`Listening to a new node: ${name}`);
|
||||||
|
|
||||||
|
socket.on('message', (data: WebSocket.Data) => {
|
||||||
|
const message = parseMessage(data);
|
||||||
|
|
||||||
|
if (!message) return;
|
||||||
|
|
||||||
|
// console.log('received', message);
|
||||||
|
|
||||||
|
const update = getBestBlock(message);
|
||||||
|
|
||||||
|
if (update) {
|
||||||
|
this.updateBestBlock(update);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
updateBestBlock(update: BestBlock) {
|
||||||
|
if (this.height < update.height) {
|
||||||
|
this.height = update.height;
|
||||||
|
|
||||||
|
console.log(`Best block for ${this.name} is ${this.height}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static fromSocket(socket: WebSocket): Promise<Node> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
function cleanup() {
|
||||||
|
clearTimeout(timeout);
|
||||||
|
socket.removeEventListener('message');
|
||||||
|
}
|
||||||
|
|
||||||
|
function handler(data: WebSocket.Data) {
|
||||||
|
const message = parseMessage(data);
|
||||||
|
|
||||||
|
if (!message) {
|
||||||
|
cleanup();
|
||||||
|
|
||||||
|
return reject(new Error('Invalid message'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (message.msg === "system.connected") {
|
||||||
|
cleanup();
|
||||||
|
|
||||||
|
const { name, config, implementation, version } = message;
|
||||||
|
|
||||||
|
resolve(new Node(socket, name, config, implementation, version));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.on('message', handler);
|
||||||
|
|
||||||
|
const timeout = setTimeout(() => {
|
||||||
|
cleanup();
|
||||||
|
|
||||||
|
return reject(new Error('Timeout on waiting for system.connected message'));
|
||||||
|
}, 5000);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
-2
@@ -1,9 +1,17 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "es6",
|
"target": "es2017",
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"outDir": "dist",
|
"outDir": "dist",
|
||||||
"sourceMap": true
|
"strictNullChecks": true,
|
||||||
|
"sourceMap": true,
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"noEmitOnError": false,
|
||||||
|
// "noUnusedLocals": true,
|
||||||
|
// "noUnusedParameters": true,
|
||||||
|
"pretty": true,
|
||||||
|
"noErrorTruncation": true,
|
||||||
|
"noImplicitAny": true
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"./node_modules/@types/node/index.d.ts",
|
"./node_modules/@types/node/index.d.ts",
|
||||||
|
|||||||
Reference in New Issue
Block a user