UNPKG

envio

Version:

A latency and sync speed optimized, developer friendly blockchain data indexer.

221 lines (210 loc) • 9.61 kB
// Generated by ReScript, PLEASE EDIT WITH CARE import * as Utils from "./Utils.res.mjs"; import * as ChainMap from "./ChainMap.res.mjs"; import * as FetchState from "./FetchState.res.mjs"; import * as ReorgDetection from "./ReorgDetection.res.mjs"; function hasReadyItem(fetchStates) { return ChainMap.values(fetchStates).some(fetchState => { if (FetchState.isActivelyIndexing(fetchState)) { return FetchState.hasReadyItem(fetchState); } else { return false; } }); } function getChainAfterBatchIfProgressed(chainBeforeBatch, progressBlockNumberAfterBatch, fetchStateAfterBatch, batchSize) { if (chainBeforeBatch.progressBlockNumber < progressBlockNumberAfterBatch) { return { batchSize: batchSize, progressBlockNumber: progressBlockNumberAfterBatch, sourceBlockNumber: chainBeforeBatch.sourceBlockNumber, totalEventsProcessed: chainBeforeBatch.totalEventsProcessed + batchSize, fetchState: fetchStateAfterBatch, isProgressAtHeadWhenBatchCreated: progressBlockNumberAfterBatch >= chainBeforeBatch.sourceBlockNumber - chainBeforeBatch.chainConfig.blockLag }; } } function getProgressedChainsById(chainsBeforeBatch, batchSizePerChain, progressBlockNumberPerChain) { let progressedChainsById = {}; ChainMap.values(chainsBeforeBatch).forEach(chainBeforeBatch => { let fetchState = chainBeforeBatch.fetchState; let progressBlockNumber = progressBlockNumberPerChain[fetchState.chainId.toString()]; let progressBlockNumberAfterBatch = progressBlockNumber !== undefined ? progressBlockNumber : chainBeforeBatch.progressBlockNumber; let batchSize = batchSizePerChain[fetchState.chainId.toString()]; let progressedChain; if (batchSize !== undefined) { let leftItems = fetchState.buffer.slice(batchSize); progressedChain = getChainAfterBatchIfProgressed(chainBeforeBatch, progressBlockNumberAfterBatch, FetchState.updateInternal(fetchState, undefined, undefined, leftItems, undefined, undefined), batchSize); } else { progressedChain = getChainAfterBatchIfProgressed(chainBeforeBatch, progressBlockNumberAfterBatch, chainBeforeBatch.fetchState, 0); } if (progressedChain !== undefined) { progressedChainsById[chainBeforeBatch.fetchState.chainId] = progressedChain; return; } }); return progressedChainsById; } function addReorgCheckpoints(prevCheckpointId, reorgDetection, fromBlockExclusive, toBlockExclusive, chainId, mutCheckpointIds, mutCheckpointChainIds, mutCheckpointBlockNumbers, mutCheckpointBlockHashes, mutCheckpointEventsProcessed) { if (!(reorgDetection.shouldRollbackOnReorg && !Utils.Dict.isEmpty(reorgDetection.dataByBlockNumber))) { return prevCheckpointId; } let prevCheckpointId$1 = prevCheckpointId; for (let blockNumber = fromBlockExclusive + 1, blockNumber_finish = toBlockExclusive - 1; blockNumber <= blockNumber_finish; ++blockNumber) { let hash = ReorgDetection.getHashByBlockNumber(reorgDetection, blockNumber); if (hash !== null) { let checkpointId = prevCheckpointId$1 + 1n; prevCheckpointId$1 = checkpointId; mutCheckpointIds.push(checkpointId); mutCheckpointChainIds.push(chainId); mutCheckpointBlockNumbers.push(blockNumber); mutCheckpointBlockHashes.push(hash); mutCheckpointEventsProcessed.push(0); } } return prevCheckpointId$1; } function prepareBatch(checkpointIdBeforeBatch, chainsBeforeBatch, batchSizeTarget, isInReorgThreshold) { let preparedFetchStates = FetchState.sortForUnorderedBatch(ChainMap.values(chainsBeforeBatch).map(chainBeforeBatch => chainBeforeBatch.fetchState), batchSizeTarget); let chainIdx = 0; let preparedNumber = preparedFetchStates.length; let totalBatchSize = 0; let prevCheckpointId = checkpointIdBeforeBatch; let mutBatchSizePerChain = {}; let mutProgressBlockNumberPerChain = {}; let items = []; let checkpointIds = []; let checkpointChainIds = []; let checkpointBlockNumbers = []; let checkpointBlockHashes = []; let checkpointEventsProcessed = []; while (totalBatchSize < batchSizeTarget && chainIdx < preparedNumber) { let fetchState = preparedFetchStates[chainIdx]; let chainBatchSize = FetchState.getReadyItemsCount(fetchState, batchSizeTarget - totalBatchSize, 0); let chainBeforeBatch = ChainMap.get(chainsBeforeBatch, ChainMap.Chain.makeUnsafe(fetchState.chainId)); let prevBlockNumber = chainBeforeBatch.progressBlockNumber; if (chainBatchSize > 0) { for (let idx = 0, idx_finish = chainBatchSize - 1; idx <= idx_finish; ++idx) { let item = fetchState.buffer[idx]; let blockNumber = item.blockNumber; if (blockNumber !== prevBlockNumber) { let chainId = fetchState.chainId; let fromBlockExclusive = prevBlockNumber; let reorgDetection = chainBeforeBatch.reorgDetection; let prevCheckpointId$1 = prevCheckpointId; let tmp; if (reorgDetection.shouldRollbackOnReorg && !Utils.Dict.isEmpty(reorgDetection.dataByBlockNumber)) { let prevCheckpointId$2 = prevCheckpointId$1; for (let blockNumber$1 = fromBlockExclusive + 1, blockNumber_finish = blockNumber - 1; blockNumber$1 <= blockNumber_finish; ++blockNumber$1) { let hash = ReorgDetection.getHashByBlockNumber(reorgDetection, blockNumber$1); if (hash !== null) { let checkpointId = prevCheckpointId$2 + 1n; prevCheckpointId$2 = checkpointId; checkpointIds.push(checkpointId); checkpointChainIds.push(chainId); checkpointBlockNumbers.push(blockNumber$1); checkpointBlockHashes.push(hash); checkpointEventsProcessed.push(0); } } tmp = prevCheckpointId$2; } else { tmp = prevCheckpointId$1; } prevCheckpointId = tmp; let checkpointId$1 = prevCheckpointId + 1n; checkpointIds.push(checkpointId$1); checkpointChainIds.push(fetchState.chainId); checkpointBlockNumbers.push(blockNumber); checkpointBlockHashes.push(ReorgDetection.getHashByBlockNumber(chainBeforeBatch.reorgDetection, blockNumber)); checkpointEventsProcessed.push(1); prevBlockNumber = blockNumber; prevCheckpointId = checkpointId$1; } else { let lastIndex = checkpointEventsProcessed.length - 1; checkpointEventsProcessed[lastIndex] = checkpointEventsProcessed[lastIndex] + 1; } items.push(item); } totalBatchSize = totalBatchSize + chainBatchSize; mutBatchSizePerChain[fetchState.chainId] = chainBatchSize; } let progressBlockNumberAfterBatch = FetchState.getProgressBlockNumberAt(fetchState, chainBatchSize); let chainId$1 = fetchState.chainId; let toBlockExclusive = progressBlockNumberAfterBatch + 1; let fromBlockExclusive$1 = prevBlockNumber; let reorgDetection$1 = chainBeforeBatch.reorgDetection; let prevCheckpointId$3 = prevCheckpointId; let tmp$1; if (reorgDetection$1.shouldRollbackOnReorg && !Utils.Dict.isEmpty(reorgDetection$1.dataByBlockNumber)) { let prevCheckpointId$4 = prevCheckpointId$3; for (let blockNumber$2 = fromBlockExclusive$1 + 1, blockNumber_finish$1 = toBlockExclusive - 1; blockNumber$2 <= blockNumber_finish$1; ++blockNumber$2) { let hash$1 = ReorgDetection.getHashByBlockNumber(reorgDetection$1, blockNumber$2); if (hash$1 !== null) { let checkpointId$2 = prevCheckpointId$4 + 1n; prevCheckpointId$4 = checkpointId$2; checkpointIds.push(checkpointId$2); checkpointChainIds.push(chainId$1); checkpointBlockNumbers.push(blockNumber$2); checkpointBlockHashes.push(hash$1); checkpointEventsProcessed.push(0); } } tmp$1 = prevCheckpointId$4; } else { tmp$1 = prevCheckpointId$3; } prevCheckpointId = tmp$1; mutProgressBlockNumberPerChain[fetchState.chainId] = progressBlockNumberAfterBatch; chainIdx = chainIdx + 1; }; return { totalBatchSize: totalBatchSize, items: items, progressedChainsById: getProgressedChainsById(chainsBeforeBatch, mutBatchSizePerChain, mutProgressBlockNumberPerChain), isInReorgThreshold: isInReorgThreshold, checkpointIds: checkpointIds, checkpointChainIds: checkpointChainIds, checkpointBlockNumbers: checkpointBlockNumbers, checkpointBlockHashes: checkpointBlockHashes, checkpointEventsProcessed: checkpointEventsProcessed }; } let make = prepareBatch; function findFirstEventBlockNumber(batch, chainId) { let idx = 0; let result; let checkpointsLength = batch.checkpointIds.length; while (idx < checkpointsLength && result === undefined) { let checkpointChainId = batch.checkpointChainIds[idx]; if (checkpointChainId === chainId && batch.checkpointEventsProcessed[idx] > 0) { result = batch.checkpointBlockNumbers[idx]; } else { idx = idx + 1; } }; return result; } function findLastEventItem(batch, chainId) { let idx = batch.items.length - 1; let result; while (idx >= 0 && result === undefined) { let item = batch.items[idx]; if (item.kind === 0 && item.chain === chainId) { result = item; } else { idx = idx - 1; } }; return result; } export { hasReadyItem, getProgressedChainsById, addReorgCheckpoints, prepareBatch, make, findFirstEventBlockNumber, findLastEventItem, } /* Utils Not a pure module */