フォークを用いた迅速かつ容易なサブグラフのデバッグ
Reading time: 6 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!
サブグラフのフォークとは、他のサブグラフのストア(通常はリモート) からエンティティをフェッチするプロセスです。
デバッグの文脈では、サブグラフのフォークにより、ブロックXへの同期を待つことなく、ブロック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.
サブグラフのデバッグに集中し続けるために、物事をシンプルにして、Ethereum Gravity スマート コントラクトのインデックスを作成する を実行してみましょう。
以下は、Gravatar
のインデックスを作成するために定義されたハンドラで、バグが全くありません。
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.
通常の試すであろう修正方法:
- マッピングソースを変更して問題の解決を試す(解決されないことは分かっていても)
- Re-deploy the subgraph to (or another remote Graph Node).
- 同期を待つ
- 再び問題が発生した場合は、1に戻る
このように、通常のデバッグ処理とほぼ同じですが、1つだけ、処理を恐ろしく遅くするステップがあります:3. 同期を待つ
サブグラフのフォークを利用することで、このステップを実質的に省略することができます。その方法は次の通りです:
- Spin-up a local Graph Node with the appropriate fork-base set.
- マッピングのソースを変更し、問題を解決する
- Deploy to the local Graph Node, forking the failing subgraph and starting from the problematic block.
- もし再度、壊れる場合1に戻る
さて、ここで2つの疑問が生じます:
- フォークベースとは?
- フォーキングは誰ですか?
回答:
fork-base
は「ベース」URLで、subgraph idが追加されたときのURL (<fork-base>/<subgraph-id>
) はサブグラフのストアに対する有効な GraphQL endpoint であることを示します。- フォーキングは簡単であり煩雑な手間はありません
$ graph deploy <subgraph-name> --debug-fork <subgraph-id> --ipfs http://localhost:5001 --node http://localhost:8020
また、サブグラフマニフェストのdataSources.source.startBlock
フィールドを問題のあるブロックの番号に設定することを忘れないでください。そうすれば、不要なブロックのインデックス作成を省略して、フォークを利用することができます。
そこで、以下の通りです:
- 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/
- よく調べてみると、2つのハンドラで
Gravatar
をインデックスする際に使用されるid
表現にミスマッチがあることに気づきました。handleNewGravatar
はそれを hex (event.params.id.toHex()
) に変換しますが、handleUpdatedGravatar
は int32 (event.params.id.toI32()
) を使用するのでhandleUpdatedGravatar
は "Gravatar not found!" でパニックになってしまうのです。両方ともid
を16進数に変換するようにしています。 - 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)