AWS Lambda(Node.js)からAWS AppSync(GraphQL)のAPIを利用してみた


吉岡です。最近寒くなってきましたね。 鍋と熱燗とコタツの季節が来たと思うと、少しテンションが上がります!

さて、今回はAWS Amplifyを利用して開発を行った際にAppSync(GraphQL)について得た知見について書きたいと思います。

背景

AWS Amplifyを利用してウェブアプリケーションを作りました。そして、バックエンド側でAWS AppSyncを利用して入力されたデータに対して、定期的にLambda(Node.js)を実行して、不要になったデータの削除する処理を行う処理を実装しました。


簡略図

ちなみに、AWS Amplify と AWS AppSyncはAWSが提供しているマネージドサービスで、フロントエンドがデプロイできたり、GraphQLをお手軽に利用できるサービスになります。

参考:AWS Amplify
https://aws.amazon.com/jp/amplify/

参考:AWS AppSync
https://aws.amazon.com/jp/appsync/

問題発生

まずは、今回一番のハマりどころであった、APIへアクセスする際の認証について書きたいと思います。

AppSyncにアクセスする時に制限をかける場合はIAMを利用した方法とApiKeyを利用した方法があります。今回はApiKeyを利用したアクセスではなく、IAM(ロール)を利用したアクセスを考えました。(ApiKeyの管理とかしたくない)

  1. まず最初に、Amplifyのドキュメント(Functions - Overview - Amplify Docs)にLambdaからAppSync(GraphQL)へのアクセス方法が書かれていましたので、そちらを参考にささっとコードを書いて実行したのですが、うまく動かず。。

  2. 他に情報はないかと思い、検索すると情報はそこそこ出てきました(技術系ブログがよく引っかかりました)。ですが、その多くはApiKeyを利用したアクセス方法の解説でした。IAM(ロール)を利用したアクセス方法はなかなかこれと言った情報が見つかりませんでした。

  3. 仕方なくAWSのドキュメントに戻り、「認証」というキーワードを頼りにあちこち調べたら、認証モードが IAM である場合には、 IAM クレデンシャルを使用した署名をリクエストに付与する必要がということで、何やら署名を取得しないといけないようです。
    AWS API リクエストの署名 - AWS 全般のリファレンス

  4. 上記ドキュメントを読みながら、さらに調べましたところ、なんと!参考サイト(上記Amplifyのドキュメント)のやり方ではなく、AppSyncのドキュメント(NodeJS クライアントアプリを作成する - AWS AppSync)の方を参考にすると解決できました!!

AppSyncのドキュメントを見るのはそりゃそうか!最初っからAppSyncで探せば良かった!!と思いつつも、Amplifyのドキュメントのサンプルで動かなかったのは謎です。。(cognitoの絡みかしら?と思いつつ、そっとブラウザのタブを閉じました。)

コード

実際のコードは以下のような感じです。

const aws = require('aws-sdk')
const AWSAppSyncClient = require('aws-appsync').default
const gql = require('graphql-tag')

const listTempUserDatas = gql`
  query ListUserDatas(
    $filter: ModelUserDataFilterInput
    $limit: Int
    $nextToken: String
  ) {
    listUserDatas(filter: $filter, limit: $limit, nextToken: $nextToken) {
      items {
        id
        email
        name
        timestamp
      }
      nextToken
    }
  }
`

const url = process.env.API_TEMPDATAAPI_GRAPHQLAPIENDPOINTOUTPUT
const region = process.env.REGION
const client = new AWSAppSyncClient({
  url: url,
  region: region,
  auth: {
    type: 'AWS_IAM',
    credentials: ()=> aws.config.credentials
  },
  disableOffline: true
})

exports.handler = async (event) => {

  console.log('Reference Time:', new Date(referenceTime))

  try {
    const response = await client.query({ query: listTempUserDatas })
    const items = response.data.listTempUserDatas.items
    console.log('items: ',items)

    return {
      statusCode: 200,
      body: items,
      headers: {
        "Access-Control-Allow-Origin": "*",
      }
    }
  } catch (err) {
    console.log('error posting to appsync: ', err)
  }
}

その他の問題

その他、いくつかハマったところがありましたので、紹介したいと思います。

1. LambdaのLayerについて

const AWSAppSyncClient = require('aws-appsync').default

aws-appsyncをrequireしてるのですが、これを通常のnpm installを利用すると Lambda 関数 xxxx のデプロイパッケージが大きすぎて、インラインコード編集を有効にできません。 というメッセージが表示されてインライン編集ができなくなってしまいます。 別途aws-appsyncがrequireされたLayerを準備して、使用するLambdaに設定(追加)する必要がありました。

Layerについては以下のドキュメントをご確認ください。
AWS Lambda レイヤー - AWS Lambda

2. Node.jsの非同期処理について

そもそもNode.jsをよく理解していなかった話ですが、LambdaでNode.jsを利用して通信する場合は非同期処理(async, await)の利用は必須でした。
Node.js の AWS Lambda 関数ハンドラー - AWS Lambda

最初よく分かってなくて、なかなか思ったようなレスポンスが得られなくて苦労しました。

3. ドキュメントの話

Amplifyを利用しているからと行ってAmplifyのドキュメントばかり調べるのではなく、Amplifyが利用しているサービスのドキュメントも調べる。(今回はAppSyncのドキュメントも見るべきでした)

まとめ

以上、無事にLambdaからAppSyncにアクセスできるようになり、無事にスケジューリングされた処理を実行できるようになりました!個人的には学習コストは高めだと思いますが、覚えてしまえば非常に便利で開発速度が上がりそうです。

今後も、積極的にAWS Amplifyを利用していきたいと思います!!


My Redmine

こちらの記事もオススメです!
AWS Amplify のログイン認証機能を試してみた
「AWS Amplify」を利用して、ログイン画面の実装について手順を紹介します。
お客様のご指摘から「My Redmine」を改善できました
お客様のご協力により、サービスを改善できたことはとてもうれしいです。
ラズパイを使って室温と外気温の関係を視覚的に調査
想像していた以上に簡単に室温管理・分析のための仕組みを構築することができました。
フレックスタイム制の会社側視点でのメリット
フレックスタイム制の導入で従業員の満足度向上・労務管理の簡素化などが実現できました。
マインドマップを使ってAWSクラウドプラクティショナー試験の勉強をしています
マインドマップ作成ツール「XMind」を使用。マインドマップを用いることで頭の中が整理されより理解を深めることができます。
ファーエンドテクノロジーからのお知らせ(2020/11/25更新)
RubyWorld Conference 2020にファーエンドテクノロジーの坂本が登壇します
12月17日(木)にオンラインで開催される「RubyWorld Conference 2020」に弊社エンジニアの坂本が登壇します。オープンソースのプロジェクト管理ソフトウェア「Redmine」の脆弱性診断をRubyとSeleniumで自動化したことを発表します。
RedMica 1.2 バージョンアップのお知らせ
My Redmineで提供しているソフトウェアをRedMica 1.1からRedMica 1.2へバージョンアップいたします。
「RedMica 1.2」リリース Redmine互換のプロジェクト管理ソフトウェア(ファーエンドテクノロジー版Redmine)
Redmine 4.2の新機能を先行して利用できるRedMica 1.2 (2020-11) をリリースしました。
ファーエンドテクノロジー代表の前田剛が「Ruby Prize 2020」の候補者に推薦
Ruby Prize 2020にファーエンドテクノロジーの前田剛(Redmineコミッター)を候補者として推薦して頂きました。
Redmineの最新情報をメールでお知らせする「Redmine News」配信中
新バージョンやセキュリティ修正のリリース情報、そのほか最新情報を迅速にお届け