UNPKG

envio

Version:

A latency and sync speed optimized, developer friendly blockchain data indexer.

113 lines (109 loc) 3.43 kB
// 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 */