Débogage rapide et facile des subgraph à l'aide de Forks
Reading time: 4 min
As with many systems processing large amounts of data, The Graph's Indexers (Graph Nodes) may take quite some time to sync-up your subgraph with the target blockchain. The discrepancy between quick changes with the purpose of debugging and long wait times needed for indexing is extremely counterproductive and we are well aware of that. This is why we are introducing subgraph forking, developed by , and in this article I will show you how this feature can be used to substantially speed-up subgraph debugging!
Subgraph forking est le processus qui consiste à récupérer paresseusement des entités du magasin d'un autre subgraph (généralement un magasin distant).
Dans le contexte du débogage, un subgraph fork vous permet de déboguer votre subgraph défaillant au bloc X sans avoir à attendre la synchronisation avec le bloc X.
When you deploy a subgraph to a remote Graph Node for indexing and it fails at block X, the good news is that the Graph Node will still serve GraphQL queries using its store, which is synced-up to block X. That's great! This means we can take advantage of this "up-to-date" store to fix the bugs arising when indexing block X.
In a nutshell, we are going to fork the failing subgraph from a remote Graph Node that is guaranteed to have the subgraph indexed up to block X in order to provide the locally deployed subgraph being debugged at block X an up-to-date view of the indexing state.
Pour rester concentré sur le débogage des subgraphs, gardons les choses simples et exécutons le indexant le contrat intelligent Ethereum Gravity.
Voici les gestionnaires définis pour l'indexation des Gravatar
s, exempts de tout bogue :
export function handleNewGravatar(event: NewGravatar): void {let gravatar = new Gravatar(event.params.id.toHex().toString())gravatar.owner = event.params.ownergravatar.displayName = event.params.displayNamegravatar.imageUrl = event.params.imageUrlgravatar.save()}export function handleUpdatedGravatar(event: UpdatedGravatar): void {let gravatar = Gravatar.load(event.params.id.toI32().toString())if (gravatar == null) {log.critical('Gravatar introuvable!', [])return}gravatar.owner = event.params.ownergravatar.displayName = event.params.displayNamegravatar.imageUrl = event.params.imageUrlgravatar.save()}
Oops, how unfortunate, when I deploy my perfect looking subgraph to it fails with the "Gravatar not found!" error.
La méthode habituelle pour tenter de résoudre le problème est la suivante :
- Apportez une modification à la source des mappages, ce qui, selon vous, résoudra le problème (même si je sais que ce ne sera pas le cas).
- Re-deploy the subgraph to (or another remote Graph Node).
- Attendez qu’il soit synchronisé.
- S'il se casse à nouveau, revenez au point 1, sinon : Hourra !
C'est en effet assez familier avec un processus de débogage ordinaire, mais il y a une étape qui ralentit horriblement le processus : 3. Attendez qu'il se synchronise.
En utilisant le forçage de subgraphs, nous pouvons essentiellement éliminer cette étape. Voici à quoi cela ressemble :
- Spin-up a local Graph Node with the appropriate fork-base set.
- Apportez une modification à la source des mappings qui, selon vous, résoudra le problème.
- Deploy to the local Graph Node, forking the failing subgraph and starting from the problematic block.
- S'il casse à nouveau, revenez à 1, sinon : Hourra !
Maintenant, vous pouvez avoir 2 questions :
- base de fourche quoi ???
- Fourcher qui ?!
Je réponds :
fork-base
est l'URL "de base", de sorte que lorsque l'id du subgraph est ajouté, l'URL résultante (<fork-base>/<subgraph-id>
) est un point de terminaison GraphQL valide pour le magasin du subgraph.- Fourcher est facile, pas besoin de transpirer :
$ graph deploy <subgraph-name> --debug-fork <subgraph-id>-id> ; --ipfs http://localhost:5001 --node http://localhost:8020
N'oubliez pas non plus de définir le champ dataSources.source.startBlock
dans le manifeste du subgraph au numéro du bloc problématique, afin de ne pas indexer les blocs inutiles et de profiter du fork !
Voici donc ce que je fais :
- I spin-up a local Graph Node () with the
fork-base
option set to:https://api.thegraph.com/subgraphs/id/
, since I will fork a subgraph, the buggy one I deployed earlier, from .
$ cargo run -p graph-node --release -- \--postgres-url postgresql://USERNAME[:PASSWORD]@localhost:5432/graph-node \--ethereum-rpc NOM_RÉSEAU : [CAPABILITIES] :URL \--ipfs 127.0.0.1:5001--fork-base https://api.thegraph.com/subgraphs/id/
- Après une inspection minutieuse, je remarque qu'il y a un décalage dans les représentations des
identifiants
utilisés lors de l'indexation desGravatars
dans mes deux gestionnaires. Alors quehandleNewGravatar
le convertit en hexadécimal (event.params.id.toHex()
),handleUpdatedGravatar
utilise un int32 (event.params.id.toI32()
), ce qui provoque la panique dehandleUpdatedGravatar
avec "Gravatar not found!". J'ai fait en sorte que les deux convertissent l'identifiant
en hexadécimal. - After I made the changes I deploy my subgraph to the local Graph Node, forking the failing subgraph and setting
dataSources.source.startBlock
to6190343
insubgraph.yaml
:
$ graph deploy gravity --debug-fork QmNp169tKvomnH3cPXTfGg4ZEhAHA6kEq5oy1XDqAxqHmW --ipfs http://localhost:5001 --node http://localhost:8020
- I inspect the logs produced by the local Graph Node and, Hooray!, everything seems to be working.
- I deploy my now bug-free subgraph to a remote Graph Node and live happily ever after! (no potatoes tho)