Closed7

Hasura調査

tkc310tkc310

Hasuraはフルマネージド / セルフホスティング(OSS)が選べる。
日本語記事で機能比較をしているものが見つからないので調査してみる。

Hasuraとは

  • Haskellで作られている。Haskell + 阿修羅 = Hasuraらしい。(阿修羅は魔神や鬼の側面があるのでアイコンには角が生えてる)
  • データベースからGraphQLによるシンプルなCRUDを自動生成するサービス
  • CRUDに加えていくつかの機能が存在
    • 認証 - HasuraのGraphQL APIへのリスエストを認証済みかどうか判定できる
    • アクセス制約 - リソース毎の参照・更新条件
    • キャッシュ - クエリ(参照)オペレーションコードをハッシュ化してキャッシュ (persisted queryの仕組みに近い)
    • 外部APIとの連携 - バリデーションや更新ロジックを持たせたい場合はリクエストを別APIに流すことができる
      • remote schema - 別に建てたGraphQL API(以下、自前GraphQL)からintrospectionでスキーマを取得してHasuraに連携、クライアントからのリクエストはHasuraを経由して自前GraphQLに委譲
      • actions - 別に建てたREST API(以下、自前REST)にHasuraへのリクエストを委譲できる
    • イベント(webhook)、スケジュール、クーロンなどの機能もある
  • クエリ(参照)はHasura / ミューテーション(更新)は自前APIというアーキテクチャが選択でき、コードを減らせる・立ち上がりが早くなるためスタートアップとの親和性が高い (CQS)
  • 外部APIとの連携方法についてはHasura公式ブログのNestJS and Hasuraで説明されている (NestJSは癖(DI & moduleによる依存解決の規約)があるため他WAFを利用する場合は読みにくいかも)

製品の種類

Hasuraは製品として下記3つを提供している。

  • Hasura CE (community edition)
    • セルフホスティング型のOSS
  • Hasura Cloud
    • フルマネージド型のPaas
  • Hasura EE (enterprise edition)
    • セルフホスティング(オンプレミス含む)型にCloudの機能を付与したプラン?
      • シングルテナントのフルマネージド型 or サポート付きのセルフホスティングを選択できると解釈したけど詳しく見ていない
    • セキュリティ、パフォーマンス、サポート付

価格

https://hasura.io/pricing/

feature highlightsを比較すれば差分の概要は掴めそう

Cloud

price - hasura cloud

セルフホスティング

price - hasura self-hosting

tkc310tkc310

CloudとCE版セルフホスティング(以下CE)の比較

Cloudは課金コンテンツのため「CloudにはあるけどCEにはない」機能を見ていく

  • Cloudの未課金
    • CloudはFreeでもPosgreSQL以外を選択できる
    • リソースのロールベースによるアクセス制限は全ての製品で可能
  • Cloudの課金 - Professional - $1.5/h (active) - 最大 1.5x24x31=$1,116(*140=¥156,000) + 通信料 / 月
    • クエリキャッシュ
    • リードレプリカによるスケールアウト
    • データの監視・統合 - e.g. Hasura上でデータ変更を検知して自前APIなどにwebhookしたり、複数のデータソース間で同期できたり
    • 前述のロールベースに加えて、ホワイトリストによるリソースのアクセス制限
    • データベースの上限開放 (Freeは2)
    • 通信量制限開放 - $0.13/GB
    • APIリクエスト量制限が6MBに緩和 (Freeは3MB、エンプラで上限解放)
  • Cloudの課金 - Enterprise - custom price
    • APIリクエスト量の上限解放 - 6MBは割と早く到達しそう
    • VPCに組み込める
    • キャッシュとリードレプリカによるスケールアウトが上限解放
    • SSOなどの認証を組み合わせることができる
    • サポート付き - (professionalはないのか..) 企業で利用する場合はEnterpriseになりそう

priceから読み取れるのは以上

tkc310tkc310

Hasura Cloudを試す

せっかくなので試したログも残す

Hasura公式 GraphQL Backendコースの日本語版

https://hasura.io/learn/ja/graphql/hasura/introduction/

目次

  1. Hasura Cloudにサインアップ
  2. サインアップ後、プロジェクトが作成されているので「Launch Console」を選択
  3. 3つのタイプから管理画面のタイプを選択する
  4. データベースを作成
  5. usersテーブル作成
  6. GraphiQLからusersリソースのミューテーション、クエリを叩く
  7. todosテーブル作成
  8. GraphiQLからtodosリソースのミューテーション、クエリを叩く
  9. 過去30秒以内にログインしたユーザを検索する (online_users View作成)
  10. online_usersusers のリレーションシップを作成
  11. todosテーブルに権限を追加
  12. usersテーブルに権限を追加
  13. online_users Viewに権限を追加
  14. GraphiQLでヘッダーを設定してクエリを叩いてみる

1. Hasura Cloudにサインアップ

https://cloud.hasura.io/

2. サインアップ後、プロジェクトが作成されているので「Launch Console」を選択

3. 3つのタイプから管理画面のタイプを選択する

ロジックを持つことができる GraphQL Backend を選択
selecting hasura cloud type

4. データベースを作成

BaaSのNeonと連携できるため、Neonを選択 (サインアップはHasuraアカウントでSSOできる)

5. usersテーブル作成

操作はHasura管理画面(コンソール)から行える

6. GraphiQLからusersリソースのミューテーション、クエリを叩く

テーブルを作成した時点でGraphQLのCRUD操作が行えるため、ミューテーションとクエリを叩いてみる

  • ミューテーション

  • クエリ

7. todosテーブル作成

なお、外部キー制約を設定するとリレーションシップを作成してくれる。
todos.user_id を users.id の外部キーとして登録して、cascade(親リソースの削除・更新を小リソースにも反映)にしておく。

リレーションシップタブに移動すると前述の外部キー制約がリレーションシップとして提案されているので、nameを user に変更して登録する。

外部キー制約の登録と別インターフェースになっているのは、このようにフィールドとしてアクセスする時の名前などをカスタマイズできるようにする目的だと想定できる。

8. GraphiQLからtodosリソースのミューテーション、クエリを叩く

  • ミューテーション

  • クエリ

  • リレーションシップクエリ

9. 過去30秒以内にログインしたユーザを検索する (online_users View作成)

ロジックをもたせる方法として、Viewを利用する。
Data > SQLから下記の online_users Viewを追加する。

VIewを追加すると、このviewに対してもCRUD操作が可能になる。

CREATE OR REPLACE VIEW "public"."online_users" AS
 SELECT users.id,
    users.last_seen
   FROM users
  WHERE (users.last_seen >= (now() - '00:00:30'::interval));

usersテーブルのレコードを編集して last_soonnow() に更新する。
下記のように online_users をクエリ参照すると更新したユーザのみが返ってくる。
(更新から30秒以内に確認する)

10. online_usersusers のリレーションシップを作成

先程追加した online_users ビューに users のリレーションシップを追加することで online_users には存在しない users リソースのフィールドを参照できる。

先程の手順でレコードの users.last_soon を編集して下記のクエリを叩くと online_users.user が参照できていることが分かる

query {
  online_users {
    id
    last_seen
    user {
      id
      name
    }
  }
}

11. todosテーブルに権限を追加

長いので公式ドキュメントに譲る
https://hasura.io/learn/ja/graphql/hasura/authorization/1-todos-table-permissions/

12. usersテーブルに権限を追加

長いので公式ドキュメントに譲る
https://hasura.io/learn/ja/graphql/hasura/authorization/2-users-table-permissions/

13. online_users Viewに権限を追加

長いので公式ドキュメントに譲る
https://hasura.io/learn/ja/graphql/hasura/authorization/3-online-users-permissions/

14. GraphiQLでヘッダーを設定してクエリを叩いてみる

todosを取得するクエリを叩いて制限が掛かっているか確認する。

ヘッダー

x-hasura-role - user
x-hasura-user-id - 1

クエリ

query {
  todos {
    id
    title
    is_public
    is_completed
    user_id
  }
}

ヘッダーに指定したユーザのtodoのみが取得されていることが分かる。
x-hasura-user-id ヘッダーの値を変えればレスポンスも変わる

tkc310tkc310

後日、NestJSのGraphQLエンドポイントからremote schemaを利用してHasura連携する方法を試したら追記する予定
https://speakerdeck.com/lightnet328/bao-su-kai-fa-falsetamefalse-hasura-huo-yong?slide=11

下記をやりたい

  1. Hasuraでリソース追加
  2. NestJSでリソース追加
  3. Hasuraから2のremote schemaを取得
  4. Hasuraでschema.graphqlを出力 (1,2の複合リソース)
  5. クライアントでGraphQL Code Generatorを利用して4を読み込む、レスポンス型とhooks生成

公式チュートリアル
カスタムビジネスロジック

tkc310tkc310

Hasura x persisted queryについて

Hasuraとしてはpersisted queryの対応はしない方針らしい
https://github.com/hasura/graphql-engine/issues/273#issuecomment-1361430094

  • キャッシュ機構でpersisted queryのmanifestに相当するバックエンドロジックは持っている
  • 現状だとApollo Clientに依存することになる (apollo clientはクエリのsha256ハッシュを作ってリクエスト時にパラメータ送信するpersisted query用のapiを持っている)
  • manifestを生成するライブラリ(npm)もメンテされているものは現状なさそう (the guild謹製のプラグインは詳しく探していない)
  • Hasura x persisted queryを行いたい場合は、自前でmanifestを作ってredisなどで保持・保持したハッシュとリクエストハッシュを検証するロジックの実装が必要
    • Hasuraのキャッシュ機構とバッティングしそうなため運用も気を付ける必要がありそう
    • (hasuraインスタンスも含めたblue/greenデプロイ機構を作るなど?)
tkc310tkc310

Hasura上でカスタムロジックを実現する方法

  • remote schema - 外部APIにロジックを委譲する手段 (hasura上ではない)
  • actions - faasと連携すればコンソール上で編集可能 (半分hasura上といえる)
  • sql view - sqlに依存するがsqlで実現できることは可能 (利用はリレーションシップ位に留めたい気持ち)
  • computed field - posgresqlの関数を利用 (これはコードで表現したい気持ち)

①認証 + ②ロールベースアクセス制御(権限) + ③CRUDで表現できるものはHasuraを利用して、これで表現できないものは外部APIに委譲するのが妥当そうに思える。(詳しくない現状においては)

コードが存在しないことはレビューやメンテナンスのコストを減らしてくれるので初速は確実に早くなりそう、一方で共通モジュールやgeneratorを利用することで①〜③はある程度自動化できてしまえそうな気もしている。
nest.js x prismaのgenerator plugin

上記以外にHasuraのメリット・デメリットを思いついたら追記していく。

pros

  • リレーションシップでネストされたリソースを取得する際に、HasuraはN+1を解決してくれるらしいので自前でdataloaderの設定をする必要もなくなる。(フレームワークとdataloaderライブラリにもよるが、自分が利用していたgrapheneでは都度リレーションシップごとに設定が必要だったので、それなりに手間な印象)

cons

  • a
tkc310tkc310

Hasuraを使う予定がなくなったため一旦クローズする

このスクラップは2023/07/22にクローズされました