envio
Version:
A latency and sync speed optimized, developer friendly blockchain data indexer.
113 lines (109 loc) • 3.43 kB
JavaScript
// Generated by ReScript, PLEASE EDIT WITH CARE
import * as Utils from "../Utils.res.mjs";
import * as Logging from "../Logging.res.mjs";
import * as Prometheus from "../Prometheus.res.mjs";
import * as Stdlib_Int from "@rescript/runtime/lib/es6/Stdlib_Int.js";
import * as Eventsource from "eventsource";
import * as Primitive_int from "@rescript/runtime/lib/es6/Primitive_int.js";
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
function subscribe(hyperSyncUrl, apiToken, chainId, onHeight) {
let eventsourceRef = {
contents: undefined
};
let errorCount = {
contents: 0
};
let timeoutIdRef = {
contents: setTimeout(() => {}, 0)
};
let updateTimeoutId = () => {
clearTimeout(timeoutIdRef.contents);
let newTimeoutId = setTimeout(() => {
Logging.trace({
msg: "Timeout fired for height stream",
chainId: chainId,
url: hyperSyncUrl,
staleTimeMillis: 15000
});
refreshEventSource();
}, 15000);
timeoutIdRef.contents = newTimeoutId;
};
let scheduleReconnect = () => {
clearTimeout(timeoutIdRef.contents);
let delay = 50 * (Math.pow(2.0, errorCount.contents) | 0) | 0;
timeoutIdRef.contents = setTimeout(() => refreshEventSource(), Primitive_int.min(delay, 60000));
};
let refreshEventSource = () => {
let es = eventsourceRef.contents;
if (es !== undefined) {
Primitive_option.valFromOption(es).close();
}
let userAgent = `hyperindex/` + Utils.EnvioPackage.value.version;
let es$1 = new Eventsource.EventSource(hyperSyncUrl + `/height/sse`, {
fetch: (url, args) => {
let newrecord = {...args};
return fetch(url, (newrecord.headers = Object.fromEntries([
[
"Authorization",
`Bearer ` + apiToken
],
[
"User-Agent",
userAgent
]
]), newrecord));
}
});
eventsourceRef.contents = Primitive_option.some(es$1);
updateTimeoutId();
es$1.onopen = () => {
errorCount.contents = 0;
Logging.trace({
msg: "SSE connection opened for height stream",
chainId: chainId,
url: hyperSyncUrl
});
};
es$1.onerror = error => {
errorCount.contents = errorCount.contents + 1 | 0;
Logging.trace({
msg: "EventSource error on height stream, reconnecting",
chainId: chainId,
url: hyperSyncUrl,
status: error.status,
error: error.message,
errorCount: errorCount.contents
});
scheduleReconnect();
};
es$1.addEventListener("ping", _event => updateTimeoutId());
es$1.addEventListener("height", event => {
let height = Stdlib_Int.fromString(event.data, undefined);
if (height !== undefined) {
Prometheus.SourceRequestCount.increment("HyperSync", chainId, "heightStream");
updateTimeoutId();
return onHeight(height);
} else {
return Logging.trace({
msg: "Height was not a number in event.data",
chainId: chainId,
data: event.data
});
}
});
};
refreshEventSource();
return () => {
clearTimeout(timeoutIdRef.contents);
let es = eventsourceRef.contents;
if (es !== undefined) {
Primitive_option.valFromOption(es).close();
return;
}
};
}
export {
subscribe,
}
/* Utils Not a pure module */