envio 2.22.0 → 2.22.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +7 -6
- package/src/Address.res.js +30 -0
- package/src/ChainMap.res.js +77 -0
- package/src/Envio.res.js +16 -0
- package/src/ErrorHandling.res.js +56 -0
- package/src/EventUtils.res.js +75 -0
- package/src/EvmTypes.res.js +16 -0
- package/src/FetchState.res.js +969 -0
- package/src/Hasura.res.js +245 -0
- package/src/Internal.res.js +50 -0
- package/src/LazyLoader.res.js +117 -0
- package/src/LoadManager.res.js +124 -0
- package/src/LogSelection.res.js +203 -0
- package/src/Logging.res.js +247 -0
- package/src/Persistence.res.js +90 -0
- package/src/PgStorage.res +18 -4
- package/src/PgStorage.res.js +125 -0
- package/src/Prometheus.res.js +750 -0
- package/src/ReorgDetection.res.js +223 -0
- package/src/Throttler.res.js +60 -0
- package/src/Time.res.js +41 -0
- package/src/TopicFilter.res.js +86 -0
- package/src/Utils.res.js +527 -0
- package/src/bindings/BigDecimal.res.js +41 -0
- package/src/bindings/BigInt.res.js +138 -0
- package/src/bindings/Ethers.res.js +109 -0
- package/src/bindings/Express.res.js +2 -0
- package/src/bindings/Hrtime.res.js +66 -0
- package/src/bindings/NodeJs.res.js +29 -0
- package/src/bindings/Pino.res.js +95 -0
- package/src/bindings/Postgres.res.js +16 -0
- package/src/bindings/PromClient.res.js +17 -0
- package/src/bindings/Promise.res.js +25 -0
- package/src/bindings/SDSL.res.js +8 -0
- package/src/bindings/Viem.res.js +45 -0
- package/src/db/EntityHistory.res.js +307 -0
- package/src/db/Schema.res.js +54 -0
- package/src/db/Table.res.js +365 -0
- package/src/sources/Fuel.res.js +28 -0
- package/src/sources/HyperFuel.res.js +193 -0
- package/src/sources/HyperFuelClient.res.js +19 -0
- package/src/sources/HyperSync.res.js +301 -0
- package/src/sources/HyperSyncClient.res.js +99 -0
- package/src/sources/HyperSyncJsonApi.res.js +259 -0
- package/src/sources/Rpc.res.js +198 -0
- package/src/sources/Source.res.js +9 -0
- package/src/sources/SourceManager.res.js +366 -0
- package/src/vendored/Rest.res.js +574 -0
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var Viem = require("viem");
|
|
5
|
+
var Utils = require("../Utils.res.js");
|
|
6
|
+
var $$BigInt = require("../bindings/BigInt.res.js");
|
|
7
|
+
var Address = require("../Address.res.js");
|
|
8
|
+
var Belt_Array = require("rescript/lib/js/belt_Array.js");
|
|
9
|
+
var Caml_option = require("rescript/lib/js/caml_option.js");
|
|
10
|
+
var S$RescriptSchema = require("rescript-schema/src/S.res.js");
|
|
11
|
+
|
|
12
|
+
function makeRpcRoute(method, paramsSchema, resultSchema) {
|
|
13
|
+
var idSchema = S$RescriptSchema.literal(1);
|
|
14
|
+
var versionSchema = S$RescriptSchema.literal("2.0");
|
|
15
|
+
return function () {
|
|
16
|
+
return {
|
|
17
|
+
method: "POST",
|
|
18
|
+
path: "",
|
|
19
|
+
input: (function (s) {
|
|
20
|
+
s.field("method", S$RescriptSchema.literal(method));
|
|
21
|
+
s.field("id", idSchema);
|
|
22
|
+
s.field("jsonrpc", versionSchema);
|
|
23
|
+
return s.field("params", paramsSchema);
|
|
24
|
+
}),
|
|
25
|
+
responses: [(function (s) {
|
|
26
|
+
s.field("jsonrpc", versionSchema);
|
|
27
|
+
s.field("id", idSchema);
|
|
28
|
+
return s.field("result", resultSchema);
|
|
29
|
+
})]
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function makeHexSchema(fromStr) {
|
|
35
|
+
return S$RescriptSchema.transform(S$RescriptSchema.string, (function (s) {
|
|
36
|
+
return {
|
|
37
|
+
p: (function (str) {
|
|
38
|
+
var v = fromStr(str);
|
|
39
|
+
if (v !== undefined) {
|
|
40
|
+
return Caml_option.valFromOption(v);
|
|
41
|
+
} else {
|
|
42
|
+
return s.fail("The string is not valid hex", undefined);
|
|
43
|
+
}
|
|
44
|
+
}),
|
|
45
|
+
s: (function (value) {
|
|
46
|
+
return Viem.toHex(value);
|
|
47
|
+
})
|
|
48
|
+
};
|
|
49
|
+
}));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
var hexBigintSchema = makeHexSchema($$BigInt.fromString);
|
|
53
|
+
|
|
54
|
+
var hexIntSchema = makeHexSchema(function (v) {
|
|
55
|
+
return Number(v);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
var topicFilterSchema = S$RescriptSchema.union([
|
|
59
|
+
S$RescriptSchema.literal(null),
|
|
60
|
+
S$RescriptSchema.schema(function (s) {
|
|
61
|
+
return s.m(S$RescriptSchema.array(S$RescriptSchema.string));
|
|
62
|
+
}),
|
|
63
|
+
S$RescriptSchema.schema(function (s) {
|
|
64
|
+
return s.m(S$RescriptSchema.string);
|
|
65
|
+
})
|
|
66
|
+
]);
|
|
67
|
+
|
|
68
|
+
var topicQuerySchema = S$RescriptSchema.array(topicFilterSchema);
|
|
69
|
+
|
|
70
|
+
function makeTopicQuery(topic0Opt, topic1Opt, topic2Opt, topic3Opt) {
|
|
71
|
+
var topic0 = topic0Opt !== undefined ? topic0Opt : [];
|
|
72
|
+
var topic1 = topic1Opt !== undefined ? topic1Opt : [];
|
|
73
|
+
var topic2 = topic2Opt !== undefined ? topic2Opt : [];
|
|
74
|
+
var topic3 = topic3Opt !== undefined ? topic3Opt : [];
|
|
75
|
+
var topics = [
|
|
76
|
+
topic0,
|
|
77
|
+
topic1,
|
|
78
|
+
topic2,
|
|
79
|
+
topic3
|
|
80
|
+
];
|
|
81
|
+
var isLastTopicEmpty = function () {
|
|
82
|
+
var match = Utils.$$Array.last(topics);
|
|
83
|
+
if (match !== undefined) {
|
|
84
|
+
return match.length === 0;
|
|
85
|
+
} else {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
while(isLastTopicEmpty()) {
|
|
90
|
+
topics.pop();
|
|
91
|
+
};
|
|
92
|
+
var toTopicFilter = function (topic) {
|
|
93
|
+
var len = topic.length;
|
|
94
|
+
if (len !== 1) {
|
|
95
|
+
if (len !== 0) {
|
|
96
|
+
return topic;
|
|
97
|
+
} else {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
var single = topic[0];
|
|
102
|
+
return single;
|
|
103
|
+
};
|
|
104
|
+
return Belt_Array.map(topics, toTopicFilter);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function mapTopicQuery(param) {
|
|
108
|
+
return makeTopicQuery(param.topic0, param.topic1, param.topic2, param.topic3);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
var paramsSchema = S$RescriptSchema.object(function (s) {
|
|
112
|
+
return {
|
|
113
|
+
fromBlock: s.f("fromBlock", hexIntSchema),
|
|
114
|
+
toBlock: s.f("toBlock", hexIntSchema),
|
|
115
|
+
address: s.f("address", S$RescriptSchema.array(Address.schema)),
|
|
116
|
+
topics: s.f("topics", topicQuerySchema)
|
|
117
|
+
};
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
var logSchema = S$RescriptSchema.object(function (s) {
|
|
121
|
+
return {
|
|
122
|
+
address: s.f("address", Address.schema),
|
|
123
|
+
topics: s.f("topics", S$RescriptSchema.array(S$RescriptSchema.string)),
|
|
124
|
+
data: s.f("data", S$RescriptSchema.string),
|
|
125
|
+
blockNumber: s.f("blockNumber", hexIntSchema),
|
|
126
|
+
transactionHash: s.f("transactionHash", S$RescriptSchema.string),
|
|
127
|
+
transactionIndex: s.f("transactionIndex", hexIntSchema),
|
|
128
|
+
blockHash: s.f("blockHash", S$RescriptSchema.string),
|
|
129
|
+
logIndex: s.f("logIndex", hexIntSchema),
|
|
130
|
+
removed: s.f("removed", S$RescriptSchema.bool)
|
|
131
|
+
};
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
var route = makeRpcRoute("eth_getLogs", S$RescriptSchema.tuple1(paramsSchema), S$RescriptSchema.array(logSchema));
|
|
135
|
+
|
|
136
|
+
var GetLogs = {
|
|
137
|
+
topicFilterSchema: topicFilterSchema,
|
|
138
|
+
topicQuerySchema: topicQuerySchema,
|
|
139
|
+
makeTopicQuery: makeTopicQuery,
|
|
140
|
+
mapTopicQuery: mapTopicQuery,
|
|
141
|
+
paramsSchema: paramsSchema,
|
|
142
|
+
logSchema: logSchema,
|
|
143
|
+
route: route
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
var blockSchema = S$RescriptSchema.object(function (s) {
|
|
147
|
+
return {
|
|
148
|
+
difficulty: s.f("difficulty", S$RescriptSchema.$$null(hexBigintSchema)),
|
|
149
|
+
extraData: s.f("extraData", S$RescriptSchema.string),
|
|
150
|
+
gasLimit: s.f("gasLimit", hexBigintSchema),
|
|
151
|
+
gasUsed: s.f("gasUsed", hexBigintSchema),
|
|
152
|
+
hash: s.f("hash", S$RescriptSchema.string),
|
|
153
|
+
logsBloom: s.f("logsBloom", S$RescriptSchema.string),
|
|
154
|
+
miner: s.f("miner", Address.schema),
|
|
155
|
+
mixHash: s.f("mixHash", S$RescriptSchema.$$null(S$RescriptSchema.string)),
|
|
156
|
+
nonce: s.f("nonce", S$RescriptSchema.$$null(hexBigintSchema)),
|
|
157
|
+
number: s.f("number", hexIntSchema),
|
|
158
|
+
parentHash: s.f("parentHash", S$RescriptSchema.string),
|
|
159
|
+
receiptsRoot: s.f("receiptsRoot", S$RescriptSchema.string),
|
|
160
|
+
sha3Uncles: s.f("sha3Uncles", S$RescriptSchema.string),
|
|
161
|
+
size: s.f("size", hexBigintSchema),
|
|
162
|
+
stateRoot: s.f("stateRoot", S$RescriptSchema.string),
|
|
163
|
+
timestamp: s.f("timestamp", hexIntSchema),
|
|
164
|
+
totalDifficulty: s.f("totalDifficulty", S$RescriptSchema.$$null(hexBigintSchema)),
|
|
165
|
+
transactions: s.f("transactions", S$RescriptSchema.array(S$RescriptSchema.json(false))),
|
|
166
|
+
transactionsRoot: s.f("transactionsRoot", S$RescriptSchema.string),
|
|
167
|
+
uncles: s.f("uncles", S$RescriptSchema.$$null(S$RescriptSchema.array(S$RescriptSchema.string)))
|
|
168
|
+
};
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
var route$1 = makeRpcRoute("eth_getBlockByNumber", S$RescriptSchema.tuple(function (s) {
|
|
172
|
+
return {
|
|
173
|
+
blockNumber: s.item(0, hexIntSchema),
|
|
174
|
+
includeTransactions: s.item(1, S$RescriptSchema.bool)
|
|
175
|
+
};
|
|
176
|
+
}), S$RescriptSchema.$$null(blockSchema));
|
|
177
|
+
|
|
178
|
+
var GetBlockByNumber = {
|
|
179
|
+
blockSchema: blockSchema,
|
|
180
|
+
route: route$1
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
var route$2 = makeRpcRoute("eth_blockNumber", S$RescriptSchema.tuple(function (param) {
|
|
184
|
+
|
|
185
|
+
}), hexIntSchema);
|
|
186
|
+
|
|
187
|
+
var GetBlockHeight = {
|
|
188
|
+
route: route$2
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
exports.makeRpcRoute = makeRpcRoute;
|
|
192
|
+
exports.makeHexSchema = makeHexSchema;
|
|
193
|
+
exports.hexBigintSchema = hexBigintSchema;
|
|
194
|
+
exports.hexIntSchema = hexIntSchema;
|
|
195
|
+
exports.GetLogs = GetLogs;
|
|
196
|
+
exports.GetBlockByNumber = GetBlockByNumber;
|
|
197
|
+
exports.GetBlockHeight = GetBlockHeight;
|
|
198
|
+
/* hexBigintSchema Not a pure module */
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var Caml_exceptions = require("rescript/lib/js/caml_exceptions.js");
|
|
5
|
+
|
|
6
|
+
var GetItemsError = /* @__PURE__ */Caml_exceptions.create("Source.GetItemsError");
|
|
7
|
+
|
|
8
|
+
exports.GetItemsError = GetItemsError;
|
|
9
|
+
/* No side effect */
|
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var Caml = require("rescript/lib/js/caml.js");
|
|
5
|
+
var Utils = require("../Utils.res.js");
|
|
6
|
+
var Hrtime = require("../bindings/Hrtime.res.js");
|
|
7
|
+
var Js_exn = require("rescript/lib/js/js_exn.js");
|
|
8
|
+
var Source = require("./Source.res.js");
|
|
9
|
+
var Logging = require("../Logging.res.js");
|
|
10
|
+
var Internal = require("../Internal.res.js");
|
|
11
|
+
var Belt_Array = require("rescript/lib/js/belt_Array.js");
|
|
12
|
+
var FetchState = require("../FetchState.res.js");
|
|
13
|
+
var Prometheus = require("../Prometheus.res.js");
|
|
14
|
+
var Belt_Option = require("rescript/lib/js/belt_Option.js");
|
|
15
|
+
var ErrorHandling = require("../ErrorHandling.res.js");
|
|
16
|
+
var Caml_js_exceptions = require("rescript/lib/js/caml_js_exceptions.js");
|
|
17
|
+
|
|
18
|
+
function getActiveSource(sourceManager) {
|
|
19
|
+
return sourceManager.activeSource;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function makeGetHeightRetryInterval(initialRetryInterval, backoffMultiplicative, maxRetryInterval) {
|
|
23
|
+
return function (retry) {
|
|
24
|
+
var backoff = retry === 0 ? 1 : Math.imul(retry, backoffMultiplicative);
|
|
25
|
+
return Caml.int_min(Math.imul(initialRetryInterval, backoff), maxRetryInterval);
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function make(sources, maxPartitionConcurrency, newBlockFallbackStallTimeoutOpt, stalledPollingIntervalOpt, getHeightRetryIntervalOpt) {
|
|
30
|
+
var newBlockFallbackStallTimeout = newBlockFallbackStallTimeoutOpt !== undefined ? newBlockFallbackStallTimeoutOpt : 20000;
|
|
31
|
+
var stalledPollingInterval = stalledPollingIntervalOpt !== undefined ? stalledPollingIntervalOpt : 5000;
|
|
32
|
+
var getHeightRetryInterval = getHeightRetryIntervalOpt !== undefined ? getHeightRetryIntervalOpt : makeGetHeightRetryInterval(1000, 2, 60000);
|
|
33
|
+
var source = sources.find(function (source) {
|
|
34
|
+
return source.sourceFor === "Sync";
|
|
35
|
+
});
|
|
36
|
+
var initialActiveSource = source !== undefined ? source : Js_exn.raiseError("Invalid configuration, no data-source for historical sync provided");
|
|
37
|
+
Prometheus.IndexingMaxConcurrency.set(maxPartitionConcurrency, initialActiveSource.chain);
|
|
38
|
+
Prometheus.IndexingConcurrency.set(0, initialActiveSource.chain);
|
|
39
|
+
return {
|
|
40
|
+
sources: new Set(sources),
|
|
41
|
+
statusStart: Hrtime.makeTimer(),
|
|
42
|
+
status: "Idle",
|
|
43
|
+
maxPartitionConcurrency: maxPartitionConcurrency,
|
|
44
|
+
newBlockFallbackStallTimeout: newBlockFallbackStallTimeout,
|
|
45
|
+
stalledPollingInterval: stalledPollingInterval,
|
|
46
|
+
getHeightRetryInterval: getHeightRetryInterval,
|
|
47
|
+
activeSource: initialActiveSource,
|
|
48
|
+
waitingForNewBlockStateId: undefined,
|
|
49
|
+
fetchingPartitionsCount: 0
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function trackNewStatus(sourceManager, newStatus) {
|
|
54
|
+
var promCounter;
|
|
55
|
+
switch (newStatus) {
|
|
56
|
+
case "Idle" :
|
|
57
|
+
promCounter = Prometheus.IndexingIdleTime.counter;
|
|
58
|
+
break;
|
|
59
|
+
case "WaitingForNewBlock" :
|
|
60
|
+
promCounter = Prometheus.IndexingSourceWaitingTime.counter;
|
|
61
|
+
break;
|
|
62
|
+
case "Querieng" :
|
|
63
|
+
promCounter = Prometheus.IndexingQueryTime.counter;
|
|
64
|
+
break;
|
|
65
|
+
|
|
66
|
+
}
|
|
67
|
+
Prometheus.SafeCounter.incrementMany(promCounter, sourceManager.activeSource.chain, Hrtime.intFromMillis(Hrtime.toMillis(Hrtime.timeSince(sourceManager.statusStart))));
|
|
68
|
+
sourceManager.statusStart = Hrtime.makeTimer();
|
|
69
|
+
sourceManager.status = newStatus;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async function fetchNext(sourceManager, fetchState, currentBlockHeight, executeQuery, waitForNewBlock, onNewBlock, targetBufferSize, stateId) {
|
|
73
|
+
var queries = FetchState.getNextQuery(fetchState, sourceManager.maxPartitionConcurrency - sourceManager.fetchingPartitionsCount | 0, targetBufferSize, currentBlockHeight, stateId);
|
|
74
|
+
if (typeof queries !== "object") {
|
|
75
|
+
switch (queries) {
|
|
76
|
+
case "WaitingForNewBlock" :
|
|
77
|
+
var waitingStateId = sourceManager.waitingForNewBlockStateId;
|
|
78
|
+
if (waitingStateId !== undefined && waitingStateId >= stateId) {
|
|
79
|
+
return ;
|
|
80
|
+
}
|
|
81
|
+
trackNewStatus(sourceManager, "WaitingForNewBlock");
|
|
82
|
+
sourceManager.waitingForNewBlockStateId = stateId;
|
|
83
|
+
var currentBlockHeight$1 = await waitForNewBlock(currentBlockHeight);
|
|
84
|
+
var waitingStateId$1 = sourceManager.waitingForNewBlockStateId;
|
|
85
|
+
if (waitingStateId$1 !== undefined && waitingStateId$1 === stateId) {
|
|
86
|
+
trackNewStatus(sourceManager, "Idle");
|
|
87
|
+
sourceManager.waitingForNewBlockStateId = undefined;
|
|
88
|
+
return onNewBlock(currentBlockHeight$1);
|
|
89
|
+
} else {
|
|
90
|
+
return ;
|
|
91
|
+
}
|
|
92
|
+
case "ReachedMaxConcurrency" :
|
|
93
|
+
case "NothingToQuery" :
|
|
94
|
+
return ;
|
|
95
|
+
|
|
96
|
+
}
|
|
97
|
+
} else {
|
|
98
|
+
var queries$1 = queries._0;
|
|
99
|
+
FetchState.startFetchingQueries(fetchState, queries$1, stateId);
|
|
100
|
+
sourceManager.fetchingPartitionsCount = sourceManager.fetchingPartitionsCount + queries$1.length | 0;
|
|
101
|
+
Prometheus.IndexingConcurrency.set(sourceManager.fetchingPartitionsCount, sourceManager.activeSource.chain);
|
|
102
|
+
trackNewStatus(sourceManager, "Querieng");
|
|
103
|
+
await Promise.all(Belt_Array.map(queries$1, (function (q) {
|
|
104
|
+
var promise = executeQuery(q);
|
|
105
|
+
promise.then(function (param) {
|
|
106
|
+
sourceManager.fetchingPartitionsCount = sourceManager.fetchingPartitionsCount - 1 | 0;
|
|
107
|
+
Prometheus.IndexingConcurrency.set(sourceManager.fetchingPartitionsCount, sourceManager.activeSource.chain);
|
|
108
|
+
if (sourceManager.fetchingPartitionsCount === 0) {
|
|
109
|
+
return trackNewStatus(sourceManager, "Idle");
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
});
|
|
113
|
+
return promise;
|
|
114
|
+
})));
|
|
115
|
+
return ;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
async function getSourceNewHeight(sourceManager, source, currentBlockHeight, status, logger) {
|
|
120
|
+
var newHeight = 0;
|
|
121
|
+
var retry = 0;
|
|
122
|
+
while(newHeight <= currentBlockHeight && status.contents !== "Done") {
|
|
123
|
+
try {
|
|
124
|
+
var endTimer = Prometheus.SourceGetHeightDuration.startTimer({
|
|
125
|
+
source: source.name,
|
|
126
|
+
chainId: source.chain
|
|
127
|
+
});
|
|
128
|
+
var height = await source.getHeightOrThrow();
|
|
129
|
+
endTimer();
|
|
130
|
+
newHeight = height;
|
|
131
|
+
if (height <= currentBlockHeight) {
|
|
132
|
+
retry = 0;
|
|
133
|
+
var pollingInterval = status.contents === "Stalled" ? sourceManager.stalledPollingInterval : source.pollingInterval;
|
|
134
|
+
await Utils.delay(pollingInterval);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
}
|
|
138
|
+
catch (raw_exn){
|
|
139
|
+
var exn = Caml_js_exceptions.internalToOCamlException(raw_exn);
|
|
140
|
+
var retryInterval = sourceManager.getHeightRetryInterval(retry);
|
|
141
|
+
Logging.childTrace(logger, {
|
|
142
|
+
msg: "Height retrieval from " + source.name + " source failed. Retrying in " + String(retryInterval) + "ms.",
|
|
143
|
+
source: source.name,
|
|
144
|
+
err: Internal.prettifyExn(exn)
|
|
145
|
+
});
|
|
146
|
+
retry = retry + 1 | 0;
|
|
147
|
+
await Utils.delay(retryInterval);
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
Prometheus.SourceHeight.set(source.name, source.chain, newHeight);
|
|
151
|
+
return newHeight;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
async function waitForNewBlock(sourceManager, currentBlockHeight) {
|
|
155
|
+
var logger = Logging.createChild({
|
|
156
|
+
chainId: sourceManager.activeSource.chain,
|
|
157
|
+
currentBlockHeight: currentBlockHeight
|
|
158
|
+
});
|
|
159
|
+
Logging.childTrace(logger, "Initiating check for new blocks.");
|
|
160
|
+
var syncSources = [];
|
|
161
|
+
var fallbackSources = [];
|
|
162
|
+
sourceManager.sources.forEach(function (source) {
|
|
163
|
+
if (source.sourceFor === "Sync" || source === sourceManager.activeSource) {
|
|
164
|
+
syncSources.push(source);
|
|
165
|
+
} else {
|
|
166
|
+
fallbackSources.push(source);
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
var status = {
|
|
170
|
+
contents: "Active"
|
|
171
|
+
};
|
|
172
|
+
var match = await Promise.race(Belt_Array.concat(Belt_Array.map(syncSources, (async function (source) {
|
|
173
|
+
return [
|
|
174
|
+
source,
|
|
175
|
+
await getSourceNewHeight(sourceManager, source, currentBlockHeight, status, logger)
|
|
176
|
+
];
|
|
177
|
+
})), [Utils.delay(sourceManager.newBlockFallbackStallTimeout).then(function () {
|
|
178
|
+
if (status.contents !== "Done") {
|
|
179
|
+
status.contents = "Stalled";
|
|
180
|
+
if (fallbackSources.length !== 0) {
|
|
181
|
+
Logging.childWarn(logger, "No new blocks detected within " + String(sourceManager.newBlockFallbackStallTimeout / 1000 | 0) + "s. Continuing polling with fallback RPC sources from the configuration.");
|
|
182
|
+
} else {
|
|
183
|
+
Logging.childWarn(logger, "No new blocks detected within " + String(sourceManager.newBlockFallbackStallTimeout / 1000 | 0) + "s. Polling will continue at a reduced rate. For better reliability, refer to our RPC fallback guide: https://docs.envio.dev/docs/HyperIndex/rpc-sync");
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return Promise.race(Belt_Array.map(fallbackSources, (async function (source) {
|
|
187
|
+
return [
|
|
188
|
+
source,
|
|
189
|
+
await getSourceNewHeight(sourceManager, source, currentBlockHeight, status, logger)
|
|
190
|
+
];
|
|
191
|
+
})));
|
|
192
|
+
})]));
|
|
193
|
+
var newBlockHeight = match[1];
|
|
194
|
+
var source = match[0];
|
|
195
|
+
sourceManager.activeSource = source;
|
|
196
|
+
var log = status.contents === "Stalled" ? Logging.childInfo : Logging.childTrace;
|
|
197
|
+
log(logger, {
|
|
198
|
+
msg: "New blocks successfully found.",
|
|
199
|
+
source: source.name,
|
|
200
|
+
newBlockHeight: newBlockHeight
|
|
201
|
+
});
|
|
202
|
+
status.contents = "Done";
|
|
203
|
+
return newBlockHeight;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function getNextSyncSource(sourceManager, initialSource, attemptFallbacksOpt) {
|
|
207
|
+
var attemptFallbacks = attemptFallbacksOpt !== undefined ? attemptFallbacksOpt : false;
|
|
208
|
+
var before = [];
|
|
209
|
+
var after = [];
|
|
210
|
+
var hasActive = {
|
|
211
|
+
contents: false
|
|
212
|
+
};
|
|
213
|
+
sourceManager.sources.forEach(function (source) {
|
|
214
|
+
if (source === sourceManager.activeSource) {
|
|
215
|
+
hasActive.contents = true;
|
|
216
|
+
return ;
|
|
217
|
+
}
|
|
218
|
+
var match = source.sourceFor;
|
|
219
|
+
var tmp;
|
|
220
|
+
tmp = match === "Sync" ? true : attemptFallbacks || source === initialSource;
|
|
221
|
+
if (tmp) {
|
|
222
|
+
(
|
|
223
|
+
hasActive.contents ? after : before
|
|
224
|
+
).push(source);
|
|
225
|
+
return ;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
});
|
|
229
|
+
var s = Belt_Array.get(after, 0);
|
|
230
|
+
if (s !== undefined) {
|
|
231
|
+
return s;
|
|
232
|
+
}
|
|
233
|
+
var s$1 = Belt_Array.get(before, 0);
|
|
234
|
+
if (s$1 !== undefined) {
|
|
235
|
+
return s$1;
|
|
236
|
+
} else {
|
|
237
|
+
return sourceManager.activeSource;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
async function executeQuery(sourceManager, query, currentBlockHeight) {
|
|
242
|
+
var match = query.target;
|
|
243
|
+
var toBlockRef;
|
|
244
|
+
toBlockRef = typeof match !== "object" ? undefined : (
|
|
245
|
+
match.TAG === "EndBlock" ? match.toBlock : match.toBlock
|
|
246
|
+
);
|
|
247
|
+
var responseRef;
|
|
248
|
+
var retryRef = 0;
|
|
249
|
+
var initialSource = sourceManager.activeSource;
|
|
250
|
+
while(Belt_Option.isNone(responseRef)) {
|
|
251
|
+
var source = sourceManager.activeSource;
|
|
252
|
+
var toBlock = toBlockRef;
|
|
253
|
+
var retry = retryRef;
|
|
254
|
+
var logger = Logging.createChild({
|
|
255
|
+
chainId: source.chain,
|
|
256
|
+
logType: "Block Range Query",
|
|
257
|
+
partitionId: query.partitionId,
|
|
258
|
+
source: source.name,
|
|
259
|
+
fromBlock: query.fromBlock,
|
|
260
|
+
toBlock: toBlock,
|
|
261
|
+
addresses: FetchState.addressesByContractNameCount(query.addressesByContractName),
|
|
262
|
+
retry: retry
|
|
263
|
+
});
|
|
264
|
+
try {
|
|
265
|
+
var response = await source.getItemsOrThrow(query.fromBlock, toBlock, query.addressesByContractName, query.indexingContracts, currentBlockHeight, query.partitionId, query.selection, retry, logger);
|
|
266
|
+
Logging.childTrace(logger, {
|
|
267
|
+
msg: "Fetched block range from server",
|
|
268
|
+
toBlock: response.latestFetchedBlockNumber,
|
|
269
|
+
numEvents: response.parsedQueueItems.length,
|
|
270
|
+
stats: response.stats
|
|
271
|
+
});
|
|
272
|
+
responseRef = response;
|
|
273
|
+
}
|
|
274
|
+
catch (raw_error){
|
|
275
|
+
var error = Caml_js_exceptions.internalToOCamlException(raw_error);
|
|
276
|
+
if (error.RE_EXN_ID === Source.GetItemsError) {
|
|
277
|
+
var error$1 = error._1;
|
|
278
|
+
if (error$1.TAG === "FailedGettingItems") {
|
|
279
|
+
var match$1 = error$1.retry;
|
|
280
|
+
var attemptedToBlock = error$1.attemptedToBlock;
|
|
281
|
+
if (match$1.TAG === "WithSuggestedToBlock") {
|
|
282
|
+
var toBlock$1 = match$1.toBlock;
|
|
283
|
+
Logging.childTrace(logger, {
|
|
284
|
+
msg: "Failed getting data for the block range. Immediately retrying with the suggested block range from response.",
|
|
285
|
+
toBlock: attemptedToBlock,
|
|
286
|
+
suggestedToBlock: toBlock$1
|
|
287
|
+
});
|
|
288
|
+
toBlockRef = toBlock$1;
|
|
289
|
+
retryRef = 0;
|
|
290
|
+
} else {
|
|
291
|
+
var backoffMillis = match$1.backoffMillis;
|
|
292
|
+
var attemptFallbacks = retry >= 10;
|
|
293
|
+
var nextSource = !(retry === 0 || retry === 1) && retry % 2 === 0 ? getNextSyncSource(sourceManager, initialSource, attemptFallbacks) : source;
|
|
294
|
+
var log = retry >= 4 ? Logging.childWarn : Logging.childTrace;
|
|
295
|
+
log(logger, {
|
|
296
|
+
msg: match$1.message,
|
|
297
|
+
toBlock: attemptedToBlock,
|
|
298
|
+
backOffMilliseconds: backoffMillis,
|
|
299
|
+
retry: retry,
|
|
300
|
+
err: Internal.prettifyExn(error$1.exn)
|
|
301
|
+
});
|
|
302
|
+
var shouldSwitch = nextSource !== source;
|
|
303
|
+
if (shouldSwitch) {
|
|
304
|
+
Logging.childInfo(logger, {
|
|
305
|
+
msg: "Switching to another data-source",
|
|
306
|
+
source: nextSource.name
|
|
307
|
+
});
|
|
308
|
+
sourceManager.activeSource = nextSource;
|
|
309
|
+
} else {
|
|
310
|
+
await Utils.delay(backoffMillis < 60000 ? backoffMillis : 60000);
|
|
311
|
+
}
|
|
312
|
+
retryRef = retryRef + 1 | 0;
|
|
313
|
+
}
|
|
314
|
+
} else {
|
|
315
|
+
var nextSource$1 = getNextSyncSource(sourceManager, initialSource, undefined);
|
|
316
|
+
var notAlreadyDeleted = sourceManager.sources.delete(source);
|
|
317
|
+
if (notAlreadyDeleted) {
|
|
318
|
+
var exit = 0;
|
|
319
|
+
switch (error$1.TAG) {
|
|
320
|
+
case "UnsupportedSelection" :
|
|
321
|
+
Logging.childError(logger, error$1.message);
|
|
322
|
+
break;
|
|
323
|
+
case "FailedGettingFieldSelection" :
|
|
324
|
+
case "FailedParsingItems" :
|
|
325
|
+
exit = 1;
|
|
326
|
+
break;
|
|
327
|
+
case "FailedGettingItems" :
|
|
328
|
+
break;
|
|
329
|
+
|
|
330
|
+
}
|
|
331
|
+
if (exit === 1) {
|
|
332
|
+
Logging.childError(logger, {
|
|
333
|
+
msg: error$1.message,
|
|
334
|
+
err: Internal.prettifyExn(error$1.exn),
|
|
335
|
+
blockNumber: error$1.blockNumber,
|
|
336
|
+
logIndex: error$1.logIndex
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
}
|
|
341
|
+
if (nextSource$1 === source) {
|
|
342
|
+
ErrorHandling.mkLogAndRaise(logger, "The indexer doesn't have data-sources which can continue fetching. Please, check the error logs or reach out to the Envio team.", null);
|
|
343
|
+
} else {
|
|
344
|
+
Logging.childInfo(logger, {
|
|
345
|
+
msg: "Switching to another data-source",
|
|
346
|
+
source: nextSource$1.name
|
|
347
|
+
});
|
|
348
|
+
sourceManager.activeSource = nextSource$1;
|
|
349
|
+
retryRef = 0;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
} else {
|
|
353
|
+
ErrorHandling.mkLogAndRaise(logger, "Failed to fetch block Range", error);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
};
|
|
357
|
+
return responseRef;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
exports.make = make;
|
|
361
|
+
exports.getActiveSource = getActiveSource;
|
|
362
|
+
exports.fetchNext = fetchNext;
|
|
363
|
+
exports.waitForNewBlock = waitForNewBlock;
|
|
364
|
+
exports.executeQuery = executeQuery;
|
|
365
|
+
exports.makeGetHeightRetryInterval = makeGetHeightRetryInterval;
|
|
366
|
+
/* Utils Not a pure module */
|