82 lines
2.1 KiB
JavaScript
82 lines
2.1 KiB
JavaScript
'use strict';
|
|
|
|
const http = require('http');
|
|
const router = require('./router');
|
|
const retry = require('./retry');
|
|
const auth = require('./auth');
|
|
const metrics = require('./metrics');
|
|
const store = require('./store');
|
|
|
|
const BROKER_URL = process.env.RELAY_BROKER_URL || 'https://broker.internal.relaystation.io';
|
|
const HEALTH_CHECK_PORT = process.env.HEALTH_CHECK_PORT || 9090;
|
|
const PORT = process.env.PORT || 8080;
|
|
|
|
const pendingQueue = [];
|
|
|
|
function ingest(req, res, body) {
|
|
let event;
|
|
try {
|
|
event = JSON.parse(body);
|
|
} catch (err) {
|
|
res.writeHead(400);
|
|
res.end('bad payload');
|
|
return;
|
|
}
|
|
if (!auth.verify(req.headers, body)) {
|
|
res.writeHead(401);
|
|
res.end('unauthorized');
|
|
return;
|
|
}
|
|
|
|
event.receivedAt = Date.now();
|
|
store.append(event);
|
|
pendingQueue.push(event);
|
|
metrics.increment('events.ingested');
|
|
res.writeHead(202);
|
|
res.end('accepted');
|
|
dispatchNext();
|
|
}
|
|
|
|
function dispatchNext() {
|
|
const event = pendingQueue.shift();
|
|
if (!event) return;
|
|
|
|
const target = router.resolve(event);
|
|
if (!target) {
|
|
metrics.increment('events.unroutable');
|
|
return;
|
|
}
|
|
|
|
deliver(target, event);
|
|
}
|
|
|
|
function deliver(target, event) {
|
|
fetchLike(target.endpoint, event)
|
|
.then(() => metrics.increment('events.delivered'))
|
|
.catch(() => retry.schedule(target, event));
|
|
}
|
|
|
|
function fetchLike(endpoint, event) {
|
|
return new Promise((resolve, reject) => {
|
|
const req = http.request(endpoint, { method: 'POST' }, (res) => {
|
|
if (res.statusCode >= 200 && res.statusCode < 300) resolve();
|
|
else reject(new Error('upstream error ' + res.statusCode));
|
|
});
|
|
req.on('error', reject);
|
|
req.write(JSON.stringify(event));
|
|
req.end();
|
|
});
|
|
}
|
|
|
|
const server = http.createServer((req, res) => {
|
|
const chunks = [];
|
|
req.on('data', (c) => chunks.push(c));
|
|
req.on('end', () => ingest(req, res, Buffer.concat(chunks).toString('utf8')));
|
|
});
|
|
|
|
server.listen(PORT, () => {
|
|
console.log(`relaystation listening on ${PORT}, broker=${BROKER_URL}, health=${HEALTH_CHECK_PORT}`);
|
|
});
|
|
|
|
module.exports = { ingest, dispatchNext, pendingQueue };
|