import { argv } from 'yargs'; import { pack, unpack } from 'msgpackr'; import { Reply } from 'zeromq'; import { renderGaugeImage } from '../../libs/gauge-renderer'; interface Params { method: string; args: any[]; kwargs: Record; } const unsafeMethods = ['bind', 'constructor', 'toString', 'toJSON']; class GaugeServer { private socket: Reply; async bind(port?: string) { this.socket = new Reply(); await this.socket.bind(port); console.log(`gauge server listening at ${port}`); try { for await (const [data] of this.socket) { const { method, args, kwargs } = (unpack(data) as Params) ?? {}; console.log(`request: ${method}`); if (!unsafeMethods.includes(method) && this[method]) { try { const data = await this[method]?.(args, kwargs); console.log(`success: ${method}`); await this.socket.send( pack({ code: 0, msg: 'success', data, }) ); } catch (err) { console.error(`fail: ${method}, error: ${err}`); await this.socket.send( pack({ code: -1, msg: `Error: ${JSON.stringify(err)}`, data: null, }) ); } } else { console.error(`fail: ${method}, error: no method`); await this.socket.send( pack({ code: -1, msg: `no method: ${method}`, data: null, }) ); } } } catch (err) { console.log('restarting gauge server..', err.stack); await this.socket.close(); await this.bind(port); } } async predict(args?: any[], kwargs?: Record) { let source, gauge, baseY; if (args) { [source, gauge, baseY] = args; } if (kwargs) { ({ source, gauge, baseY } = kwargs); } return renderGaugeImage(source, gauge, baseY); } } async function main() { const server = new GaugeServer(); await server.bind(`tcp://*:${argv.port}`); } main();