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.
Files changed (175) hide show
  1. package/README.md +164 -30
  2. package/bin.mjs +49 -0
  3. package/evm.schema.json +79 -169
  4. package/fuel.schema.json +50 -21
  5. package/index.d.ts +497 -1
  6. package/index.js +4 -0
  7. package/package.json +42 -31
  8. package/rescript.json +4 -1
  9. package/src/Batch.res +11 -8
  10. package/src/Batch.res.mjs +11 -9
  11. package/src/ChainFetcher.res +531 -0
  12. package/src/ChainFetcher.res.mjs +339 -0
  13. package/src/ChainManager.res +190 -0
  14. package/src/ChainManager.res.mjs +166 -0
  15. package/src/Change.res +3 -3
  16. package/src/Config.gen.ts +19 -0
  17. package/src/Config.res +737 -22
  18. package/src/Config.res.mjs +703 -26
  19. package/src/{Indexer.res → Ctx.res} +1 -1
  20. package/src/Ecosystem.res +9 -124
  21. package/src/Ecosystem.res.mjs +19 -160
  22. package/src/Env.res +30 -74
  23. package/src/Env.res.mjs +25 -87
  24. package/src/Envio.gen.ts +3 -1
  25. package/src/Envio.res +20 -9
  26. package/src/EventProcessing.res +469 -0
  27. package/src/EventProcessing.res.mjs +337 -0
  28. package/src/EvmTypes.gen.ts +6 -0
  29. package/src/EvmTypes.res +1 -0
  30. package/src/FetchState.res +1256 -639
  31. package/src/FetchState.res.mjs +1135 -612
  32. package/src/GlobalState.res +1190 -0
  33. package/src/GlobalState.res.mjs +1183 -0
  34. package/src/GlobalStateManager.res +68 -0
  35. package/src/GlobalStateManager.res.mjs +75 -0
  36. package/src/GlobalStateManager.resi +7 -0
  37. package/src/HandlerLoader.res +89 -0
  38. package/src/HandlerLoader.res.mjs +79 -0
  39. package/src/HandlerRegister.res +357 -0
  40. package/src/HandlerRegister.res.mjs +299 -0
  41. package/src/{EventRegister.resi → HandlerRegister.resi} +13 -13
  42. package/src/Hasura.res +111 -175
  43. package/src/Hasura.res.mjs +88 -150
  44. package/src/InMemoryStore.res +1 -1
  45. package/src/InMemoryStore.res.mjs +3 -3
  46. package/src/InMemoryTable.res +1 -1
  47. package/src/InMemoryTable.res.mjs +1 -1
  48. package/src/Internal.gen.ts +4 -0
  49. package/src/Internal.res +230 -12
  50. package/src/Internal.res.mjs +115 -1
  51. package/src/LoadLayer.res +444 -0
  52. package/src/LoadLayer.res.mjs +296 -0
  53. package/src/LoadLayer.resi +32 -0
  54. package/src/LogSelection.res +33 -27
  55. package/src/LogSelection.res.mjs +6 -0
  56. package/src/Logging.res +21 -7
  57. package/src/Logging.res.mjs +16 -8
  58. package/src/Main.res +377 -0
  59. package/src/Main.res.mjs +339 -0
  60. package/src/Persistence.res +7 -21
  61. package/src/Persistence.res.mjs +3 -3
  62. package/src/PgStorage.gen.ts +10 -0
  63. package/src/PgStorage.res +116 -69
  64. package/src/PgStorage.res.d.mts +5 -0
  65. package/src/PgStorage.res.mjs +93 -50
  66. package/src/Prometheus.res +294 -224
  67. package/src/Prometheus.res.mjs +353 -340
  68. package/src/ReorgDetection.res +6 -10
  69. package/src/ReorgDetection.res.mjs +6 -6
  70. package/src/SafeCheckpointTracking.res +4 -4
  71. package/src/SafeCheckpointTracking.res.mjs +2 -2
  72. package/src/Sink.res +4 -2
  73. package/src/Sink.res.mjs +2 -1
  74. package/src/TableIndices.res +0 -1
  75. package/src/TestIndexer.res +692 -0
  76. package/src/TestIndexer.res.mjs +527 -0
  77. package/src/TestIndexerProxyStorage.res +205 -0
  78. package/src/TestIndexerProxyStorage.res.mjs +151 -0
  79. package/src/TopicFilter.res +1 -1
  80. package/src/Types.ts +1 -1
  81. package/src/UserContext.res +424 -0
  82. package/src/UserContext.res.mjs +279 -0
  83. package/src/Utils.res +97 -26
  84. package/src/Utils.res.mjs +91 -44
  85. package/src/bindings/BigInt.res +10 -0
  86. package/src/bindings/BigInt.res.mjs +15 -0
  87. package/src/bindings/ClickHouse.res +120 -23
  88. package/src/bindings/ClickHouse.res.mjs +118 -28
  89. package/src/bindings/DateFns.res +74 -0
  90. package/src/bindings/DateFns.res.mjs +22 -0
  91. package/src/bindings/EventSource.res +8 -1
  92. package/src/bindings/EventSource.res.mjs +8 -1
  93. package/src/bindings/Express.res +1 -0
  94. package/src/bindings/Hrtime.res +14 -1
  95. package/src/bindings/Hrtime.res.mjs +22 -2
  96. package/src/bindings/Hrtime.resi +4 -0
  97. package/src/bindings/Lodash.res +0 -1
  98. package/src/bindings/NodeJs.res +49 -3
  99. package/src/bindings/NodeJs.res.mjs +11 -3
  100. package/src/bindings/Pino.res +24 -10
  101. package/src/bindings/Pino.res.mjs +14 -8
  102. package/src/bindings/Postgres.gen.ts +8 -0
  103. package/src/bindings/Postgres.res +5 -1
  104. package/src/bindings/Postgres.res.d.mts +5 -0
  105. package/src/bindings/PromClient.res +0 -10
  106. package/src/bindings/PromClient.res.mjs +0 -3
  107. package/src/bindings/Vitest.res +142 -0
  108. package/src/bindings/Vitest.res.mjs +9 -0
  109. package/src/bindings/WebSocket.res +27 -0
  110. package/src/bindings/WebSocket.res.mjs +2 -0
  111. package/src/bindings/Yargs.res +8 -0
  112. package/src/bindings/Yargs.res.mjs +2 -0
  113. package/src/db/EntityHistory.res +7 -7
  114. package/src/db/EntityHistory.res.mjs +9 -9
  115. package/src/db/InternalTable.res +59 -111
  116. package/src/db/InternalTable.res.mjs +73 -104
  117. package/src/db/Table.res +27 -8
  118. package/src/db/Table.res.mjs +25 -14
  119. package/src/sources/Evm.res +84 -0
  120. package/src/sources/Evm.res.mjs +105 -0
  121. package/src/sources/EvmChain.res +94 -0
  122. package/src/sources/EvmChain.res.mjs +60 -0
  123. package/src/sources/Fuel.res +19 -34
  124. package/src/sources/Fuel.res.mjs +34 -16
  125. package/src/sources/FuelSDK.res +38 -0
  126. package/src/sources/FuelSDK.res.mjs +29 -0
  127. package/src/sources/HyperFuel.res +2 -2
  128. package/src/sources/HyperFuel.resi +1 -1
  129. package/src/sources/HyperFuelClient.res +2 -2
  130. package/src/sources/HyperFuelSource.res +33 -13
  131. package/src/sources/HyperFuelSource.res.mjs +24 -16
  132. package/src/sources/HyperSync.res +36 -6
  133. package/src/sources/HyperSync.res.mjs +9 -7
  134. package/src/sources/HyperSync.resi +4 -0
  135. package/src/sources/HyperSyncClient.res +1 -1
  136. package/src/sources/HyperSyncHeightStream.res +47 -116
  137. package/src/sources/HyperSyncHeightStream.res.mjs +46 -73
  138. package/src/sources/HyperSyncSource.res +118 -139
  139. package/src/sources/HyperSyncSource.res.mjs +104 -121
  140. package/src/sources/Rpc.res +86 -14
  141. package/src/sources/Rpc.res.mjs +101 -9
  142. package/src/sources/RpcSource.res +621 -364
  143. package/src/sources/RpcSource.res.mjs +843 -410
  144. package/src/sources/RpcWebSocketHeightStream.res +181 -0
  145. package/src/sources/RpcWebSocketHeightStream.res.mjs +196 -0
  146. package/src/sources/Source.res +7 -5
  147. package/src/sources/SourceManager.res +325 -225
  148. package/src/sources/SourceManager.res.mjs +314 -171
  149. package/src/sources/SourceManager.resi +17 -6
  150. package/src/sources/Svm.res +81 -0
  151. package/src/sources/Svm.res.mjs +90 -0
  152. package/src/tui/Tui.res +247 -0
  153. package/src/tui/Tui.res.mjs +337 -0
  154. package/src/tui/bindings/Ink.res +371 -0
  155. package/src/tui/bindings/Ink.res.mjs +72 -0
  156. package/src/tui/bindings/Style.res +123 -0
  157. package/src/tui/bindings/Style.res.mjs +2 -0
  158. package/src/tui/components/BufferedProgressBar.res +40 -0
  159. package/src/tui/components/BufferedProgressBar.res.mjs +57 -0
  160. package/src/tui/components/CustomHooks.res +122 -0
  161. package/src/tui/components/CustomHooks.res.mjs +179 -0
  162. package/src/tui/components/Messages.res +41 -0
  163. package/src/tui/components/Messages.res.mjs +75 -0
  164. package/src/tui/components/SyncETA.res +174 -0
  165. package/src/tui/components/SyncETA.res.mjs +263 -0
  166. package/src/tui/components/TuiData.res +47 -0
  167. package/src/tui/components/TuiData.res.mjs +34 -0
  168. package/svm.schema.json +112 -0
  169. package/bin.js +0 -48
  170. package/src/EventRegister.res +0 -241
  171. package/src/EventRegister.res.mjs +0 -240
  172. package/src/bindings/Ethers.gen.ts +0 -14
  173. package/src/bindings/Ethers.res +0 -204
  174. package/src/bindings/Ethers.res.mjs +0 -130
  175. /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, newBlockFallbackStallTimeoutOpt, stalledPollingIntervalOpt, getHeightRetryIntervalOpt) {
28
- var newBlockFallbackStallTimeout = newBlockFallbackStallTimeoutOpt !== undefined ? newBlockFallbackStallTimeoutOpt : 20000;
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 === "Sync";
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
- sources: new Set(sources),
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
- newBlockFallbackStallTimeout: newBlockFallbackStallTimeout,
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.incrementMany(promCounter, sourceManager.activeSource.chain, Hrtime.intFromMillis(Hrtime.toMillis(Hrtime.timeSince(sourceManager.statusStart))));
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, currentBlockHeight, executeQuery, waitForNewBlock, onNewBlock, stateId) {
72
- var queries = FetchState.getNextQuery(fetchState, sourceManager.maxPartitionConcurrency - sourceManager.fetchingPartitionsCount | 0, currentBlockHeight, stateId);
73
- if (typeof queries !== "object") {
74
- switch (queries) {
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 currentBlockHeight$1 = await waitForNewBlock(currentBlockHeight);
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(currentBlockHeight$1);
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$1 = queries._0;
98
- FetchState.startFetchingQueries(fetchState, queries$1, stateId);
99
- sourceManager.fetchingPartitionsCount = sourceManager.fetchingPartitionsCount + queries$1.length | 0;
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$1, (function (q) {
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
- async function getSourceNewHeight(sourceManager, source, currentBlockHeight, status, logger) {
119
- var newHeight = 0;
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 <= currentBlockHeight && status.contents !== "Done") {
122
- try {
123
- var endTimer = Prometheus.SourceGetHeightDuration.startTimer({
124
- source: source.name,
125
- chainId: source.chain
126
- });
127
- var height = await source.getHeightOrThrow();
128
- endTimer();
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
- catch (raw_exn){
138
- var exn = Caml_js_exceptions.internalToOCamlException(raw_exn);
139
- var retryInterval = sourceManager.getHeightRetryInterval(retry);
140
- Logging.childTrace(logger, {
141
- msg: "Height retrieval from " + source.name + " source failed. Retrying in " + String(retryInterval) + "ms.",
142
- source: source.name,
143
- err: Utils.prettifyExn(exn)
144
- });
145
- retry = retry + 1 | 0;
146
- await Utils.delay(retryInterval);
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
- Prometheus.SourceHeight.set(source.name, source.chain, newHeight);
238
+ if (newHeight > initialHeight) {
239
+ Prometheus.SourceHeight.set(source.name, source.chain, newHeight);
240
+ }
150
241
  return newHeight;
151
242
  }
152
243
 
153
- async function waitForNewBlock(sourceManager, currentBlockHeight) {
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
- currentBlockHeight: currentBlockHeight
333
+ knownHeight: knownHeight
157
334
  });
158
335
  Logging.childTrace(logger, "Initiating check for new blocks.");
159
- var isInitialHeightFetch = currentBlockHeight === 0;
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 match = await Promise.race(Belt_Array.concat(Belt_Array.map(syncSources, (async function (source) {
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, source, currentBlockHeight, status, logger)
343
+ sourceState.source,
344
+ await getSourceNewHeight(sourceManager, sourceState, knownHeight, status, logger)
176
345
  ];
177
- })), [Utils.delay(sourceManager.newBlockFallbackStallTimeout).then(function () {
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(sourceManager.newBlockFallbackStallTimeout / 1000 | 0) + "s. Continuing polling with fallback RPC sources from the configuration.");
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(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");
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 (source) {
363
+ return Promise.race(Belt_Array.map(fallbackSources, (async function (sourceState) {
187
364
  return [
188
- source,
189
- await getSourceNewHeight(sourceManager, source, currentBlockHeight, status, logger)
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 getNextSyncSource(sourceManager, initialSource, currentSource, 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 === 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 source = sourceRef;
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, currentBlockHeight, query.partitionId, query.selection, retry, logger);
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$1 = error$1.retry;
446
+ var match = error$1.retry;
297
447
  var attemptedToBlock = error$1.attemptedToBlock;
298
448
  var exn = error$1.exn;
299
- switch (match$1.TAG) {
449
+ switch (match.TAG) {
300
450
  case "WithSuggestedToBlock" :
301
- var toBlock$1 = match$1.toBlock;
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$1.backoffMillis;
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$1.message,
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 = nextSource !== source;
470
+ var shouldSwitch = retry === 0 || retry === 1 ? false : retry % 2 === 0;
323
471
  if (shouldSwitch) {
324
- Logging.childInfo(logger, {
325
- msg: "Switching to another data-source",
326
- source: nextSource.name
327
- });
328
- sourceRef = nextSource;
329
- shouldUpdateActiveSource = true;
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 nextSource$1 = getNextSyncSource(sourceManager, initialSource, source, true);
337
- var hasAnotherSource = nextSource$1 !== initialSource;
338
- Logging.childWarn(logger, {
339
- msg: match$1.message + (
340
- hasAnotherSource ? " - Attempting to another source" : ""
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
- if (hasAnotherSource) {
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 nextSource$2 = getNextSyncSource(sourceManager, initialSource, source, undefined);
360
- var notAlreadyDeleted = sourceManager.sources.delete(source);
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
- if (nextSource$2 === source) {
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 ,