Scalar DB GraphQL
このブログ記事では、 Scalar DB の GraphQL インターフェースについて説明します。(英語版はこちら)
Scalar DB GraphQL の概要
Scalar DB GraphQLは、クエリ言語であるGraphQLを用いてScalar DBにアクセスするためのインタフェースです。Scalar DBのCRUD APIはJava言語のAPIであるためJavaからのみアクセス可能ですが、GraphQLインタフェースを使用することにより、幅広いプログラミング言語からScalar DBへのアクセスが可能になります。
Scalar DB GraphQLは、商用ライセンスで提供されています。製品はDocker imageとして提供されています。また、Helm chartを用いてKubernetes環境にインストールすることも可能です。
特徴
Scalar DB GraphQLは以下のような特徴を持ちます。
- Scalar DBのテーブルに対して、CRUD操作を行うためのGraphQLスキーマを自動的に生成する
- クライアントとの通信手段としてHTTPサーバーを提供する
- ディレクティブによりトランザクションをサポートする
Scalar DB GraphQLは、起動時に、Scalar DBテーブルのメタデータを読み込み、それらのテーブルのCRUD操作を行うためのGraphQLスキーマを生成します。テーブルはあらかじめScalar DBがサポートするストレージ・データベース上に作成しておく必要があります。
ビルトインのHTTPサーバーを通じて、GraphQLクライアントは各テーブルのCRUD操作にマッピングされたGraphQLクエリやミューテーションを実行することができます。また、複数のHTTPリクエストにまたがるトランザクションもサポートされています。
アーキテクチャ
下記の図は、Scalar DB GraphQLの構造を示します。
GraphQL Java componentsはScalar DB Java APIを用いて構築されており、下記のように、GraphQLの処理やストレージへのアクセスを行います。
- GraphQL schemaの生成(起動時)
- GraphQLクエリを解釈、Scalar DB APIを実行
- 実行結果をJSONフォーマットで返却
HTTP serverは、クライアントとGraphQL Java componentsの間でのリクエストとレスポンスのやりとりを仲介するだけの役割を持ちます。
GraphQL schema の例
以下では、具体的なScalar DBのテーブルの例を用いて、どのようにGraphQLスキーマが生成されどのようにクエリがが実行されるかを説明します。
データベースに下記のJSONで記述されたスキーマが作成されているとします。スキーマ定義についてはこちらの記事を参照してください。
このデータベースの名前空間 "sample"
を指定してScalar DB GraphQLを起動すると、下記のような GraphQL schema が生成されます。
このように、1つのテーブルに対して、get、scan、put、deleteのCRUD操作を行うためのフィールドが、QueryとMutationのタイプに生成されます。(Subscriptionタイプはサポートされていません。)また、入力やレスポンスを表現するためのInputType、Typeも同時に生成されます。
クライアントは、生成されたGraphQLスキーマに基づき、クエリを組み立て、実行できます。GraphiQLを用いたブラウザ上での対話的インタフェースにより、クエリを組み立てることもできます。
最初の例として、次のGraphQLクエリは orders
テーブルのgetオペレーションを実行します。orders_get
フィールドとその引数はScalar DBのGetオペレーションを表します。その後に続くselection setには、取得したいカラム名をリストします。
Scalar DB Transactional APIのCRUD操作が、GraphQLのQueryとMutationのルートタイプのフィールドに1対1で対応しています。次の表はその対応を示します。
トランザクション
Scalar DB GraphQLでは、全てのオペレーションはトランザクションの下で実行されます。
ユーザーは @transaction
というディレクティブを使って、トランザクションを操作できます。ディレクティブとは、GraphQLオペレーションに追加の設定を与えるために使用される文法です。 @transaction
ディレクティブは query、mutation のどちらにも付加することができます。
GraphQLオペレーションが実行されたトランザクションが継続している場合、トランザクションIDは、レスポンスの "extensions"
キーにより返却されます。後続のオペレーションでこのトランザクションIDを指定することにより、1つのトランザクションを複数のGraphQLオペレーションにまたがって継続することができます。
具体的な例を使って説明します。ここでは account
というテーブルが存在すると仮定します。
引数を持たない @transaction
ディレクティブを付けると、新たにトランザクションが開始されます。
レスポンスのJSONの "extensions"
フィールドに、このオペレーションが実行されたトランザクションのIDが返却されます。
アクティブなトランザクションは、サーバー上に保持されています。続くオペレーションの @transaction
ディレクティブの引数にトランザクションIDを指定すると、サーバーはアクティブなトランザクションを検索し、継続してオペレーションを実行します。
また、ディレクティブの引数に commit: true
を指定すると、オペレーションの最後にトランザクションをコミットします。
トランザクションをabortする必要がある場合は、mutation操作で abort
を実行します。 abort
フィールドは単独で使用しなければなりません。
特別な場合として、 @transaction
ディレクティブを省略することも可能です。この場合は、@transaction(commit: true)
を指定したのと全く同じ意味になります。つまり、オペレーションの実行前にトランザクションが開始され、実行後にコミットされます。1回のオペレーションでトランザクションが完結するような場合に使用します。
GraphQL の実行例
いくつかの実行例を示します。
次の例は、トランザクションを開始し、ordersテーブルに2つのレコードをputし、コミットします。前述のように、 @transaction(commit: true)
を付与したのと同じ意味になります。
レスポンス:
次の例は、新たにトランザクションを開始し、上の例で挿入したordersテーブルのレコードをgetします。 commit: true
が指定されていないのでトランザクションはコミットされず、レスポンスの "extensions"
フィールドにトランザクションIDが返却されます。
レスポンス:
次のmutationは上記で取得したレコードを同じトランザクションで更新し、トランザクションをコミットします。
レスポンス:
まとめ
この記事では、Scalar DBのGraphQLインターフェースについて紹介しました。GraphQLインターフェースを起動するとデータベース上の指定した名前空間のテーブルに対してGraphQLスキーマが生成されます。GraphQLのオペレーションを使用すれば、Javaプログラミングを行わずにCRUD操作を実行することができます。