メインコンテンツまでスキップ
バージョン: 3.14

ScalarDB Cluster GraphQL をはじめよう

注記

このページは英語版のページが機械翻訳されたものです。英語版との間に矛盾または不一致がある場合は、英語版を正としてください。

ScalarDB Cluster gRPC API の詳細については、以下を参照してください。

前提条件

  • 以下のいずれかの Java 開発キット (JDK):
    • Oracle JDK LTS バージョン (8、11、17、または 21)
    • OpenJDK LTS バージョン (8、11、17、または 21)
  • Kubernetes クラスターで実行されている ScalarDB Cluster

サンプルアプリケーション

このチュートリアルでは、口座間で資金を移動できる電子マネーアプリケーションを作成するプロセスについて説明します。

次の図は、サンプルアプリケーションのシステムアーキテクチャを示しています。

                              +-----------------------------------------------------------------------------------------------------------------------------------------+
| [Kubernetes クラスター] |
| |
| [ポッド] [ポッド] [ポッド] |
| |
| +-------+ |
| +---> | Envoy | ---+ |
| | +-------+ | |
| | | |
+------------------------+ | +---------+ | +-------+ | +--------------------+ |
| Schema Loader | --+-> | サービス | ---+---> | Envoy | ---+---------> | サービス | ---+ |
| (間接クライアントモード) | | | (Envoy) | | +-------+ | | (ScalarDB Cluster) | | |
+------------------------+ | +---------+ | | +--------------------+ | +------------------------+ |
| | +-------+ | | +---> | ScalarDB Cluster ノード | ---+ |
| +---> | Envoy | ---+ | | +------------------------+ | |
| +-------+ | | | |
| | | +------------------------+ | +------------+ |
| +---+---> | ScalarDB Cluster ノード | ---+---> | PostgreSQL | |
| | | +------------------------+ | +------------+ |
| | | | |
| | | +------------------------+ | |
| | +---> | ScalarDB Cluster ノード | ---+ |
| | +------------------------+ |
+------------+ | +----------------------------+ | |
| ブラウザ | ------+---------------------------------------> | サービス | ---+ |
| (GraphiQL) | | | (ScalarDB Cluster GraphQL) | |
+------------+ | +----------------------------+ |
| |
+-----------------------------------------------------------------------------------------------------------------------------------------+

ステップ 1. schema.json を作成する

以下は簡単なサンプルスキーマです。

schema.json を作成し、ファイルに次の内容を追加します。

{
"emoney.account": {
"transaction": true,
"partition-key": [
"id"
],
"clustering-key": [],
"columns": {
"id": "TEXT",
"balance": "INT"
}
}
}

ステップ 2. database.properties を作成する

ScalarDB Cluster の Schema Loader 用に database.properties を作成する必要があります。

ただし、まず Envoy (scalardb-cluster-envoy) のサービスリソースの EXTERNAL-IP アドレスを取得する必要があります。

EXTERNAL-IP アドレスを確認するには、次のコマンドを実行します。

kubectl get svc scalardb-cluster-envoy
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
scalardb-cluster-envoy LoadBalancer 10.105.121.51 localhost 60053:30641/TCP 16h

この場合、EXTERNAL-IP アドレスは localhost です。

次に、database.properties を作成し、ファイルに次の内容を追加します。

scalar.db.transaction_manager=cluster
scalar.db.contact_points=indirect:localhost

ScalarDB Cluster に接続するには、scalar.db.transaction_manager プロパティに cluster を指定する必要があります。

また、このチュートリアルでは indirect クライアントモードを使用して Envoy のサービスリソースに接続します。

クライアントモードの詳細については、Java API を使用した ScalarDB Cluster の開発者ガイド を参照してください。

ステップ 3. スキーマをロードする

ScalarDB Cluster 経由でスキーマをロードするには、ScalarDB Cluster 専用の Schema Loader (Schema Loader for Cluster) を使用する必要があります。Schema Loader for Cluster の使用方法は、JAR ファイルの名前が異なることを除いて、Schema Loader for ScalarDB の使用方法と基本的に同じです。Cluster 用の Schema Loader は、ScalarDB リリース からダウンロードできます。JAR ファイルをダウンロードしたら、次のコマンドで Cluster 用の Schema Loader を実行できます。

java -jar scalardb-cluster-schema-loader-3.14.0-all.jar --config database.properties -f schema.json --coordinator

ステップ 4. GraphiQL から操作を実行する

ScalarDB Cluster では、scalar.db.graphql.graphiql プロパティが true に設定されている場合 (true がデフォルト値)、GraphiQL IDE が使用可能になります。

ScalarDB Cluster GraphQL (scalardb-cluster-graphql) のサービスリソースの EXTERNAL-IP アドレスを取得するには、次のコマンドを実行します。

kubectl get svc scalardb-cluster-graphql
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
scalardb-cluster-graphql LoadBalancer 10.105.74.214 localhost 8080:30514/TCP 16h

この場合、EXTERNAL-IP アドレスは localhost、GraphiQL IDE のエンドポイント URL は http://localhost:8080/graphql です。 Web ブラウザでその URL を開くと、GraphiQL 画面が表示されます。

最初のレコードを挿入してみましょう。左ペインに次のミューテーションを貼り付け、ウィンドウ上部の三角形の Execute Query ボタンを押します。

mutation PutUser1 {
account_put(put: {key: {id: "user1"}, values: {balance: 1000}})
}

ScalarDB GraphQL は常にトランザクションを使用してクエリを実行します。上記のクエリは新しいトランザクションを開始し、ScalarDB Put コマンドを実行し、実行の最後にトランザクションをコミットします。

GraphQL サーバーからの次の応答が右側のペインに表示されます。

{
"data": {
"account_put": true
}
}

"data" フィールドには実行結果が含まれます。この応答は、ミューテーションの account_put フィールドが成功したことを示しています。ミューテーションの結果タイプは Boolean! で、操作が成功したかどうかを示します。

次に、挿入したレコードを取得しましょう。左ペインの前のミューテーションの横に次のクエリを貼り付けて、Execute Query ボタンをクリックします。上記の mutation PutUser1 を削除していないため、ボタンの下にプルダウンメニューが表示され、実行する操作を選択できます。 以下に示すように、GetUser1 を選択します。

query GetUser1 {
account_get(get: {key: {id: "user1"}}) {
account {
id
balance
}
}
}

右側のペインに次の結果が表示されます。

{
"data": {
"account_get": {
"account": {
"id": "user1",
"balance": 1000
}
}
}
}

GraphQL API と ScalarDB Java API 間のマッピング

自動的に生成された GraphQL スキーマは、クエリ、ミューテーション、および入出力のオブジェクトタイプを定義し、ターゲット名前空間内のすべてのテーブルに対して CRUD 操作を実行できるようにします。

これらの操作は、DistributedTransaction インターフェースで定義されている ScalarDB API と一致するように設計されています。

名前空間に account テーブルがあると仮定すると、次のクエリとミューテーションが生成されます。

ScalarDB APIGraphQL ルートタイプGraphQL フィールド
get(Get get)Queryaccount_get(get: account_GetInput!): account_GetPayload
scan(Scan scan)Queryaccount_scan(scan: account_ScanInput!): account_ScanPayload
put(Put put)Mutationaccount_put(put: account_PutInput!): Boolean!
put(java.util.List<Put> puts)Mutationaccount_bulkPut(put: [account_PutInput!]!): Boolean!
delete(Delete delete)Mutationaccount_delete(delete: account_DeleteInput!): Boolean!
delete(java.util.List<Delete> deletes)Mutationaccount_bulkDelete(delete: [account_DeleteInput!]!): Boolean!
mutate(java.util.List<? extends Mutation> mutations)Mutationaccount_mutate(put: [account_PutInput!]delete: [account_DeleteInput!]): Boolean!

クラスタリングキーのないテーブルでは、scan フィールドは生成されないことに注意してください。これが、この電子マネーサンプルアプリケーションで account_scan フィールドが使用できない理由です。

生成されたすべての GraphQL タイプは、GraphiQL のドキュメントエクスプローラー (左上隅の < Docs リンク) で確認できます。

ステップ 5. GraphiQL からの複数のリクエストにまたがるトランザクションを実行する

複数の GraphQL リクエストにまたがるトランザクションを実行してみましょう。

生成されたスキーマには、トランザクションを識別できる @transaction ディレクティブが用意されています。このディレクティブは、クエリとミューテーションの両方で使用できます。

トランザクションを開始する前に、次のミューテーションを使用して必要なレコードを挿入する必要があります。

mutation PutUser2 {
account_put(put: {key: {id: "user2"}, values: {balance: 1000}})
}

操作を実行する前にトランザクションを開始する

以下を実行して、クエリまたはミューテーションに引数のない @transaction ディレクティブを追加すると、実行時に新しいトランザクションが開始されます。

query GetAccounts @transaction {
user1: account_get(get: {key: {id: "user1"}}) {
account { balance }
}
user2: account_get(get: {key: {id: "user2"}}) {
account { balance }
}
}

上記のコマンドを実行すると、extensions フィールドにトランザクション ID が入った結果が返されます。extensions の id 値は、リクエスト内の操作が実行されたトランザクション ID です。この場合、リクエストによって開始されたトランザクションの新しい ID は次のとおりです。

{
"data": {
"user1": {
"account": {
"balance": 1000
}
},
"user2": {
"account": {
"balance": 1000
}
}
},
"extensions": {
"transaction": {
"id": "c88da8a6-a13f-4857-82fe-45f1ab4150f9"
}
}
}

継続トランザクションで操作を実行する

開始したトランザクションで次のクエリまたはミューテーションを実行するには、トランザクション ID を @transactionid 引数として指定します。次の例では、同じトランザクションで user1 のアカウントから user2 のアカウントに残高を転送することにより、前の例で取得した 2 つのアカウントを更新します。

mutation Transfer @transaction(id: "c88da8a6-a13f-4857-82fe-45f1ab4150f9") {
user1: account_put(put: {key: {id: "user1"}, values: {balance: 750}})
user2: account_put(put: {key: {id: "user2"}, values: {balance: 1250}})
}

GraphQL で開始されたトランザクションには 1 分のタイムアウト (デフォルト) があり、タイムアウトを超えると自動的にアボートされることに注意してください。

トランザクションをコミットする

継続中のトランザクションをコミットするには、@transaction ディレクティブの引数として idcommit: true フラグの両方を指定します。

query GetAndCommit @transaction(id: "c88da8a6-a13f-4857-82fe-45f1ab4150f9", commit: true) {
user1: account_get(get: {key: {id: "user1"}}) {
account { balance }
}
user2: account_get(get: {key: {id: "user2"}}) {
account { balance }
}
}

注: @transaction(commit: true) のように id 引数なしで commit: true フラグを指定すると、新しいトランザクションが開始され、1 つの操作に対してのみコミットされます。この動作は、GraphiQL を使用した上記の例で見られるように、@transaction ディレクティブを指定しない場合とまったく同じです。つまり、@transaction(commit: true) が指定されている場合は、ディレクティブ自体を省略できます。

トランザクションをアボートまたはロールバックする

トランザクションを明示的にアボートまたはロールバックする必要がある場合は、abort または rollback ミューテーションフィールドを互換的に使用できます (どちらも効果と使用方法は同じです)。これらのフィールドを他の操作と混在させることはできないため、次のように abort または rollback ミューテーションフィールドのみを指定する必要があります。

mutation AbortTx @transaction(id: "c88da8a6-a13f-4857-82fe-45f1ab4150f9") {
abort
}

または:

mutation RollbackTx @transaction(id: "c88da8a6-a13f-4857-82fe-45f1ab4150f9") {
rollback
}

参照

その他の ScalarDB Cluster チュートリアルについては、以下を参照してください。

Java API で ScalarDB Cluster を使用するアプリケーションの開発の詳細については、以下を参照してください。

ScalarDB Cluster gRPC API の詳細については、以下を参照してください。