Recetario > Debugging rápido y sencillo de subgrafos mediante Forks

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 LimeChain, and in this article I will show you how this feature can be used to substantially speed-up subgraph debugging!

¿Bien, qué es?

Enlace a esta sección

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.

¡¿Qué?! ¿Cómo?

Enlace a esta sección

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.

¡Por favor, muéstrame algo de código!

Enlace a esta sección

Para mantenernos enfocados en el debugging de subgrafos, simplifiquemos las cosas y sigamos con el example-subgraph que indexa el contrato inteligente Ethereum Gravity.

Estos son los handlers definidos para indexar Gravatars, 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.owner
gravatar.displayName = event.params.displayName
gravatar.imageUrl = event.params.imageUrl
gravatar.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.owner
gravatar.displayName = event.params.displayName
gravatar.imageUrl = event.params.imageUrl
gravatar.save()
}

Oops, how unfortunate, when I deploy my perfect looking subgraph to Subgraph Studio it fails with the "Gravatar not found!" error.

La forma habitual de intentar una solución es:

  1. Realiza un cambio en la fuente de mapeos, que crees que resolverá el problema (aunque sé que no lo hará).
  2. Re-deploy the subgraph to Subgraph Studio (or another remote Graph Node).
  3. Espera a que se sincronice.
  4. 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:

  1. Spin-up a local Graph Node with the appropriate fork-base set.
  2. Realiza un cambio en la fuente de mapeos, que crees que resolverá el problema.
  3. Deploy to the local Graph Node, forking the failing subgraph and starting from the problematic block.
  4. Si se vuelve a romper, vuelve a 1, de lo contrario: ¡Hurra!

Ahora, puedes tener 2 preguntas:

  1. fork-base que???
  2. Bifurcando a quien?!

Y yo respondo:

  1. 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.
  2. 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:

  1. I spin-up a local Graph Node (here is how to do it) 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 Subgraph Studio.
$ 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/
  1. Después de una inspección cuidadosa, noté que hay una falta de coincidencia en las representaciones de id utilizadas al indexar Gravatar en mis dos handlers. Mientras que handleNewGravatar lo convierte en hexadecimal (event.params.id.toHex()), handleUpdatedGravatar usa un int32 (event. params.id.toI32()) que hace que handleUpdatedGravatar entre en pánico con "¡Gravatar no encontrado!". Hago que ambos conviertan el id en un hexadecimal.
  2. After I made the changes I deploy my subgraph to the local Graph Node, forking the failing subgraph and setting dataSources.source.startBlock to 6190343 in subgraph.yaml:
$ graph deploy gravity --debug-fork QmNp169tKvomnH3cPXTfGg4ZEhAHA6kEq5oy1XDqAxqHmW --ipfs http://localhost:5001 --node http://localhost:8020
  1. I inspect the logs produced by the local Graph Node and, Hooray!, everything seems to be working.
  2. I deploy my now bug-free subgraph to a remote Graph Node and live happily ever after! (no potatoes tho)
Editar página

Anterior
Python (Subgrounds)
Siguiente
Construcción de subgrafos en NEAR
Editar página