AWS Lambda Powertools Python入門
第 6 回 EventHandler Utility - GraphQL 編
Author : 福井 厚
皆さん、こんにちは。AWSソリューションアーキテクトの福井です。本連載は、AWS Lambda Powertools for Python の提供する様々なユーティリティーについて、その利用方法を紹介するシリーズです。
さて、第 5 回 では、AWS Lambda Powertools for Python の EventHandler ユーティリティーの REST API の使い方についてご紹介しました。今回は Event Handler の GraphQL API についてご紹介します。なお本記事は、AWS Lambda Powertools Python 1.29.2 を対象としています。
この連載記事のその他の記事はこちら
- 選択
- AWS Lambda Powertools Python 入門 第 1 回
- 第 2 回 ~Tracer Utility
- 第 3 回 ~Logger Utility
- 第 4 回 ~Metrics Utility
- 第 5 回 ~EventHandler Utility - REST API 編
- 第 6 回 EventHandler Utility - GraphQL 編
Event Handler (Core Utilities)
AWS Lambda Powertools for Python の Event Handler は、REST API と GraphQL API の両方が提供されています。前回は、REST API について紹介しましたが、今回は GraphQL API について紹介します。
Event Handler GraphQL API を利用することで GraphQL API のクエリパラメータを自動的に関数の引数に変換してくれます。また関数のレスポインスを自動的に GraphQL フィールドにマップする機能も提供しています。
GraphQL API
AWS AppSync Direct Lambda Resolver と Amplify GraphQL Transformer のためのイベントハンドラです。
このユーティリティーの主な特長は以下の通りです。
- 自動的に API の引数をパースして関数の引数に変換
- GraphQL のフィールド名に厳密に一致するか、またはフィールドすべてを関数へ渡すかを選択可能
- リゾルバとアイデンティティー情報へアクセスするための Data classes utilities との統合
- Python 3.8 以上の非同期関数とジェネレーターをサポート
Direct Lambda Resolverとは : Apache Velocity Template (VTL) をバイパスするためのカスタムの AppSyncリゾルバ と、関数のレスポンスを自動的に GraphQL フィールドにマップする機能を提供
利用方法
AWS Lambda Powertools PythonをLambda関数に組み込む方法については、第 1 回 の記事を参照ください。
このユーティリティーを利用するためには、作成済みの AppSync GraphQL API と、Lambda 関数を実行可能な IAM パーミッションが必要です。それ以外はこのユーティリティーの利用に追加のパーミッションは必要ありません。
今回は以下の Serverless Application Model (SAM) テンプレートを実行して AppSync API のサンプルを AppSync Direct Lambda Resolver と共に利用します。
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: >
05_eventhandler_graphql_demo
Sample SAM Template for 05_eventhandler_graphql_demo
Globals:
Function:
Timeout: 5
Tracing: Active
Environment:
Variables:
LOG_LEVEL: INFO
POWERTOOLS_LOGGER_SAMPLE_RATE: 0.1
POWERTOOLS_LOGGER_LOG_EVENT: true
POWERTOOLS_SERVICE_NAME: sample_resolver
Resources:
# Lambda function
TodosFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: src/
Handler: app.lambda_handler
Runtime: python3.9
Architectures:
- x86_64
# AWS Lambda Powertools for Python
Layers:
- !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPython:36
# IAM Permissions and Roles
AppSyncServiceRole:
Type: "AWS::IAM::Role"
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Service:
- "appsync.amazonaws.com"
Action:
- "sts:AssumeRole"
InvokeLambdaResolverPolicy:
Type: "AWS::IAM::Policy"
Properties:
PolicyName: "DirectAppSyncLambda"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Action: "lambda:invokeFunction"
Resource:
- !GetAtt TodosFunction.Arn
Roles:
- !Ref AppSyncServiceRole
# GraphQL API
TodosApi:
Type: "AWS::AppSync::GraphQLApi"
Properties:
Name: TodosApi
AuthenticationType: "API_KEY"
XrayEnabled: true
TodosApiKey:
Type: AWS::AppSync::ApiKey
Properties:
ApiId: !GetAtt TodosApi.ApiId
TodosApiSchema:
Type: "AWS::AppSync::GraphQLSchema"
Properties:
ApiId: !GetAtt TodosApi.ApiId
Definition: |
schema {
query:Query
}
type Query {
getTodo(id: ID!): Todo
listTodos: [Todo]
}
type Todo {
id: ID!
title: String
description: String
done: Boolean
}
# Lambda Direct Data Source and Resolver
TodosFunctionDataSource:
Type: "AWS::AppSync::DataSource"
Properties:
ApiId: !GetAtt TodosApi.ApiId
Name: "HelloWorldLambdaDirectResolver"
Type: "AWS_LAMBDA"
ServiceRoleArn: !GetAtt AppSyncServiceRole.Arn
LambdaConfig:
LambdaFunctionArn: !GetAtt TodosFunction.Arn
ListTodosResolver:
Type: "AWS::AppSync::Resolver"
Properties:
ApiId: !GetAtt TodosApi.ApiId
TypeName: "Query"
FieldName: "listTodos"
DataSourceName: !GetAtt TodosFunctionDataSource.Name
GetTodoResolver:
Type: "AWS::AppSync::Resolver"
Properties:
ApiId: !GetAtt TodosApi.ApiId
TypeName: "Query"
FieldName: "getTodo"
DataSourceName: !GetAtt TodosFunctionDataSource.Name
Outputs:
HelloWorldFunction:
Description: "Hello World Lambda Function ARN"
Value: !GetAtt TodosFunction.Arn
HelloWorldAPI:
Value: !GetAtt TodosApi.Arn
この SAM テンプレートで実行される GraphQL スキーマは以下の通りです。
schema {
query: Query
}
type Query {
getTodo(id: ID!): Todo
listTodos: [Todo]
}
type Todo {
id: ID!
userId: String
title: String
completed: Boolean
}
Resolver デコレーター
app.resolver() デコレーターを利用して関数を GraphQL タイプとフィールドにマッチさせることができます。
このサンプルでは 2 つの Python の関数を利用して Query タイプ内の getTodo と listTodos の 2 つのフィールドを解決します。スキーマ定義に従ってアウトプットを生成するためにスカラタイプのユーティリティー (この後、スカラ関数についても説明します) を利用しています。このクエリの Lambda Direct Data Source と Resolver として以下の Lambda 関数が実行されます。
Tips : GraphQL 引数は関数のキーワード引数に渡されます。(例 : getTodo(id: “id_value”) は get_todo(id=“id_value”) を呼び出します。)
スカラ関数
AWS AppSync Scalar types と共に実行する場合、データ検証の目的で同じ値を生成したいと思うかもしれません。利便性のため、最も一般的に利用される値を scalar_types_utils モジュールの関数として利用可能にしています。
以下のテーブルに関連するスカラ値を返す関数をリストしています。
スカラ型 | スカラ関数 | サンプル値 |
ID | scalar_types_utils.make_id() | e916c84d-48b6-484c-bef3-cee3e4d86ebf |
AWSDate | scalar_types_utils.aws_date() | 2022-07-08Z |
AWSTime | scalar_types_utils.aws_time() | 15:11:00.189Z |
AWSDateTime | scalar_types_utils.aws_datetime() | 2022-07-08T15:11:00.189Z |
AWSTimestamp | scalar_types_utils.aws_timestamp() | 1657293060 |
まとめ
いかがでしたでしょうか。今回は、AWS Lambda Powertools Python の EventHandler ユーティリティーの GraphQL API について紹介しました。
Event Handler Utility の Resolver デコレーターを利用することで、簡単に Appsync の GraphQL を AWS Lambda 関数にマップできることがご理解頂けたのではないでしょうか。
今回で AWS Lambda Powertools for Python のコアユーティリティーの紹介は終わりました。次回からはそれ以外のユーティリティーについてご紹介したいと思います。どうかお楽しみに。
この連載記事のその他の記事はこちら
- 選択
- AWS Lambda Powertools Python 入門 第 1 回
- 第 2 回 ~Tracer Utility
- 第 3 回 ~Logger Utility
- 第 4 回 ~Metrics Utility
- 第 5 回 ~EventHandler Utility - REST API 編
- 第 6 回 EventHandler Utility - GraphQL 編
筆者プロフィール
福井 厚
アマゾン ウェブ サービス ジャパン合同会社
シニアソリューションアーキテクト
Developerスペシャリスト - DevAx
2015 年からアマゾンウェブサービスジャパンでソリューションアーキテクトとして活動。最近は、Developer スペシャリスト SA として日々開発者の方にクラウドネイティブなモダンアプリケーション開発の技術支援を行なっています。
AWS を無料でお試しいただけます