| |
| |
| |
| |
| |
| |
| |
| |
| 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'); |
| 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(); |