Debugging rápido y sencillo de subgrafos mediante 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 es el proceso de obtener entidades de otro almacén de subgrafos (por lo general uno remoto).
En el contexto de la depuración, subgraph forking te permite depurar tu subgrafo fallido en el bloque X sin necesidad de esperar a sincronizar para bloquear 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.
Para mantenernos enfocados en el debugging de subgrafos, simplifiquemos las cosas y sigamos con el que indexa el contrato inteligente Ethereum Gravity.
Estos son los handlers definidos para indexar Gravatar
s, sin errores de ningún tipo:
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 not found!', [])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 forma habitual de intentar una solución es:
- Realiza un cambio en la fuente de mapeos, que crees que resolverá el problema (aunque sé que no lo hará).
- Re-deploy the subgraph to (or another remote Graph Node).
- Espera a que se sincronice.
- Si se vuelve a romper vuelve a 1, de lo contrario: ¡Hurra!
De hecho, es bastante familiar para un proceso de depuración ordinario, pero hay un paso que ralentiza terriblemente el proceso: 3. Espera a que se sincronice.
Usando bifurcación de subgrafo podemos eliminar esencialmente este paso. Así es como se ve:
- Spin-up a local Graph Node with the appropriate fork-base set.
- Realiza un cambio en la fuente de mapeos, que crees que resolverá el problema.
- Deploy to the local Graph Node, forking the failing subgraph and starting from the problematic block.
- Si se vuelve a romper, vuelve a 1, de lo contrario: ¡Hurra!
Ahora, puedes tener 2 preguntas:
- fork-base que???
- Bifurcando a quien?!
Y yo respondo:
fork-base
es la URL "base", de modo que cuando se agrega el id de subgrafo, la URL resultante (<fork- base>/<subgraph-id>
) es un punto final de GraphQL válido para la tienda del subgrafo.- Bifurcar es fácil, no hay necesidad de sudar:
$ graph deploy <subgraph-name> --debug-fork <subgraph-id> --ipfs http://localhost:5001 --node http://localhost:8020
Además, no olvides configurar el campo dataSources.source.startBlock
en el manifiesto del subgrafo con el número del bloque problemático, para que puedas omitir la indexación de bloques innecesarios y aprovechar la bifurcación!
Entonces, esto es lo que hago:
- 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 NETWORK_NAME:[CAPABILITIES]:URL \--ipfs 127.0.0.1:5001--fork-base https://api.thegraph.com/subgraphs/id/
- Después de una inspección cuidadosa, noté que hay una falta de coincidencia en las representaciones de
id
utilizadas al indexarGravatar
en mis dos handlers. Mientras quehandleNewGravatar
lo convierte en hexadecimal (event.params.id.toHex()
),handleUpdatedGravatar
usa un int32 (event. params.id.toI32()
) que hace quehandleUpdatedGravatar
entre en pánico con "¡Gravatar no encontrado!". Hago que ambos conviertan elid
en un hexadecimal. - 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)