envio 3.0.0-alpha.2 → 3.0.0-alpha.20
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/README.md +164 -30
- package/bin.mjs +49 -0
- package/evm.schema.json +79 -169
- package/fuel.schema.json +50 -21
- package/index.d.ts +497 -1
- package/index.js +4 -0
- package/package.json +42 -31
- package/rescript.json +4 -1
- package/src/Batch.res +11 -8
- package/src/Batch.res.mjs +11 -9
- package/src/ChainFetcher.res +531 -0
- package/src/ChainFetcher.res.mjs +339 -0
- package/src/ChainManager.res +190 -0
- package/src/ChainManager.res.mjs +166 -0
- package/src/Change.res +3 -3
- package/src/Config.gen.ts +19 -0
- package/src/Config.res +737 -22
- package/src/Config.res.mjs +703 -26
- package/src/{Indexer.res → Ctx.res} +1 -1
- package/src/Ecosystem.res +9 -124
- package/src/Ecosystem.res.mjs +19 -160
- package/src/Env.res +30 -74
- package/src/Env.res.mjs +25 -87
- package/src/Envio.gen.ts +3 -1
- package/src/Envio.res +20 -9
- package/src/EventProcessing.res +469 -0
- package/src/EventProcessing.res.mjs +337 -0
- package/src/EvmTypes.gen.ts +6 -0
- package/src/EvmTypes.res +1 -0
- package/src/FetchState.res +1256 -639
- package/src/FetchState.res.mjs +1135 -612
- package/src/GlobalState.res +1190 -0
- package/src/GlobalState.res.mjs +1183 -0
- package/src/GlobalStateManager.res +68 -0
- package/src/GlobalStateManager.res.mjs +75 -0
- package/src/GlobalStateManager.resi +7 -0
- package/src/HandlerLoader.res +89 -0
- package/src/HandlerLoader.res.mjs +79 -0
- package/src/HandlerRegister.res +357 -0
- package/src/HandlerRegister.res.mjs +299 -0
- package/src/{EventRegister.resi → HandlerRegister.resi} +13 -13
- package/src/Hasura.res +111 -175
- package/src/Hasura.res.mjs +88 -150
- package/src/InMemoryStore.res +1 -1
- package/src/InMemoryStore.res.mjs +3 -3
- package/src/InMemoryTable.res +1 -1
- package/src/InMemoryTable.res.mjs +1 -1
- package/src/Internal.gen.ts +4 -0
- package/src/Internal.res +230 -12
- package/src/Internal.res.mjs +115 -1
- package/src/LoadLayer.res +444 -0
- package/src/LoadLayer.res.mjs +296 -0
- package/src/LoadLayer.resi +32 -0
- package/src/LogSelection.res +33 -27
- package/src/LogSelection.res.mjs +6 -0
- package/src/Logging.res +21 -7
- package/src/Logging.res.mjs +16 -8
- package/src/Main.res +377 -0
- package/src/Main.res.mjs +339 -0
- package/src/Persistence.res +7 -21
- package/src/Persistence.res.mjs +3 -3
- package/src/PgStorage.gen.ts +10 -0
- package/src/PgStorage.res +116 -69
- package/src/PgStorage.res.d.mts +5 -0
- package/src/PgStorage.res.mjs +93 -50
- package/src/Prometheus.res +294 -224
- package/src/Prometheus.res.mjs +353 -340
- package/src/ReorgDetection.res +6 -10
- package/src/ReorgDetection.res.mjs +6 -6
- package/src/SafeCheckpointTracking.res +4 -4
- package/src/SafeCheckpointTracking.res.mjs +2 -2
- package/src/Sink.res +4 -2
- package/src/Sink.res.mjs +2 -1
- package/src/TableIndices.res +0 -1
- package/src/TestIndexer.res +692 -0
- package/src/TestIndexer.res.mjs +527 -0
- package/src/TestIndexerProxyStorage.res +205 -0
- package/src/TestIndexerProxyStorage.res.mjs +151 -0
- package/src/TopicFilter.res +1 -1
- package/src/Types.ts +1 -1
- package/src/UserContext.res +424 -0
- package/src/UserContext.res.mjs +279 -0
- package/src/Utils.res +97 -26
- package/src/Utils.res.mjs +91 -44
- package/src/bindings/BigInt.res +10 -0
- package/src/bindings/BigInt.res.mjs +15 -0
- package/src/bindings/ClickHouse.res +120 -23
- package/src/bindings/ClickHouse.res.mjs +118 -28
- package/src/bindings/DateFns.res +74 -0
- package/src/bindings/DateFns.res.mjs +22 -0
- package/src/bindings/EventSource.res +8 -1
- package/src/bindings/EventSource.res.mjs +8 -1
- package/src/bindings/Express.res +1 -0
- package/src/bindings/Hrtime.res +14 -1
- package/src/bindings/Hrtime.res.mjs +22 -2
- package/src/bindings/Hrtime.resi +4 -0
- package/src/bindings/Lodash.res +0 -1
- package/src/bindings/NodeJs.res +49 -3
- package/src/bindings/NodeJs.res.mjs +11 -3
- package/src/bindings/Pino.res +24 -10
- package/src/bindings/Pino.res.mjs +14 -8
- package/src/bindings/Postgres.gen.ts +8 -0
- package/src/bindings/Postgres.res +5 -1
- package/src/bindings/Postgres.res.d.mts +5 -0
- package/src/bindings/PromClient.res +0 -10
- package/src/bindings/PromClient.res.mjs +0 -3
- package/src/bindings/Vitest.res +142 -0
- package/src/bindings/Vitest.res.mjs +9 -0
- package/src/bindings/WebSocket.res +27 -0
- package/src/bindings/WebSocket.res.mjs +2 -0
- package/src/bindings/Yargs.res +8 -0
- package/src/bindings/Yargs.res.mjs +2 -0
- package/src/db/EntityHistory.res +7 -7
- package/src/db/EntityHistory.res.mjs +9 -9
- package/src/db/InternalTable.res +59 -111
- package/src/db/InternalTable.res.mjs +73 -104
- package/src/db/Table.res +27 -8
- package/src/db/Table.res.mjs +25 -14
- package/src/sources/Evm.res +84 -0
- package/src/sources/Evm.res.mjs +105 -0
- package/src/sources/EvmChain.res +94 -0
- package/src/sources/EvmChain.res.mjs +60 -0
- package/src/sources/Fuel.res +19 -34
- package/src/sources/Fuel.res.mjs +34 -16
- package/src/sources/FuelSDK.res +38 -0
- package/src/sources/FuelSDK.res.mjs +29 -0
- package/src/sources/HyperFuel.res +2 -2
- package/src/sources/HyperFuel.resi +1 -1
- package/src/sources/HyperFuelClient.res +2 -2
- package/src/sources/HyperFuelSource.res +33 -13
- package/src/sources/HyperFuelSource.res.mjs +24 -16
- package/src/sources/HyperSync.res +36 -6
- package/src/sources/HyperSync.res.mjs +9 -7
- package/src/sources/HyperSync.resi +4 -0
- package/src/sources/HyperSyncClient.res +1 -1
- package/src/sources/HyperSyncHeightStream.res +47 -116
- package/src/sources/HyperSyncHeightStream.res.mjs +46 -73
- package/src/sources/HyperSyncSource.res +118 -139
- package/src/sources/HyperSyncSource.res.mjs +104 -121
- package/src/sources/Rpc.res +86 -14
- package/src/sources/Rpc.res.mjs +101 -9
- package/src/sources/RpcSource.res +621 -364
- package/src/sources/RpcSource.res.mjs +843 -410
- package/src/sources/RpcWebSocketHeightStream.res +181 -0
- package/src/sources/RpcWebSocketHeightStream.res.mjs +196 -0
- package/src/sources/Source.res +7 -5
- package/src/sources/SourceManager.res +325 -225
- package/src/sources/SourceManager.res.mjs +314 -171
- package/src/sources/SourceManager.resi +17 -6
- package/src/sources/Svm.res +81 -0
- package/src/sources/Svm.res.mjs +90 -0
- package/src/tui/Tui.res +247 -0
- package/src/tui/Tui.res.mjs +337 -0
- package/src/tui/bindings/Ink.res +371 -0
- package/src/tui/bindings/Ink.res.mjs +72 -0
- package/src/tui/bindings/Style.res +123 -0
- package/src/tui/bindings/Style.res.mjs +2 -0
- package/src/tui/components/BufferedProgressBar.res +40 -0
- package/src/tui/components/BufferedProgressBar.res.mjs +57 -0
- package/src/tui/components/CustomHooks.res +122 -0
- package/src/tui/components/CustomHooks.res.mjs +179 -0
- package/src/tui/components/Messages.res +41 -0
- package/src/tui/components/Messages.res.mjs +75 -0
- package/src/tui/components/SyncETA.res +174 -0
- package/src/tui/components/SyncETA.res.mjs +263 -0
- package/src/tui/components/TuiData.res +47 -0
- package/src/tui/components/TuiData.res.mjs +34 -0
- package/svm.schema.json +112 -0
- package/bin.js +0 -48
- package/src/EventRegister.res +0 -241
- package/src/EventRegister.res.mjs +0 -240
- package/src/bindings/Ethers.gen.ts +0 -14
- package/src/bindings/Ethers.res +0 -204
- package/src/bindings/Ethers.res.mjs +0 -130
- /package/src/{Indexer.res.mjs → Ctx.res.mjs} +0 -0
|
@@ -10,6 +10,7 @@ import * as Belt_Array from "rescript/lib/es6/belt_Array.js";
|
|
|
10
10
|
import * as FetchState from "../FetchState.res.mjs";
|
|
11
11
|
import * as Prometheus from "../Prometheus.res.mjs";
|
|
12
12
|
import * as Belt_Option from "rescript/lib/es6/belt_Option.js";
|
|
13
|
+
import * as Caml_option from "rescript/lib/es6/caml_option.js";
|
|
13
14
|
import * as ErrorHandling from "../ErrorHandling.res.mjs";
|
|
14
15
|
import * as Caml_js_exceptions from "rescript/lib/es6/caml_js_exceptions.js";
|
|
15
16
|
|
|
@@ -17,6 +18,34 @@ function getActiveSource(sourceManager) {
|
|
|
17
18
|
return sourceManager.activeSource;
|
|
18
19
|
}
|
|
19
20
|
|
|
21
|
+
function getSourceRole(sourceFor, isLive, hasLive) {
|
|
22
|
+
if (isLive) {
|
|
23
|
+
switch (sourceFor) {
|
|
24
|
+
case "Sync" :
|
|
25
|
+
if (hasLive) {
|
|
26
|
+
return "Secondary";
|
|
27
|
+
} else {
|
|
28
|
+
return "Primary";
|
|
29
|
+
}
|
|
30
|
+
case "Fallback" :
|
|
31
|
+
return "Secondary";
|
|
32
|
+
case "Live" :
|
|
33
|
+
return "Primary";
|
|
34
|
+
|
|
35
|
+
}
|
|
36
|
+
} else {
|
|
37
|
+
switch (sourceFor) {
|
|
38
|
+
case "Sync" :
|
|
39
|
+
return "Primary";
|
|
40
|
+
case "Fallback" :
|
|
41
|
+
return "Secondary";
|
|
42
|
+
case "Live" :
|
|
43
|
+
return ;
|
|
44
|
+
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
20
49
|
function makeGetHeightRetryInterval(initialRetryInterval, backoffMultiplicative, maxRetryInterval) {
|
|
21
50
|
return function (retry) {
|
|
22
51
|
var backoff = retry === 0 ? 1 : Math.imul(retry, backoffMultiplicative);
|
|
@@ -24,27 +53,44 @@ function makeGetHeightRetryInterval(initialRetryInterval, backoffMultiplicative,
|
|
|
24
53
|
};
|
|
25
54
|
}
|
|
26
55
|
|
|
27
|
-
function make(sources, maxPartitionConcurrency,
|
|
28
|
-
var
|
|
56
|
+
function make(sources, maxPartitionConcurrency, isLive, newBlockStallTimeoutOpt, newBlockStallTimeoutLiveOpt, stalledPollingIntervalOpt, recoveryTimeoutOpt, getHeightRetryIntervalOpt) {
|
|
57
|
+
var newBlockStallTimeout = newBlockStallTimeoutOpt !== undefined ? newBlockStallTimeoutOpt : 60000;
|
|
58
|
+
var newBlockStallTimeoutLive = newBlockStallTimeoutLiveOpt !== undefined ? newBlockStallTimeoutLiveOpt : 20000;
|
|
29
59
|
var stalledPollingInterval = stalledPollingIntervalOpt !== undefined ? stalledPollingIntervalOpt : 5000;
|
|
60
|
+
var recoveryTimeout = recoveryTimeoutOpt !== undefined ? recoveryTimeoutOpt : 60000.0;
|
|
30
61
|
var getHeightRetryInterval = getHeightRetryIntervalOpt !== undefined ? getHeightRetryIntervalOpt : makeGetHeightRetryInterval(1000, 2, 60000);
|
|
62
|
+
var hasLive = sources.some(function (s) {
|
|
63
|
+
return s.sourceFor === "Live";
|
|
64
|
+
});
|
|
31
65
|
var source = sources.find(function (source) {
|
|
32
|
-
return source.sourceFor === "
|
|
66
|
+
return getSourceRole(source.sourceFor, isLive, hasLive) === "Primary";
|
|
33
67
|
});
|
|
34
68
|
var initialActiveSource = source !== undefined ? source : Js_exn.raiseError("Invalid configuration, no data-source for historical sync provided");
|
|
35
69
|
Prometheus.IndexingMaxConcurrency.set(maxPartitionConcurrency, initialActiveSource.chain);
|
|
36
70
|
Prometheus.IndexingConcurrency.set(0, initialActiveSource.chain);
|
|
37
71
|
return {
|
|
38
|
-
|
|
72
|
+
sourcesState: Belt_Array.map(sources, (function (source) {
|
|
73
|
+
return {
|
|
74
|
+
source: source,
|
|
75
|
+
knownHeight: 0,
|
|
76
|
+
unsubscribe: undefined,
|
|
77
|
+
pendingHeightResolvers: [],
|
|
78
|
+
disabled: false,
|
|
79
|
+
lastFailedAt: undefined
|
|
80
|
+
};
|
|
81
|
+
})),
|
|
39
82
|
statusStart: Hrtime.makeTimer(),
|
|
40
83
|
status: "Idle",
|
|
41
84
|
maxPartitionConcurrency: maxPartitionConcurrency,
|
|
42
|
-
|
|
85
|
+
newBlockStallTimeout: newBlockStallTimeout,
|
|
86
|
+
newBlockStallTimeoutLive: newBlockStallTimeoutLive,
|
|
43
87
|
stalledPollingInterval: stalledPollingInterval,
|
|
44
88
|
getHeightRetryInterval: getHeightRetryInterval,
|
|
45
89
|
activeSource: initialActiveSource,
|
|
46
90
|
waitingForNewBlockStateId: undefined,
|
|
47
|
-
fetchingPartitionsCount: 0
|
|
91
|
+
fetchingPartitionsCount: 0,
|
|
92
|
+
recoveryTimeout: recoveryTimeout,
|
|
93
|
+
hasLive: hasLive
|
|
48
94
|
};
|
|
49
95
|
}
|
|
50
96
|
|
|
@@ -63,15 +109,15 @@ function trackNewStatus(sourceManager, newStatus) {
|
|
|
63
109
|
break;
|
|
64
110
|
|
|
65
111
|
}
|
|
66
|
-
Prometheus.SafeCounter.
|
|
112
|
+
Prometheus.SafeCounter.handleFloat(promCounter, sourceManager.activeSource.chain, Hrtime.toSecondsFloat(Hrtime.timeSince(sourceManager.statusStart)));
|
|
67
113
|
sourceManager.statusStart = Hrtime.makeTimer();
|
|
68
114
|
sourceManager.status = newStatus;
|
|
69
115
|
}
|
|
70
116
|
|
|
71
|
-
async function fetchNext(sourceManager, fetchState,
|
|
72
|
-
var
|
|
73
|
-
if (typeof
|
|
74
|
-
switch (
|
|
117
|
+
async function fetchNext(sourceManager, fetchState, executeQuery, waitForNewBlock, onNewBlock, stateId) {
|
|
118
|
+
var nextQuery = FetchState.getNextQuery(fetchState, sourceManager.maxPartitionConcurrency - sourceManager.fetchingPartitionsCount | 0);
|
|
119
|
+
if (typeof nextQuery !== "object") {
|
|
120
|
+
switch (nextQuery) {
|
|
75
121
|
case "WaitingForNewBlock" :
|
|
76
122
|
var waitingStateId = sourceManager.waitingForNewBlockStateId;
|
|
77
123
|
if (waitingStateId !== undefined && waitingStateId >= stateId) {
|
|
@@ -79,12 +125,12 @@ async function fetchNext(sourceManager, fetchState, currentBlockHeight, executeQ
|
|
|
79
125
|
}
|
|
80
126
|
trackNewStatus(sourceManager, "WaitingForNewBlock");
|
|
81
127
|
sourceManager.waitingForNewBlockStateId = stateId;
|
|
82
|
-
var
|
|
128
|
+
var knownHeight = await waitForNewBlock(fetchState.knownHeight);
|
|
83
129
|
var waitingStateId$1 = sourceManager.waitingForNewBlockStateId;
|
|
84
130
|
if (waitingStateId$1 !== undefined && waitingStateId$1 === stateId) {
|
|
85
131
|
trackNewStatus(sourceManager, "Idle");
|
|
86
132
|
sourceManager.waitingForNewBlockStateId = undefined;
|
|
87
|
-
return onNewBlock(
|
|
133
|
+
return onNewBlock(knownHeight);
|
|
88
134
|
} else {
|
|
89
135
|
return ;
|
|
90
136
|
}
|
|
@@ -94,12 +140,12 @@ async function fetchNext(sourceManager, fetchState, currentBlockHeight, executeQ
|
|
|
94
140
|
|
|
95
141
|
}
|
|
96
142
|
} else {
|
|
97
|
-
var queries
|
|
98
|
-
FetchState.startFetchingQueries(fetchState, queries
|
|
99
|
-
sourceManager.fetchingPartitionsCount = sourceManager.fetchingPartitionsCount + queries
|
|
143
|
+
var queries = nextQuery._0;
|
|
144
|
+
FetchState.startFetchingQueries(fetchState, queries);
|
|
145
|
+
sourceManager.fetchingPartitionsCount = sourceManager.fetchingPartitionsCount + queries.length | 0;
|
|
100
146
|
Prometheus.IndexingConcurrency.set(sourceManager.fetchingPartitionsCount, sourceManager.activeSource.chain);
|
|
101
147
|
trackNewStatus(sourceManager, "Querieng");
|
|
102
|
-
await Promise.all(Belt_Array.map(queries
|
|
148
|
+
await Promise.all(Belt_Array.map(queries, (function (q) {
|
|
103
149
|
var promise = executeQuery(q);
|
|
104
150
|
promise.then(function (param) {
|
|
105
151
|
sourceManager.fetchingPartitionsCount = sourceManager.fetchingPartitionsCount - 1 | 0;
|
|
@@ -115,78 +161,209 @@ async function fetchNext(sourceManager, fetchState, currentBlockHeight, executeQ
|
|
|
115
161
|
}
|
|
116
162
|
}
|
|
117
163
|
|
|
118
|
-
|
|
119
|
-
|
|
164
|
+
function disableSource(sourceManager, sourceState) {
|
|
165
|
+
if (sourceState.disabled) {
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
sourceState.disabled = true;
|
|
169
|
+
var unsubscribe = sourceState.unsubscribe;
|
|
170
|
+
if (unsubscribe !== undefined) {
|
|
171
|
+
unsubscribe();
|
|
172
|
+
}
|
|
173
|
+
if (sourceState.source.sourceFor === "Live") {
|
|
174
|
+
var hasOtherLive = sourceManager.sourcesState.some(function (s) {
|
|
175
|
+
if (s !== sourceState && !s.disabled) {
|
|
176
|
+
return s.source.sourceFor === "Live";
|
|
177
|
+
} else {
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
sourceManager.hasLive = hasOtherLive;
|
|
182
|
+
}
|
|
183
|
+
return true;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
async function getSourceNewHeight(sourceManager, sourceState, knownHeight, status, logger) {
|
|
187
|
+
var source = sourceState.source;
|
|
188
|
+
var initialHeight = sourceState.knownHeight;
|
|
189
|
+
var newHeight = initialHeight;
|
|
120
190
|
var retry = 0;
|
|
121
|
-
while(newHeight <=
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
newHeight = height;
|
|
130
|
-
if (height <= currentBlockHeight) {
|
|
131
|
-
retry = 0;
|
|
132
|
-
var pollingInterval = status.contents === "Stalled" ? sourceManager.stalledPollingInterval : source.pollingInterval;
|
|
133
|
-
await Utils.delay(pollingInterval);
|
|
191
|
+
while(newHeight <= knownHeight && status.contents !== "Done") {
|
|
192
|
+
var match = sourceState.unsubscribe;
|
|
193
|
+
if (match !== undefined) {
|
|
194
|
+
var height = await new Promise((function (resolve, _reject) {
|
|
195
|
+
sourceState.pendingHeightResolvers.push(resolve);
|
|
196
|
+
}));
|
|
197
|
+
if (height > initialHeight) {
|
|
198
|
+
newHeight = height;
|
|
134
199
|
}
|
|
135
200
|
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
201
|
+
} else {
|
|
202
|
+
try {
|
|
203
|
+
var height$1 = await source.getHeightOrThrow();
|
|
204
|
+
newHeight = height$1;
|
|
205
|
+
if (height$1 <= knownHeight) {
|
|
206
|
+
retry = 0;
|
|
207
|
+
var createSubscription = source.createHeightSubscription;
|
|
208
|
+
if (createSubscription !== undefined) {
|
|
209
|
+
var unsubscribe = createSubscription(function (newHeight) {
|
|
210
|
+
sourceState.knownHeight = newHeight;
|
|
211
|
+
var resolvers = sourceState.pendingHeightResolvers;
|
|
212
|
+
sourceState.pendingHeightResolvers = [];
|
|
213
|
+
Belt_Array.forEach(resolvers, (function (resolve) {
|
|
214
|
+
resolve(newHeight);
|
|
215
|
+
}));
|
|
216
|
+
});
|
|
217
|
+
sourceState.unsubscribe = unsubscribe;
|
|
218
|
+
} else {
|
|
219
|
+
var pollingInterval = status.contents === "Stalled" ? sourceManager.stalledPollingInterval : source.pollingInterval;
|
|
220
|
+
await Utils.delay(pollingInterval);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
}
|
|
225
|
+
catch (raw_exn){
|
|
226
|
+
var exn = Caml_js_exceptions.internalToOCamlException(raw_exn);
|
|
227
|
+
var retryInterval = sourceManager.getHeightRetryInterval(retry);
|
|
228
|
+
Logging.childTrace(logger, {
|
|
229
|
+
msg: "Height retrieval from " + source.name + " source failed. Retrying in " + String(retryInterval) + "ms.",
|
|
230
|
+
source: source.name,
|
|
231
|
+
err: Utils.prettifyExn(exn)
|
|
232
|
+
});
|
|
233
|
+
retry = retry + 1 | 0;
|
|
234
|
+
await Utils.delay(retryInterval);
|
|
235
|
+
}
|
|
147
236
|
}
|
|
148
237
|
};
|
|
149
|
-
|
|
238
|
+
if (newHeight > initialHeight) {
|
|
239
|
+
Prometheus.SourceHeight.set(source.name, source.chain, newHeight);
|
|
240
|
+
}
|
|
150
241
|
return newHeight;
|
|
151
242
|
}
|
|
152
243
|
|
|
153
|
-
|
|
244
|
+
function compareByOldestFailure(a, b) {
|
|
245
|
+
var match = a.lastFailedAt;
|
|
246
|
+
var match$1 = b.lastFailedAt;
|
|
247
|
+
if (match !== undefined) {
|
|
248
|
+
if (match$1 !== undefined) {
|
|
249
|
+
if (match < match$1) {
|
|
250
|
+
return -1;
|
|
251
|
+
} else if (match > match$1) {
|
|
252
|
+
return 1;
|
|
253
|
+
} else {
|
|
254
|
+
return 0;
|
|
255
|
+
}
|
|
256
|
+
} else {
|
|
257
|
+
return 1;
|
|
258
|
+
}
|
|
259
|
+
} else if (match$1 !== undefined) {
|
|
260
|
+
return -1;
|
|
261
|
+
} else {
|
|
262
|
+
return 0;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
function getNextSources(sourceManager, isLive, excludedSources) {
|
|
267
|
+
var now = Date.now();
|
|
268
|
+
var workingPrimarySources = [];
|
|
269
|
+
var allPrimarySources = [];
|
|
270
|
+
var workingSecondarySources = [];
|
|
271
|
+
for(var i = 0 ,i_finish = sourceManager.sourcesState.length; i < i_finish; ++i){
|
|
272
|
+
var sourceState = sourceManager.sourcesState[i];
|
|
273
|
+
if (!sourceState.disabled) {
|
|
274
|
+
var isExcluded = excludedSources !== undefined ? Caml_option.valFromOption(excludedSources).has(sourceState) : false;
|
|
275
|
+
if (!isExcluded) {
|
|
276
|
+
var failedAt = sourceState.lastFailedAt;
|
|
277
|
+
var isWorking = failedAt !== undefined ? now - failedAt >= sourceManager.recoveryTimeout : true;
|
|
278
|
+
var match = getSourceRole(sourceState.source.sourceFor, isLive, sourceManager.hasLive);
|
|
279
|
+
if (match !== undefined) {
|
|
280
|
+
if (match === "Primary") {
|
|
281
|
+
allPrimarySources.push(sourceState);
|
|
282
|
+
if (isWorking) {
|
|
283
|
+
workingPrimarySources.push(sourceState);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
} else if (isWorking) {
|
|
287
|
+
workingSecondarySources.push(sourceState);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
}
|
|
297
|
+
if (workingPrimarySources.length !== 0) {
|
|
298
|
+
return workingPrimarySources;
|
|
299
|
+
} else if (workingSecondarySources.length !== 0) {
|
|
300
|
+
return workingSecondarySources;
|
|
301
|
+
} else {
|
|
302
|
+
return allPrimarySources.sort(compareByOldestFailure);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
function getNextSource(sourceManager, isLive, excludedSources) {
|
|
307
|
+
var sources = getNextSources(sourceManager, isLive, excludedSources);
|
|
308
|
+
var first = Belt_Array.get(sources, 0);
|
|
309
|
+
if (first === undefined) {
|
|
310
|
+
return ;
|
|
311
|
+
}
|
|
312
|
+
if (first.source === sourceManager.activeSource) {
|
|
313
|
+
return first;
|
|
314
|
+
}
|
|
315
|
+
var result = sources.find(function (s) {
|
|
316
|
+
return s.source === sourceManager.activeSource;
|
|
317
|
+
});
|
|
318
|
+
if (result !== undefined) {
|
|
319
|
+
if (result === undefined) {
|
|
320
|
+
return ;
|
|
321
|
+
} else {
|
|
322
|
+
return Caml_option.some(result);
|
|
323
|
+
}
|
|
324
|
+
} else {
|
|
325
|
+
return Belt_Array.get(sources, 0);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
async function waitForNewBlock(sourceManager, knownHeight, isLive) {
|
|
330
|
+
var sourcesState = sourceManager.sourcesState;
|
|
154
331
|
var logger = Logging.createChild({
|
|
155
332
|
chainId: sourceManager.activeSource.chain,
|
|
156
|
-
|
|
333
|
+
knownHeight: knownHeight
|
|
157
334
|
});
|
|
158
335
|
Logging.childTrace(logger, "Initiating check for new blocks.");
|
|
159
|
-
var
|
|
160
|
-
var syncSources = [];
|
|
161
|
-
var fallbackSources = [];
|
|
162
|
-
sourceManager.sources.forEach(function (source) {
|
|
163
|
-
if (source.sourceFor === "Sync" || source.sourceFor === "Live" && !isInitialHeightFetch || source === sourceManager.activeSource) {
|
|
164
|
-
syncSources.push(source);
|
|
165
|
-
} else {
|
|
166
|
-
fallbackSources.push(source);
|
|
167
|
-
}
|
|
168
|
-
});
|
|
336
|
+
var mainSources = getNextSources(sourceManager, isLive, undefined);
|
|
169
337
|
var status = {
|
|
170
338
|
contents: "Active"
|
|
171
339
|
};
|
|
172
|
-
var
|
|
340
|
+
var stallTimeout = isLive ? sourceManager.newBlockStallTimeoutLive : sourceManager.newBlockStallTimeout;
|
|
341
|
+
var match = await Promise.race(Belt_Array.concat(Belt_Array.map(mainSources, (async function (sourceState) {
|
|
173
342
|
return [
|
|
174
|
-
source,
|
|
175
|
-
await getSourceNewHeight(sourceManager,
|
|
343
|
+
sourceState.source,
|
|
344
|
+
await getSourceNewHeight(sourceManager, sourceState, knownHeight, status, logger)
|
|
176
345
|
];
|
|
177
|
-
})), [Utils.delay(
|
|
346
|
+
})), [Utils.delay(stallTimeout).then(function () {
|
|
347
|
+
var fallbackSources = [];
|
|
348
|
+
Belt_Array.forEach(sourcesState, (function (sourceState) {
|
|
349
|
+
if (!mainSources.includes(sourceState) && Belt_Option.isSome(getSourceRole(sourceState.source.sourceFor, isLive, sourceManager.hasLive))) {
|
|
350
|
+
fallbackSources.push(sourceState);
|
|
351
|
+
return ;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
}));
|
|
178
355
|
if (status.contents !== "Done") {
|
|
179
356
|
status.contents = "Stalled";
|
|
180
357
|
if (fallbackSources.length !== 0) {
|
|
181
|
-
Logging.childWarn(logger, "No new blocks detected within " + String(
|
|
358
|
+
Logging.childWarn(logger, "No new blocks detected within " + String(stallTimeout / 1000 | 0) + "s. Continuing polling with secondary RPC sources from the configuration.");
|
|
182
359
|
} else {
|
|
183
|
-
Logging.childWarn(logger, "No new blocks detected within " + String(
|
|
360
|
+
Logging.childWarn(logger, "No new blocks detected within " + String(stallTimeout / 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
361
|
}
|
|
185
362
|
}
|
|
186
|
-
return Promise.race(Belt_Array.map(fallbackSources, (async function (
|
|
363
|
+
return Promise.race(Belt_Array.map(fallbackSources, (async function (sourceState) {
|
|
187
364
|
return [
|
|
188
|
-
source,
|
|
189
|
-
await getSourceNewHeight(sourceManager,
|
|
365
|
+
sourceState.source,
|
|
366
|
+
await getSourceNewHeight(sourceManager, sourceState, knownHeight, status, logger)
|
|
190
367
|
];
|
|
191
368
|
})));
|
|
192
369
|
})]));
|
|
@@ -203,66 +380,38 @@ async function waitForNewBlock(sourceManager, currentBlockHeight) {
|
|
|
203
380
|
return newBlockHeight;
|
|
204
381
|
}
|
|
205
382
|
|
|
206
|
-
function
|
|
207
|
-
var
|
|
208
|
-
var
|
|
209
|
-
var after = [];
|
|
210
|
-
var hasActive = {
|
|
211
|
-
contents: false
|
|
212
|
-
};
|
|
213
|
-
sourceManager.sources.forEach(function (source) {
|
|
214
|
-
if (source === currentSource) {
|
|
215
|
-
hasActive.contents = true;
|
|
216
|
-
return ;
|
|
217
|
-
}
|
|
218
|
-
var match = source.sourceFor;
|
|
219
|
-
var tmp;
|
|
220
|
-
switch (match) {
|
|
221
|
-
case "Sync" :
|
|
222
|
-
tmp = true;
|
|
223
|
-
break;
|
|
224
|
-
case "Fallback" :
|
|
225
|
-
case "Live" :
|
|
226
|
-
tmp = attemptFallbacks || source === initialSource;
|
|
227
|
-
break;
|
|
228
|
-
|
|
229
|
-
}
|
|
230
|
-
if (tmp) {
|
|
231
|
-
(
|
|
232
|
-
hasActive.contents ? after : before
|
|
233
|
-
).push(source);
|
|
234
|
-
return ;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
});
|
|
238
|
-
var s = Belt_Array.get(after, 0);
|
|
239
|
-
if (s !== undefined) {
|
|
240
|
-
return s;
|
|
241
|
-
}
|
|
242
|
-
var s$1 = Belt_Array.get(before, 0);
|
|
243
|
-
if (s$1 !== undefined) {
|
|
244
|
-
return s$1;
|
|
245
|
-
} else {
|
|
246
|
-
return currentSource;
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
async function executeQuery(sourceManager, query, currentBlockHeight) {
|
|
251
|
-
var match = query.target;
|
|
252
|
-
var toBlockRef;
|
|
253
|
-
toBlockRef = typeof match !== "object" ? undefined : (
|
|
254
|
-
match.TAG === "EndBlock" ? match.toBlock : match.toBlock
|
|
255
|
-
);
|
|
383
|
+
async function executeQuery(sourceManager, query, knownHeight, isLive) {
|
|
384
|
+
var excludedSourcesRef;
|
|
385
|
+
var toBlockRef = query.toBlock;
|
|
256
386
|
var responseRef;
|
|
257
387
|
var retryRef = 0;
|
|
258
|
-
var initialSource = sourceManager.activeSource;
|
|
259
|
-
var sourceRef = initialSource;
|
|
260
|
-
var shouldUpdateActiveSource = false;
|
|
261
388
|
while(Belt_Option.isNone(responseRef)) {
|
|
262
|
-
var
|
|
389
|
+
var s = getNextSource(sourceManager, isLive, excludedSourcesRef);
|
|
390
|
+
var sourceState;
|
|
391
|
+
if (s !== undefined) {
|
|
392
|
+
if (s.source !== sourceManager.activeSource) {
|
|
393
|
+
var logger = Logging.createChild({
|
|
394
|
+
chainId: sourceManager.activeSource.chain
|
|
395
|
+
});
|
|
396
|
+
Logging.childInfo(logger, {
|
|
397
|
+
msg: "Switching data-source",
|
|
398
|
+
source: s.source.name,
|
|
399
|
+
previousSource: sourceManager.activeSource.name,
|
|
400
|
+
fromBlock: query.fromBlock
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
sourceState = s;
|
|
404
|
+
} else {
|
|
405
|
+
var logger$1 = Logging.createChild({
|
|
406
|
+
chainId: sourceManager.activeSource.chain
|
|
407
|
+
});
|
|
408
|
+
sourceState = ErrorHandling.mkLogAndRaise(logger$1, "The indexer doesn't have data-sources which can continue fetching. Please, check the error logs or reach out to the Envio team.", null);
|
|
409
|
+
}
|
|
410
|
+
sourceManager.activeSource = sourceState.source;
|
|
411
|
+
var source = sourceState.source;
|
|
263
412
|
var toBlock = toBlockRef;
|
|
264
413
|
var retry = retryRef;
|
|
265
|
-
var logger = Logging.createChild({
|
|
414
|
+
var logger$2 = Logging.createChild({
|
|
266
415
|
chainId: source.chain,
|
|
267
416
|
logType: "Block Range Query",
|
|
268
417
|
partitionId: query.partitionId,
|
|
@@ -273,13 +422,14 @@ async function executeQuery(sourceManager, query, currentBlockHeight) {
|
|
|
273
422
|
retry: retry
|
|
274
423
|
});
|
|
275
424
|
try {
|
|
276
|
-
var response = await source.getItemsOrThrow(query.fromBlock, toBlock, query.addressesByContractName, query.indexingContracts,
|
|
277
|
-
Logging.childTrace(logger, {
|
|
425
|
+
var response = await source.getItemsOrThrow(query.fromBlock, toBlock, query.addressesByContractName, query.indexingContracts, knownHeight, query.partitionId, query.selection, retry, logger$2);
|
|
426
|
+
Logging.childTrace(logger$2, {
|
|
278
427
|
msg: "Fetched block range from server",
|
|
279
428
|
toBlock: response.latestFetchedBlockNumber,
|
|
280
429
|
numEvents: response.parsedQueueItems.length,
|
|
281
430
|
stats: response.stats
|
|
282
431
|
});
|
|
432
|
+
sourceState.lastFailedAt = undefined;
|
|
283
433
|
responseRef = response;
|
|
284
434
|
}
|
|
285
435
|
catch (raw_error){
|
|
@@ -293,13 +443,13 @@ async function executeQuery(sourceManager, query, currentBlockHeight) {
|
|
|
293
443
|
exit = 1;
|
|
294
444
|
break;
|
|
295
445
|
case "FailedGettingItems" :
|
|
296
|
-
var match
|
|
446
|
+
var match = error$1.retry;
|
|
297
447
|
var attemptedToBlock = error$1.attemptedToBlock;
|
|
298
448
|
var exn = error$1.exn;
|
|
299
|
-
switch (match
|
|
449
|
+
switch (match.TAG) {
|
|
300
450
|
case "WithSuggestedToBlock" :
|
|
301
|
-
var toBlock$1 = match
|
|
302
|
-
Logging.childTrace(logger, {
|
|
451
|
+
var toBlock$1 = match.toBlock;
|
|
452
|
+
Logging.childTrace(logger$2, {
|
|
303
453
|
msg: "Failed getting data for the block range. Immediately retrying with the suggested block range from response.",
|
|
304
454
|
toBlock: attemptedToBlock,
|
|
305
455
|
suggestedToBlock: toBlock$1
|
|
@@ -308,47 +458,53 @@ async function executeQuery(sourceManager, query, currentBlockHeight) {
|
|
|
308
458
|
retryRef = 0;
|
|
309
459
|
break;
|
|
310
460
|
case "WithBackoff" :
|
|
311
|
-
var backoffMillis = match
|
|
312
|
-
var attemptFallbacks = retry >= 10;
|
|
313
|
-
var nextSource = !(retry === 0 || retry === 1) && retry % 2 === 0 ? getNextSyncSource(sourceManager, initialSource, source, attemptFallbacks) : source;
|
|
461
|
+
var backoffMillis = match.backoffMillis;
|
|
314
462
|
var log = retry >= 4 ? Logging.childWarn : Logging.childTrace;
|
|
315
|
-
log(logger, {
|
|
316
|
-
msg: match
|
|
463
|
+
log(logger$2, {
|
|
464
|
+
msg: match.message,
|
|
317
465
|
toBlock: attemptedToBlock,
|
|
318
466
|
backOffMilliseconds: backoffMillis,
|
|
319
467
|
retry: retry,
|
|
320
468
|
err: Utils.prettifyExn(exn)
|
|
321
469
|
});
|
|
322
|
-
var shouldSwitch =
|
|
470
|
+
var shouldSwitch = retry === 0 || retry === 1 ? false : retry % 2 === 0;
|
|
323
471
|
if (shouldSwitch) {
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
472
|
+
var now = Date.now();
|
|
473
|
+
sourceState.lastFailedAt = now;
|
|
474
|
+
var nextSource = getNextSource(sourceManager, isLive, excludedSourcesRef);
|
|
475
|
+
var hasWorkingAlternative;
|
|
476
|
+
if (nextSource !== undefined) {
|
|
477
|
+
var failedAt = nextSource.lastFailedAt;
|
|
478
|
+
hasWorkingAlternative = failedAt !== undefined ? now - failedAt >= sourceManager.recoveryTimeout : true;
|
|
479
|
+
} else {
|
|
480
|
+
hasWorkingAlternative = false;
|
|
481
|
+
}
|
|
482
|
+
if (!hasWorkingAlternative) {
|
|
483
|
+
await Utils.delay(backoffMillis < 60000 ? backoffMillis : 60000);
|
|
484
|
+
}
|
|
485
|
+
|
|
330
486
|
} else {
|
|
331
487
|
await Utils.delay(backoffMillis < 60000 ? backoffMillis : 60000);
|
|
332
488
|
}
|
|
333
489
|
retryRef = retryRef + 1 | 0;
|
|
334
490
|
break;
|
|
335
491
|
case "ImpossibleForTheQuery" :
|
|
336
|
-
var
|
|
337
|
-
var
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
492
|
+
var s$1 = excludedSourcesRef;
|
|
493
|
+
var excludedSources;
|
|
494
|
+
if (s$1 !== undefined) {
|
|
495
|
+
excludedSources = Caml_option.valFromOption(s$1);
|
|
496
|
+
} else {
|
|
497
|
+
var s$2 = new Set();
|
|
498
|
+
excludedSourcesRef = Caml_option.some(s$2);
|
|
499
|
+
excludedSources = s$2;
|
|
500
|
+
}
|
|
501
|
+
excludedSources.add(sourceState);
|
|
502
|
+
Logging.childWarn(logger$2, {
|
|
503
|
+
msg: match.message + " - Attempting another source",
|
|
342
504
|
toBlock: attemptedToBlock,
|
|
343
505
|
err: Utils.prettifyExn(exn)
|
|
344
506
|
});
|
|
345
|
-
|
|
346
|
-
sourceRef = nextSource$1;
|
|
347
|
-
shouldUpdateActiveSource = false;
|
|
348
|
-
retryRef = 0;
|
|
349
|
-
} else {
|
|
350
|
-
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);
|
|
351
|
-
}
|
|
507
|
+
retryRef = 0;
|
|
352
508
|
break;
|
|
353
509
|
|
|
354
510
|
}
|
|
@@ -356,15 +512,14 @@ async function executeQuery(sourceManager, query, currentBlockHeight) {
|
|
|
356
512
|
|
|
357
513
|
}
|
|
358
514
|
if (exit === 1) {
|
|
359
|
-
var
|
|
360
|
-
|
|
361
|
-
if (notAlreadyDeleted) {
|
|
515
|
+
var notAlreadyDisabled = disableSource(sourceManager, sourceState);
|
|
516
|
+
if (notAlreadyDisabled) {
|
|
362
517
|
switch (error$1.TAG) {
|
|
363
518
|
case "UnsupportedSelection" :
|
|
364
|
-
Logging.childError(logger, error$1.message);
|
|
519
|
+
Logging.childError(logger$2, error$1.message);
|
|
365
520
|
break;
|
|
366
521
|
case "FailedGettingFieldSelection" :
|
|
367
|
-
Logging.childError(logger, {
|
|
522
|
+
Logging.childError(logger$2, {
|
|
368
523
|
msg: error$1.message,
|
|
369
524
|
err: Utils.prettifyExn(error$1.exn),
|
|
370
525
|
blockNumber: error$1.blockNumber,
|
|
@@ -376,31 +531,19 @@ async function executeQuery(sourceManager, query, currentBlockHeight) {
|
|
|
376
531
|
|
|
377
532
|
}
|
|
378
533
|
}
|
|
379
|
-
|
|
380
|
-
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);
|
|
381
|
-
} else {
|
|
382
|
-
Logging.childInfo(logger, {
|
|
383
|
-
msg: "Switching to another data-source",
|
|
384
|
-
source: nextSource$2.name
|
|
385
|
-
});
|
|
386
|
-
sourceRef = nextSource$2;
|
|
387
|
-
shouldUpdateActiveSource = true;
|
|
388
|
-
retryRef = 0;
|
|
389
|
-
}
|
|
534
|
+
retryRef = 0;
|
|
390
535
|
}
|
|
391
536
|
|
|
392
537
|
} else {
|
|
393
|
-
ErrorHandling.mkLogAndRaise(logger, "Failed to fetch block Range", error);
|
|
538
|
+
ErrorHandling.mkLogAndRaise(logger$2, "Failed to fetch block Range", error);
|
|
394
539
|
}
|
|
395
540
|
}
|
|
396
541
|
};
|
|
397
|
-
if (shouldUpdateActiveSource) {
|
|
398
|
-
sourceManager.activeSource = sourceRef;
|
|
399
|
-
}
|
|
400
542
|
return responseRef;
|
|
401
543
|
}
|
|
402
544
|
|
|
403
545
|
export {
|
|
546
|
+
getSourceRole ,
|
|
404
547
|
make ,
|
|
405
548
|
getActiveSource ,
|
|
406
549
|
fetchNext ,
|