AWS Lambda Powertools Python入門

第 6  回 EventHandler Utility - GraphQL 編

2022-11-02
デベロッパーのためのクラウド活用方法

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 ResolverAmplify 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 タイプ内の getTodolistTodos  の 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 編

builders.flash メールメンバーへ登録することで
AWS のベストプラクティスを毎月無料でお試しいただけます


筆者プロフィール

福井 厚
アマゾン ウェブ サービス ジャパン合同会社
シニアソリューションアーキテクト
Developerスペシャリスト - DevAx

2015 年からアマゾンウェブサービスジャパンでソリューションアーキテクトとして活動。最近は、Developer スペシャリスト SA として日々開発者の方にクラウドネイティブなモダンアプリケーション開発の技術支援を行なっています。

AWS を無料でお試しいただけます

AWS 無料利用枠の詳細はこちら ≫
5 ステップでアカウント作成できます
無料サインアップ ≫
ご不明な点がおありですか?
日本担当チームへ相談する