envio 3.3.0-alpha.4 → 3.3.0-alpha.5
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/evm.schema.json +10 -0
- package/package.json +7 -7
- package/src/Batch.res.mjs +1 -1
- package/src/ChainState.res +41 -7
- package/src/ChainState.res.mjs +22 -18
- package/src/ChainState.resi +3 -1
- package/src/Config.res +3 -0
- package/src/Config.res.mjs +3 -1
- package/src/Core.res +0 -3
- package/src/FetchState.res +63 -133
- package/src/FetchState.res.mjs +107 -166
- package/src/IndexingAddresses.res +105 -0
- package/src/IndexingAddresses.res.mjs +100 -0
- package/src/IndexingAddresses.resi +32 -0
- package/src/Main.res +4 -15
- package/src/Main.res.mjs +6 -14
- package/src/Metrics.res +33 -0
- package/src/Metrics.res.mjs +39 -0
- package/src/Prometheus.res +2 -20
- package/src/Prometheus.res.mjs +83 -95
- package/src/bindings/Viem.res +0 -41
- package/src/bindings/Viem.res.mjs +1 -43
- package/src/sources/Evm.res +7 -36
- package/src/sources/Evm.res.mjs +4 -36
- package/src/sources/EvmChain.res +3 -1
- package/src/sources/EvmChain.res.mjs +2 -1
- package/src/sources/EvmRpcClient.res +36 -5
- package/src/sources/EvmRpcClient.res.mjs +7 -4
- package/src/sources/HyperSyncClient.res +0 -35
- package/src/sources/HyperSyncClient.res.mjs +1 -8
- package/src/sources/Rpc.res +15 -47
- package/src/sources/Rpc.res.mjs +25 -56
- package/src/sources/RpcSource.res +30 -73
- package/src/sources/RpcSource.res.mjs +24 -73
- package/src/sources/Svm.res +7 -15
- package/src/sources/Svm.res.mjs +4 -15
- package/src/sources/TransactionStore.res +14 -2
- package/src/sources/TransactionStore.res.mjs +10 -2
package/src/FetchState.res
CHANGED
|
@@ -1,11 +1,5 @@
|
|
|
1
|
-
type contractConfig = {startBlock: option<int>}
|
|
2
|
-
|
|
3
1
|
type indexingAddress = Internal.indexingContract
|
|
4
2
|
|
|
5
|
-
let deriveEffectiveStartBlock = (~registrationBlock: int, ~contractStartBlock: option<int>) => {
|
|
6
|
-
Pervasives.max(Pervasives.max(registrationBlock, 0), contractStartBlock->Option.getOr(0))
|
|
7
|
-
}
|
|
8
|
-
|
|
9
3
|
type blockNumberAndTimestamp = {
|
|
10
4
|
blockNumber: int,
|
|
11
5
|
blockTimestamp: int,
|
|
@@ -536,10 +530,8 @@ type t = {
|
|
|
536
530
|
startBlock: int,
|
|
537
531
|
endBlock: option<int>,
|
|
538
532
|
normalSelection: selection,
|
|
539
|
-
// By address
|
|
540
|
-
indexingAddresses: dict<indexingAddress>,
|
|
541
533
|
// By contract name
|
|
542
|
-
contractConfigs: dict<contractConfig>,
|
|
534
|
+
contractConfigs: dict<IndexingAddresses.contractConfig>,
|
|
543
535
|
// Not used for logic - only metadata
|
|
544
536
|
chainId: int,
|
|
545
537
|
// The block number of the latest block which was added to the queue
|
|
@@ -592,6 +584,25 @@ let bufferBlock = ({optimizedPartitions, latestOnBlockBlockNumber}: t) => {
|
|
|
592
584
|
}
|
|
593
585
|
}
|
|
594
586
|
|
|
587
|
+
// Number of buffered items at or below the ready frontier (processable now,
|
|
588
|
+
// i.e. not stuck behind a gap from a lagging partition or out-of-order chunk).
|
|
589
|
+
// The buffer is kept sorted, so binary-search the frontier in O(log n).
|
|
590
|
+
let bufferReadyCount = (fetchState: t) => {
|
|
591
|
+
let frontier = fetchState->bufferBlockNumber
|
|
592
|
+
let buffer = fetchState.buffer
|
|
593
|
+
let lo = ref(0)
|
|
594
|
+
let hi = ref(buffer->Array.length)
|
|
595
|
+
while lo.contents < hi.contents {
|
|
596
|
+
let mid = (lo.contents + hi.contents) / 2
|
|
597
|
+
if buffer->Array.getUnsafe(mid)->Internal.getItemBlockNumber <= frontier {
|
|
598
|
+
lo := mid + 1
|
|
599
|
+
} else {
|
|
600
|
+
hi := mid
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
lo.contents
|
|
604
|
+
}
|
|
605
|
+
|
|
595
606
|
/*
|
|
596
607
|
Comparitor for two events from the same chain. No need for chain id or timestamp
|
|
597
608
|
*/
|
|
@@ -607,8 +618,6 @@ let compareBufferItem = (a: Internal.item, b: Internal.item) => {
|
|
|
607
618
|
// Some big number which should be bigger than any log index
|
|
608
619
|
let blockItemLogIndex = 16777216
|
|
609
620
|
|
|
610
|
-
let numAddresses = fetchState => fetchState.indexingAddresses->Utils.Dict.size
|
|
611
|
-
|
|
612
621
|
// Appends Block items produced by the onBlock handlers for every block in
|
|
613
622
|
// (fromBlock, maxBlockNumber] into mutItems and returns the new
|
|
614
623
|
// latestOnBlockBlockNumber pointer. maxOnBlockBufferSize bounds how many items
|
|
@@ -673,7 +682,6 @@ Runs partition optimization when partitions change.
|
|
|
673
682
|
let updateInternal = (
|
|
674
683
|
fetchState: t,
|
|
675
684
|
~optimizedPartitions=fetchState.optimizedPartitions,
|
|
676
|
-
~indexingAddresses=fetchState.indexingAddresses,
|
|
677
685
|
~mutItems=?,
|
|
678
686
|
~blockLag=fetchState.blockLag,
|
|
679
687
|
~knownHeight=fetchState.knownHeight,
|
|
@@ -729,7 +737,6 @@ let updateInternal = (
|
|
|
729
737
|
maxOnBlockBufferSize: fetchState.maxOnBlockBufferSize,
|
|
730
738
|
optimizedPartitions,
|
|
731
739
|
latestOnBlockBlockNumber,
|
|
732
|
-
indexingAddresses,
|
|
733
740
|
blockLag,
|
|
734
741
|
knownHeight,
|
|
735
742
|
buffer: switch mutItemsRef.contents {
|
|
@@ -757,12 +764,6 @@ let updateInternal = (
|
|
|
757
764
|
~blockNumber=updatedFetchState->bufferBlockNumber,
|
|
758
765
|
~chainId=fetchState.chainId,
|
|
759
766
|
)
|
|
760
|
-
if indexingAddresses !== fetchState.indexingAddresses {
|
|
761
|
-
Prometheus.IndexingAddresses.set(
|
|
762
|
-
~addressesCount=updatedFetchState->numAddresses,
|
|
763
|
-
~chainId=fetchState.chainId,
|
|
764
|
-
)
|
|
765
|
-
}
|
|
766
767
|
|
|
767
768
|
updatedFetchState
|
|
768
769
|
}
|
|
@@ -993,6 +994,7 @@ OptimizedPartitions.t => {
|
|
|
993
994
|
|
|
994
995
|
let registerDynamicContracts = (
|
|
995
996
|
fetchState: t,
|
|
997
|
+
~indexingAddresses: IndexingAddresses.t,
|
|
996
998
|
// These are raw items which might have dynamic contracts received from contractRegister call.
|
|
997
999
|
// Might contain duplicates which we should filter out
|
|
998
1000
|
items: array<Internal.item>,
|
|
@@ -1004,11 +1006,10 @@ let registerDynamicContracts = (
|
|
|
1004
1006
|
)
|
|
1005
1007
|
}
|
|
1006
1008
|
|
|
1007
|
-
let indexingAddresses = fetchState.indexingAddresses
|
|
1008
1009
|
let registeringContractsByContract: dict<dict<indexingAddress>> = Dict.make()
|
|
1009
1010
|
let earliestRegisteringEventBlockNumber = ref(%raw(`Infinity`))
|
|
1010
1011
|
// Addresses registered for contracts without matching events. These are not
|
|
1011
|
-
// added to partitions, but they are tracked on
|
|
1012
|
+
// added to partitions, but they are tracked on indexingAddresses
|
|
1012
1013
|
// so that later conflicting registrations are detected, and are persisted
|
|
1013
1014
|
// to envio_addresses so they can be picked up on restart with updated config.
|
|
1014
1015
|
let noEventsAddresses: dict<indexingAddress> = Dict.make()
|
|
@@ -1034,15 +1035,13 @@ let registerDynamicContracts = (
|
|
|
1034
1035
|
address: dc.address,
|
|
1035
1036
|
contractName: dc.contractName,
|
|
1036
1037
|
registrationBlock: dc.registrationBlock,
|
|
1037
|
-
effectiveStartBlock: deriveEffectiveStartBlock(
|
|
1038
|
+
effectiveStartBlock: IndexingAddresses.deriveEffectiveStartBlock(
|
|
1038
1039
|
~registrationBlock=dc.registrationBlock,
|
|
1039
1040
|
~contractStartBlock,
|
|
1040
1041
|
),
|
|
1041
1042
|
}
|
|
1042
1043
|
// Prevent registering already indexing contracts
|
|
1043
|
-
switch indexingAddresses->
|
|
1044
|
-
dc.address->Address.toString,
|
|
1045
|
-
) {
|
|
1044
|
+
switch indexingAddresses->IndexingAddresses.get(dc.address->Address.toString) {
|
|
1046
1045
|
| Some(existingContract) =>
|
|
1047
1046
|
// FIXME: Instead of filtering out duplicates,
|
|
1048
1047
|
// we should check the block number first.
|
|
@@ -1097,7 +1096,7 @@ let registerDynamicContracts = (
|
|
|
1097
1096
|
address: dc.address,
|
|
1098
1097
|
contractName: dc.contractName,
|
|
1099
1098
|
registrationBlock: dc.registrationBlock,
|
|
1100
|
-
effectiveStartBlock: deriveEffectiveStartBlock(
|
|
1099
|
+
effectiveStartBlock: IndexingAddresses.deriveEffectiveStartBlock(
|
|
1101
1100
|
~registrationBlock=dc.registrationBlock,
|
|
1102
1101
|
~contractStartBlock=None,
|
|
1103
1102
|
),
|
|
@@ -1105,9 +1104,7 @@ let registerDynamicContracts = (
|
|
|
1105
1104
|
// Prevent duplicate logging/persistence when the same address is
|
|
1106
1105
|
// already tracked on fetchState, either from the db on startup or
|
|
1107
1106
|
// from an earlier registration in this batch.
|
|
1108
|
-
switch indexingAddresses->
|
|
1109
|
-
dc.address->Address.toString,
|
|
1110
|
-
) {
|
|
1107
|
+
switch indexingAddresses->IndexingAddresses.get(dc.address->Address.toString) {
|
|
1111
1108
|
| Some(existingContract) =>
|
|
1112
1109
|
if existingContract.contractName != dc.contractName {
|
|
1113
1110
|
fetchState->warnDifferentContractType(~existingContract, ~dc=dcAsIndexingAddress)
|
|
@@ -1161,12 +1158,10 @@ let registerDynamicContracts = (
|
|
|
1161
1158
|
// Only dcs for contracts without events. Track them on
|
|
1162
1159
|
// indexingAddresses so subsequent registrations see them, but don't touch
|
|
1163
1160
|
// partitions since there's nothing to fetch for them.
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
fetchState->updateInternal(~indexingAddresses=newIndexingContracts)
|
|
1161
|
+
indexingAddresses->IndexingAddresses.register(noEventsAddresses)
|
|
1162
|
+
fetchState
|
|
1167
1163
|
| (_, _) => {
|
|
1168
1164
|
let newPartitions = []
|
|
1169
|
-
let newIndexingAddresses = indexingAddresses->Utils.Dict.shallowCopy
|
|
1170
1165
|
let dynamicContractsRef = ref(fetchState.optimizedPartitions.dynamicContracts)
|
|
1171
1166
|
let mutExistingPartitions = fetchState.optimizedPartitions.entities->Dict.valuesToArray
|
|
1172
1167
|
|
|
@@ -1248,10 +1243,10 @@ let registerDynamicContracts = (
|
|
|
1248
1243
|
}
|
|
1249
1244
|
|
|
1250
1245
|
let registeringContracts = registeringContractsByContract->Dict.getUnsafe(contractName)
|
|
1251
|
-
|
|
1246
|
+
indexingAddresses->IndexingAddresses.register(registeringContracts)
|
|
1252
1247
|
}
|
|
1253
1248
|
// Include no-events dcs so later batches detect conflicts against them.
|
|
1254
|
-
|
|
1249
|
+
indexingAddresses->IndexingAddresses.register(noEventsAddresses)
|
|
1255
1250
|
|
|
1256
1251
|
let optimizedPartitions = createPartitionsFromIndexingAddresses(
|
|
1257
1252
|
~registeringContractsByContract,
|
|
@@ -1264,7 +1259,7 @@ let registerDynamicContracts = (
|
|
|
1264
1259
|
~progressBlockNumber=0,
|
|
1265
1260
|
)
|
|
1266
1261
|
|
|
1267
|
-
fetchState->updateInternal(~optimizedPartitions
|
|
1262
|
+
fetchState->updateInternal(~optimizedPartitions)
|
|
1268
1263
|
}
|
|
1269
1264
|
}
|
|
1270
1265
|
}
|
|
@@ -1277,6 +1272,7 @@ newItems are ordered earliest to latest (as they are returned from the worker)
|
|
|
1277
1272
|
*/
|
|
1278
1273
|
let handleQueryResult = (
|
|
1279
1274
|
fetchState: t,
|
|
1275
|
+
~indexingAddresses: IndexingAddresses.t,
|
|
1280
1276
|
~query: query,
|
|
1281
1277
|
~latestFetchedBlock: blockNumberAndTimestamp,
|
|
1282
1278
|
~newItems,
|
|
@@ -1289,7 +1285,8 @@ let handleQueryResult = (
|
|
|
1289
1285
|
switch item {
|
|
1290
1286
|
| Internal.Event({eventConfig, payload, blockNumber}) =>
|
|
1291
1287
|
switch eventConfig.clientAddressFilter {
|
|
1292
|
-
| Some(filter) =>
|
|
1288
|
+
| Some(filter) =>
|
|
1289
|
+
filter(payload, blockNumber, indexingAddresses->IndexingAddresses.rawForFilter)
|
|
1293
1290
|
| None => true
|
|
1294
1291
|
}
|
|
1295
1292
|
| _ => true
|
|
@@ -1462,11 +1459,16 @@ let getNextQuery = (
|
|
|
1462
1459
|
!isOnBlockBehindTheHead,
|
|
1463
1460
|
)
|
|
1464
1461
|
|
|
1465
|
-
//
|
|
1466
|
-
// flight) so processing always has buffer without ballooning memory.
|
|
1467
|
-
//
|
|
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
1468
|
let maxQueryBlockNumber = {
|
|
1469
|
-
switch buffer->Array.get(
|
|
1469
|
+
switch buffer->Array.get(
|
|
1470
|
+
fetchState->bufferReadyCount + budget + chainPendingBudget->Float.toInt - 1,
|
|
1471
|
+
) {
|
|
1470
1472
|
| Some(item) =>
|
|
1471
1473
|
// Just in case check that we don't query beyond the current block
|
|
1472
1474
|
Pervasives.min(item->Internal.getItemBlockNumber, knownHeight)
|
|
@@ -1625,6 +1627,7 @@ let make = (
|
|
|
1625
1627
|
~startBlock,
|
|
1626
1628
|
~endBlock,
|
|
1627
1629
|
~eventConfigs: array<Internal.eventConfig>,
|
|
1630
|
+
~contractConfigs: dict<IndexingAddresses.contractConfig>,
|
|
1628
1631
|
~addresses: array<Internal.indexingAddress>,
|
|
1629
1632
|
~maxAddrInPartition,
|
|
1630
1633
|
~chainId,
|
|
@@ -1643,31 +1646,8 @@ let make = (
|
|
|
1643
1646
|
let notDependingOnAddresses = []
|
|
1644
1647
|
let normalEventConfigs = []
|
|
1645
1648
|
let contractNamesWithNormalEvents = Utils.Set.make()
|
|
1646
|
-
let indexingAddresses = Dict.make()
|
|
1647
|
-
let contractConfigs: dict<contractConfig> = Dict.make()
|
|
1648
1649
|
|
|
1649
1650
|
eventConfigs->Array.forEach(ec => {
|
|
1650
|
-
switch contractConfigs->Utils.Dict.dangerouslyGetNonOption(ec.contractName) {
|
|
1651
|
-
| Some({startBlock}) =>
|
|
1652
|
-
contractConfigs->Dict.set(
|
|
1653
|
-
ec.contractName,
|
|
1654
|
-
{
|
|
1655
|
-
startBlock: switch (startBlock, ec.startBlock) {
|
|
1656
|
-
| (Some(a), Some(b)) => Some(Pervasives.min(a, b))
|
|
1657
|
-
| (Some(_) as s, None) | (None, Some(_) as s) => s
|
|
1658
|
-
| (None, None) => None
|
|
1659
|
-
},
|
|
1660
|
-
},
|
|
1661
|
-
)
|
|
1662
|
-
| None =>
|
|
1663
|
-
contractConfigs->Dict.set(
|
|
1664
|
-
ec.contractName,
|
|
1665
|
-
{
|
|
1666
|
-
startBlock: ec.startBlock,
|
|
1667
|
-
},
|
|
1668
|
-
)
|
|
1669
|
-
}
|
|
1670
|
-
|
|
1671
1651
|
if ec.dependsOnAddresses {
|
|
1672
1652
|
normalEventConfigs->Array.push(ec)
|
|
1673
1653
|
contractNamesWithNormalEvents->Utils.Set.add(ec.contractName)->ignore
|
|
@@ -1707,32 +1687,16 @@ let make = (
|
|
|
1707
1687
|
|
|
1708
1688
|
addresses->Array.forEach(contract => {
|
|
1709
1689
|
let contractName = contract.contractName
|
|
1710
|
-
let contractStartBlock = switch contractConfigs->Utils.Dict.dangerouslyGetNonOption(
|
|
1711
|
-
contractName,
|
|
1712
|
-
) {
|
|
1713
|
-
| Some({startBlock}) => startBlock
|
|
1714
|
-
| None => None
|
|
1715
|
-
}
|
|
1716
|
-
let ia: indexingAddress = {
|
|
1717
|
-
address: contract.address,
|
|
1718
|
-
contractName: contract.contractName,
|
|
1719
|
-
registrationBlock: contract.registrationBlock,
|
|
1720
|
-
effectiveStartBlock: deriveEffectiveStartBlock(
|
|
1721
|
-
~registrationBlock=contract.registrationBlock,
|
|
1722
|
-
~contractStartBlock,
|
|
1723
|
-
),
|
|
1724
|
-
}
|
|
1725
|
-
// Track the address on fetchState regardless of whether it currently has
|
|
1726
|
-
// matching events. This way, if the config is updated later to add events
|
|
1727
|
-
// for this contract, the address is already known.
|
|
1728
|
-
indexingAddresses->Dict.set(contract.address->Address.toString, ia)
|
|
1729
1690
|
|
|
1730
1691
|
// Only addresses whose contract has events that depend on addresses get
|
|
1731
1692
|
// registered for active fetching via partitions.
|
|
1732
1693
|
if contractNamesWithNormalEvents->Utils.Set.has(contractName) {
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1694
|
+
registeringContractsByContract
|
|
1695
|
+
->Utils.Dict.getOrInsertEmptyDict(contractName)
|
|
1696
|
+
->Dict.set(
|
|
1697
|
+
contract.address->Address.toString,
|
|
1698
|
+
IndexingAddresses.makeIndexingAddress(~contract, ~contractConfigs),
|
|
1699
|
+
)
|
|
1736
1700
|
|
|
1737
1701
|
// Detect dynamic contracts by registrationBlock
|
|
1738
1702
|
if contract.registrationBlock !== -1 {
|
|
@@ -1792,7 +1756,6 @@ let make = (
|
|
|
1792
1756
|
endBlock,
|
|
1793
1757
|
latestOnBlockBlockNumber,
|
|
1794
1758
|
normalSelection,
|
|
1795
|
-
indexingAddresses,
|
|
1796
1759
|
blockLag,
|
|
1797
1760
|
onBlockConfigs,
|
|
1798
1761
|
maxOnBlockBufferSize,
|
|
@@ -1801,8 +1764,6 @@ let make = (
|
|
|
1801
1764
|
firstEventBlock,
|
|
1802
1765
|
}
|
|
1803
1766
|
|
|
1804
|
-
let numAddresses = indexingAddresses->Utils.Dict.size
|
|
1805
|
-
Prometheus.IndexingAddresses.set(~addressesCount=numAddresses, ~chainId)
|
|
1806
1767
|
Prometheus.IndexingPartitions.set(
|
|
1807
1768
|
~partitionsCount=optimizedPartitions->OptimizedPartitions.count,
|
|
1808
1769
|
~chainId,
|
|
@@ -1819,25 +1780,6 @@ let make = (
|
|
|
1819
1780
|
|
|
1820
1781
|
let bufferSize = ({buffer}: t) => buffer->Array.length
|
|
1821
1782
|
|
|
1822
|
-
// Number of buffered items at or below the ready frontier (processable now,
|
|
1823
|
-
// i.e. not stuck behind a gap from a lagging partition or out-of-order chunk).
|
|
1824
|
-
// The buffer is kept sorted, so binary-search the frontier in O(log n).
|
|
1825
|
-
let bufferReadyCount = (fetchState: t) => {
|
|
1826
|
-
let frontier = fetchState->bufferBlockNumber
|
|
1827
|
-
let buffer = fetchState.buffer
|
|
1828
|
-
let lo = ref(0)
|
|
1829
|
-
let hi = ref(buffer->Array.length)
|
|
1830
|
-
while lo.contents < hi.contents {
|
|
1831
|
-
let mid = (lo.contents + hi.contents) / 2
|
|
1832
|
-
if buffer->Array.getUnsafe(mid)->Internal.getItemBlockNumber <= frontier {
|
|
1833
|
-
lo := mid + 1
|
|
1834
|
-
} else {
|
|
1835
|
-
hi := mid
|
|
1836
|
-
}
|
|
1837
|
-
}
|
|
1838
|
-
lo.contents
|
|
1839
|
-
}
|
|
1840
|
-
|
|
1841
1783
|
let rollbackPendingQueries = (mutPendingQueries: array<pendingQuery>, ~targetBlockNumber) => {
|
|
1842
1784
|
// - Remove queries where fromBlock > target
|
|
1843
1785
|
// - Cap fetchedBlock at target where fetchedBlock > target
|
|
@@ -1869,18 +1811,11 @@ Always recreates optimized partitions to avoid duplicate addresses:
|
|
|
1869
1811
|
- Non-wildcard with lfb <= target: keep, adjust pending queries and mergeBlock
|
|
1870
1812
|
- Non-wildcard with lfb > target: delete, track addresses for recreation
|
|
1871
1813
|
*/
|
|
1872
|
-
let rollback = (fetchState: t, ~targetBlockNumber) => {
|
|
1873
|
-
// Step 1:
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
fetchState.indexingAddresses->Utils.Dict.forEachWithKey((indexingContract, address) => {
|
|
1878
|
-
if indexingContract.registrationBlock > targetBlockNumber {
|
|
1879
|
-
let _ = addressesToRemove->Utils.Set.add(address->Address.unsafeFromString)
|
|
1880
|
-
} else {
|
|
1881
|
-
indexingAddresses->Dict.set(address, indexingContract)
|
|
1882
|
-
}
|
|
1883
|
-
})
|
|
1814
|
+
let rollback = (fetchState: t, ~indexingAddresses: IndexingAddresses.t, ~targetBlockNumber) => {
|
|
1815
|
+
// Step 1: Prune addresses registered after the target block. The pruned index is
|
|
1816
|
+
// then the source of truth for partition cleanup below — an address survives iff
|
|
1817
|
+
// it's still in the index.
|
|
1818
|
+
indexingAddresses->IndexingAddresses.rollbackInPlace(~targetBlockNumber)
|
|
1884
1819
|
|
|
1885
1820
|
// Step 2: Categorize partitions
|
|
1886
1821
|
let keptPartitions = []
|
|
@@ -1910,18 +1845,12 @@ let rollback = (fetchState: t, ~targetBlockNumber) => {
|
|
|
1910
1845
|
| _ if p.latestFetchedBlock.blockNumber > targetBlockNumber =>
|
|
1911
1846
|
p.addressesByContractName->Utils.Dict.forEachWithKey((addresses, contractName) => {
|
|
1912
1847
|
addresses->Array.forEach(address => {
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
indexingAddresses
|
|
1916
|
-
->Utils.Dict.dangerouslyGetNonOption(address->Address.toString)
|
|
1917
|
-
->Option.isSome
|
|
1918
|
-
) {
|
|
1848
|
+
switch indexingAddresses->IndexingAddresses.get(address->Address.toString) {
|
|
1849
|
+
| Some(indexingContract) =>
|
|
1919
1850
|
let registeringContracts =
|
|
1920
1851
|
registeringContractsByContract->Utils.Dict.getOrInsertEmptyDict(contractName)
|
|
1921
|
-
registeringContracts->Dict.set(
|
|
1922
|
-
|
|
1923
|
-
indexingAddresses->Dict.getUnsafe(address->Address.toString),
|
|
1924
|
-
)
|
|
1852
|
+
registeringContracts->Dict.set(address->Address.toString, indexingContract)
|
|
1853
|
+
| None => ()
|
|
1925
1854
|
}
|
|
1926
1855
|
})
|
|
1927
1856
|
})
|
|
@@ -1934,11 +1863,13 @@ let rollback = (fetchState: t, ~targetBlockNumber) => {
|
|
|
1934
1863
|
| other => other
|
|
1935
1864
|
}
|
|
1936
1865
|
|
|
1937
|
-
//
|
|
1866
|
+
// Drop addresses pruned from the index
|
|
1938
1867
|
let rollbackedAddressesByContractName = Dict.make()
|
|
1939
1868
|
addressesByContractName->Utils.Dict.forEachWithKey((addresses, contractName) => {
|
|
1940
1869
|
let keptAddresses =
|
|
1941
|
-
addresses->Array.filter(address =>
|
|
1870
|
+
addresses->Array.filter(address =>
|
|
1871
|
+
indexingAddresses->IndexingAddresses.get(address->Address.toString)->Option.isSome
|
|
1872
|
+
)
|
|
1942
1873
|
if keptAddresses->Array.length > 0 {
|
|
1943
1874
|
rollbackedAddressesByContractName->Dict.set(contractName, keptAddresses)
|
|
1944
1875
|
}
|
|
@@ -1982,7 +1913,6 @@ let rollback = (fetchState: t, ~targetBlockNumber) => {
|
|
|
1982
1913
|
),
|
|
1983
1914
|
}->updateInternal(
|
|
1984
1915
|
~optimizedPartitions,
|
|
1985
|
-
~indexingAddresses,
|
|
1986
1916
|
~mutItems=fetchState.buffer->Array.filter(item =>
|
|
1987
1917
|
switch item {
|
|
1988
1918
|
| Event({blockNumber})
|