しばやん雑記

Azure とメイドさんが大好きなフリーランスのプログラマーのブログ

AWS Lambda で C# を使って SendGrid の Event Webhook を受信する処理を書いた

AWS Lambda が C# に対応したと聞いたので、Visual Studio を使って試してみることにします。

そして今日は SendGrid Advent Calendar の担当日でもあるので、ありがちですが Event Webhook を受け取る処理を書いてみます。まずは Lambda の C# 対応については公式ブログを。

Announcing C# Support for AWS Lambda | AWS Compute Blog

AWS Toolkit for Visual Studio がアップデートされたらしいので、Lambda Function は Visual Studio を使って作成していくことにします。

インストールするとプロジェクトテンプレートが追加されるのでわかりやすいですね。

f:id:shiba-yan:20161202142854p:plain

Serverless Application も気になりますが、とりあえず AWS Lambda Project を選びます。

作成されたプロジェクトの構造はシンプルです。普通の .NET Core コンソールアプリケーションをデプロイする形になるみたいです。この辺りは Azure Functions とは異なりますね。

f:id:shiba-yan:20161202143240p:plain

Lambda Project が用意できたので、実際に Event Webhook を処理するためのコードを書いていきます。Event Webhook から送信されてくる JSON の構造はドキュメントの通りです。

Event Webhook - SendGrid Documentation | SendGrid

JSON はクラスにマッピングしますが、LambdaSerializer が input というパラメータに対してデシリアライズを自動で行ってくれるようなので、かなりすっきりと書くことが出来ました。

本来なら DynamoDB などに入れると思いますが、今回はログにデータを書き出すだけにしておきました。

using Amazon.Lambda.Core;

using Newtonsoft.Json;

[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))]

namespace AWSLambda1
{
    public class Function
    {
        public string FunctionHandler(EventWebhookData[] input, ILambdaContext context)
        {
            foreach (var data in input)
            {
                context.Logger.LogLine($"{data.Email} - {data.Event}");
            }

            return "OK";
        }
    }
    
    public class EventWebhookData
    {
        [JsonProperty("sg_message_id")]
        public string SgMessageId { get; set; }

        [JsonProperty("email")]
        public string Email { get; set; }

        [JsonProperty("timestamp")]
        public long Timestamp { get; set; }

        [JsonProperty("smtpid")]
        public string SmtpId { get; set; }

        [JsonProperty("event")]
        public string Event { get; set; }
    }
}

JsonSerializer は JSON.NET を使っているので、プロパティに別名を付けることが出来ます。

これで Lambda Function の実装は終わったので AWS にデプロイします。事前に認証情報の作成が必要ですが、Web アプリケーションなどと同様にプロジェクト右クリックメニューからデプロイが行えます。

f:id:shiba-yan:20161202143504p:plain

ダイアログでは Lambda Function の名前や .NET Core のランタイム設定などを行います。作成時にエントリポイント周りは自動的に設定されるので、そんなに手間はかかりません。

これでデプロイを実行すると Lambda リソースが作成されます。

f:id:shiba-yan:20161202144221p:plain

Webhook として Lambda を実行するには API Gateway を使う必要がありますが、この辺りは本質的な部分ではないので省略します。適当に POST でリソースを追加するだけで問題ないです。

API Gateway を作成すれば、あとは SendGrid の設定から作成した URL を設定するだけです。

f:id:shiba-yan:20161202163409p:plain

この設定画面からはテスト送信が行えるようになっているので、試しに実行しておきます。少しタイムラグはありますが、数秒後には送信が行われるはずです。

Lambda の実行ログを CloudWatch から確認します。

f:id:shiba-yan:20161202163239p:plain

テストデータを正しくパースしてログに書き出していることが確認できました。気になる実行時間は初回はやはり少し時間がかかりましたが、2 回目以降はかなり高速に処理されていました。

Azure Functions と AWS Lambda の両方で C# が使えるようになりましたが、Azure Functions は .NET Framework 4.6.2 なのに対して、AWS Lambda は .NET Core 1.0 と違いがあります。

利用できるライブラリに差が出てくるので、少し注意したいです。