eth-json-rpc-middleware
Version:
Ethereum-related json-rpc-engine middleware.
84 lines • 3.54 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createInflightCacheMiddleware = void 0;
const clone_1 = __importDefault(require("clone"));
const json_rpc_engine_1 = require("json-rpc-engine");
const logging_utils_1 = require("./logging-utils");
const cache_1 = require("./utils/cache");
const log = logging_utils_1.createModuleLogger(logging_utils_1.projectLogger, 'inflight-cache');
function createInflightCacheMiddleware() {
const inflightRequests = {};
return json_rpc_engine_1.createAsyncMiddleware(async (req, res, next) => {
// allow cach to be skipped if so specified
if (req.skipCache) {
return next();
}
// get cacheId, if cacheable
const cacheId = cache_1.cacheIdentifierForPayload(req);
// if not cacheable, skip
if (!cacheId) {
log('Request is not cacheable, proceeding. req = %o', req);
return next();
}
// check for matching requests
let activeRequestHandlers = inflightRequests[cacheId];
// if found, wait for the active request to be handled
if (activeRequestHandlers) {
// setup the response listener and wait for it to be called
// it will handle copying the result and request fields
log('Running %i handler(s) for request %o', activeRequestHandlers.length, req);
await createActiveRequestHandler(res, activeRequestHandlers);
return undefined;
}
// setup response handler array for subsequent requests
activeRequestHandlers = [];
inflightRequests[cacheId] = activeRequestHandlers;
// allow request to be handled normally
log('Carrying original request forward %o', req);
// eslint-disable-next-line node/callback-return
await next();
// clear inflight requests
delete inflightRequests[cacheId];
// schedule activeRequestHandlers to be handled
log('Running %i collected handler(s) for request %o', activeRequestHandlers.length, req);
handleActiveRequest(res, activeRequestHandlers);
// complete
return undefined;
});
function createActiveRequestHandler(res, activeRequestHandlers) {
const { resolve, promise } = deferredPromise();
activeRequestHandlers.push((handledRes) => {
// append a copy of the result and error to the response
res.result = clone_1.default(handledRes.result);
res.error = clone_1.default(handledRes.error);
resolve();
});
return promise;
}
function handleActiveRequest(res, activeRequestHandlers) {
// use setTimeout so we can resolve our original request first
setTimeout(() => {
activeRequestHandlers.forEach((handler) => {
try {
handler(res);
}
catch (err) {
// catch error so all requests are handled correctly
console.error(err);
}
});
});
}
}
exports.createInflightCacheMiddleware = createInflightCacheMiddleware;
function deferredPromise() {
let resolve;
const promise = new Promise((_resolve) => {
resolve = _resolve;
});
return { resolve, promise };
}
//# sourceMappingURL=inflight-cache.js.map
;