envio 3.3.0-alpha.6 → 3.3.0-alpha.7

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.
@@ -90,23 +90,41 @@ let deriveContractNameByAddress: dict<array<Address.t>> => dict<
90
90
  result
91
91
  })
92
92
 
93
+ // Bounds for the no-history default estimate below. Also used by SourceManager
94
+ // as the floor for its own maxNumLogs-style safety net.
95
+ let minEstResponseSize = 2_000.
96
+ let maxEstResponseSize = 10_000.
97
+
93
98
  // Default estimate for a query whose partition hasn't responded yet, so the
94
99
  // shared budget still accounts for unknown queries instead of treating them as
95
- // free.
96
- let defaultEstResponseSize = 10_000.
100
+ // free. Scaled down as partitionsCount grows: assuming every partition's first
101
+ // query is "big" starves the rest of that tick's admission when many
102
+ // partitions share the same buffer, so the per-partition default shrinks
103
+ // accordingly — clamped to [minEstResponseSize, maxEstResponseSize] either way.
104
+ let calculateDefaultEstResponseSize = (~partitionsCount) =>
105
+ Pervasives.max(
106
+ minEstResponseSize,
107
+ Pervasives.min(maxEstResponseSize, 20_000. /. partitionsCount->Int.toFloat),
108
+ )
97
109
 
98
110
  // Estimated items a query will return, from the partition's event density
99
111
  // (items/block derived from its last response) and the query's block range.
100
- // toBlock None is the open-ended tail, capped at maxQueryBlockNumber. A partition
112
+ // toBlock None is the open-ended tail, capped at knownHeight. A partition
101
113
  // that responded with no items has density 0, so its queries cost 0 — correct,
102
114
  // they don't fill the buffer. Only a partition that has never responded
103
- // (prevQueryRange 0) has no signal, so it falls back to defaultEstResponseSize.
104
- let calculateEstResponseSize = (p: partition, ~fromBlock, ~toBlock, ~maxQueryBlockNumber) =>
115
+ // (prevQueryRange 0) has no signal, so it falls back to calculateDefaultEstResponseSize.
116
+ let calculateEstResponseSize = (
117
+ p: partition,
118
+ ~fromBlock,
119
+ ~toBlock,
120
+ ~knownHeight,
121
+ ~partitionsCount,
122
+ ) =>
105
123
  if p.prevQueryRange > 0 {
106
124
  let density = p.prevRangeSize->Int.toFloat /. p.prevQueryRange->Int.toFloat
107
- (toBlock->Option.getOr(maxQueryBlockNumber) - fromBlock + 1)->Int.toFloat *. density
125
+ (toBlock->Option.getOr(knownHeight) - fromBlock + 1)->Int.toFloat *. density
108
126
  } else {
109
- defaultEstResponseSize
127
+ calculateDefaultEstResponseSize(~partitionsCount)
110
128
  }
111
129
 
112
130
  // Calculate the chunk range from history using min-of-last-3-ranges heuristic
@@ -545,8 +563,8 @@ type t = {
545
563
  // Buffer of items ordered from earliest to latest
546
564
  buffer: array<Internal.item>,
547
565
  // Caps how far ahead onBlock items are pre-generated (set to 2x the batch
548
- // size). Fetch depth is bounded separately by getNextQuery's itemBudget, the
549
- // chain's per-tick slice of the indexer-wide pool.
566
+ // size). Event fetch depth is bounded separately, by CrossChainState's
567
+ // cross-chain admission against the indexer-wide buffer pool.
550
568
  maxOnBlockBufferSize: int,
551
569
  onBlockConfigs: array<Internal.onBlockConfig>,
552
570
  knownHeight: int,
@@ -1352,14 +1370,15 @@ let pushQueriesForRange = (
1352
1370
  ~partitionId: string,
1353
1371
  ~rangeFromBlock: int,
1354
1372
  ~rangeEndBlock: option<int>,
1355
- ~maxQueryBlockNumber: int,
1373
+ ~knownHeight: int,
1356
1374
  ~maybeChunkRange: option<int>,
1357
1375
  ~maxChunks: int,
1358
1376
  ~partition: partition,
1359
1377
  ~selection: selection,
1360
1378
  ~addressesByContractName: dict<array<Address.t>>,
1379
+ ~partitionsCount: int,
1361
1380
  ) => {
1362
- if rangeFromBlock <= maxQueryBlockNumber && maxChunks > 0 {
1381
+ if rangeFromBlock <= knownHeight && maxChunks > 0 {
1363
1382
  switch rangeEndBlock {
1364
1383
  | Some(endBlock) if rangeFromBlock > endBlock => ()
1365
1384
  | _ =>
@@ -1375,7 +1394,8 @@ let pushQueriesForRange = (
1375
1394
  partition,
1376
1395
  ~fromBlock=rangeFromBlock,
1377
1396
  ~toBlock=rangeEndBlock,
1378
- ~maxQueryBlockNumber,
1397
+ ~knownHeight,
1398
+ ~partitionsCount,
1379
1399
  ),
1380
1400
  chainId: 0,
1381
1401
  progress: 0.,
@@ -1384,7 +1404,7 @@ let pushQueriesForRange = (
1384
1404
  | Some(chunkRange) =>
1385
1405
  let maxBlock = switch rangeEndBlock {
1386
1406
  | Some(eb) => eb
1387
- | None => maxQueryBlockNumber
1407
+ | None => knownHeight
1388
1408
  }
1389
1409
  let chunkSize = Js.Math.ceil_int(chunkRange->Int.toFloat *. 1.8)
1390
1410
  if rangeFromBlock + chunkSize * 2 - 1 <= maxBlock {
@@ -1404,7 +1424,8 @@ let pushQueriesForRange = (
1404
1424
  partition,
1405
1425
  ~fromBlock=chunkFromBlock.contents,
1406
1426
  ~toBlock=Some(chunkToBlock),
1407
- ~maxQueryBlockNumber,
1427
+ ~knownHeight,
1428
+ ~partitionsCount,
1408
1429
  ),
1409
1430
  chainId: 0,
1410
1431
  progress: 0.,
@@ -1425,7 +1446,8 @@ let pushQueriesForRange = (
1425
1446
  partition,
1426
1447
  ~fromBlock=rangeFromBlock,
1427
1448
  ~toBlock=rangeEndBlock,
1428
- ~maxQueryBlockNumber,
1449
+ ~knownHeight,
1450
+ ~partitionsCount,
1429
1451
  ),
1430
1452
  chainId: 0,
1431
1453
  progress: 0.,
@@ -1437,45 +1459,27 @@ let pushQueriesForRange = (
1437
1459
  }
1438
1460
  }
1439
1461
 
1462
+ // Candidate queries are sized against the natural ceiling (head/endBlock/mergeBlock),
1463
+ // not a share of the shared buffer — CrossChainState.checkAndFetch's admission loop
1464
+ // is what actually bounds how much gets fetched per tick, by estResponseSize (which
1465
+ // the HyperSync/SVM sources also enforce server-side via a maxNumLogs-style cap, so
1466
+ // a wrong estimate truncates the response instead of overshooting the buffer).
1440
1467
  let getNextQuery = (
1441
- {buffer, optimizedPartitions, blockLag, latestOnBlockBlockNumber, knownHeight} as fetchState: t,
1442
- ~budget,
1443
- ~chainPendingBudget,
1468
+ {optimizedPartitions, blockLag, latestOnBlockBlockNumber, knownHeight, endBlock}: t,
1444
1469
  ) => {
1445
1470
  let headBlockNumber = knownHeight - blockLag
1446
1471
  if headBlockNumber <= 0 {
1447
1472
  WaitingForNewBlock
1448
- } else if budget <= 0 {
1449
- // No room left in the shared buffer pool for this chain; wait for processing
1450
- // to drain before fetching more.
1451
- NothingToQuery
1452
1473
  } else {
1453
1474
  let isOnBlockBehindTheHead = latestOnBlockBlockNumber < headBlockNumber
1454
1475
  let shouldWaitForNewBlock = ref(
1455
- switch fetchState.endBlock {
1476
+ switch endBlock {
1456
1477
  | Some(endBlock) => headBlockNumber < endBlock
1457
1478
  | None => true
1458
1479
  } &&
1459
1480
  !isOnBlockBehindTheHead,
1460
1481
  )
1461
1482
 
1462
- // Fetch at most `budget` items past the ready frontier (plus what's already
1463
- // in flight) so processing always has buffer without ballooning memory.
1464
- // budget already excludes items at/below the frontier (they're in the shared
1465
- // totalReadyCount), so offset the index by bufferReadyCount — otherwise the
1466
- // ready prefix is subtracted twice and the buffer caps at a fraction of its
1467
- // target. A partition that fetched further is skipped until the buffer drains.
1468
- let maxQueryBlockNumber = {
1469
- switch buffer->Array.get(
1470
- fetchState->bufferReadyCount + budget + chainPendingBudget->Float.toInt - 1,
1471
- ) {
1472
- | Some(item) =>
1473
- // Just in case check that we don't query beyond the current block
1474
- Pervasives.min(item->Internal.getItemBlockNumber, knownHeight)
1475
- | None => knownHeight
1476
- }
1477
- }
1478
-
1479
1483
  let queries = []
1480
1484
 
1481
1485
  let partitionsCount = optimizedPartitions.idsInAscOrder->Array.length
@@ -1501,7 +1505,7 @@ let getNextQuery = (
1501
1505
  let partitionQueriesStart = queries->Array.length
1502
1506
 
1503
1507
  // Compute queryEndBlock for this partition
1504
- let queryEndBlock = Utils.Math.minOptInt(fetchState.endBlock, p.mergeBlock)
1508
+ let queryEndBlock = Utils.Math.minOptInt(endBlock, p.mergeBlock)
1505
1509
  let queryEndBlock = switch blockLag {
1506
1510
  | 0 => queryEndBlock
1507
1511
  | _ =>
@@ -1509,15 +1513,6 @@ let getNextQuery = (
1509
1513
  // because otherwise HyperSync might return bigger range
1510
1514
  Utils.Math.minOptInt(Some(headBlockNumber), queryEndBlock)
1511
1515
  }
1512
- // Enforce the response range up until target block
1513
- // Otherwise for indexers with 100+ partitions
1514
- // we might blow up the buffer size to more than 600k events
1515
- // simply because of HyperSync returning extra blocks
1516
- let queryEndBlock = switch (queryEndBlock, maxQueryBlockNumber < knownHeight) {
1517
- | (Some(endBlock), true) => Some(Pervasives.min(maxQueryBlockNumber, endBlock))
1518
- | (None, true) => Some(maxQueryBlockNumber)
1519
- | (_, false) => queryEndBlock
1520
- }
1521
1516
 
1522
1517
  let maybeChunkRange = getMinHistoryRange(p)
1523
1518
 
@@ -1535,7 +1530,7 @@ let getNextQuery = (
1535
1530
  ~partitionId,
1536
1531
  ~rangeFromBlock=cursor.contents,
1537
1532
  ~rangeEndBlock=Utils.Math.minOptInt(Some(pq.fromBlock - 1), queryEndBlock),
1538
- ~maxQueryBlockNumber,
1533
+ ~knownHeight,
1539
1534
  ~maybeChunkRange,
1540
1535
  ~maxChunks=maxPendingChunksPerPartition -
1541
1536
  pendingCount -
@@ -1544,6 +1539,7 @@ let getNextQuery = (
1544
1539
  ~partition=p,
1545
1540
  ~selection=p.selection,
1546
1541
  ~addressesByContractName=p.addressesByContractName,
1542
+ ~partitionsCount,
1547
1543
  )
1548
1544
  }
1549
1545
  switch pq {
@@ -1563,7 +1559,7 @@ let getNextQuery = (
1563
1559
  ~partitionId,
1564
1560
  ~rangeFromBlock=cursor.contents,
1565
1561
  ~rangeEndBlock=queryEndBlock,
1566
- ~maxQueryBlockNumber,
1562
+ ~knownHeight,
1567
1563
  ~maybeChunkRange,
1568
1564
  ~maxChunks=maxPendingChunksPerPartition -
1569
1565
  pendingCount -
@@ -1572,6 +1568,7 @@ let getNextQuery = (
1572
1568
  ~partition=p,
1573
1569
  ~selection=p.selection,
1574
1570
  ~addressesByContractName=p.addressesByContractName,
1571
+ ~partitionsCount,
1575
1572
  )
1576
1573
  }
1577
1574
 
@@ -8,6 +8,7 @@ import * as Stdlib_Int from "@rescript/runtime/lib/es6/Stdlib_Int.js";
8
8
  import * as Primitive_int from "@rescript/runtime/lib/es6/Primitive_int.js";
9
9
  import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
10
10
  import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
11
+ import * as Primitive_float from "@rescript/runtime/lib/es6/Primitive_float.js";
11
12
  import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
12
13
  import * as IndexingAddresses from "./IndexingAddresses.res.mjs";
13
14
 
@@ -21,12 +22,16 @@ let deriveContractNameByAddress = Utils.$$WeakMap.memoize(addressesByContractNam
21
22
  return result;
22
23
  });
23
24
 
24
- function calculateEstResponseSize(p, fromBlock, toBlock, maxQueryBlockNumber) {
25
+ function calculateDefaultEstResponseSize(partitionsCount) {
26
+ return Primitive_float.max(2000, Primitive_float.min(10000, 20000 / partitionsCount));
27
+ }
28
+
29
+ function calculateEstResponseSize(p, fromBlock, toBlock, knownHeight, partitionsCount) {
25
30
  if (p.prevQueryRange <= 0) {
26
- return 10000;
31
+ return calculateDefaultEstResponseSize(partitionsCount);
27
32
  }
28
33
  let density = p.prevRangeSize / p.prevQueryRange;
29
- return ((Stdlib_Option.getOr(toBlock, maxQueryBlockNumber) - fromBlock | 0) + 1 | 0) * density;
34
+ return ((Stdlib_Option.getOr(toBlock, knownHeight) - fromBlock | 0) + 1 | 0) * density;
30
35
  }
31
36
 
32
37
  function getMinHistoryRange(p) {
@@ -977,15 +982,15 @@ function startFetchingQueries(param, queries) {
977
982
  }
978
983
  }
979
984
 
980
- function pushQueriesForRange(queries, partitionId, rangeFromBlock, rangeEndBlock, maxQueryBlockNumber, maybeChunkRange, maxChunks, partition, selection, addressesByContractName) {
981
- if (!(rangeFromBlock <= maxQueryBlockNumber && maxChunks > 0)) {
985
+ function pushQueriesForRange(queries, partitionId, rangeFromBlock, rangeEndBlock, knownHeight, maybeChunkRange, maxChunks, partition, selection, addressesByContractName, partitionsCount) {
986
+ if (!(rangeFromBlock <= knownHeight && maxChunks > 0)) {
982
987
  return;
983
988
  }
984
989
  if (rangeEndBlock !== undefined && rangeFromBlock > rangeEndBlock) {
985
990
  return;
986
991
  }
987
992
  if (maybeChunkRange !== undefined) {
988
- let maxBlock = rangeEndBlock !== undefined ? rangeEndBlock : maxQueryBlockNumber;
993
+ let maxBlock = rangeEndBlock !== undefined ? rangeEndBlock : knownHeight;
989
994
  let chunkSize = Js_math.ceil_int(maybeChunkRange * 1.8);
990
995
  if (((rangeFromBlock + (chunkSize << 1) | 0) - 1 | 0) <= maxBlock) {
991
996
  let chunkFromBlock = rangeFromBlock;
@@ -997,7 +1002,7 @@ function pushQueriesForRange(queries, partitionId, rangeFromBlock, rangeEndBlock
997
1002
  fromBlock: chunkFromBlock,
998
1003
  toBlock: chunkToBlock,
999
1004
  isChunk: true,
1000
- estResponseSize: calculateEstResponseSize(partition, chunkFromBlock, chunkToBlock, maxQueryBlockNumber),
1005
+ estResponseSize: calculateEstResponseSize(partition, chunkFromBlock, chunkToBlock, knownHeight, partitionsCount),
1001
1006
  chainId: 0,
1002
1007
  progress: 0,
1003
1008
  selection: selection,
@@ -1013,7 +1018,7 @@ function pushQueriesForRange(queries, partitionId, rangeFromBlock, rangeEndBlock
1013
1018
  fromBlock: rangeFromBlock,
1014
1019
  toBlock: rangeEndBlock,
1015
1020
  isChunk: rangeEndBlock !== undefined,
1016
- estResponseSize: calculateEstResponseSize(partition, rangeFromBlock, rangeEndBlock, maxQueryBlockNumber),
1021
+ estResponseSize: calculateEstResponseSize(partition, rangeFromBlock, rangeEndBlock, knownHeight, partitionsCount),
1017
1022
  chainId: 0,
1018
1023
  progress: 0,
1019
1024
  selection: selection,
@@ -1026,7 +1031,7 @@ function pushQueriesForRange(queries, partitionId, rangeFromBlock, rangeEndBlock
1026
1031
  fromBlock: rangeFromBlock,
1027
1032
  toBlock: rangeEndBlock,
1028
1033
  isChunk: false,
1029
- estResponseSize: calculateEstResponseSize(partition, rangeFromBlock, rangeEndBlock, maxQueryBlockNumber),
1034
+ estResponseSize: calculateEstResponseSize(partition, rangeFromBlock, rangeEndBlock, knownHeight, partitionsCount),
1030
1035
  chainId: 0,
1031
1036
  progress: 0,
1032
1037
  selection: selection,
@@ -1034,24 +1039,19 @@ function pushQueriesForRange(queries, partitionId, rangeFromBlock, rangeEndBlock
1034
1039
  });
1035
1040
  }
1036
1041
 
1037
- function getNextQuery(fetchState, budget, chainPendingBudget) {
1038
- let knownHeight = fetchState.knownHeight;
1039
- let blockLag = fetchState.blockLag;
1040
- let optimizedPartitions = fetchState.optimizedPartitions;
1042
+ function getNextQuery(param) {
1043
+ let knownHeight = param.knownHeight;
1044
+ let blockLag = param.blockLag;
1045
+ let endBlock = param.endBlock;
1046
+ let optimizedPartitions = param.optimizedPartitions;
1041
1047
  let headBlockNumber = knownHeight - blockLag | 0;
1042
1048
  if (headBlockNumber <= 0) {
1043
1049
  return "WaitingForNewBlock";
1044
1050
  }
1045
- if (budget <= 0) {
1046
- return "NothingToQuery";
1047
- }
1048
- let isOnBlockBehindTheHead = fetchState.latestOnBlockBlockNumber < headBlockNumber;
1049
- let endBlock = fetchState.endBlock;
1051
+ let isOnBlockBehindTheHead = param.latestOnBlockBlockNumber < headBlockNumber;
1050
1052
  let shouldWaitForNewBlock = (
1051
1053
  endBlock !== undefined ? headBlockNumber < endBlock : true
1052
1054
  ) && !isOnBlockBehindTheHead;
1053
- let item = fetchState.buffer[((bufferReadyCount(fetchState) + budget | 0) + (chainPendingBudget | 0) | 0) - 1 | 0];
1054
- let maxQueryBlockNumber = item !== undefined ? Primitive_int.min(item.blockNumber, knownHeight) : knownHeight;
1055
1055
  let queries = [];
1056
1056
  let partitionsCount = optimizedPartitions.idsInAscOrder.length;
1057
1057
  let idxRef = 0;
@@ -1066,14 +1066,8 @@ function getNextQuery(fetchState, budget, chainPendingBudget) {
1066
1066
  shouldWaitForNewBlock = false;
1067
1067
  }
1068
1068
  let partitionQueriesStart = queries.length;
1069
- let queryEndBlock = Utils.$$Math.minOptInt(fetchState.endBlock, p.mergeBlock);
1069
+ let queryEndBlock = Utils.$$Math.minOptInt(endBlock, p.mergeBlock);
1070
1070
  let queryEndBlock$1 = blockLag !== 0 ? Utils.$$Math.minOptInt(headBlockNumber, queryEndBlock) : queryEndBlock;
1071
- let match = maxQueryBlockNumber < knownHeight;
1072
- let queryEndBlock$2 = queryEndBlock$1 !== undefined ? (
1073
- match ? Primitive_int.min(maxQueryBlockNumber, queryEndBlock$1) : queryEndBlock$1
1074
- ) : (
1075
- match ? maxQueryBlockNumber : queryEndBlock$1
1076
- );
1077
1071
  let maybeChunkRange = getMinHistoryRange(p);
1078
1072
  let cursor = p.latestFetchedBlock.blockNumber + 1 | 0;
1079
1073
  let canContinue = true;
@@ -1084,16 +1078,16 @@ function getNextQuery(fetchState, budget, chainPendingBudget) {
1084
1078
  let addressesByContractName = p.addressesByContractName;
1085
1079
  let selection = p.selection;
1086
1080
  let maxChunks = (10 - pendingCount | 0) - (queries.length - partitionQueriesStart | 0) | 0;
1087
- let rangeEndBlock = Utils.$$Math.minOptInt(pq.fromBlock - 1 | 0, queryEndBlock$2);
1081
+ let rangeEndBlock = Utils.$$Math.minOptInt(pq.fromBlock - 1 | 0, queryEndBlock$1);
1088
1082
  let rangeFromBlock = cursor;
1089
- if (rangeFromBlock <= maxQueryBlockNumber && maxChunks > 0) {
1083
+ if (rangeFromBlock <= knownHeight && maxChunks > 0) {
1090
1084
  let exit = 0;
1091
1085
  if (!(rangeEndBlock !== undefined && rangeFromBlock > rangeEndBlock)) {
1092
1086
  exit = 1;
1093
1087
  }
1094
1088
  if (exit === 1) {
1095
1089
  if (maybeChunkRange !== undefined) {
1096
- let maxBlock = rangeEndBlock !== undefined ? rangeEndBlock : maxQueryBlockNumber;
1090
+ let maxBlock = rangeEndBlock !== undefined ? rangeEndBlock : knownHeight;
1097
1091
  let chunkSize = Js_math.ceil_int(maybeChunkRange * 1.8);
1098
1092
  if (((rangeFromBlock + (chunkSize << 1) | 0) - 1 | 0) <= maxBlock) {
1099
1093
  let chunkFromBlock = rangeFromBlock;
@@ -1105,7 +1099,7 @@ function getNextQuery(fetchState, budget, chainPendingBudget) {
1105
1099
  fromBlock: chunkFromBlock,
1106
1100
  toBlock: chunkToBlock,
1107
1101
  isChunk: true,
1108
- estResponseSize: calculateEstResponseSize(p, chunkFromBlock, chunkToBlock, maxQueryBlockNumber),
1102
+ estResponseSize: calculateEstResponseSize(p, chunkFromBlock, chunkToBlock, knownHeight, partitionsCount),
1109
1103
  chainId: 0,
1110
1104
  progress: 0,
1111
1105
  selection: selection,
@@ -1120,7 +1114,7 @@ function getNextQuery(fetchState, budget, chainPendingBudget) {
1120
1114
  fromBlock: rangeFromBlock,
1121
1115
  toBlock: rangeEndBlock,
1122
1116
  isChunk: rangeEndBlock !== undefined,
1123
- estResponseSize: calculateEstResponseSize(p, rangeFromBlock, rangeEndBlock, maxQueryBlockNumber),
1117
+ estResponseSize: calculateEstResponseSize(p, rangeFromBlock, rangeEndBlock, knownHeight, partitionsCount),
1124
1118
  chainId: 0,
1125
1119
  progress: 0,
1126
1120
  selection: selection,
@@ -1133,7 +1127,7 @@ function getNextQuery(fetchState, budget, chainPendingBudget) {
1133
1127
  fromBlock: rangeFromBlock,
1134
1128
  toBlock: rangeEndBlock,
1135
1129
  isChunk: false,
1136
- estResponseSize: calculateEstResponseSize(p, rangeFromBlock, rangeEndBlock, maxQueryBlockNumber),
1130
+ estResponseSize: calculateEstResponseSize(p, rangeFromBlock, rangeEndBlock, knownHeight, partitionsCount),
1137
1131
  chainId: 0,
1138
1132
  progress: 0,
1139
1133
  selection: selection,
@@ -1145,9 +1139,9 @@ function getNextQuery(fetchState, budget, chainPendingBudget) {
1145
1139
  }
1146
1140
  let toBlock = pq.toBlock;
1147
1141
  if (toBlock !== undefined && pq.isChunk) {
1148
- let match$1 = pq.fetchedBlock;
1149
- if (match$1 !== undefined) {
1150
- let blockNumber = match$1.blockNumber;
1142
+ let match = pq.fetchedBlock;
1143
+ if (match !== undefined) {
1144
+ let blockNumber = match.blockNumber;
1151
1145
  cursor = blockNumber < toBlock ? blockNumber + 1 | 0 : toBlock + 1 | 0;
1152
1146
  } else {
1153
1147
  cursor = toBlock + 1 | 0;
@@ -1162,14 +1156,14 @@ function getNextQuery(fetchState, budget, chainPendingBudget) {
1162
1156
  let selection$1 = p.selection;
1163
1157
  let maxChunks$1 = (10 - pendingCount | 0) - (queries.length - partitionQueriesStart | 0) | 0;
1164
1158
  let rangeFromBlock$1 = cursor;
1165
- if (rangeFromBlock$1 <= maxQueryBlockNumber && maxChunks$1 > 0) {
1159
+ if (rangeFromBlock$1 <= knownHeight && maxChunks$1 > 0) {
1166
1160
  let exit$1 = 0;
1167
- if (!(queryEndBlock$2 !== undefined && rangeFromBlock$1 > queryEndBlock$2)) {
1161
+ if (!(queryEndBlock$1 !== undefined && rangeFromBlock$1 > queryEndBlock$1)) {
1168
1162
  exit$1 = 1;
1169
1163
  }
1170
1164
  if (exit$1 === 1) {
1171
1165
  if (maybeChunkRange !== undefined) {
1172
- let maxBlock$1 = queryEndBlock$2 !== undefined ? queryEndBlock$2 : maxQueryBlockNumber;
1166
+ let maxBlock$1 = queryEndBlock$1 !== undefined ? queryEndBlock$1 : knownHeight;
1173
1167
  let chunkSize$1 = Js_math.ceil_int(maybeChunkRange * 1.8);
1174
1168
  if (((rangeFromBlock$1 + (chunkSize$1 << 1) | 0) - 1 | 0) <= maxBlock$1) {
1175
1169
  let chunkFromBlock$1 = rangeFromBlock$1;
@@ -1181,7 +1175,7 @@ function getNextQuery(fetchState, budget, chainPendingBudget) {
1181
1175
  fromBlock: chunkFromBlock$1,
1182
1176
  toBlock: chunkToBlock$1,
1183
1177
  isChunk: true,
1184
- estResponseSize: calculateEstResponseSize(p, chunkFromBlock$1, chunkToBlock$1, maxQueryBlockNumber),
1178
+ estResponseSize: calculateEstResponseSize(p, chunkFromBlock$1, chunkToBlock$1, knownHeight, partitionsCount),
1185
1179
  chainId: 0,
1186
1180
  progress: 0,
1187
1181
  selection: selection$1,
@@ -1194,9 +1188,9 @@ function getNextQuery(fetchState, budget, chainPendingBudget) {
1194
1188
  queries.push({
1195
1189
  partitionId: partitionId,
1196
1190
  fromBlock: rangeFromBlock$1,
1197
- toBlock: queryEndBlock$2,
1198
- isChunk: queryEndBlock$2 !== undefined,
1199
- estResponseSize: calculateEstResponseSize(p, rangeFromBlock$1, queryEndBlock$2, maxQueryBlockNumber),
1191
+ toBlock: queryEndBlock$1,
1192
+ isChunk: queryEndBlock$1 !== undefined,
1193
+ estResponseSize: calculateEstResponseSize(p, rangeFromBlock$1, queryEndBlock$1, knownHeight, partitionsCount),
1200
1194
  chainId: 0,
1201
1195
  progress: 0,
1202
1196
  selection: selection$1,
@@ -1207,9 +1201,9 @@ function getNextQuery(fetchState, budget, chainPendingBudget) {
1207
1201
  queries.push({
1208
1202
  partitionId: partitionId,
1209
1203
  fromBlock: rangeFromBlock$1,
1210
- toBlock: queryEndBlock$2,
1204
+ toBlock: queryEndBlock$1,
1211
1205
  isChunk: false,
1212
- estResponseSize: calculateEstResponseSize(p, rangeFromBlock$1, queryEndBlock$2, maxQueryBlockNumber),
1206
+ estResponseSize: calculateEstResponseSize(p, rangeFromBlock$1, queryEndBlock$1, knownHeight, partitionsCount),
1213
1207
  chainId: 0,
1214
1208
  progress: 0,
1215
1209
  selection: selection$1,
@@ -1656,7 +1650,9 @@ function updateKnownHeight(fetchState, knownHeight) {
1656
1650
  }
1657
1651
  }
1658
1652
 
1659
- let defaultEstResponseSize = 10000;
1653
+ let minEstResponseSize = 2000;
1654
+
1655
+ let maxEstResponseSize = 10000;
1660
1656
 
1661
1657
  let blockItemLogIndex = 16777216;
1662
1658
 
@@ -1664,7 +1660,9 @@ let maxPendingChunksPerPartition = 10;
1664
1660
 
1665
1661
  export {
1666
1662
  deriveContractNameByAddress,
1667
- defaultEstResponseSize,
1663
+ minEstResponseSize,
1664
+ maxEstResponseSize,
1665
+ calculateDefaultEstResponseSize,
1668
1666
  calculateEstResponseSize,
1669
1667
  getMinHistoryRange,
1670
1668
  getMinQueryRange,
@@ -216,9 +216,13 @@ let deriveSrcAddress = (
216
216
  ~providedSrcAddress: option<Address.t>,
217
217
  ~eventConfig: Internal.eventConfig,
218
218
  ~chainConfig: Config.chain,
219
+ ~config: Config.t,
219
220
  ): Address.t => {
220
221
  switch providedSrcAddress {
221
- | Some(addr) => addr
222
+ // Canonicalize to the configured casing; the fallback addresses below already
223
+ // come from the parsed config and need no normalization. Relaxed (not
224
+ // Config.normalizeUserAddress) so test placeholders like "0xfoo" are allowed.
225
+ | Some(addr) => config->Config.normalizeSimulateAddress(addr)
222
226
  | None =>
223
227
  if eventConfig.isWildcard {
224
228
  dummySrcAddress
@@ -287,6 +291,7 @@ let parse = (~simulateItems: array<JSON.t>, ~config: Config.t, ~chainConfig: Con
287
291
  ~providedSrcAddress=item.srcAddress,
288
292
  ~eventConfig,
289
293
  ~chainConfig,
294
+ ~config,
290
295
  )
291
296
 
292
297
  let rawItem = rawJson->(Utils.magic: JSON.t => {..})
@@ -1,5 +1,6 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
+ import * as Config from "./Config.res.mjs";
3
4
  import * as Address from "./Address.res.mjs";
4
5
  import * as ChainMap from "./ChainMap.res.mjs";
5
6
  import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
@@ -150,9 +151,9 @@ function firstContractAddress(chainConfig, contractName) {
150
151
  return found.contents;
151
152
  }
152
153
 
153
- function deriveSrcAddress(providedSrcAddress, eventConfig, chainConfig) {
154
+ function deriveSrcAddress(providedSrcAddress, eventConfig, chainConfig, config) {
154
155
  if (providedSrcAddress !== undefined) {
155
- return Primitive_option.valFromOption(providedSrcAddress);
156
+ return Config.normalizeSimulateAddress(config, Primitive_option.valFromOption(providedSrcAddress));
156
157
  }
157
158
  if (eventConfig.isWildcard) {
158
159
  return dummySrcAddress;
@@ -203,7 +204,7 @@ function parse(simulateItems, config, chainConfig) {
203
204
  currentLogIndex.contents = li$1 + 1 | 0;
204
205
  logIndex = li$1;
205
206
  }
206
- let srcAddress = deriveSrcAddress(rawJson.srcAddress, eventConfig, chainConfig);
207
+ let srcAddress = deriveSrcAddress(rawJson.srcAddress, eventConfig, chainConfig, config);
207
208
  let blockJson = rawJson.block;
208
209
  let blockJson$1 = (blockJson == null) ? undefined : Primitive_option.some(blockJson);
209
210
  let transactionJson = rawJson.transaction;
@@ -239,6 +239,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
239
239
  ~knownHeight,
240
240
  ~partitionId as _,
241
241
  ~selection: FetchState.selection,
242
+ ~itemsTarget as _,
242
243
  ~retry,
243
244
  ~logger,
244
245
  ) => {
@@ -196,7 +196,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
196
196
  client = ErrorHandling.mkLogAndRaise(undefined, "Failed to instantiate the HyperFuel client", exn);
197
197
  }
198
198
  let getSelectionConfig = memoGetSelectionConfig(chain);
199
- let getItemsOrThrow = async (fromBlock, toBlock, addressesByContractName, contractNameByAddress, knownHeight, param, selection, retry, logger) => {
199
+ let getItemsOrThrow = async (fromBlock, toBlock, addressesByContractName, contractNameByAddress, knownHeight, param, selection, param$1, retry, logger) => {
200
200
  let totalTimeRef = Performance.now();
201
201
  let selectionConfig = getSelectionConfig(selection);
202
202
  let recieptsSelection = selectionConfig.getRecieptsSelection(addressesByContractName);
@@ -64,6 +64,7 @@ module GetLogs = {
64
64
  ~toBlockInclusive,
65
65
  ~addressesWithTopics,
66
66
  ~fieldSelection,
67
+ ~maxNumLogs,
67
68
  ): HyperSyncClient.QueryTypes.query => {
68
69
  fromBlock,
69
70
  toBlockExclusive: ?switch toBlockInclusive {
@@ -72,6 +73,7 @@ module GetLogs = {
72
73
  },
73
74
  logs: addressesWithTopics,
74
75
  fieldSelection,
76
+ maxNumLogs,
75
77
  }
76
78
 
77
79
  // Rust encodes structured failures as a JSON payload in the napi error's
@@ -105,6 +107,7 @@ module GetLogs = {
105
107
  ~toBlock,
106
108
  ~logSelections: array<LogSelection.t>,
107
109
  ~fieldSelection,
110
+ ~maxNumLogs,
108
111
  ): logsQueryPage => {
109
112
  let addressesWithTopics = logSelections->Array.flatMap(({addresses, topicSelections}) =>
110
113
  topicSelections->Array.map(({topic0, topic1, topic2, topic3}) => {
@@ -123,6 +126,7 @@ module GetLogs = {
123
126
  ~toBlockInclusive=toBlock,
124
127
  ~addressesWithTopics,
125
128
  ~fieldSelection,
129
+ ~maxNumLogs,
126
130
  )
127
131
 
128
132
  let (res, transactionStore) = switch await client.getEventItems(~query) {
@@ -62,12 +62,13 @@ function mapExn(queryResponse) {
62
62
 
63
63
  let $$Error = /* @__PURE__ */Primitive_exceptions.create("HyperSync.GetLogs.Error");
64
64
 
65
- function makeRequestBody(fromBlock, toBlockInclusive, addressesWithTopics, fieldSelection) {
65
+ function makeRequestBody(fromBlock, toBlockInclusive, addressesWithTopics, fieldSelection, maxNumLogs) {
66
66
  return {
67
67
  fromBlock: fromBlock,
68
68
  toBlock: toBlockInclusive !== undefined ? toBlockInclusive + 1 | 0 : undefined,
69
69
  logs: addressesWithTopics,
70
- fieldSelection: fieldSelection
70
+ fieldSelection: fieldSelection,
71
+ maxNumLogs: maxNumLogs
71
72
  };
72
73
  }
73
74
 
@@ -92,7 +93,7 @@ function extractMissingParams(exn) {
92
93
  }
93
94
  }
94
95
 
95
- async function query(client, fromBlock, toBlock, logSelections, fieldSelection) {
96
+ async function query(client, fromBlock, toBlock, logSelections, fieldSelection, maxNumLogs) {
96
97
  let addressesWithTopics = logSelections.flatMap(param => {
97
98
  let addresses = param.addresses;
98
99
  return param.topicSelections.map(param => {
@@ -100,7 +101,7 @@ async function query(client, fromBlock, toBlock, logSelections, fieldSelection)
100
101
  return HyperSyncClient.QueryTypes.makeLogSelection(addresses, topics);
101
102
  });
102
103
  });
103
- let query$1 = makeRequestBody(fromBlock, toBlock, addressesWithTopics, fieldSelection);
104
+ let query$1 = makeRequestBody(fromBlock, toBlock, addressesWithTopics, fieldSelection, maxNumLogs);
104
105
  let match;
105
106
  try {
106
107
  match = await client.getEventItems(query$1);
@@ -33,6 +33,7 @@ module GetLogs: {
33
33
  ~toBlock: option<int>,
34
34
  ~logSelections: array<LogSelection.t>,
35
35
  ~fieldSelection: HyperSyncClient.QueryTypes.fieldSelection,
36
+ ~maxNumLogs: int,
36
37
  ) => promise<logsQueryPage>
37
38
  }
38
39
 
@@ -232,6 +232,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
232
232
  ~knownHeight,
233
233
  ~partitionId as _,
234
234
  ~selection,
235
+ ~itemsTarget,
235
236
  ~retry,
236
237
  ~logger,
237
238
  ) => {
@@ -258,6 +259,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
258
259
  ~toBlock,
259
260
  ~logSelections,
260
261
  ~fieldSelection=selectionConfig.fieldSelection,
262
+ ~maxNumLogs=itemsTarget,
261
263
  ) catch {
262
264
  | HyperSync.GetLogs.Error(error) =>
263
265
  throw(
@@ -149,7 +149,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
149
149
  }
150
150
  };
151
151
  };
152
- let getItemsOrThrow = async (fromBlock, toBlock, addressesByContractName, contractNameByAddress, knownHeight, param, selection, retry, logger) => {
152
+ let getItemsOrThrow = async (fromBlock, toBlock, addressesByContractName, contractNameByAddress, knownHeight, param, selection, itemsTarget, retry, logger) => {
153
153
  let totalTimeRef = Performance.now();
154
154
  let selectionConfig = getSelectionConfig(selection);
155
155
  let logSelections;
@@ -163,7 +163,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
163
163
  Prometheus.SourceRequestCount.increment(name, chain, "getLogs");
164
164
  let pageUnsafe;
165
165
  try {
166
- pageUnsafe = await HyperSync.GetLogs.query(client, fromBlock, toBlock, logSelections, selectionConfig.fieldSelection);
166
+ pageUnsafe = await HyperSync.GetLogs.query(client, fromBlock, toBlock, logSelections, selectionConfig.fieldSelection, itemsTarget);
167
167
  } catch (raw_error) {
168
168
  let error = Primitive_exceptions.internalToException(raw_error);
169
169
  if (error.RE_EXN_ID === HyperSync.GetLogs.$$Error) {