envio 3.6.0 → 3.6.1

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "envio",
3
- "version": "3.6.0",
3
+ "version": "3.6.1",
4
4
  "type": "module",
5
5
  "description": "A latency and sync speed optimized, developer friendly blockchain data indexer.",
6
6
  "bin": "./bin.mjs",
@@ -69,10 +69,10 @@
69
69
  "tsx": "4.21.0"
70
70
  },
71
71
  "optionalDependencies": {
72
- "envio-linux-x64": "3.6.0",
73
- "envio-linux-x64-musl": "3.6.0",
74
- "envio-linux-arm64": "3.6.0",
75
- "envio-darwin-x64": "3.6.0",
76
- "envio-darwin-arm64": "3.6.0"
72
+ "envio-linux-x64": "3.6.1",
73
+ "envio-linux-x64-musl": "3.6.1",
74
+ "envio-linux-arm64": "3.6.1",
75
+ "envio-darwin-x64": "3.6.1",
76
+ "envio-darwin-arm64": "3.6.1"
77
77
  }
78
78
  }
@@ -549,10 +549,16 @@ let targetBlock = (cs: t, ~chainTargetItems: float) => {
549
549
  let bufferBlockNumber = fetchState->FetchState.bufferBlockNumber
550
550
  switch cs->effectiveDensity {
551
551
  | Some(density) if density > 0. =>
552
- Pervasives.min(
553
- fetchCeiling,
554
- bufferBlockNumber + Math.ceil(chainTargetItems /. density)->Float.toInt,
555
- )
552
+ // Decided by comparison so no unbounded value is ever converted to int:
553
+ // at low densities chainTargetItems /. density exceeds the int range, and
554
+ // truncating it wraps negative — the target collapses below the frontier
555
+ // and the chain stops querying. The division only runs when its result is
556
+ // provably below the ceiling-bounded range.
557
+ if density *. (fetchCeiling - bufferBlockNumber)->Int.toFloat <= chainTargetItems {
558
+ fetchCeiling
559
+ } else {
560
+ bufferBlockNumber + Math.ceil(chainTargetItems /. density)->Float.toInt
561
+ }
556
562
  | _ => Pervasives.min(bufferBlockNumber + coldTargetRange, fetchCeiling)
557
563
  }
558
564
  }
@@ -368,7 +368,11 @@ function targetBlock(cs, chainTargetItems) {
368
368
  let bufferBlockNumber = FetchState.bufferBlockNumber(fetchState);
369
369
  let density = effectiveDensity(cs);
370
370
  if (density !== undefined && density > 0) {
371
- return Primitive_int.min(fetchCeiling$1, bufferBlockNumber + (Math.ceil(chainTargetItems / density) | 0) | 0);
371
+ if (density * (fetchCeiling$1 - bufferBlockNumber | 0) <= chainTargetItems) {
372
+ return fetchCeiling$1;
373
+ } else {
374
+ return bufferBlockNumber + (Math.ceil(chainTargetItems / density) | 0) | 0;
375
+ }
372
376
  } else {
373
377
  return Primitive_int.min(bufferBlockNumber + 20000 | 0, fetchCeiling$1);
374
378
  }
package/src/Metrics.res CHANGED
@@ -445,15 +445,15 @@ let renderMetrics = (b: builder, metrics: t) => {
445
445
  ~entries=chains,
446
446
  ~value=m => m.endBlock->Option.map(Int.toFloat),
447
447
  )
448
- b->series(
448
+ b->seriesOpt(
449
449
  ~name="envio_source_request_total",
450
- ~help="The number of requests made to data sources.",
450
+ ~help="The number of requests made to data sources. Heights pushed by a subscription stream are counted here too, under the heightPush and heightPushIgnored methods.",
451
451
  ~kind="counter",
452
452
  ~entries=sourceRequests,
453
- ~value=s => s.count->Int.toFloat,
453
+ ~value=s => s.count > 0 ? Some(s.count->Int.toFloat) : None,
454
454
  )
455
- // Skips a method's seconds line when it has no timing (e.g. heightSubscription,
456
- // which only ever records a count).
455
+ // Skips a method's seconds line when it has no timing (e.g. heightPush, which
456
+ // only ever records a count).
457
457
  b->seriesOpt(
458
458
  ~name="envio_source_request_seconds_total",
459
459
  ~help="Cumulative time spent on data source requests.",
@@ -144,7 +144,11 @@ function renderMetrics(b, metrics) {
144
144
  single(b, "envio_indexing_target_buffer_size", "The indexer-wide target buffer size shared across all chains. The actual number of items in the queue may exceed this value, but the indexer always tries to keep the buffer filled up to this target.", "gauge", metrics.targetBufferSize);
145
145
  series(b, "envio_indexing_buffer_block", "The highest block number that has been fully fetched by the indexer.", "gauge", chains, m => m.bufferBlockNumber);
146
146
  seriesOpt(b, "envio_indexing_end_block", "The block number to stop indexing at. (inclusive)", "gauge", chains, m => Stdlib_Option.map(m.endBlock, prim => prim));
147
- series(b, "envio_source_request_total", "The number of requests made to data sources.", "counter", sourceRequests, s => s.count);
147
+ seriesOpt(b, "envio_source_request_total", "The number of requests made to data sources. Heights pushed by a subscription stream are counted here too, under the heightPush and heightPushIgnored methods.", "counter", sourceRequests, s => {
148
+ if (s.count > 0) {
149
+ return s.count;
150
+ }
151
+ });
148
152
  seriesOpt(b, "envio_source_request_seconds_total", "Cumulative time spent on data source requests.", "counter", sourceRequests, s => {
149
153
  if (s.seconds !== 0) {
150
154
  return s.seconds;
@@ -468,16 +468,16 @@ let getSourceNewHeight = async (
468
468
  // head on every (re)connect; waking the wait loop on a height we already
469
469
  // know spins it and leaks fallback pollers (#1270).
470
470
  if newHeight > sourceState.knownHeight {
471
+ sourceState->recordRequestStats([{Source.method: "heightPush", seconds: 0.}])
471
472
  sourceState.knownHeight = newHeight
472
473
  let resolvers = sourceState.pendingHeightResolvers
473
474
  sourceState.pendingHeightResolvers = []
474
475
  resolvers->Array.forEach(resolve => resolve(newHeight))
476
+ } else {
477
+ sourceState->recordRequestStats([{Source.method: "heightPushIgnored", seconds: 0.}])
475
478
  }
476
479
  })
477
480
  sourceState.unsubscribe = Some(unsubscribe)
478
- // Count a subscription (re)start rather than every pushed height —
479
- // there's no request/response to time here.
480
- sourceState->recordRequestStats([{Source.method: "heightSubscription", seconds: 0.}])
481
481
  | _ =>
482
482
  // Slowdown polling when the chain isn't progressing
483
483
  let pollingInterval = if reducedPolling {
@@ -724,9 +724,7 @@ let executeQuery = async (
724
724
  ) {
725
725
  | Some(s) =>
726
726
  if s.source !== sourceManager.activeSource {
727
- let logger = Logging.createChild(
728
- ~params={"chainId": sourceManager.activeSource.chainId},
729
- )
727
+ let logger = Logging.createChild(~params={"chainId": sourceManager.activeSource.chainId})
730
728
  logger->Logging.childInfo({
731
729
  "msg": "Switching data-source",
732
730
  "source": s.source.name,
@@ -736,9 +734,7 @@ let executeQuery = async (
736
734
  }
737
735
  s
738
736
  | None =>
739
- let logger = Logging.createChild(
740
- ~params={"chainId": sourceManager.activeSource.chainId},
741
- )
737
+ let logger = Logging.createChild(~params={"chainId": sourceManager.activeSource.chainId})
742
738
  %raw(`null`)->ErrorHandling.mkLogAndRaise(~logger, ~msg=noSourcesError)
743
739
  }
744
740
  sourceManager.activeSource = sourceState.source
@@ -895,9 +891,7 @@ let getBlockHashes = async (sourceManager: t, ~blockNumbers: array<int>, ~isReal
895
891
  let sourceState = switch sourceManager->getNextSource(~isRealtime) {
896
892
  | Some(s) => s
897
893
  | None =>
898
- let logger = Logging.createChild(
899
- ~params={"chainId": sourceManager.activeSource.chainId},
900
- )
894
+ let logger = Logging.createChild(~params={"chainId": sourceManager.activeSource.chainId})
901
895
  %raw(`null`)->ErrorHandling.mkLogAndRaise(
902
896
  ~logger,
903
897
  ~msg="No data-sources available for fetching block hashes.",
@@ -388,18 +388,21 @@ async function getSourceNewHeight(sourceManager, sourceState, knownHeight, stall
388
388
  if (createSubscription !== undefined && isRealtime) {
389
389
  let unsubscribe = createSubscription(newHeight => {
390
390
  if (newHeight <= sourceState.knownHeight) {
391
- return;
391
+ return recordRequestStats(sourceState, [{
392
+ method: "heightPushIgnored",
393
+ seconds: 0
394
+ }]);
392
395
  }
396
+ recordRequestStats(sourceState, [{
397
+ method: "heightPush",
398
+ seconds: 0
399
+ }]);
393
400
  sourceState.knownHeight = newHeight;
394
401
  let resolvers = sourceState.pendingHeightResolvers;
395
402
  sourceState.pendingHeightResolvers = [];
396
403
  resolvers.forEach(resolve => resolve(newHeight));
397
404
  });
398
405
  sourceState.unsubscribe = unsubscribe;
399
- recordRequestStats(sourceState, [{
400
- method: "heightSubscription",
401
- seconds: 0
402
- }]);
403
406
  } else {
404
407
  exit = 1;
405
408
  }