Azure Durable FunctionsのFunctions Chainingを試してみたので記載していきます。
試した内容はDurable Fuctionsの公式にサイトにあるSamplesとWalkthrouthsの内容です。
Azure Durable Functionsのローカル実行環境を構築していない人は下記を参照してください。
本記事はローカル実行環境が構築済みであることを前提とします。
※本記事は2017年7月25日時点の情報となります。
Function Chaining 基本編
Function Chainingとは特定の順序で分散している関数を順次実行していくパターンです。
下記の図を見るとイメージしやすいかと思いますが1回のトリガーでF1 → F2 → F3 → F4と関数を順次実行していくイメージです。
今までは分散している関数をトリガー別に順次呼び出す必要がありましたが、 orchestrator functionを利用することで関数をまとめて実行することができるようになりました。
公式サイトにあるサンプルソース(VSSample)の中身を見ていきましょう。
サンプルソースにあるHelloSequesnce.csがFunction Chainingのサンプルになります。
このソース内にはE1_HelloSequenceというorchestrator functionとE1_SayHelloという関数が用意されています。
実行時に呼び出すのはE1_HelloSequenceになります、E1_HelloSequenceを呼び出すとE1_SayHelloを非同期で順次呼び出して最終的に値を返すというものです。
public static class HelloSequence
{
[FunctionName("E1_HelloSequence")]
public static async Task<List<string>> Run([OrchestrationTrigger] DurableOrchestrationContext context)
{
var outputs = new List<string>();
outputs.Add(await context.CallFunctionAsync<string>("E1_SayHello", "Tokyo"));
outputs.Add(await context.CallFunctionAsync<string>("E1_SayHello", "Seattle"));
outputs.Add(await context.CallFunctionAsync<string>("E1_SayHello", "London"));
return outputs;
}
[FunctionName("E1_SayHello")]
public static string SayHello([ActivityTrigger] DurableActivityContext helloContext)
{
string name = helloContext.GetInput<string>();
return $"Hello {name}!";
}
}
それではローカル実行して試してみましょう。VS2017でFunctionsを実行してポストマンを起動して下記のURLをPOSTして呼び出します。
POSTして正常に処理が完了するとレスポンスとして3つのURLが返却されます。
- statusQueryGetUri
- sendEventPostUri
- terminatePostUri
サンプルサイトではstatusQueryGetUriしか利用していません。statusQueryGetUriは状態を確認するためのURLでGETで叩くと処理状況を確認することができます。orchestrators/E1_HelloSequenceはorchetratorsのキューを追加し状態確認用のURLを返却します。キューが追加されると非同期でE1_HelloSequenceが実行されるので状態を確認用URLで状況と結果を確認するわけです。
状態確認用のURLをGETで叩いてみると処理結果を確認することができます。E1_SayHelloが3回呼び出されてそれぞれに処理が行われて返却されていることが確認できます。これは
sendEventPostUriとterminatePostUriはStateful SingletonパターンやHuman Interactパターンで利用します。ここでは利用しないのでスルーしてください。
Function Chaining 応用編
基本編では1回のトリガーで1つのFunctionを複数回呼ぶ処理になっていました。少しいじって2つのFunctionを交互に呼ぶように変更してみましょう。
E1_SayHello_PreとE1_SayHello_Sufという関数を追加してみました。E1_SayHello_PreはHelloの前に名前を付けて返します、E1_SayHello_Sufは従来どおりHelloの後に名前を付けて返す関数です。それをE1_HelloSequenceから交互に呼び出すようにしてみました。
public static class HelloSequence
{
[FunctionName("E1_HelloSequence")]
public static async Task<List<string>> Run([OrchestrationTrigger] DurableOrchestrationContext context)
{
var outputs = new List<string>();
outputs.Add(await context.CallFunctionAsync<string>("E1_SayHello_Pre", "Tokyo"));
outputs.Add(await context.CallFunctionAsync<string>("E1_SayHello_Suf", "Seattle"));
outputs.Add(await context.CallFunctionAsync<string>("E1_SayHello_Pre", "London"));
outputs.Add(await context.CallFunctionAsync<string>("E1_SayHello_Suf", "Tokyo"));
outputs.Add(await context.CallFunctionAsync<string>("E1_SayHello_Pre", "Seattle"));
outputs.Add(await context.CallFunctionAsync<string>("E1_SayHello_Suf", "London"));
return outputs;
}
[FunctionName("E1_SayHello_Pre")]
public static string SayHello_Prefix([ActivityTrigger] DurableActivityContext helloContext)
{
string name = helloContext.GetInput<string>();
return $"{name}! Hello";
}
[FunctionName("E1_SayHello_Suf")]
public static string SayHello_Suffix([ActivityTrigger] DurableActivityContext helloContext)
{
string name = helloContext.GetInput<string>();
return $"Hello {name}!";
}
}
ポストマンで実行して試してみましょう。URLは基本編と同じです。
処理結果を見れば交互に関数が実行されているのがわかると思います。
複数のFunctionを一回のトリガーで実行できるようになったため、Functionを最小単位で開発して必要なものを組み合わせて一つの処理を実現することができるようになりました。さしずめOrchestrators FunctionはMainメソッドでそこから各種Functionを呼び出すという従来からある形を体現しているのだと思います。
コメント