Durable Functions では、IDurableOrchestrationContext .CreateTimer を使うことで、関数の実行中に任意の時間待機できる。
大人の事情により、処理の途中で 2 時間待機する必要があったけど、Durable Functions のおかげでシンプルに実装できた。
using System; using System.Collections.Generic; using System.Data.Common; using System.Net.Http; using System.Threading.Tasks; using Microsoft.Azure.WebJobs; using Microsoft.Azure.WebJobs.Extensions.DurableTask; using Microsoft.Azure.WebJobs.Extensions.Http; namespace SampleFunctions { // 処理途中で 2 時間待機する Durable Function public sealed class SampleDurableFunction { [FunctionName(nameof(SampleDurableFunction) + "_" + nameof(HttpStart))] public async Task<HttpResponseMessage> HttpStart( [HttpTrigger(AuthorizationLevel.Function, methods: "delete", Route = "tenants/{tenantId}")] HttpRequestMessage req, [DurableClient] IDurableOrchestrationClient starter, string tenantId) { var instanceId = await starter.StartNewAsync( nameof(SampleDurableFunction), input: tenantId); return starter.CreateCheckStatusResponse(req, instanceId); } [FunctionName(nameof(SampleDurableFunction))] public async Task RunOrchestrator( [OrchestrationTrigger] IDurableOrchestrationContext context) { var tenantId = context.GetInput<string>(); var retryOptions = new RetryOptions( firstRetryInterval: TimeSpan.FromSeconds(5), maxNumberOfAttempts: 3); // テナントのデータベースの一覧を取得 var databaseNames = await context.CallActivityWithRetryAsync<string[]>( functionName: nameof(SampleDurableFunction) + "_" + nameof(GetTenantDatabaseNames), retryOptions: retryOptions, input: tenantId); // テナント情報を削除 await context.CallActivityWithRetryAsync<string>( functionName: nameof(SampleDurableFunction) + "_" + nameof(DeleteTenant), retryOptions: retryOptions, input: tenantId); // 大人の事情で 2 時間待機 var deadline = context.CurrentUtcDateTime.AddHours(2); await context.CreateTimer(deadline, System.Threading.CancellationToken.None); // 2 時間待機した後、データベースを消す foreach (var databaseName in databaseNames) { await context.CallActivityWithRetryAsync( functionName: nameof(SampleDurableFunction) + "_" + nameof(DropTenantDatabase), retryOptions: retryOptions, input: databaseName); } } // テナントのデータベース名一覧を取得 [FunctionName(nameof(SampleDurableFunction) + "_" + nameof(GetTenantDatabaseNames))] public async Task<string[]> GetTenantDatabaseNames([ActivityTrigger] string tenantId) { // テナントのデータベースの一覧を取得する処理(省略) } // テナントを削除 [FunctionName(nameof(SampleDurableFunction) + "_" + nameof(DeleteTenant))] public async Task DeleteTenant([ActivityTrigger] string tenantId) { // データベースからテナントの情報を削除する処理(省略) } // テナントのデータベースを削除 [FunctionName(nameof(SampleDurableFunction) + "_" + nameof(DropTenantDatabase))] public async Task DropTenantDatabase([ActivityTrigger] string databaseName) { // データベースを削除する処理(省略) } } }