このエントリは2023/05/13現在の情報に基づいています。将来の機能追加や変更に伴い、記載内容からの乖離が発生する可能性があります。
前回とは違う人から、以下のような質問をもらった。
問い合わせ
現在Logic Appsでとある処理をする仕組みを構築中なのだが、Javaにおけるtry-catch-finallyのように、tryブロック内で例外が発生した場合にはcatchブロックで処理をし、そのあとfinallyブロックで後始末をさせるようにしたい。そのようなことは可能か?
なんとも微妙な表現だが、ブロック単位で処理をして、ブロック内で例外が出たら別のブロックで補正をした上で、後始末のブロックを呼び出したい、とのことらしい。
Scopeの利用
Logic Appsにはスコープ (Scope) というものがあり、Consumption、Standardの両SKUで利用可能。
Azure Logic Apps でスコープを使用してグループの状態に基づいてアクションを実行する / Run actions based on group status by using scopes in Azure Logic Apps
https://learn.microsoft.com/azure/logic-apps/logic-apps-control-flow-run-steps-group-scopes
このScopeに対して実行条件を設定することで、成功時・失敗時などによってブロックを呼び出す・呼び出さないの制御ができる。
Azure Logic Apps におけるエラーと例外の処理 / Handle errors and exceptions in Azure Logic Apps
https://learn.microsoft.com/azure/logic-apps/logic-apps-exception-handling
実行条件
各アクションの実行結果は以下の4種類に分類されるが、後続アクションは前のアクションの結果に基づいて実行を制御できる。制御はrunAfter
プロパティに設定することで行う。
Succeeded
Failed
Skipped
TimedOut
“実行条件” の動作を管理する / Manage the “run after” behavior
https://learn.microsoft.com/azure/logic-apps/logic-apps-exception-handling#manage-the-run-after-behavior
実行条件を設定すると、アクションに緑(成功時、デザイナーで作成した場合のデフォルト設定)、橙(タイムアウト時)、赤(失敗時)、灰(スキップ時)の4色のマークがつく。何もついていない場合は緑(成功時)が設定されていると読み替えてよい。
この実行条件は各アクションだけでなく、スコープに対しても設定できる。そのため、tryブロックに相当するスコープ、catchブロックに相当するスコープ、finallyブロックに相当するスコープをそれぞれ作成し、条件を設定すればいい。
以下の例は、tryスコープで失敗時に実行する、と条件設定した場合。スコープには下図右のように赤い丸がついている。


スコープの成功・失敗とは
スコープの成功・失敗は、最後に実行されたアクションの成功・失敗によって決まる。
下図左のような場合、すべて首尾よく成功すれば当然成功ではあるが、例えばSet_divというアクションでゼロ除算が発生した場合、Set_mulというアクションはスキップされるので、この場合Set_divの結果がtryスコープの結果として扱われる(ゼロ除算時でtryスコープは失敗)。
下図右の場合、各アクションは成功時および失敗時に動作するよう実行条件が設定されている。このような場合、Set_divというアクションでゼロ除算が発生したとしても、Set_mulが実行されるため、Set_mulの実行結果がtryスコープの結果として扱われる(ゼロ除算時にも成功する可能性がある)ので、注意が必要。
スコープとその結果を使用してアクションを評価する / Evaluate actions with scopes and their results
https://learn.microsoft.com/azure/logic-apps/logic-apps-exception-handling#evaluate-actions-with-scopes-and-their-results


スコープのどのアクションで失敗したのかを把握したい
スコープに複数のアクションがある場合、例外が発生したアクションを把握するには、@result('scope')
で結果を取得できる。
@result('scope')
https://learn.microsoft.com/azure/logic-apps/workflow-definition-language-functions-reference#result
スコープは複数のアクションを配置できるため、result関数は配列を返す。結果の取得方法などの詳細は以下。
エラーのコンテキストと結果を取得する / Get context and results for failures
https://learn.microsoft.com/azure/logic-apps/logic-apps-exception-handling#get-context-and-results-for-failures
ケーススタディ
2個の数値を渡し、その数値を加減乗除した結果を返す、というシンプルなフローを考える。除数がゼロの場合、ゼロ除算になって例外が発生するので、エラーの理由を付けて応答を返し、例外が発生しなければ、そのまま結果を返すようにしたい。具体的には、以下のような動作を期待している。


スコープの作成とアクションの追加
ブロックを構成するために、スコープを作成する。その中にアクションを入れていく(下図左)。今回は簡単に加減乗除ではあるが、もちろんその他のアクションも追加できる。なお、実行条件によっては、下図右のようなフローも作成できるが、今回はシンプルに左側(成功時のみ後続アクションを実行)の構成にする。


フローの作成自体は特に変わったことはない。catchスコープはtryスコープが失敗時に動作するように構成しておく。下図では、Set_result (normal) というアクションはtryスコープが成功時に動作する。

最後、HTTPリクエストに対するレスポンスを返すアクションをfinallyブロックに相当するようなアクションとして構成する。
【注意】
runAfter
プロパティは、アクションもしくはスコープ内ではOR条件だが、複数アクションもしくはスコープを設定している場合はAND条件として取り扱われる。
以下の例だと、Responseアクションでは成功時とスキップ時を含めている。これは、tryスコープの実行結果如何で下表のように動作するアクションやスコープが変わる。
tryスコープ | Set_result (normal) | catch |
---|---|---|
成功時 | 実行 | スキップ |
失敗時 | スキップ | 実行 |
Responseアクションは、いずれの実行結果にも対応する必要があるので、
- Set_result (normal) アクションは成功もしくはスキップ
- catchスコープは成功もしくはスキップ
するときに動作するように実行条件を設定しなければならない。

もし上の例でResponseアクションの実行条件からスキップ時を省くと、例えば正常実行フローでSet_result (normal) アクションが動作した後、Responseアクションは動作しない。これはcatchスコープ由来の実行条件を満たさないために実行がスキップされるため。
実行履歴を確認すると、以下のようにスキップされた理由を確認できる。

実行フローは以下のように見える。
