tardis-machine
Version:
Locally runnable server with built-in data caching, providing both tick-level historical and consolidated real-time cryptocurrency market data via HTTP and WebSocket APIs
76 lines • 3.43 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.replayHttp = void 0;
const events_1 = require("events");
const tardis_dev_1 = require("tardis-dev");
const url_1 = __importDefault(require("url"));
const debug_1 = require("../debug");
const replayHttp = async (req, res) => {
try {
const startTimestamp = new Date().getTime();
const parsedQuery = url_1.default.parse(req.url, true).query;
const optionsString = parsedQuery['options'];
const replayOptions = JSON.parse(optionsString);
(0, debug_1.debug)('GET /replay request started, options: %o', replayOptions);
const streamedMessagesCount = await writeMessagesToResponse(res, replayOptions);
const endTimestamp = new Date().getTime();
(0, debug_1.debug)('GET /replay request finished, options: %o, time: %d seconds, total messages count:%d', replayOptions, (endTimestamp - startTimestamp) / 1000, streamedMessagesCount);
}
catch (e) {
const errorInfo = {
responseText: e.responseText,
message: e.message,
url: e.url
};
(0, debug_1.debug)('GET /replay request error: %o', e);
console.error('GET /replay request error:', e);
if (!res.finished) {
res.statusCode = e.status || 500;
res.end(JSON.stringify(errorInfo));
}
}
};
exports.replayHttp = replayHttp;
async function writeMessagesToResponse(res, replayOptions) {
const responsePrefixBuffer = Buffer.from('{"localTimestamp":"');
const responseMiddleBuffer = Buffer.from('","message":');
const responseSuffixBuffer = Buffer.from('}\n');
const newLineBuffer = Buffer.from('\n');
const BATCH_SIZE = 32;
// not 100% sure that's necessary since we're returning ndjson in fact, not json
res.setHeader('Content-Type', 'application/x-json-stream');
let buffers = [];
let totalMessagesCount = 0;
const messages = (0, tardis_dev_1.replay)({ ...replayOptions, skipDecoding: true });
for await (let messageWithTimestamp of messages) {
totalMessagesCount++;
if (messageWithTimestamp === undefined) {
// if received message is undefined (disconnect)
// return it as new line
buffers.push(newLineBuffer);
}
else {
// instead of writing each message directly to response,
// let's batch them and send in BATCH_SIZE batches (each message is 5 buffers: prefix etc)
// also instead of converting messages to string or parsing them let's manually stich together desired json response using buffers which is faster
buffers.push(responsePrefixBuffer, messageWithTimestamp.localTimestamp, responseMiddleBuffer, messageWithTimestamp.message, responseSuffixBuffer);
if (buffers.length >= BATCH_SIZE * 5) {
const ok = res.write(Buffer.concat(buffers));
buffers = [];
if (!ok) {
await (0, events_1.once)(res, 'drain');
}
}
}
}
if (buffers.length > 0) {
res.write(Buffer.concat(buffers));
buffers = [];
}
res.end('');
return totalMessagesCount;
}
//# sourceMappingURL=replay.js.map