Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

indexer-common,indexer-agent: auto graft resolve with limit #481

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

hopeyen
Copy link
Contributor

@hopeyen hopeyen commented Sep 12, 2022

Currently, to index a subgraph deployment with grafting dependencies, indexers must manually deploy and index the graft base deployments.

To enable auto resolve feature on the indexer-agent, we add new start-up parameter

  • auto-graft-resolver-limit the maximum depth of grafting dependency to automatically resolve (number, default is 0)
  • ipfs-endpoint the endpoint to an ipfs node to query subgraph manifest data for graft specifications before deploying a subgraph

In particular, these two parameters, along with indexingStatusResolver, are passed into SubgraphManger

  statusResolver: IndexingStatusResolver
  autoGraftResolverLimit: number                 // default 0 such that the agent will not automatically resolve any grafting dependency. 
  ipfsEndpoint?: string

These 2 parameters allow indexers to control the depth of grafting dependency the agent should auto resolve. If the dependency depth is within the provided limit (inclusive), the agent start by indexing the root of the dependencies.

  • If the reconciliation conflict comes from indexingRules, then agent attempts the target deployment periodically.
  • If allocating with actionQueue while the grafting dependencies aren't resolved, then indexer agent will automatically deploy the base level deployment and fails the action.
  • indexingStatusResolver is used to check for grafting deployment's status before trying to ensure the indexing status of the target deployment.

For testing purposes I made these random subgraphs with dependencies on the testnet

  • indexing goerli, graft depth of 2, QmU21JhpGJmLimvFwWWdFiGftf8BRbqGdSxwHhCatWDC2m
  • indexing mainnet, graft depth of 2, QmSxFyuizxc42A8gAXXzSu34wndzWxswEQUURqhghms4J7

Resolves #439

@hopeyen hopeyen force-pushed the hope/grafting-auto-resolve branch 2 times, most recently from 0608a51 to edb1d02 Compare October 5, 2022 23:32
@hopeyen hopeyen marked this pull request as ready for review October 5, 2022 23:32
@hopeyen hopeyen requested review from tilacog and fordN March 31, 2023 21:14
Copy link
Contributor

@tilacog tilacog left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hopeyen Thanks for this!

I'm adding these review comments as notes for when I rebase this PR due to the recent L2 changes.

@@ -126,6 +126,7 @@ const setup = async () => {
await sequelize.sync({ force: true })

const statusEndpoint = 'http://localhost:8030/graphql'
const ipfsEndpoint = 'https://ipfs.network.thegraph.com'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be configurable with the current value as the default.

@@ -139,6 +140,7 @@ const setup = async () => {
})

const indexNodeIDs = ['node_1']
const autoGraftResolverLimit = 1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider setting this value to zero to disable the feature in tests, except when testing the feature itself.

Comment on lines +705 to +709
try {
this.indexer.ensure(name, deployment)
} catch {
this.indexer.resolveGrafting(name, deployment, 0)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's ensure we accurately identify and handle all potential errors here, considering that resolving grafts may introduce its own errors.

Comment on lines +385 to +390
if (
!Number.isInteger(argv['auto-graft-resolver-limit']) ||
argv['auto-graft-resolver-limit'] < 0
) {
return 'Invalid --auto-graft-resolver-limit provided. Must be >= 0 and an integer.'
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could rely on yargs' coercion instead of manually implementing this validation.
https://yargs.js.org/docs/#api-reference-coercekey-fn

) {
this.indexerManagement = indexerManagement
this.statusResolver = statusResolver
this.logger = logger
this.indexerAddress = indexerAddress
this.allocationManagementMode = allocationManagementMode
this.autoGraftResolverLimit = autoGraftResolverLimit
this.ipfsEndpoint = ipfsUrl + '/api/v0/cat?arg='
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer using the URL type when constructing URLs like this.
We get the benefit of it being checked for correctness in runtime.

Comment on lines +247 to +254
// Simple fetch for subgraph manifest
async subgraphManifest(targetDeployment: SubgraphDeploymentID) {
const ipfsFile = await fetch(this.ipfsEndpoint + targetDeployment.ipfsHash, {
method: 'POST',
redirect: 'follow',
})
return yaml.parse(await ipfsFile.text())
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd consider handling IO and throwing errors with more meaningful messages here.

models,
subgraphDeploymentID,
indexNode,
0,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we set grafting depth to zero here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC the depth is set to 0 as the initialization to the recursive resolveGrafting which should stop when depth gets incremented to the depths limit

Comment on lines +297 to +298
graftStatus[0].chains[0].latestBlock &&
graftStatus[0].chains[0].latestBlock.number >= manifest.graft.block
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd validate the array length before accessing elements by index.

Comment on lines +308 to +313
} catch {
throw indexerError(
IndexerErrorCode.IE074,
`Base deployment hasn't synced to the graft block, try again later`,
)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't get why the error message here is the same as the one right above.

Also, we might be interested in actually catching the original error and propagating it within the IndexerError.

Comment on lines +321 to +333
async stop_sync(
logger: Logger,
deployment: SubgraphDeploymentID,
models: IndexerManagementModels,
) {
const neverIndexingRule = {
identifier: deployment.ipfsHash,
identifierType: SubgraphIdentifierType.DEPLOYMENT,
decisionBasis: IndexingDecisionBasis.NEVER,
} as Partial<IndexingRuleAttributes>

await upsertIndexingRule(logger, models, neverIndexingRule)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm unsure if a similar function is already defined elsewhere.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Automatically resolve and index grafting dependencies
2 participants