From b2cf99790079998890e95fbd670e94eedf001e0a Mon Sep 17 00:00:00 2001 From: prathamesh0 <42446521+prathamesh0@users.noreply.github.com> Date: Fri, 16 Sep 2022 09:23:41 +0530 Subject: [PATCH] Update CLI to fill state to create checkpoints (#187) * Update CLI to fill state to create checkpoints * Accomodate changes in codegen --- .../templates/fill-state-template.handlebars | 8 +++++ .../src/templates/indexer-template.handlebars | 8 ++++- packages/eden-watcher/src/fill-state.ts | 8 +++++ packages/eden-watcher/src/indexer.ts | 8 ++++- packages/util/src/ipld-database.ts | 29 +++++++++---------- 5 files changed, 43 insertions(+), 18 deletions(-) diff --git a/packages/codegen/src/templates/fill-state-template.handlebars b/packages/codegen/src/templates/fill-state-template.handlebars index 7f117f34..4cda86fe 100644 --- a/packages/codegen/src/templates/fill-state-template.handlebars +++ b/packages/codegen/src/templates/fill-state-template.handlebars @@ -63,6 +63,9 @@ export const fillState = async ( const blockHash = blocks[0].blockHash; + // Create initial state for contracts + await indexer.createInit(blockHash, blockNumber); + // Fill state for each contract in contractEntitiesMap const contractStatePromises = Array.from(contractEntitiesMap.entries()) .map(async ([contractAddress, entities]): Promise => { @@ -90,7 +93,12 @@ export const fillState = async ( // Persist subgraph state to the DB await indexer.dumpSubgraphState(blockHash, true); + + // Create checkpoints + await indexer.processCheckpoint(blockHash); } + // TODO: Push state to IPFS + log(`Filled state for subgraph entities in range: [${startBlock}, ${endBlock}]`); }; diff --git a/packages/codegen/src/templates/indexer-template.handlebars b/packages/codegen/src/templates/indexer-template.handlebars index a113b5ce..0d1126e0 100644 --- a/packages/codegen/src/templates/indexer-template.handlebars +++ b/packages/codegen/src/templates/indexer-template.handlebars @@ -419,7 +419,7 @@ export class Indexer implements IPLDIndexerInterface { return this._baseIndexer.createStateCheckpoint(contractAddress, block, data); } - // Method to be used by checkpoint CLI. + // Method to be used by export-state CLI. async createCheckpoint (contractAddress: string, blockHash: string): Promise { const block = await this.getBlockProgress(blockHash); assert(block); @@ -427,6 +427,12 @@ export class Indexer implements IPLDIndexerInterface { return this._baseIndexer.createCheckpoint(this, contractAddress, block); } + // Method to be used by fill-state CLI. + async createInit (blockHash: string, blockNumber: number): Promise { + // Create initial state for contracts. + await this._baseIndexer.createInit(this, blockHash, blockNumber); + } + async saveOrUpdateIPLDBlock (ipldBlock: IPLDBlock): Promise { return this._baseIndexer.saveOrUpdateIPLDBlock(ipldBlock); } diff --git a/packages/eden-watcher/src/fill-state.ts b/packages/eden-watcher/src/fill-state.ts index bf624613..2e6639e8 100644 --- a/packages/eden-watcher/src/fill-state.ts +++ b/packages/eden-watcher/src/fill-state.ts @@ -67,6 +67,9 @@ export const fillState = async ( const blockHash = blocks[0].blockHash; + // Create initial state for contracts + await indexer.createInit(blockHash, blockNumber); + // Fill state for each contract in contractEntitiesMap const contractStatePromises = Array.from(contractEntitiesMap.entries()) .map(async ([contractAddress, entities]): Promise => { @@ -95,10 +98,15 @@ export const fillState = async ( // Persist subgraph state to the DB await indexer.dumpSubgraphState(blockHash, true); + // Create checkpoints + await indexer.processCheckpoint(blockHash); + console.timeEnd(`time:fill-state-${blockNumber}`); } console.timeEnd('time:fill-state'); + // TODO: Push state to IPFS + log(`Filled state for subgraph entities in range: [${startBlock}, ${endBlock}]`); }; diff --git a/packages/eden-watcher/src/indexer.ts b/packages/eden-watcher/src/indexer.ts index 43a69125..2c68a75c 100644 --- a/packages/eden-watcher/src/indexer.ts +++ b/packages/eden-watcher/src/indexer.ts @@ -349,7 +349,7 @@ export class Indexer implements IPLDIndexerInterface { return this._baseIndexer.createStateCheckpoint(contractAddress, block, data); } - // Method to be used by checkpoint CLI. + // Method to be used by export-state CLI. async createCheckpoint (contractAddress: string, blockHash: string): Promise { const block = await this.getBlockProgress(blockHash); assert(block); @@ -357,6 +357,12 @@ export class Indexer implements IPLDIndexerInterface { return this._baseIndexer.createCheckpoint(this, contractAddress, block); } + // Method to be used by fill-state CLI. + async createInit (blockHash: string, blockNumber: number): Promise { + // Create initial state for contracts. + await this._baseIndexer.createInit(this, blockHash, blockNumber); + } + async saveOrUpdateIPLDBlock (ipldBlock: IPLDBlock): Promise { return this._baseIndexer.saveOrUpdateIPLDBlock(ipldBlock); } diff --git a/packages/util/src/ipld-database.ts b/packages/util/src/ipld-database.ts index db31c7b4..6ebb935d 100644 --- a/packages/util/src/ipld-database.ts +++ b/packages/util/src/ipld-database.ts @@ -27,27 +27,24 @@ export class IPLDDatabase extends Database { ? queryBuilder.andWhere('ipld_block.kind = :kind', { kind }) : queryBuilder.andWhere('ipld_block.kind != :kind', { kind: StateKind.DiffStaged }); - // Get the first two entries. - queryBuilder.limit(2); + // Get the first three entries. + queryBuilder.limit(3); const results = await queryBuilder.getMany(); - switch (results.length) { - case 0: - // No result found. - return; - case 1: - // Return the only IPLD block entry found. - return results[0]; - case 2: - // If there are two entries in the result and both are at the same block number, give preference to checkpoint kind. - if (results[0].block.blockNumber === results[1].block.blockNumber) { - return (results[1].kind === StateKind.Checkpoint) ? results[1] : results[0]; + if (results.length) { + // Sort by (block number desc, id desc) to get the latest entry. + // At same height, IPLD blocks are expected in order ['init', 'diff', 'checkpoint'], + // and are given preference in order ['checkpoint', 'diff', 'init'] + results.sort((result1, result2) => { + if (result1.block.blockNumber === result2.block.blockNumber) { + return (result1.id > result2.id) ? -1 : 1; } else { - return results[0]; + return (result1.block.blockNumber > result2.block.blockNumber) ? -1 : 1; } - default: - throw new Error(`Unexpected results length ${results.length}`); + }); + + return results[0]; } }