4 minutos
Debugging de Subgraphs Rápido e Fácil Com Forks
Assim como vários sistemas que processam uma abundância de dados, os Indexadores do Graph (Graph Nodes) podem demorar um pouco para sincronizar o seu subgraph com a blockchain de destino. A discrepância entre mudanças rápidas para fins de solução de problemas e os longos tempos de espera necessários para o indexing é extremamente contraprodutiva, e nós sabemos muito bem disso. É por isso que introduzimos o forking de subgraphs, programado pela LimeChain; neste artigo. Veja como dá para acelerar bastante o processo de debug de subgraphs!
Ok, o que é isso?
O forking de subgraphs é o processo de retirar entidades tranquilamente do armazenamento de outro subgraph (normalmente, remoto).
No contexto do debug, o forking de subgraphs permite debugar o seu subgraph falho no bloco X sem precisar esperar que ele sincronize até o bloco X.
O quê?! Como?!
Quando um subgraph é implementado em um Graph Node remoto para indexação, e ele falha no bloco X, a boa notícia é que o Graph Node ainda servirá queries GraphQL com o seu armazenamento, que é sincronizado até o bloco X. Ótimo! Podemos aproveitar este armazenamento “atualizado” para consertar os bugs que surgem ao indexar o bloco X.
Resumindo, faremos um fork do subgraph falho de um Graph Node remoto para garantir que o subgraph seja indexado até o bloco X, para fornecer ao subgraph implantado localmente uma visão atualizada do estado da indexação; sendo este debugado no bloco X.
Por favor, quero ver códigos!
Para manter o foco no debug de subgraphs, vamos começar com coisas simples: siga o example-subgraph a indexar o contrato inteligente Ethereum Gravity.
Aqui estão os handlers definidos para a indexação dos Gravatars
, sem qualquer bug:
1export function handleNewGravatar(event: NewGravatar): void {2 let gravatar = new Gravatar(event.params.id.toHex().toString())3 gravatar.owner = event.params.owner4 gravatar.displayName = event.params.displayName5 gravatar.imageUrl = event.params.imageUrl6 gravatar.save()7}89export function handleUpdatedGravatar(event: UpdatedGravatar): void {10 let gravatar = Gravatar.load(event.params.id.toI32().toString())11 if (gravatar == null) {12 log.critical('Gravatar not found!', [])13 return14 }15 gravatar.owner = event.params.owner16 gravatar.displayName = event.params.displayName17 gravatar.imageUrl = event.params.imageUrl18 gravatar.save()19}
Que pena! Quando eu implanto o meu lindo subgraph no Subgraph Studio, ele apresenta o erro “Gravatar not found” (Gravatar não encontrado).
A maneira mais comum de tentar consertar este erro é:
- Fazer uma mudança na fonte dos mapeamentos, que talvez possa resolver o problema (mas é claro que não vai).
- Implante o subgraph novamente no Subgraph Studio (ou outro Graph Node remoto).
- Esperar que ele se sincronize.
- Se quebrar novamente, volte ao passo 1. Se não: Eba!
É um típico processo ordinário de debug, mas há um passo que atrasa muito o processo: 3. Esperar que ele se sincronize.
Com o forking de subgraphs, essencialmente, podemos eliminar este passo. É mais ou menos assim:
- Crie um Graph Node local com o conjunto de fork-base apropriado.
- Faça uma mudança na fonte dos mapeamentos, que talvez possa resolver o problema.
- Implante-o no Graph Node local, faça um fork do subgraph falho, e comece do bloco problemático_.
- Se quebrar novamente, volte ao passo 1. Se não: Eba!
Agora, você deve ter duas perguntas:
- Que fork-base???
- Forkar quem?!
E eu respondo:
fork-base
é o URL “base”, tal que quando a id de subgraph é atrelada, o URL resultante (<fork-base>/<subgraph-id>
) se torna um endpoint válido da GraphQL para o armazenamento do subgraph.- Forking é fácil, não precisa se preocupar:
1$ graph deploy <subgraph-name> --debug-fork <subgraph-id> --ipfs http://localhost:5001 --node http://localhost:8020
Aliás, não esqueça de preencher o campo dataSources.source.startBlock
no manifest do subgraph com o número do bloco problemático, para pular a indexação de blocos desnecessários e tomar vantagem do fork!
Aqui está o que eu faço:
- Eu monto um Graph Node local (veja como) com a opção
fork-base
dehttps://api.thegraph.com/subgraphs/id/
, já que eu vou forkar um subgraph, o bugado que eu lancei anteriormente, do Subgraph Studio.
1$ cargo run -p graph-node --release -- \2 --postgres-url postgresql://USERNAME[:PASSWORD]@localhost:5432/graph-node \3 --ethereum-rpc NETWORK_NAME:[CAPABILITIES]:URL \4 --ipfs 127.0.0.1:50015 --fork-base https://api.thegraph.com/subgraphs/id/
- Após vistoriar com cuidado, percebo uma discrepância nas representações de
id
usadas ao indexarGravatar
s nos meus dois handlers. EnquantohandleNewGravatar
o converte a um hex (event.params.id.toHex()
), ohandleUpdatedGravatar
usa um int32 (event.params.id.toI32()
). Assim, ohandleUpdatedGravatar
entra em pânico com o “Gravatar não encontrado!”. Eu faço os dois converterem oid
em um hex. - Após ter feito as mudanças, implanto o meu subgraph no Graph Node local, fazendo um fork do subgraph falho e programando o
dataSources.source.startBlock
em6190343
nosubgraph.yaml
:
1$ graph deploy gravity --debug-fork QmNp169tKvomnH3cPXTfGg4ZEhAHA6kEq5oy1XDqAxqHmW --ipfs http://localhost:5001 --node http://localhost:8020
- Eu verifico os logs produzidos pelo Graph Node local e… eba! Parece que deu tudo certo.
- Agora que o meu subgraph está livre de bugs, o implantarei num Graph Node remoto e viverei feliz para sempre! (mas sem batatas)