envio
Version:
A latency and sync speed optimized, developer friendly blockchain data indexer.
113 lines (104 loc) • 3.26 kB
JavaScript
// Generated by ReScript, PLEASE EDIT WITH CARE
import * as Utils from "./Utils.res.mjs";
import * as JsSdsl from "js-sdsl";
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
let LoaderTimeout = /* @__PURE__ */Primitive_exceptions.create("LazyLoader.LoaderTimeout");
function make(loaderFn, onError, cacheSizeOpt, loaderPoolSizeOpt, retryDelayMillisOpt, timeoutMillisOpt) {
let cacheSize = cacheSizeOpt !== undefined ? cacheSizeOpt : 10000;
let loaderPoolSize = loaderPoolSizeOpt !== undefined ? loaderPoolSizeOpt : 10;
let retryDelayMillis = retryDelayMillisOpt !== undefined ? retryDelayMillisOpt : 5000;
let timeoutMillis = timeoutMillisOpt !== undefined ? timeoutMillisOpt : 300000;
return {
_cacheSize: cacheSize,
_loaderPoolSize: loaderPoolSize,
_retryDelayMillis: retryDelayMillis,
_timeoutMillis: timeoutMillis,
externalPromises: new Map(),
resolvers: new Map(),
inProgress: new Set(),
loaderQueue: new JsSdsl.Queue(),
loadedKeys: new JsSdsl.Queue(),
loaderFn: loaderFn,
onError: onError
};
}
function deleteKey(_obj, _k) {
((delete _obj[_k]));
}
function timeoutAfter(timeoutMillis) {
return Utils.delay(timeoutMillis).then(() => Promise.reject({
RE_EXN_ID: LoaderTimeout,
_1: `Query took longer than ` + (timeoutMillis / 1000 | 0).toString() + ` seconds`
}));
}
async function loadNext(am, k) {
am.inProgress.add(k);
let awaitTaskPromiseAndLoadNextWithTimeout = async () => {
let val = await Promise.race([
am.loaderFn(k),
timeoutAfter(am._timeoutMillis)
]);
Stdlib_Option.forEach(am.resolvers.get(k), r => {
am.resolvers.delete(k);
r(val);
});
am.inProgress.delete(k);
let loadedKeysNumber = am.loadedKeys.push(k);
if (loadedKeysNumber > am._cacheSize) {
let old = am.loadedKeys.pop();
if (old !== undefined) {
am.externalPromises.delete(Primitive_option.valFromOption(old));
}
}
let next = am.loaderQueue.pop();
if (next !== undefined) {
return await loadNext(am, Primitive_option.valFromOption(next));
}
};
let tmp;
let exit = 0;
let val;
try {
val = await awaitTaskPromiseAndLoadNextWithTimeout();
exit = 1;
} catch (raw_err) {
let err = Primitive_exceptions.internalToException(raw_err);
let onError = am.onError;
if (onError !== undefined) {
onError(am, err);
}
await Utils.delay(am._retryDelayMillis);
tmp = awaitTaskPromiseAndLoadNextWithTimeout();
}
if (exit === 1) {
tmp = Promise.resolve();
}
return await tmp;
}
function get(am, k) {
let x = am.externalPromises.get(k);
if (x !== undefined) {
return x;
}
let promise = new Promise((resolve, param) => {
am.resolvers.set(k, resolve);
});
am.externalPromises.set(k, promise);
if (am.inProgress.size < am._loaderPoolSize) {
loadNext(am, k);
} else {
am.loaderQueue.push(k);
}
return promise;
}
export {
LoaderTimeout,
make,
deleteKey,
timeoutAfter,
loadNext,
get,
}
/* Utils Not a pure module */