Back to OScope
oscope/tools/firehose.mjs
Code
39 lines (35 loc) · 1.95 KB
// The firehose on its own: one connection to the stream, passed on to as many local readers as you like.
// OScope itself already does this at ws://localhost:3000/firehose; use this when you want the stream without the page.
//
// npm run firehose -> ws://127.0.0.1:3100
// readers may add ?pools=pump,pump-amm to get only those pools
//
// Settings: FEED_URL (the stream), FIREHOSE_PORT (3100), FIREHOSE_HOST (127.0.0.1).
// Point OScope at it with FEED_URL=ws://127.0.0.1:3100 to run several things on one stream connection.
import { WebSocketServer } from 'ws';
import { config } from '../src/config.mjs';
import { connectFeed } from '../src/feed.mjs';
const port = Number(process.env.FIREHOSE_PORT) || 3100;
const host = process.env.FIREHOSE_HOST || '127.0.0.1';
const readers = new Set();
let n = 0;
const wss = new WebSocketServer({ port, host, maxPayload: 4096, perMessageDeflate: false });
wss.on('connection', (ws, req) => {
if (req.headers.origin) return ws.close(1008, 'tools only'); // web pages you visit cannot read it
const pools = new URL(req.url, 'http://x').searchParams.get('pools');
const r = { ws, pools: pools ? new Set(pools.split(',')) : null };
readers.add(r);
ws.on('close', () => readers.delete(r));
});
wss.on('listening', () => console.log(`\n Firehose on ws://${host}:${port}\n Stream ${config.feedUrl}\n`));
wss.on('error', e => { console.error(e.code === 'EADDRINUSE' ? `Port ${port} is in use: FIREHOSE_PORT=${port + 1} npm run firehose` : e.message); process.exit(1); });
connectFeed(config.feedUrl, (f, raw) => {
n++;
let text = raw;
for (const r of readers) {
if (r.pools && !r.pools.has(f.pool)) continue;
if (r.ws.bufferedAmount > 8e6) { r.ws.terminate(); continue; }
r.ws.send(text ??= JSON.stringify(f));
}
});
setInterval(() => { console.log(`${new Date().toTimeString().slice(0, 8)} ${n.toLocaleString('en-US')} messages in the last 30 s, ${readers.size} reader(s)`); n = 0; }, 30000).unref();