眠いしお腹すいたし(´・ω・`)

C#関連を主に書きます。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

Azure Functionsのカスタムトリガーの作り方を調べてみた

ちょっと前にカスタムの出力バインディングの作り方

tamafuyou.hatenablog.com

を調べたのですが、今回は独自なカスタムのトリガーの作成方法を調べて見ました。

今回の成果物はこちら

github.com

今回参考にしたサイトはこちら

GitHub - Azure/azure-webjobs-sdk: Azure WebJobs SDK

それでは早速

今回はSlackのReal Time Messaging API

api.slack.com

を用いてSlackでメッセージを書き込んだらファンクションが実行されるトリガーの作成を行いました。

Slackでこういう事をする場合にはOutgoing WebHooksを使うのが普通ですが今回はトリガーの学習なのでRTMを使ってみました。

RTMはWebSocketを使用したリアルタイムAPIなのですが、これまで実装するとなるとちょっとめんどくさいので今回はSlackConnectorというライブラリを使用しました。

www.nuget.org

この辺を見てもらえればわかるかと思います。

それでは解説ヾ(`・ω・´)ノ

作るべきクラス

作るべきクラスは以下

  • IExtensionConfigProviderの実装クラス
  • ITriggerBindingProviderの実装クラス
  • ITriggerBindingの実装クラス
  • IListenerの実装クラス
  • パラメータ用のArributeクラス

になります。

Attributeクラス

実装はSlackMessageTriggerAttributeクラスです。

SampleProjects/SlackMessageTriggerAttribute.cs at master · yuka1984/SampleProjects · GitHub

本当にシンプルで十分です。パラメータに付けるためのAttributeでプロパティにAccessTokenを持たせています。このAccessTokenをキーに環境変数から値を引っ張って来てRTMへの接続に使用します。

IExtensionConfigProviderの実装クラス

実装はSlackMessageExtentionConfigクラスです。

SampleProjects/SlackMessageExtentionConfig.cs at master · yuka1984/SampleProjects · GitHub

このインターフェースの実装クラスのInitialize関数はFuncgionsのホストがスタートした時に呼び出されます。この関数内でITriggerBindingProviderを登録してあげる事でホストがファクションのパラメータバインディングを行う時に登録したProviderのTryCreateAsyncが呼び出される様になります。

ITriggerBindingProviderの実装クラス

実装クラスはSlackMessageTriggerAttributeBindingProviderです。

SampleProjects/SlackMessageTriggerAttributeBindingProvider.cs at master · yuka1984/SampleProjects · GitHub

先ほど説明した様にホストが関数を捜査してパラメータをバインディングする際にTryCreateAsync関数が呼び出されます。

gist.github.com

ですのでパラメータのAttributeが正しければITriggerBindingのインタンスを返してあげて関係ないAttributeであればnullを返してあげればOKです。

ITriggerBindingの実装クラス

実装はSlackMessageTriggerBindingクラスです。

SampleProjects/SlackMessageTriggerBinding.cs at master · yuka1984/SampleProjects · GitHub

このクラスの主な仕事はリスナークラスのインタンス生成とリスナーによってファンクションの実行が指示された際にリスナーからのデータを パラメータにバインドする事です。

gist.github.com

CreateListnerAsync関数は単純です。IListnerの実装を返してあげれば良いです。

gist.github.com

IListenerの実装クラス

実装クラスはSlackMessageListenerです。

SampleProjects/SlackMessageListener.cs at master · yuka1984/SampleProjects · GitHub

IListnerはStartAsync, StopAsync, Cancel, Disposeを実装する必要があります。

今回は単純に何も考えずStartAsyncでRTMへのコネクションを行いStopAsyncで切断を行なっています。

そして引数で受け取ったITriggeredFunctionExecuterのTryExecuteAsync関数をSlackメッセージを受信した際に実行しています。

TryExexuteAsync関数を実行するとTriggerBindingのBindAsync関数を経由してFunctionが実行される流れになります。

例えばServiceBusTriggerなどはTryExecuteAsync後に実行結果に応じて関数の実行が失敗していたらAbandonAsync、成功していたらCompleteAsyncを実行しています。なので関数実行後にキューが完了していたりするわけです。

実際にサンプルを実行すると

f:id:tamafuyou:20171029153028p:plain

f:id:tamafuyou:20171029153047p:plain

こんな感じで実行されたりします。

なお、今回の実装はあくまでもサンプルですので色々と抜けています。

インスタンスがスケールすると1つのメッセージで複数回ファンクションが実行されてしまいます。

ですのでこの感じの実装を使用する際にはSIngletonAttributeをリスナーモードで使用するか、それと同等の実装を行う必要があります。

Azure Functionsでトリガーが作れると夢が広がりますね

(ノ゚Д゚)八(゚Д゚ )ノイエーイ

ではでは