https://hasura.io/ が使ってみたらめちゃくちゃ便利なのですがあまり使ってる人が多くないようなので、hasura のいいところを挙げていきます。
hasura って何?
hasura は PostgreSQL サーバーから自動的に GraphQL サーバーを建てられるツールです。
Docker イメージとして配布されていて、対象となる PostgreSQL サーバーのアドレスや PW を設定して起動すればすぐに GraphQL サーバーとして使えます。(実際は hasura コンソールから公開するテーブルを選択したりします。詳しくはdoc)
ローカルで起動するならこういう感じです。
docker run -d -p 8080:8080 \
-e HASURA_GRAPHQL_DATABASE_URL=postgres://username:password@hostname:port/dbname \
-e HASURA_GRAPHQL_ENABLE_CONSOLE=true \
hasura/graphql-engine:latest
この場合 localhost:8080
から hasura のコンソールにアクセスでき、 localhost:8080/v1/graphql
が GraphQL エンドポイントになります。
hasura サーバーがクライアントと PostgreSQL サーバーの間に入って、GraphQL の API で PostgreSQL を操作できるイメージです。
client <- (GraphQL) -> hasura server <- (SQL) -> PostgreSQL server
例えばこんな単純なテーブルがあったとして、
hasura コンソールにある GraphiQL からはこんなふうに GraphQL が使えます。fk を考慮して JOIN したような形のデータを取得できています。
Query だけでなく、Mutation、Subscription も同様に使えます。
hasura のいいところ
PostgreSQL サーバーがあればすぐに使える
hasura は PostgreSQL サーバーと通信してスキーマ情報を解析して自動的に使える GraphQL サーバーとして動いてくれます。
Docker イメージとして配布されているので ECS や Cloud Run、GKE などの基盤を運用しているならあまり負担なく使い始められると思います。
データソースとして PostgreSQL を使っているので、RDS や CloudSQL などのこれまでの運用実績があるプラットフォームを使うことができます。
もし hasura をやめる判断をしたとしても、データソースはただの PostgreSQL なので hasura に強くロックインすることもないと思います。Prisma Cloud のような GraphQL SaaS と比べて辞めやすさが高いのが良いかと思ってます。
GraphQL サーバーを実装する手間が省ける
hasura が自動で GraphQL サーバーとして動いてくれるので GraphQL サーバーを実装する手間が省けます。
N+1 問題をケアするために Dataloder を使って GraphQL の Resolver を実装するのは結構手間だと思うので、PostgreSQL にテーブルがあって hasura で設定すればすぐに Query, Mutation, Subsucription を使えるというのは開発速度を非常に上げることができます。
実際 hasura を使ってみて、DB をいじって hasura の設定を変更して graphql-codegen でクライアントコードを生成して、タイプセーフかつ高速に開発ができたときは感動モノでした。
その一方で、ほとんどのアプリケーションではただ DB から SELECT, INSERT するだけでは済まないトランザクション内でアレコレする複雑なロジックがあり、それは hasura が生成する GraphQL オペレーションでは難しい場面が出てくると思います。hasura はその解決手段をいくつか用意しています(Remote Schemas, user-defined SQL functions)。このへんはまだ試せていないところです。
ページングや集計クエリなども自動で生成される
例えば冒頭で挙げたようなユーザーとコメントを投稿するようなサービスがあったとして、ユーザーが最後にコメントした日時とこれまでのコメント数を表示するユーザー一覧画面を実装したいとします。そのようなクエリも hasura が自動生成するオペレーションで実現できます。
query Users {
users(offset: 100, limit: 20) {
name
lastCommentAt: comments(order_by: {createdAt: desc}, limit: 1) {
createdAt
}
totalComment: comments_aggregate {
aggregate {
count
}
}
}
}
{
"data": {
"users": [
{
"name": "bob",
"lastCommentAt": [
{
"createdAt": "2020-02-12T13:21:32.555949"
}
],
"totalComment": {
"aggregate": {
"count": 2
}
}
},
{
"name": "john",
"lastCommentAt": [
{
"createdAt": "2020-02-12T13:21:47.733137"
}
],
"totalComment": {
"aggregate": {
"count": 2
}
}
}
]
}
}
where
, order_by
, limit
, offset
といった条件句と max
, count
, avg
といった集計がデフォルトで可能です。PostgreSQL が GraphQL として公開される ORM のような使い勝手です。
実際に発行される SQL がすぐにわかる
普通の GraphQL サーバーの実装は Dataloder などを介する感じになると思いますが、hasura の場合は GraphQL オペレーションが直接 SQL 文に変換されます。その SQL 文と実行計画を hasura コンソールから見ることができるのでパフォーマンスの分析などもやりやすいのではと思います。
認証認可の仕組みがある
Auth0 などと組み合わせて認証されていないリクエストを弾いたり、ロールベースで機能の制限することなどができます。 doc
hasura が Auth0 などの認証プロバイダと通信して JWT を取得します。その JWT に含まれた Auth0 から設定したデータを hasura がGraphQLオペレーション実行時に読むことができ、hasura のコンソールでルールを決めます。
JWT に埋め込んだ X-Hasura-User-Id
を使って自分のデータだけを取得するといったルールが設定できます。
このルールが適用されたときに、
query Users {
users {
name
comments {
content
}
}
}
のような全ユーザの名前をコメントを取得するような Query が発行されたとしても "user_id": { "_eq": "X-Hasura-User-Id" }
の条件が Query に埋め込まれるために他のユーザーのデータが参照されることはないといった感じです。
hasura のわからないところ
実際使ってみたり、ドキュメントを読み込んでみないとわからない気になるところ
hasura の設定をどう運用するのか?
ここまで hasura コンソールの Web UI のスクリーンショットをいくつか貼りましたが、実際に運用する段階になったとしてこの UI を本番環境でポチポチするのは避けたいところです。
hasura には Web UI 以外から設定を import/export する機能があり、http 経由で JSON を POST/GET、または CLI から書き込み・読み込みができます。そのいずれかを使って運用することになると思います。
hasura の CLI 付きの Docker イメージ hasura/graphql-engine:v1.0.0.cli-migrations
は、起動時に /hasura-migrations
に置かれた設定ファイルを読み込んで起動するようになっています。これを docker-compose と組み合わせて使うとこんな感じになると思います。
version: "3.1"
services:
hasura:
image: hasura/graphql-engine:v1.0.0.cli-migrations
volumes:
- ./hasura/hasura-migrations:/hasura-migrations
ports:
- 8888:8080
restart: always
environment:
HASURA_GRAPHQL_DATABASE_URL: postgres://postgres:@postgres:5432/mydb
- ローカルで hasura の設定を変更する
- 設定をファイルに export して Git にコミットする
- その設定ファイルが起動時に読み込まれるようなデプロイにする
その他
疲れたから一旦公開するけどなんかまた追記するかも