envio 3.15.0 → 3.16.0
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/README.md +40 -34
- package/evm.schema.json +11 -2
- package/fuel.schema.json +10 -1
- package/index.d.ts +6 -0
- package/licenses/README.md +1 -1
- package/package.json +8 -8
- package/src/Batch.res.mjs +5 -5
- package/src/BatchProcessing.res +1 -0
- package/src/BatchProcessing.res.mjs +1 -0
- package/src/ChainState.res +48 -7
- package/src/ChainState.res.mjs +27 -11
- package/src/Clock.res +57 -0
- package/src/Clock.res.mjs +72 -0
- package/src/Config.res +10 -3
- package/src/Config.res.mjs +4 -2
- package/src/Core.res +4 -40
- package/src/EffectState.res +10 -2
- package/src/EffectState.res.mjs +8 -4
- package/src/EffectState.resi +3 -1
- package/src/EntityId.res +2 -7
- package/src/EntityId.res.mjs +1 -8
- package/src/EntityTables.res +4 -1
- package/src/EntityTables.res.mjs +1 -1
- package/src/FetchState.res +157 -69
- package/src/FetchState.res.mjs +144 -49
- package/src/FinalizeBackfill.res +2 -4
- package/src/FinalizeBackfill.res.mjs +3 -4
- package/src/InMemoryTable.res +17 -16
- package/src/InMemoryTable.res.mjs +14 -15
- package/src/IndexerState.res +28 -4
- package/src/IndexerState.res.mjs +19 -6
- package/src/IndexerState.resi +4 -0
- package/src/Internal.res +0 -49
- package/src/Internal.res.mjs +1 -80
- package/src/LoadLayer.res +14 -8
- package/src/LoadLayer.res.mjs +8 -6
- package/src/Main.res.mjs +1 -1
- package/src/Persistence.res +3 -23
- package/src/Persistence.res.mjs +3 -3
- package/src/Rollback.res +0 -1
- package/src/Rollback.res.mjs +1 -1
- package/src/SafeCheckpointTracking.res +4 -4
- package/src/SafeCheckpointTracking.res.mjs +1 -1
- package/src/StagedRows.res +106 -0
- package/src/StagedRows.res.mjs +102 -0
- package/src/Staging.res +32 -14
- package/src/Staging.res.mjs +17 -20
- package/src/Storage.res +277 -948
- package/src/Storage.res.mjs +215 -707
- package/src/Supervisor.res +75 -56
- package/src/Supervisor.res.mjs +55 -26
- package/src/TestIndexer.res +22 -27
- package/src/TestIndexer.res.mjs +20 -17
- package/src/Throttler.res +15 -8
- package/src/Throttler.res.mjs +9 -6
- package/src/Throttler.resi +1 -1
- package/src/Utils.res +0 -6
- package/src/Utils.res.mjs +0 -5
- package/src/Writing.res +0 -1
- package/src/Writing.res.mjs +1 -1
- package/src/bindings/ClickHouse.res +0 -322
- package/src/bindings/ClickHouse.res.mjs +0 -338
- package/src/bindings/StorageClient.res +107 -174
- package/src/bindings/StorageClient.res.mjs +19 -8
- package/src/bindings/Vitest.res +0 -26
- package/src/bindings/Vitest.res.mjs +0 -3
- package/src/db/Table.res +24 -150
- package/src/db/Table.res.mjs +38 -272
- package/src/sources/ChainSources.res +2 -0
- package/src/sources/ChainSources.res.mjs +2 -2
- package/src/sources/EvmChain.res +3 -0
- package/src/sources/EvmChain.res.mjs +4 -2
- package/src/sources/EvmHyperSyncSource.res +2 -2
- package/src/sources/EvmHyperSyncSource.res.mjs +1 -1
- package/src/sources/EvmRpcClient.res +13 -3
- package/src/sources/EvmRpcClient.res.mjs +4 -3
- package/src/sources/EvmRpcWs.res +4 -3
- package/src/sources/EvmRpcWs.res.mjs +2 -2
- package/src/sources/HeightFeed.res +31 -10
- package/src/sources/HeightFeed.res.mjs +10 -6
- package/src/sources/HeightStream.res +32 -17
- package/src/sources/HeightStream.res.mjs +10 -10
- package/src/sources/HyperSyncSSE.res +4 -6
- package/src/sources/HyperSyncSSE.res.mjs +2 -2
- package/src/sources/RpcSource.res +10 -1
- package/src/sources/RpcSource.res.mjs +4 -3
- package/src/sources/Source.res +3 -0
- package/src/sources/SourceManager.res +84 -77
- package/src/sources/SourceManager.res.mjs +17 -20
- package/src/sources/SourceManager.resi +3 -4
- package/src/sources/StartBlockResolver.res +1 -0
- package/src/sources/StartBlockResolver.res.mjs +3 -2
- package/src/sources/SvmHyperSyncSource.res +2 -2
- package/src/sources/SvmHyperSyncSource.res.mjs +1 -1
- package/svm.schema.json +11 -2
- package/src/PgWriting.res +0 -36
- package/src/PgWriting.res.mjs +0 -34
- package/src/db/IndexDefinition.res +0 -47
- package/src/db/IndexDefinition.res.mjs +0 -67
package/src/FetchState.res.mjs
CHANGED
|
@@ -941,26 +941,47 @@ function updateInternal(fetchState, optimizedPartitionsOpt, mutItems, mutItemsSo
|
|
|
941
941
|
chainId: fetchState.chainId,
|
|
942
942
|
latestOnBlockBlockNumber: latestOnBlockBlockNumber,
|
|
943
943
|
blockLag: blockLag,
|
|
944
|
+
blockThrottle: fetchState.blockThrottle,
|
|
944
945
|
buffer: blockItems.length !== 0 ? mergeIntoBuffer(base, blockItems) : base,
|
|
945
946
|
maxOnBlockBufferSize: fetchState.maxOnBlockBufferSize,
|
|
946
947
|
onBlockRegistrations: fetchState.onBlockRegistrations,
|
|
947
948
|
knownHeight: knownHeight,
|
|
948
949
|
firstEventBlock: fetchState.firstEventBlock,
|
|
949
|
-
|
|
950
|
+
clientFilterPolicy: fetchState.clientFilterPolicy
|
|
950
951
|
};
|
|
951
952
|
}
|
|
952
953
|
|
|
953
|
-
function
|
|
954
|
+
function switchToClientSideFiltering(clientFilteredContracts, contractNames, policy, dynamicContracts, addressStore, onNotice, isAlreadyReportedOpt) {
|
|
954
955
|
let isAlreadyReported = isAlreadyReportedOpt !== undefined ? isAlreadyReportedOpt : false;
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
956
|
+
let switched = new Set(Array.from(clientFilteredContracts));
|
|
957
|
+
contractNames.forEach(contractName => {
|
|
958
|
+
if (switched.has(contractName)) {
|
|
959
|
+
return;
|
|
960
|
+
}
|
|
961
|
+
if (policy.allDynamicContracts && dynamicContracts.has(contractName)) {
|
|
962
|
+
switched.add(contractName);
|
|
963
|
+
return;
|
|
964
|
+
}
|
|
965
|
+
let threshold = policy.addressThreshold;
|
|
966
|
+
if (threshold === undefined) {
|
|
967
|
+
return;
|
|
968
|
+
}
|
|
969
|
+
let addressCount = addressStore.contractCount(contractName);
|
|
970
|
+
if (addressCount > threshold) {
|
|
971
|
+
switched.add(contractName);
|
|
972
|
+
if (!isAlreadyReported) {
|
|
973
|
+
return onNotice({
|
|
974
|
+
TAG: "SwitchedToClientSideFiltering",
|
|
975
|
+
contractName: contractName,
|
|
976
|
+
addressCount: addressCount,
|
|
977
|
+
threshold: threshold
|
|
978
|
+
});
|
|
979
|
+
} else {
|
|
980
|
+
return;
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
});
|
|
984
|
+
return switched;
|
|
964
985
|
}
|
|
965
986
|
|
|
966
987
|
function claimedFetchedBlock(p, knownHeight) {
|
|
@@ -1362,20 +1383,7 @@ function registerDynamicContracts(fetchState, addressStore, onNotice, claimCeili
|
|
|
1362
1383
|
}
|
|
1363
1384
|
}
|
|
1364
1385
|
}
|
|
1365
|
-
let
|
|
1366
|
-
let clientFilteredContracts;
|
|
1367
|
-
if (threshold !== undefined) {
|
|
1368
|
-
let clientFilteredContracts$1 = new Set(Array.from(fetchState.optimizedPartitions.clientFilteredContracts));
|
|
1369
|
-
Array.from(dynamicContractsRef).forEach(contractName => {
|
|
1370
|
-
let addressCount = addressStore.contractCount(contractName);
|
|
1371
|
-
if (!clientFilteredContracts$1.has(contractName) && addressCount > threshold) {
|
|
1372
|
-
return addClientFilteredContract(clientFilteredContracts$1, contractName, onNotice, addressCount, threshold, undefined);
|
|
1373
|
-
}
|
|
1374
|
-
});
|
|
1375
|
-
clientFilteredContracts = clientFilteredContracts$1;
|
|
1376
|
-
} else {
|
|
1377
|
-
clientFilteredContracts = fetchState.optimizedPartitions.clientFilteredContracts;
|
|
1378
|
-
}
|
|
1386
|
+
let clientFilteredContracts = switchToClientSideFiltering(fetchState.optimizedPartitions.clientFilteredContracts, Array.from(dynamicContractsRef), fetchState.clientFilterPolicy, dynamicContractsRef, addressStore, onNotice, undefined);
|
|
1379
1387
|
let registeringSetsByContract = {};
|
|
1380
1388
|
registeringContractNames.forEach(contractName => {
|
|
1381
1389
|
registeringSetsByContract[contractName] = AddressStore.makeSet(addressStore, contractName, {
|
|
@@ -1386,6 +1394,55 @@ function registerDynamicContracts(fetchState, addressStore, onNotice, claimCeili
|
|
|
1386
1394
|
return updateInternal(fetchState, optimizedPartitions, undefined, undefined, undefined, undefined);
|
|
1387
1395
|
}
|
|
1388
1396
|
|
|
1397
|
+
function switchDynamicContractsToClientSideFiltering(fetchState, addressStore) {
|
|
1398
|
+
if (fetchState.clientFilterPolicy.allDynamicContracts) {
|
|
1399
|
+
return fetchState;
|
|
1400
|
+
}
|
|
1401
|
+
let init = fetchState.clientFilterPolicy;
|
|
1402
|
+
let fetchState_optimizedPartitions = fetchState.optimizedPartitions;
|
|
1403
|
+
let fetchState_startBlock = fetchState.startBlock;
|
|
1404
|
+
let fetchState_endBlock = fetchState.endBlock;
|
|
1405
|
+
let fetchState_normalSelection = fetchState.normalSelection;
|
|
1406
|
+
let fetchState_chainId = fetchState.chainId;
|
|
1407
|
+
let fetchState_latestOnBlockBlockNumber = fetchState.latestOnBlockBlockNumber;
|
|
1408
|
+
let fetchState_blockLag = fetchState.blockLag;
|
|
1409
|
+
let fetchState_blockThrottle = fetchState.blockThrottle;
|
|
1410
|
+
let fetchState_buffer = fetchState.buffer;
|
|
1411
|
+
let fetchState_maxOnBlockBufferSize = fetchState.maxOnBlockBufferSize;
|
|
1412
|
+
let fetchState_onBlockRegistrations = fetchState.onBlockRegistrations;
|
|
1413
|
+
let fetchState_knownHeight = fetchState.knownHeight;
|
|
1414
|
+
let fetchState_firstEventBlock = fetchState.firstEventBlock;
|
|
1415
|
+
let fetchState_clientFilterPolicy = {
|
|
1416
|
+
addressThreshold: init.addressThreshold,
|
|
1417
|
+
allDynamicContracts: true
|
|
1418
|
+
};
|
|
1419
|
+
let fetchState$1 = {
|
|
1420
|
+
optimizedPartitions: fetchState_optimizedPartitions,
|
|
1421
|
+
startBlock: fetchState_startBlock,
|
|
1422
|
+
endBlock: fetchState_endBlock,
|
|
1423
|
+
normalSelection: fetchState_normalSelection,
|
|
1424
|
+
chainId: fetchState_chainId,
|
|
1425
|
+
latestOnBlockBlockNumber: fetchState_latestOnBlockBlockNumber,
|
|
1426
|
+
blockLag: fetchState_blockLag,
|
|
1427
|
+
blockThrottle: fetchState_blockThrottle,
|
|
1428
|
+
buffer: fetchState_buffer,
|
|
1429
|
+
maxOnBlockBufferSize: fetchState_maxOnBlockBufferSize,
|
|
1430
|
+
onBlockRegistrations: fetchState_onBlockRegistrations,
|
|
1431
|
+
knownHeight: fetchState_knownHeight,
|
|
1432
|
+
firstEventBlock: fetchState_firstEventBlock,
|
|
1433
|
+
clientFilterPolicy: fetchState_clientFilterPolicy
|
|
1434
|
+
};
|
|
1435
|
+
let match = fetchState_optimizedPartitions;
|
|
1436
|
+
let clientFilteredContracts = match.clientFilteredContracts;
|
|
1437
|
+
let dynamicContracts = match.dynamicContracts;
|
|
1438
|
+
let switched = new Set(Array.from(clientFilteredContracts).concat(Array.from(dynamicContracts)));
|
|
1439
|
+
if (switched.size === clientFilteredContracts.size) {
|
|
1440
|
+
return fetchState$1;
|
|
1441
|
+
} else {
|
|
1442
|
+
return updateInternal(fetchState$1, createPartitions({}, addressStore, dynamicContracts, switched, fetchState_normalSelection, match.maxAddrInPartition, match.nextPartitionIndex, Object.values(fetchState_optimizedPartitions.entities), 0, fetchState_knownHeight), undefined, undefined, undefined, undefined);
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
|
|
1389
1446
|
function handleQueryResult(fetchState, query, latestFetchedBlock, newItems) {
|
|
1390
1447
|
return updateInternal(fetchState, handleQueryResponse(fetchState.optimizedPartitions, query, fetchState.knownHeight, newItems.length, latestFetchedBlock), newItems.length !== 0 ? mergeIntoBuffer(fetchState.buffer, newItems) : undefined, true, undefined, undefined);
|
|
1391
1448
|
}
|
|
@@ -1624,15 +1681,30 @@ function acceptCandidates(candidates, reservations, chainTargetItems, partitionI
|
|
|
1624
1681
|
};
|
|
1625
1682
|
}
|
|
1626
1683
|
|
|
1627
|
-
function
|
|
1628
|
-
let
|
|
1684
|
+
function blocksBehindHeadAllowedByThrottle(param) {
|
|
1685
|
+
let blockThrottle = param.blockThrottle;
|
|
1629
1686
|
let endBlock = param.endBlock;
|
|
1630
|
-
|
|
1631
|
-
|
|
1687
|
+
if (endBlock !== undefined && (param.knownHeight - param.blockLag | 0) >= endBlock) {
|
|
1688
|
+
return 0;
|
|
1689
|
+
} else {
|
|
1690
|
+
return Primitive_int.max(0, blockThrottle - 1 | 0);
|
|
1691
|
+
}
|
|
1692
|
+
}
|
|
1693
|
+
|
|
1694
|
+
function headFetchTarget(fetchState) {
|
|
1695
|
+
return (fetchState.knownHeight - fetchState.blockLag | 0) - blocksBehindHeadAllowedByThrottle(fetchState) | 0;
|
|
1696
|
+
}
|
|
1697
|
+
|
|
1698
|
+
function getNextQuery(fetchState, chainTargetBlock, chainTargetItems) {
|
|
1699
|
+
let blockLag = fetchState.blockLag;
|
|
1700
|
+
let endBlock = fetchState.endBlock;
|
|
1701
|
+
let optimizedPartitions = fetchState.optimizedPartitions;
|
|
1702
|
+
let headBlockNumber = fetchState.knownHeight - blockLag | 0;
|
|
1632
1703
|
if (headBlockNumber <= 0) {
|
|
1633
1704
|
return "WaitingForNewBlock";
|
|
1634
1705
|
}
|
|
1635
|
-
let
|
|
1706
|
+
let caughtUpBlockNumber = headBlockNumber - blocksBehindHeadAllowedByThrottle(fetchState) | 0;
|
|
1707
|
+
let isOnBlockBehindTheHead = fetchState.latestOnBlockBlockNumber < caughtUpBlockNumber;
|
|
1636
1708
|
let shouldWaitForNewBlock = (
|
|
1637
1709
|
endBlock !== undefined ? headBlockNumber < endBlock : true
|
|
1638
1710
|
) && !isOnBlockBehindTheHead;
|
|
@@ -1658,7 +1730,7 @@ function getNextQuery(param, chainTargetBlock, chainTargetItems) {
|
|
|
1658
1730
|
}
|
|
1659
1731
|
}
|
|
1660
1732
|
inFlightCounts[idx] = inFlightCount;
|
|
1661
|
-
if (p.mutPendingQueries.length !== 0 || p.latestFetchedBlock <
|
|
1733
|
+
if (p.mutPendingQueries.length !== 0 || p.latestFetchedBlock < caughtUpBlockNumber) {
|
|
1662
1734
|
shouldWaitForNewBlock = false;
|
|
1663
1735
|
}
|
|
1664
1736
|
}
|
|
@@ -1749,10 +1821,11 @@ function getReadyItemsCount(fetchState, targetSize, fromItem) {
|
|
|
1749
1821
|
return acc;
|
|
1750
1822
|
}
|
|
1751
1823
|
|
|
1752
|
-
function make$1(startBlock, endBlock, onEventRegistrations, addressStore, addressRows, maxAddrInPartition, chainId, onNotice, maxOnBlockBufferSize, knownHeight, progressBlockNumberOpt, onBlockRegistrationsOpt, blockLagOpt, firstEventBlockOpt, clientFilterAddressThresholdOpt, isResumedOpt) {
|
|
1824
|
+
function make$1(startBlock, endBlock, onEventRegistrations, addressStore, addressRows, maxAddrInPartition, chainId, onNotice, maxOnBlockBufferSize, knownHeight, progressBlockNumberOpt, onBlockRegistrationsOpt, blockLagOpt, blockThrottleOpt, firstEventBlockOpt, clientFilterAddressThresholdOpt, isResumedOpt) {
|
|
1753
1825
|
let progressBlockNumber = progressBlockNumberOpt !== undefined ? progressBlockNumberOpt : startBlock - 1 | 0;
|
|
1754
1826
|
let onBlockRegistrations = onBlockRegistrationsOpt !== undefined ? onBlockRegistrationsOpt : [];
|
|
1755
1827
|
let blockLag = blockLagOpt !== undefined ? blockLagOpt : 0;
|
|
1828
|
+
let blockThrottle = blockThrottleOpt !== undefined ? blockThrottleOpt : 0;
|
|
1756
1829
|
let firstEventBlock = firstEventBlockOpt !== undefined ? Primitive_option.valFromOption(firstEventBlockOpt) : undefined;
|
|
1757
1830
|
let clientFilterAddressThreshold = clientFilterAddressThresholdOpt !== undefined ? Primitive_option.valFromOption(clientFilterAddressThresholdOpt) : undefined;
|
|
1758
1831
|
let isResumed = isResumedOpt !== undefined ? isResumedOpt : false;
|
|
@@ -1801,7 +1874,6 @@ function make$1(startBlock, endBlock, onEventRegistrations, addressStore, addres
|
|
|
1801
1874
|
requestedFromBlock: rejected.effectiveStartBlock
|
|
1802
1875
|
}));
|
|
1803
1876
|
let dynamicContracts = new Set();
|
|
1804
|
-
let clientFilteredContracts = new Set();
|
|
1805
1877
|
let registeringSetsByContract = {};
|
|
1806
1878
|
Array.from(contractNamesWithNormalEvents).forEach(contractName => {
|
|
1807
1879
|
if (addressStore.contractCount(contractName) > 0) {
|
|
@@ -1815,14 +1887,11 @@ function make$1(startBlock, endBlock, onEventRegistrations, addressStore, addres
|
|
|
1815
1887
|
return;
|
|
1816
1888
|
}
|
|
1817
1889
|
});
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
}
|
|
1824
|
-
});
|
|
1825
|
-
}
|
|
1890
|
+
let clientFilterPolicy = {
|
|
1891
|
+
addressThreshold: clientFilterAddressThreshold,
|
|
1892
|
+
allDynamicContracts: false
|
|
1893
|
+
};
|
|
1894
|
+
let clientFilteredContracts = switchToClientSideFiltering(new Set(), Object.keys(registeringSetsByContract), clientFilterPolicy, dynamicContracts, addressStore, onNotice, isResumed);
|
|
1826
1895
|
let optimizedPartitions = createPartitions(registeringSetsByContract, addressStore, dynamicContracts, clientFilteredContracts, normalSelection, maxAddrInPartition, partitions.length, partitions, progressBlockNumber, knownHeight);
|
|
1827
1896
|
if (optimizedPartitions.idsInAscOrder.length === 0 && Utils.$$Array.isEmpty(onBlockRegistrations$1)) {
|
|
1828
1897
|
Stdlib_JsError.throwWithMessage(`Invalid configuration: Nothing to fetch on chain ` + ChainId.toString(chainId) + `. ` + (`addresses=` + addressRows.addresses.length.toString() + `, `) + (`onEventRegistrations=` + onEventRegistrations.length.toString() + `, `) + (`normalRegistrations=` + normalRegistrations.length.toString() + `. `) + `Make sure that you provided at least one contract address to index, or have events with Wildcard mode enabled, or have onBlock handlers.`);
|
|
@@ -1853,12 +1922,13 @@ function make$1(startBlock, endBlock, onEventRegistrations, addressStore, addres
|
|
|
1853
1922
|
chainId: chainId,
|
|
1854
1923
|
latestOnBlockBlockNumber: latestOnBlockBlockNumber,
|
|
1855
1924
|
blockLag: blockLag,
|
|
1925
|
+
blockThrottle: blockThrottle,
|
|
1856
1926
|
buffer: buffer,
|
|
1857
1927
|
maxOnBlockBufferSize: maxOnBlockBufferSize,
|
|
1858
1928
|
onBlockRegistrations: onBlockRegistrations$1,
|
|
1859
1929
|
knownHeight: knownHeight,
|
|
1860
1930
|
firstEventBlock: firstEventBlock,
|
|
1861
|
-
|
|
1931
|
+
clientFilterPolicy: clientFilterPolicy
|
|
1862
1932
|
};
|
|
1863
1933
|
}
|
|
1864
1934
|
|
|
@@ -1966,12 +2036,13 @@ function rollback(fetchState, rolledBackAddressStore, targetBlockNumber) {
|
|
|
1966
2036
|
chainId: fetchState.chainId,
|
|
1967
2037
|
latestOnBlockBlockNumber: Primitive_int.min(fetchState.latestOnBlockBlockNumber, targetBlockNumber),
|
|
1968
2038
|
blockLag: fetchState.blockLag,
|
|
2039
|
+
blockThrottle: fetchState.blockThrottle,
|
|
1969
2040
|
buffer: fetchState.buffer,
|
|
1970
2041
|
maxOnBlockBufferSize: fetchState.maxOnBlockBufferSize,
|
|
1971
2042
|
onBlockRegistrations: fetchState.onBlockRegistrations,
|
|
1972
2043
|
knownHeight: fetchState.knownHeight,
|
|
1973
2044
|
firstEventBlock: fetchState.firstEventBlock,
|
|
1974
|
-
|
|
2045
|
+
clientFilterPolicy: fetchState.clientFilterPolicy
|
|
1975
2046
|
}, optimizedPartitions, fetchState.buffer.filter(item => {
|
|
1976
2047
|
let tmp;
|
|
1977
2048
|
tmp = item.kind === 0 ? item.blockNumber : item.blockNumber;
|
|
@@ -2021,12 +2092,13 @@ function resetPendingQueries(fetchState) {
|
|
|
2021
2092
|
chainId: fetchState.chainId,
|
|
2022
2093
|
latestOnBlockBlockNumber: fetchState.latestOnBlockBlockNumber,
|
|
2023
2094
|
blockLag: fetchState.blockLag,
|
|
2095
|
+
blockThrottle: fetchState.blockThrottle,
|
|
2024
2096
|
buffer: fetchState.buffer,
|
|
2025
2097
|
maxOnBlockBufferSize: fetchState.maxOnBlockBufferSize,
|
|
2026
2098
|
onBlockRegistrations: fetchState.onBlockRegistrations,
|
|
2027
2099
|
knownHeight: fetchState.knownHeight,
|
|
2028
2100
|
firstEventBlock: fetchState.firstEventBlock,
|
|
2029
|
-
|
|
2101
|
+
clientFilterPolicy: fetchState.clientFilterPolicy
|
|
2030
2102
|
};
|
|
2031
2103
|
}
|
|
2032
2104
|
|
|
@@ -2044,21 +2116,37 @@ function isActivelyIndexing(fetchState) {
|
|
|
2044
2116
|
}
|
|
2045
2117
|
|
|
2046
2118
|
function isFetchingAtHead(fetchState) {
|
|
2047
|
-
let knownHeight = fetchState.knownHeight;
|
|
2048
|
-
let blockLag = fetchState.blockLag;
|
|
2049
2119
|
let endBlock = fetchState.endBlock;
|
|
2050
2120
|
let bufferBlockNumber$1 = bufferBlockNumber(fetchState);
|
|
2051
|
-
if (knownHeight !== 0) {
|
|
2121
|
+
if (fetchState.knownHeight !== 0) {
|
|
2052
2122
|
if (endBlock !== undefined && bufferBlockNumber$1 >= endBlock) {
|
|
2053
2123
|
return true;
|
|
2054
2124
|
} else {
|
|
2055
|
-
return bufferBlockNumber$1 >= (
|
|
2125
|
+
return bufferBlockNumber$1 >= headFetchTarget(fetchState);
|
|
2056
2126
|
}
|
|
2057
2127
|
} else {
|
|
2058
2128
|
return false;
|
|
2059
2129
|
}
|
|
2060
2130
|
}
|
|
2061
2131
|
|
|
2132
|
+
function isWithinHeadClientFilteringDistance(fetchState) {
|
|
2133
|
+
let knownHeight = fetchState.knownHeight;
|
|
2134
|
+
let endBlock = fetchState.endBlock;
|
|
2135
|
+
let optimizedPartitions = fetchState.optimizedPartitions;
|
|
2136
|
+
if (!(knownHeight !== 0 && (
|
|
2137
|
+
endBlock !== undefined ? endBlock > (knownHeight - fetchState.blockLag | 0) : true
|
|
2138
|
+
))) {
|
|
2139
|
+
return false;
|
|
2140
|
+
}
|
|
2141
|
+
let id = optimizedPartitions.idsInAscOrder[0];
|
|
2142
|
+
let latestFetchedBlock = id !== undefined ? optimizedPartitions.entities[id].latestFetchedBlock : undefined;
|
|
2143
|
+
if (latestFetchedBlock !== undefined) {
|
|
2144
|
+
return (headFetchTarget(fetchState) - latestFetchedBlock | 0) <= 200;
|
|
2145
|
+
} else {
|
|
2146
|
+
return true;
|
|
2147
|
+
}
|
|
2148
|
+
}
|
|
2149
|
+
|
|
2062
2150
|
function isReadyToEnterReorgThreshold(tolerance, fetchState) {
|
|
2063
2151
|
let knownHeight = fetchState.knownHeight;
|
|
2064
2152
|
let endBlock = fetchState.endBlock;
|
|
@@ -2145,6 +2233,8 @@ let maxChainConcurrency = Env.maxChainConcurrency;
|
|
|
2145
2233
|
|
|
2146
2234
|
let chunkRangeGrowthFactor = 1.8;
|
|
2147
2235
|
|
|
2236
|
+
let headClientFilteringDistance = 200;
|
|
2237
|
+
|
|
2148
2238
|
export {
|
|
2149
2239
|
deriveSelectionStartBlock,
|
|
2150
2240
|
makeSelection,
|
|
@@ -2168,12 +2258,13 @@ export {
|
|
|
2168
2258
|
mergeIntoBuffer,
|
|
2169
2259
|
appendOnBlockItems,
|
|
2170
2260
|
updateInternal,
|
|
2171
|
-
|
|
2261
|
+
switchToClientSideFiltering,
|
|
2172
2262
|
claimedFetchedBlock,
|
|
2173
2263
|
collapseClientFilteredContracts,
|
|
2174
2264
|
reportRejectedRegistration,
|
|
2175
2265
|
createPartitions,
|
|
2176
2266
|
registerDynamicContracts,
|
|
2267
|
+
switchDynamicContractsToClientSideFiltering,
|
|
2177
2268
|
handleQueryResult,
|
|
2178
2269
|
startFetchingQueries,
|
|
2179
2270
|
maxInFlightChunksPerPartition,
|
|
@@ -2184,6 +2275,8 @@ export {
|
|
|
2184
2275
|
walkPartitionPending,
|
|
2185
2276
|
pushForwardCandidates,
|
|
2186
2277
|
acceptCandidates,
|
|
2278
|
+
blocksBehindHeadAllowedByThrottle,
|
|
2279
|
+
headFetchTarget,
|
|
2187
2280
|
getNextQuery,
|
|
2188
2281
|
hasReadyItem,
|
|
2189
2282
|
getReadyItemsCount,
|
|
@@ -2195,6 +2288,8 @@ export {
|
|
|
2195
2288
|
resetPendingQueries,
|
|
2196
2289
|
isActivelyIndexing,
|
|
2197
2290
|
isFetchingAtHead,
|
|
2291
|
+
headClientFilteringDistance,
|
|
2292
|
+
isWithinHeadClientFilteringDistance,
|
|
2198
2293
|
isReadyToEnterReorgThreshold,
|
|
2199
2294
|
getProgressPercentage,
|
|
2200
2295
|
sortForBatch,
|
package/src/FinalizeBackfill.res
CHANGED
|
@@ -40,7 +40,7 @@ let runOnce = async (state: IndexerState.t) => {
|
|
|
40
40
|
let storage = persistence->Persistence.getInitializedStorageOrThrow
|
|
41
41
|
let readyAt = Date.make()
|
|
42
42
|
|
|
43
|
-
await storage.finalizeBackfill(~
|
|
43
|
+
await storage.finalizeBackfill(~chainIds, ~readyAt)
|
|
44
44
|
|
|
45
45
|
// Only after the commit: in-memory readiness must never run ahead of the
|
|
46
46
|
// `ready_at` a restart would read back.
|
|
@@ -68,10 +68,8 @@ let run = (state: IndexerState.t) =>
|
|
|
68
68
|
// Best-effort and not awaited by the loop: indexing is already live and correct
|
|
69
69
|
// without the index, just slower.
|
|
70
70
|
let repairSchemaIndexes = (state: IndexerState.t) => {
|
|
71
|
-
let
|
|
72
|
-
let storage = persistence->Persistence.getInitializedStorageOrThrow
|
|
71
|
+
let storage = state->IndexerState.persistence->Persistence.getInitializedStorageOrThrow
|
|
73
72
|
storage.ensureSchemaIndexes(
|
|
74
|
-
~entities=persistence.allEntities,
|
|
75
73
|
~chainIds=state->IndexerState.crossChainState->CrossChainState.chainIds,
|
|
76
74
|
)
|
|
77
75
|
}
|
|
@@ -27,7 +27,7 @@ async function runOnce(state) {
|
|
|
27
27
|
let persistence = IndexerState.persistence(state);
|
|
28
28
|
let storage = Persistence.getInitializedStorageOrThrow(persistence);
|
|
29
29
|
let readyAt = new Date();
|
|
30
|
-
await storage.finalizeBackfill(
|
|
30
|
+
await storage.finalizeBackfill(chainIds, readyAt);
|
|
31
31
|
return IndexerState.markReady(state, readyAt);
|
|
32
32
|
}
|
|
33
33
|
|
|
@@ -42,9 +42,8 @@ function run(state) {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
function repairSchemaIndexes(state) {
|
|
45
|
-
let
|
|
46
|
-
|
|
47
|
-
return storage.ensureSchemaIndexes(persistence.allEntities, CrossChainState.chainIds(IndexerState.crossChainState(state)));
|
|
45
|
+
let storage = Persistence.getInitializedStorageOrThrow(IndexerState.persistence(state));
|
|
46
|
+
return storage.ensureSchemaIndexes(CrossChainState.chainIds(IndexerState.crossChainState(state)));
|
|
48
47
|
}
|
|
49
48
|
|
|
50
49
|
export {
|
package/src/InMemoryTable.res
CHANGED
|
@@ -22,6 +22,8 @@ module Entity = {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
type t = {
|
|
25
|
+
// Keys every id dict and Set below; see Table.table.
|
|
26
|
+
entityIdToKey: EntityId.t => string,
|
|
25
27
|
latestEntityChangeById: dict<Change.t<Internal.entity>>,
|
|
26
28
|
// Recorded changes (new latest ids + prevEntityChanges pushes), tracked
|
|
27
29
|
// manually so InMemoryStore can gauge size without scanning every dict.
|
|
@@ -45,12 +47,9 @@ module Entity = {
|
|
|
45
47
|
mutable hasIndexes: bool,
|
|
46
48
|
}
|
|
47
49
|
|
|
48
|
-
|
|
49
|
-
// string/int/bigint, so it's stringified to a stable key for in-memory
|
|
50
|
-
// indexing.
|
|
51
|
-
let getEntityIdUnsafe = (entity: Internal.entity): string =>
|
|
50
|
+
let getEntityKeyUnsafe = (self: t, entity: Internal.entity): string =>
|
|
52
51
|
switch (entity->(Utils.magic: Internal.entity => {"id": option<EntityId.t>}))["id"] {
|
|
53
|
-
| Some(id) => id
|
|
52
|
+
| Some(id) => self.entityIdToKey(id)
|
|
54
53
|
| None => JsError.throwWithMessage("Property 'id' does not exist on expected entity object")
|
|
55
54
|
}
|
|
56
55
|
|
|
@@ -62,7 +61,8 @@ module Entity = {
|
|
|
62
61
|
}
|
|
63
62
|
}
|
|
64
63
|
|
|
65
|
-
let make = (): t => {
|
|
64
|
+
let make = (~entityIdToKey): t => {
|
|
65
|
+
entityIdToKey,
|
|
66
66
|
latestEntityChangeById: Dict.make(),
|
|
67
67
|
changesCount: 0.,
|
|
68
68
|
dirtyIds: Utils.Set.make(),
|
|
@@ -141,10 +141,8 @@ module Entity = {
|
|
|
141
141
|
self.hasIndexes = false
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
-
let updateIndexes = (self: t, ~entity: Internal.entity) =>
|
|
144
|
+
let updateIndexes = (self: t, ~entityId: string, ~entity: Internal.entity) =>
|
|
145
145
|
if self.hasIndexes {
|
|
146
|
-
let entityId = entity->getEntityIdUnsafe
|
|
147
|
-
|
|
148
146
|
switch self.indexesByEntityId->Utils.Dict.dangerouslyGetNonOption(entityId) {
|
|
149
147
|
| None => ()
|
|
150
148
|
| Some(indexes) =>
|
|
@@ -185,7 +183,7 @@ module Entity = {
|
|
|
185
183
|
}
|
|
186
184
|
|
|
187
185
|
let set = (inMemTable: t, ~committedCheckpointId, change: Change.t<Internal.entity>) => {
|
|
188
|
-
let entityKey = change->Change.getEntityId
|
|
186
|
+
let entityKey = inMemTable.entityIdToKey(change->Change.getEntityId)
|
|
189
187
|
switch inMemTable.latestEntityChangeById->Utils.Dict.dangerouslyGetNonOption(entityKey) {
|
|
190
188
|
| Some(prev) =>
|
|
191
189
|
let prevCheckpointId = prev->Change.getCheckpointId
|
|
@@ -200,8 +198,8 @@ module Entity = {
|
|
|
200
198
|
}
|
|
201
199
|
|
|
202
200
|
switch change {
|
|
203
|
-
| Set({entity}) => inMemTable->updateIndexes(~entity)
|
|
204
|
-
| Delete(
|
|
201
|
+
| Set({entity}) => inMemTable->updateIndexes(~entityId=entityKey, ~entity)
|
|
202
|
+
| Delete(_) => inMemTable->deleteEntityFromIndexes(~entityId=entityKey)
|
|
205
203
|
}
|
|
206
204
|
inMemTable.latestEntityChangeById->Dict.set(entityKey, change)
|
|
207
205
|
if change->Change.getCheckpointId > committedCheckpointId {
|
|
@@ -214,11 +212,14 @@ module Entity = {
|
|
|
214
212
|
let initValue = (
|
|
215
213
|
inMemTable: t,
|
|
216
214
|
~committedCheckpointId,
|
|
217
|
-
~
|
|
215
|
+
~entityId: EntityId.t,
|
|
218
216
|
~entity: option<Internal.entity>,
|
|
219
217
|
) =>
|
|
220
|
-
if
|
|
221
|
-
|
|
218
|
+
if (
|
|
219
|
+
inMemTable.latestEntityChangeById
|
|
220
|
+
->Utils.Dict.dangerouslyGetNonOption(inMemTable.entityIdToKey(entityId))
|
|
221
|
+
->Option.isNone
|
|
222
|
+
) {
|
|
222
223
|
let change: Change.t<Internal.entity> = switch entity {
|
|
223
224
|
| Some(entity) => Set({entityId, entity, checkpointId: Internal.loadedFromDbCheckpointId})
|
|
224
225
|
| None => Delete({entityId, checkpointId: Internal.loadedFromDbCheckpointId})
|
|
@@ -312,7 +313,7 @@ module Entity = {
|
|
|
312
313
|
switch change->mapChangeToEntity {
|
|
313
314
|
| Some(entity) =>
|
|
314
315
|
if index.matcher(entity) {
|
|
315
|
-
inMemTable->addToIndex(~index, ~entityId=entity
|
|
316
|
+
inMemTable->addToIndex(~index, ~entityId=inMemTable->getEntityKeyUnsafe(entity))
|
|
316
317
|
}
|
|
317
318
|
| None => ()
|
|
318
319
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
3
|
import * as Utils from "./Utils.res.mjs";
|
|
4
|
-
import * as EntityId from "./EntityId.res.mjs";
|
|
5
4
|
import * as Internal from "./Internal.res.mjs";
|
|
6
5
|
import * as EntityFilter from "./db/EntityFilter.res.mjs";
|
|
7
6
|
import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
|
|
@@ -9,10 +8,10 @@ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
|
9
8
|
import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
|
|
10
9
|
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
11
10
|
|
|
12
|
-
function
|
|
11
|
+
function getEntityKeyUnsafe(self, entity) {
|
|
13
12
|
let id = entity.id;
|
|
14
13
|
if (id !== undefined) {
|
|
15
|
-
return
|
|
14
|
+
return self.entityIdToKey(Primitive_option.valFromOption(id));
|
|
16
15
|
} else {
|
|
17
16
|
return Stdlib_JsError.throwWithMessage("Property 'id' does not exist on expected entity object");
|
|
18
17
|
}
|
|
@@ -28,8 +27,9 @@ function addToIndex(self, index, entityId) {
|
|
|
28
27
|
}
|
|
29
28
|
}
|
|
30
29
|
|
|
31
|
-
function make() {
|
|
30
|
+
function make(entityIdToKey) {
|
|
32
31
|
return {
|
|
32
|
+
entityIdToKey: entityIdToKey,
|
|
33
33
|
latestEntityChangeById: {},
|
|
34
34
|
changesCount: 0,
|
|
35
35
|
dirtyIds: new Set(),
|
|
@@ -99,11 +99,10 @@ function dropCommittedChanges(self, committedCheckpointId, keepLoadedFromDb) {
|
|
|
99
99
|
self.hasIndexes = false;
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
function updateIndexes(self, entity) {
|
|
102
|
+
function updateIndexes(self, entityId, entity) {
|
|
103
103
|
if (!self.hasIndexes) {
|
|
104
104
|
return;
|
|
105
105
|
}
|
|
106
|
-
let entityId = getEntityIdUnsafe(entity);
|
|
107
106
|
let indexes = self.indexesByEntityId[entityId];
|
|
108
107
|
if (indexes !== undefined) {
|
|
109
108
|
let indexes$1 = Primitive_option.valFromOption(indexes);
|
|
@@ -144,7 +143,7 @@ function deleteEntityFromIndexes(self, entityId) {
|
|
|
144
143
|
}
|
|
145
144
|
|
|
146
145
|
function set(inMemTable, committedCheckpointId, change) {
|
|
147
|
-
let entityKey =
|
|
146
|
+
let entityKey = inMemTable.entityIdToKey(change.entityId);
|
|
148
147
|
let prev = inMemTable.latestEntityChangeById[entityKey];
|
|
149
148
|
if (prev !== undefined) {
|
|
150
149
|
let prevCheckpointId = prev.checkpointId;
|
|
@@ -156,9 +155,9 @@ function set(inMemTable, committedCheckpointId, change) {
|
|
|
156
155
|
inMemTable.changesCount = inMemTable.changesCount + 1;
|
|
157
156
|
}
|
|
158
157
|
if (change.type === "SET") {
|
|
159
|
-
updateIndexes(inMemTable, change.entity);
|
|
158
|
+
updateIndexes(inMemTable, entityKey, change.entity);
|
|
160
159
|
} else {
|
|
161
|
-
deleteEntityFromIndexes(inMemTable,
|
|
160
|
+
deleteEntityFromIndexes(inMemTable, entityKey);
|
|
162
161
|
}
|
|
163
162
|
inMemTable.latestEntityChangeById[entityKey] = change;
|
|
164
163
|
if (change.checkpointId > committedCheckpointId) {
|
|
@@ -167,18 +166,18 @@ function set(inMemTable, committedCheckpointId, change) {
|
|
|
167
166
|
}
|
|
168
167
|
}
|
|
169
168
|
|
|
170
|
-
function initValue(inMemTable, committedCheckpointId,
|
|
171
|
-
if (!Stdlib_Option.isNone(inMemTable.latestEntityChangeById[
|
|
169
|
+
function initValue(inMemTable, committedCheckpointId, entityId, entity) {
|
|
170
|
+
if (!Stdlib_Option.isNone(inMemTable.latestEntityChangeById[inMemTable.entityIdToKey(entityId)])) {
|
|
172
171
|
return;
|
|
173
172
|
}
|
|
174
173
|
let change = entity !== undefined ? ({
|
|
175
174
|
type: "SET",
|
|
176
|
-
entityId:
|
|
175
|
+
entityId: entityId,
|
|
177
176
|
entity: entity,
|
|
178
177
|
checkpointId: Internal.loadedFromDbCheckpointId
|
|
179
178
|
}) : ({
|
|
180
179
|
type: "DELETE",
|
|
181
|
-
entityId:
|
|
180
|
+
entityId: entityId,
|
|
182
181
|
checkpointId: Internal.loadedFromDbCheckpointId
|
|
183
182
|
});
|
|
184
183
|
set(inMemTable, committedCheckpointId, change);
|
|
@@ -285,7 +284,7 @@ function addEmptyIndex(inMemTable, filter, table) {
|
|
|
285
284
|
Utils.Dict.forEach(inMemTable.latestEntityChangeById, change => {
|
|
286
285
|
let entity = mapChangeToEntity(change);
|
|
287
286
|
if (entity !== undefined && index_matcher(entity)) {
|
|
288
|
-
return addToIndex(inMemTable, index,
|
|
287
|
+
return addToIndex(inMemTable, index, getEntityKeyUnsafe(inMemTable, entity));
|
|
289
288
|
}
|
|
290
289
|
});
|
|
291
290
|
}
|
|
@@ -321,7 +320,7 @@ function tryIndexFromLoadedValues(inMemTable, filter, table) {
|
|
|
321
320
|
}
|
|
322
321
|
|
|
323
322
|
let Entity = {
|
|
324
|
-
|
|
323
|
+
getEntityKeyUnsafe: getEntityKeyUnsafe,
|
|
325
324
|
addToIndex: addToIndex,
|
|
326
325
|
make: make,
|
|
327
326
|
snapshotChanges: snapshotChanges,
|