最近は本業の方でGraphQLを利用することが増えてきました。
そこで、SymbolでもREST APIだけではなくGraphQLを使ってノードからデータを取得できないかちょっと試してみます。
GraphQLを活用するメリット
複数のAPI呼び出しを1つのリクエストで実現
RESTでは複数のエンドポイントを順番に呼び出す必要がありますが、GraphQLでは必要なデータを一度に取得可能です。
例えば、こんな感じ。
query SymbolGqlExample {
# ネットワークの情報
getNetworkType {
description
name
}
# 接続先ノードの状態
getNodeHealth {
status {
apiNode
db
}
}
# 特定のブロック高の中身
getBlockByHeight(height: "65536") {
... on BlockInfoDTO {
id
block {
beneficiaryAddress
difficulty
}
}
}
}
上記のクエリを実行すると以下のようなレスポンスが取得できます
{
"data": {
"getNetworkType": {
"description": "Symbol Mainnet",
"name": "mainnet"
},
"getNodeHealth": {
"status": {
"apiNode": "up",
"db": "up"
}
},
"getBlockByHeight": {
"id": "65C57A484CF5710B720DB1A7",
"block": {
"beneficiaryAddress": "685B9B33391EFA3C823B696974702CBC56E1A57FE5F1321B",
"difficulty": "78040468282391"
}
}
}
}
クライアント側の柔軟性向上
SQLのSELECTのように、必要なデータだけを取得できます。
query SymbolGqlExample {
# 接続先ノードの状態
getNodeHealth {
status {
# apiNodeの状態はべつにいらねーや
# apiNode
db
}
}
}
結果↓
{
"data": {
"getNodeHealth": {
"status": {
"db": "up" // dbのステータスだけ取れる
}
},
}
こんな感じで、必要なデータだけ取得する事もでできるのでネットワークの帯域も節約できます。
GraphQLを使うために必要なもの
さて、GraphQLを使用するには、**リゾルバ(resolver)**の実装が必要です。リゾルバは、クライアントからのクエリに応じてデータを取得し、返却する役割を果たします。
また、リゾルバを構築するにはスキーマが必要です。スキーマはGraphQLでデータの構造やリクエストの形式を定義するものです。
今回どうするか
さすがにリゾルバやらスキーマやらを1から作っていくのは大変です。
今回はsymbol-blockchain-community/symbol-rest-clientで有志の方々がメンテしているOpenAPI仕様準拠のYAMLファイルを使って自動生成してみます。(このやり方には課題があるのですがそれは後ほど。)
やり方
(mod 2024.12.15)
執筆時動かなかったものがようやく動いたのでgithubで公開しました
symbol-graphql-server
こちらのREADME.MD記載の手順で 4.playgroundの起動
まで進めてください。
(日本語版READMEはこちら)
実際に使ってみた
Playgroundにアクセスするとこんな感じでGraphQLを試すことができます。
簡単にPlaygroundの使い方を解説すると以下のようになります。
- 左:スキーマのdocumentやクエリの実行履歴などが確認できます。Explorerからはそのスキーマに定義されたフィールドを確認できますので、クエリ作成の参考になります。(どんなデータが取れるのかなど)
- 中央: クエリを書く欄です。フォーマットもできますがコメントが消えるのでしないほうがいいw
- 右側: 実行した結果が表示されます。
まとめと課題
今回は、OpenAPI形式のYAMLを使用してスキーマとリゾルバを自動生成し、REST APIをラップする形でGraphQLを実現しました。
ただし、この手法は以下の課題があります:
- 現状、REST APIをラップしているだけであり、SymbolノードのDBに直接アクセスしているわけではない
- そのため、複数のスキーマからデータを取得しようとした場合、それぞれのスキーマに対応する回数分のREST APIリクエストが内部で実行されてしまう。
将来的には、REST APIに依存せず、ノードのデータベースと直接やり取りできるようなリゾルバの実装を目指します。
この記事で紹介したOpenAPIを用いたGraphQLサーバーは、Symbol-blockchain-communityのGitHubリポジトリにサンプルとして公開予定です。
※現在は前述した私個人のGithubリポジトリを参照してください。いずれこちらに移します。
本バージョンをv1
とし、データベース直接接続型のv2
を順次実装していければなーと思います。
そんなわけで、symbol-graphql-serverへの貢献者を募集しています!