envio 3.0.0-alpha.3 → 3.0.0-alpha.4

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.
@@ -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
 
@@ -35,7 +36,15 @@ function make(sources, maxPartitionConcurrency, newBlockFallbackStallTimeoutOpt,
35
36
  Prometheus.IndexingMaxConcurrency.set(maxPartitionConcurrency, initialActiveSource.chain);
36
37
  Prometheus.IndexingConcurrency.set(0, initialActiveSource.chain);
37
38
  return {
38
- sources: new Set(sources),
39
+ sourcesState: Belt_Array.map(sources, (function (source) {
40
+ return {
41
+ source: source,
42
+ knownHeight: 0,
43
+ unsubscribe: undefined,
44
+ pendingHeightResolvers: [],
45
+ disabled: false
46
+ };
47
+ })),
39
48
  statusStart: Hrtime.makeTimer(),
40
49
  status: "Idle",
41
50
  maxPartitionConcurrency: maxPartitionConcurrency,
@@ -115,38 +124,78 @@ async function fetchNext(sourceManager, fetchState, executeQuery, waitForNewBloc
115
124
  }
116
125
  }
117
126
 
118
- async function getSourceNewHeight(sourceManager, source, knownHeight, status, logger) {
119
- var newHeight = 0;
127
+ function disableSource(sourceState) {
128
+ if (sourceState.disabled) {
129
+ return false;
130
+ }
131
+ sourceState.disabled = true;
132
+ var unsubscribe = sourceState.unsubscribe;
133
+ if (unsubscribe !== undefined) {
134
+ unsubscribe();
135
+ }
136
+ return true;
137
+ }
138
+
139
+ async function getSourceNewHeight(sourceManager, sourceState, knownHeight, status, logger) {
140
+ var source = sourceState.source;
141
+ var initialHeight = sourceState.knownHeight;
142
+ var newHeight = initialHeight;
120
143
  var retry = 0;
121
144
  while(newHeight <= knownHeight && 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 <= knownHeight) {
131
- retry = 0;
132
- var pollingInterval = status.contents === "Stalled" ? sourceManager.stalledPollingInterval : source.pollingInterval;
133
- await Utils.delay(pollingInterval);
145
+ var match = sourceState.unsubscribe;
146
+ if (match !== undefined) {
147
+ var height = await new Promise((function (resolve, _reject) {
148
+ sourceState.pendingHeightResolvers.push(resolve);
149
+ }));
150
+ if (height > initialHeight) {
151
+ newHeight = height;
134
152
  }
135
153
 
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);
154
+ } else {
155
+ try {
156
+ var endTimer = Prometheus.SourceGetHeightDuration.startTimer({
157
+ source: source.name,
158
+ chainId: source.chain
159
+ });
160
+ var height$1 = await source.getHeightOrThrow();
161
+ endTimer();
162
+ newHeight = height$1;
163
+ if (height$1 <= knownHeight) {
164
+ retry = 0;
165
+ var createSubscription = source.createHeightSubscription;
166
+ if (createSubscription !== undefined) {
167
+ var unsubscribe = createSubscription(function (newHeight) {
168
+ sourceState.knownHeight = newHeight;
169
+ var resolvers = sourceState.pendingHeightResolvers;
170
+ sourceState.pendingHeightResolvers = [];
171
+ Belt_Array.forEach(resolvers, (function (resolve) {
172
+ resolve(newHeight);
173
+ }));
174
+ });
175
+ sourceState.unsubscribe = unsubscribe;
176
+ } else {
177
+ var pollingInterval = status.contents === "Stalled" ? sourceManager.stalledPollingInterval : source.pollingInterval;
178
+ await Utils.delay(pollingInterval);
179
+ }
180
+ }
181
+
182
+ }
183
+ catch (raw_exn){
184
+ var exn = Caml_js_exceptions.internalToOCamlException(raw_exn);
185
+ var retryInterval = sourceManager.getHeightRetryInterval(retry);
186
+ Logging.childTrace(logger, {
187
+ msg: "Height retrieval from " + source.name + " source failed. Retrying in " + String(retryInterval) + "ms.",
188
+ source: source.name,
189
+ err: Utils.prettifyExn(exn)
190
+ });
191
+ retry = retry + 1 | 0;
192
+ await Utils.delay(retryInterval);
193
+ }
147
194
  }
148
195
  };
149
- Prometheus.SourceHeight.set(source.name, source.chain, newHeight);
196
+ if (newHeight > initialHeight) {
197
+ Prometheus.SourceHeight.set(source.name, source.chain, newHeight);
198
+ }
150
199
  return newHeight;
151
200
  }
152
201
 
@@ -159,20 +208,26 @@ async function waitForNewBlock(sourceManager, knownHeight) {
159
208
  var isInitialHeightFetch = knownHeight === 0;
160
209
  var syncSources = [];
161
210
  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
- });
211
+ Belt_Array.forEach(sourceManager.sourcesState, (function (sourceState) {
212
+ var source = sourceState.source;
213
+ if (sourceState.disabled) {
214
+ return ;
215
+ } else {
216
+ if (source.sourceFor === "Sync" || source.sourceFor === "Live" && !isInitialHeightFetch || source === sourceManager.activeSource) {
217
+ syncSources.push(sourceState);
218
+ } else {
219
+ fallbackSources.push(sourceState);
220
+ }
221
+ return ;
222
+ }
223
+ }));
169
224
  var status = {
170
225
  contents: "Active"
171
226
  };
172
- var match = await Promise.race(Belt_Array.concat(Belt_Array.map(syncSources, (async function (source) {
227
+ var match = await Promise.race(Belt_Array.concat(Belt_Array.map(syncSources, (async function (sourceState) {
173
228
  return [
174
- source,
175
- await getSourceNewHeight(sourceManager, source, knownHeight, status, logger)
229
+ sourceState.source,
230
+ await getSourceNewHeight(sourceManager, sourceState, knownHeight, status, logger)
176
231
  ];
177
232
  })), [Utils.delay(sourceManager.newBlockFallbackStallTimeout).then(function () {
178
233
  if (status.contents !== "Done") {
@@ -183,10 +238,10 @@ async function waitForNewBlock(sourceManager, knownHeight) {
183
238
  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
239
  }
185
240
  }
186
- return Promise.race(Belt_Array.map(fallbackSources, (async function (source) {
241
+ return Promise.race(Belt_Array.map(fallbackSources, (async function (sourceState) {
187
242
  return [
188
- source,
189
- await getSourceNewHeight(sourceManager, source, knownHeight, status, logger)
243
+ sourceState.source,
244
+ await getSourceNewHeight(sourceManager, sourceState, knownHeight, status, logger)
190
245
  ];
191
246
  })));
192
247
  })]));
@@ -203,38 +258,42 @@ async function waitForNewBlock(sourceManager, knownHeight) {
203
258
  return newBlockHeight;
204
259
  }
205
260
 
206
- function getNextSyncSource(sourceManager, initialSource, currentSource, attemptFallbacksOpt) {
261
+ function getNextSyncSourceState(sourceManager, initialSourceState, currentSourceState, attemptFallbacksOpt) {
207
262
  var attemptFallbacks = attemptFallbacksOpt !== undefined ? attemptFallbacksOpt : false;
208
263
  var before = [];
209
264
  var after = [];
210
265
  var hasActive = {
211
266
  contents: false
212
267
  };
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;
268
+ Belt_Array.forEach(sourceManager.sourcesState, (function (sourceState) {
269
+ var source = sourceState.source;
270
+ if (sourceState.disabled) {
271
+ return ;
272
+ }
273
+ if (sourceState === currentSourceState) {
274
+ hasActive.contents = true;
275
+ return ;
276
+ }
277
+ var match = source.sourceFor;
278
+ var tmp;
279
+ switch (match) {
280
+ case "Sync" :
281
+ tmp = true;
282
+ break;
283
+ case "Fallback" :
284
+ case "Live" :
285
+ tmp = attemptFallbacks || sourceState === initialSourceState;
286
+ break;
287
+
288
+ }
289
+ if (tmp) {
290
+ (
291
+ hasActive.contents ? after : before
292
+ ).push(sourceState);
293
+ return ;
294
+ }
228
295
 
229
- }
230
- if (tmp) {
231
- (
232
- hasActive.contents ? after : before
233
- ).push(source);
234
- return ;
235
- }
236
-
237
- });
296
+ }));
238
297
  var s = Belt_Array.get(after, 0);
239
298
  if (s !== undefined) {
240
299
  return s;
@@ -243,7 +302,7 @@ function getNextSyncSource(sourceManager, initialSource, currentSource, attemptF
243
302
  if (s$1 !== undefined) {
244
303
  return s$1;
245
304
  } else {
246
- return currentSource;
305
+ return currentSourceState;
247
306
  }
248
307
  }
249
308
 
@@ -255,11 +314,15 @@ async function executeQuery(sourceManager, query, knownHeight) {
255
314
  );
256
315
  var responseRef;
257
316
  var retryRef = 0;
258
- var initialSource = sourceManager.activeSource;
259
- var sourceRef = initialSource;
317
+ var initialSourceState = sourceManager.sourcesState.find(function (s) {
318
+ return s.source === sourceManager.activeSource;
319
+ });
320
+ var initialSourceState$1 = initialSourceState === undefined ? undefined : Caml_option.some(initialSourceState);
321
+ var sourceStateRef = initialSourceState$1;
260
322
  var shouldUpdateActiveSource = false;
261
323
  while(Belt_Option.isNone(responseRef)) {
262
- var source = sourceRef;
324
+ var sourceState = sourceStateRef;
325
+ var source = sourceState.source;
263
326
  var toBlock = toBlockRef;
264
327
  var retry = retryRef;
265
328
  var logger = Logging.createChild({
@@ -310,7 +373,7 @@ async function executeQuery(sourceManager, query, knownHeight) {
310
373
  case "WithBackoff" :
311
374
  var backoffMillis = match$1.backoffMillis;
312
375
  var attemptFallbacks = retry >= 10;
313
- var nextSource = !(retry === 0 || retry === 1) && retry % 2 === 0 ? getNextSyncSource(sourceManager, initialSource, source, attemptFallbacks) : source;
376
+ var nextSourceState = !(retry === 0 || retry === 1) && retry % 2 === 0 ? getNextSyncSourceState(sourceManager, initialSourceState$1, sourceState, attemptFallbacks) : sourceState;
314
377
  var log = retry >= 4 ? Logging.childWarn : Logging.childTrace;
315
378
  log(logger, {
316
379
  msg: match$1.message,
@@ -319,13 +382,13 @@ async function executeQuery(sourceManager, query, knownHeight) {
319
382
  retry: retry,
320
383
  err: Utils.prettifyExn(exn)
321
384
  });
322
- var shouldSwitch = nextSource !== source;
385
+ var shouldSwitch = nextSourceState !== sourceState;
323
386
  if (shouldSwitch) {
324
387
  Logging.childInfo(logger, {
325
388
  msg: "Switching to another data-source",
326
- source: nextSource.name
389
+ source: nextSourceState.source.name
327
390
  });
328
- sourceRef = nextSource;
391
+ sourceStateRef = nextSourceState;
329
392
  shouldUpdateActiveSource = true;
330
393
  } else {
331
394
  await Utils.delay(backoffMillis < 60000 ? backoffMillis : 60000);
@@ -333,8 +396,8 @@ async function executeQuery(sourceManager, query, knownHeight) {
333
396
  retryRef = retryRef + 1 | 0;
334
397
  break;
335
398
  case "ImpossibleForTheQuery" :
336
- var nextSource$1 = getNextSyncSource(sourceManager, initialSource, source, true);
337
- var hasAnotherSource = nextSource$1 !== initialSource;
399
+ var nextSourceState$1 = getNextSyncSourceState(sourceManager, initialSourceState$1, sourceState, true);
400
+ var hasAnotherSource = nextSourceState$1 !== initialSourceState$1;
338
401
  Logging.childWarn(logger, {
339
402
  msg: match$1.message + (
340
403
  hasAnotherSource ? " - Attempting to another source" : ""
@@ -343,7 +406,7 @@ async function executeQuery(sourceManager, query, knownHeight) {
343
406
  err: Utils.prettifyExn(exn)
344
407
  });
345
408
  if (hasAnotherSource) {
346
- sourceRef = nextSource$1;
409
+ sourceStateRef = nextSourceState$1;
347
410
  shouldUpdateActiveSource = false;
348
411
  retryRef = 0;
349
412
  } else {
@@ -356,9 +419,9 @@ async function executeQuery(sourceManager, query, knownHeight) {
356
419
 
357
420
  }
358
421
  if (exit === 1) {
359
- var nextSource$2 = getNextSyncSource(sourceManager, initialSource, source, undefined);
360
- var notAlreadyDeleted = sourceManager.sources.delete(source);
361
- if (notAlreadyDeleted) {
422
+ var nextSourceState$2 = getNextSyncSourceState(sourceManager, initialSourceState$1, sourceState, undefined);
423
+ var notAlreadyDisabled = disableSource(sourceState);
424
+ if (notAlreadyDisabled) {
362
425
  switch (error$1.TAG) {
363
426
  case "UnsupportedSelection" :
364
427
  Logging.childError(logger, error$1.message);
@@ -376,14 +439,14 @@ async function executeQuery(sourceManager, query, knownHeight) {
376
439
 
377
440
  }
378
441
  }
379
- if (nextSource$2 === source) {
442
+ if (nextSourceState$2 === sourceState) {
380
443
  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
444
  } else {
382
445
  Logging.childInfo(logger, {
383
446
  msg: "Switching to another data-source",
384
- source: nextSource$2.name
447
+ source: nextSourceState$2.source.name
385
448
  });
386
- sourceRef = nextSource$2;
449
+ sourceStateRef = nextSourceState$2;
387
450
  shouldUpdateActiveSource = true;
388
451
  retryRef = 0;
389
452
  }
@@ -395,7 +458,7 @@ async function executeQuery(sourceManager, query, knownHeight) {
395
458
  }
396
459
  };
397
460
  if (shouldUpdateActiveSource) {
398
- sourceManager.activeSource = sourceRef;
461
+ sourceManager.activeSource = sourceStateRef.source;
399
462
  }
400
463
  return responseRef;
401
464
  }
@@ -9,7 +9,7 @@ let cleanUpRawEventFieldsInPlace: Js.Json.t => unit = %raw(`fields => {
9
9
  }`)
10
10
 
11
11
  let ecosystem: Ecosystem.t = {
12
- name: Solana,
12
+ name: Svm,
13
13
  blockFields: ["slot"],
14
14
  transactionFields: [],
15
15
  blockNumberName: "height",
@@ -36,13 +36,13 @@ let makeRPCSource = (~chain, ~rpc: string): Source.t => {
36
36
  let client = Rest.client(rpc)
37
37
 
38
38
  {
39
- name: "Solana",
39
+ name: "Svm",
40
40
  sourceFor: Sync,
41
41
  chain,
42
42
  poweredByHyperSync: false,
43
43
  pollingInterval: 10_000,
44
44
  getBlockHashes: (~blockNumbers as _, ~logger as _) =>
45
- Js.Exn.raiseError("Solana does not support getting block hashes"),
45
+ Js.Exn.raiseError("Svm does not support getting block hashes"),
46
46
  getHeightOrThrow: () => GetFinalizedSlot.route->Rest.fetch((), ~client),
47
47
  getItemsOrThrow: (
48
48
  ~fromBlock as _,
@@ -54,6 +54,6 @@ let makeRPCSource = (~chain, ~rpc: string): Source.t => {
54
54
  ~selection as _,
55
55
  ~retry as _,
56
56
  ~logger as _,
57
- ) => Js.Exn.raiseError("Solana does not support getting items"),
57
+ ) => Js.Exn.raiseError("Svm does not support getting items"),
58
58
  }
59
59
  }
@@ -28,7 +28,7 @@ function ecosystem_getId(prim) {
28
28
  }
29
29
 
30
30
  var ecosystem = {
31
- name: "solana",
31
+ name: "svm",
32
32
  blockFields: ecosystem_blockFields,
33
33
  transactionFields: ecosystem_transactionFields,
34
34
  blockNumberName: "height",
@@ -53,19 +53,19 @@ var GetFinalizedSlot = {
53
53
  function makeRPCSource(chain, rpc) {
54
54
  var client = Rest.client(rpc, undefined);
55
55
  return {
56
- name: "Solana",
56
+ name: "Svm",
57
57
  sourceFor: "Sync",
58
58
  chain: chain,
59
59
  poweredByHyperSync: false,
60
60
  pollingInterval: 10000,
61
61
  getBlockHashes: (function (param, param$1) {
62
- return Js_exn.raiseError("Solana does not support getting block hashes");
62
+ return Js_exn.raiseError("Svm does not support getting block hashes");
63
63
  }),
64
64
  getHeightOrThrow: (function () {
65
65
  return Rest.$$fetch(route, undefined, client);
66
66
  }),
67
67
  getItemsOrThrow: (function (param, param$1, param$2, param$3, param$4, param$5, param$6, param$7, param$8) {
68
- return Js_exn.raiseError("Solana does not support getting items");
68
+ return Js_exn.raiseError("Svm does not support getting items");
69
69
  })
70
70
  };
71
71
  }
@@ -1,14 +0,0 @@
1
- /* TypeScript file generated from Ethers.res by genType. */
2
-
3
- /* eslint-disable */
4
- /* tslint:disable */
5
-
6
- import * as EthersJS from './Ethers.res.mjs';
7
-
8
- import type {t as Address_t} from '../../src/Address.gen.js';
9
-
10
- export const Addresses_mockAddresses: Address_t[] = EthersJS.Addresses.mockAddresses as any;
11
-
12
- export const Addresses_defaultAddress: Address_t = EthersJS.Addresses.defaultAddress as any;
13
-
14
- export const Addresses: { mockAddresses: Address_t[]; defaultAddress: Address_t } = EthersJS.Addresses as any;