ScalarDB Cluster GraphQL をはじめよう
このページは英語版のページが機械翻訳されたものです。英語版との間に矛盾または不一致がある場合は、英語版を正としてください。
ScalarDB Cluster gRPC API の詳細については、以下を参照してください。
前提条件
- 以下のいずれかの Java Development Kit (JDK):
- Oracle JDK LTS バージョン (8、11、17、または 21)
- OpenJDK LTS バージョン (8、11、17、または 21)
- Kubernetes クラスターで実行されている ScalarDB Cluster
- ScalarDB Cluster をローカルにデプロイする方法 の手順に従ってデプロイした 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.15.6-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 API | GraphQL ルートタイプ | GraphQL フィールド |
|---|---|---|
get(Get get) | Query | account_get(get: account_GetInput!): account_GetPayload |
scan(Scan scan) | Query | account_scan(scan: account_ScanInput!): account_ScanPayload |
put(Put put) | Mutation | account_put(put: account_PutInput!): Boolean! |
put(java.util.List<Put> puts) | Mutation | account_bulkPut(put: [account_PutInput!]!): Boolean! |
delete(Delete delete) | Mutation | account_delete(delete: account_DeleteInput!): Boolean! |
delete(java.util.List<Delete> deletes) | Mutation | account_bulkDelete(delete: [account_DeleteInput!]!): Boolean! |
mutate(java.util.List<? extends Mutation> mutations) | Mutation | account_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"
}
}
}