4

新しい Servicebus キュー メッセージでトリガーする Azure Durable Functions アプリを開発しました。エラーが発生しない場合は問題なく動作しますが、アクティビティ関数でエラーが発生した場合は、失敗したことをログに記録しますが、メッセージはキューから永久に削除されます。何が原因で、メッセージがエラーでキューから消えないようにするにはどうすればよいですか?

これは再現可能なコードです。VS2017 の新しい Azure 関数テンプレートから生成されたコードです。都市が "Seattle" の場合にのみ例外が追加され、HttpTrigger ではなく ServicebusTrigger です。

            [FunctionName("Test")]
    public static async Task<List<string>> RunOrchestrator(
        [OrchestrationTrigger] DurableOrchestrationContext context)
    {
        var outputs = new List<string>();

        // Replace "hello" with the name of your Durable Activity Function.
        outputs.Add(await context.CallActivityAsync<string>("Test_Hello", "Tokyo"));
        outputs.Add(await context.CallActivityAsync<string>("Test_Hello", "Seattle"));
        outputs.Add(await context.CallActivityAsync<string>("Test_Hello", "London"));

        // returns ["Hello Tokyo!", "Hello Seattle!", "Hello London!"]
        return outputs;
    }

    [FunctionName("Test_Hello")]
    public static string SayHello([ActivityTrigger] string name, ILogger log)
    {
        log.LogInformation($"Saying hello to {name}.");
        if (name == "Seattle")
            throw new Exception("An error occurs");
        return $"Hello {name}!";
    }

    [FunctionName("Test_HttpStart")]
    public static async Task ServiceBusStart(
        [ServiceBusTrigger("somequeue", Connection = "ServiceBusQueueListenerConnectionString")]string queuemsg,
        [OrchestrationClient]DurableOrchestrationClient starter,
        ILogger log)
    {
        // Function input comes from the request content.
        var msg = JsonConvert.DeserializeObject<IncomingMessage>(queuemsg);
        string instanceId = await starter.StartNewAsync("Test", msg);
        log.LogInformation($"Started orchestration with ID = '{instanceId}'.");
    }

更新: オーケストレーション クライアント関数に例外がある場合、再試行が x 回失敗した場合、再試行してデッド レター キューにメッセージを入れるなど、正しいことを行います。

そのため、このwhileループでクライアント関数を更新し、失敗/終了/キャンセルのステータスをチェックすることで、これを回避することができました。

    [FunctionName("Test_HttpStart")]
    public static async Task ServiceBusStart(
        [ServiceBusTrigger("somequeue", Connection = "ServiceBusQueueListenerConnectionString")]string queuemsg,
        [OrchestrationClient]DurableOrchestrationClient starter,
        ILogger log)
    {
        // Function input comes from the request content.
        var msg = JsonConvert.DeserializeObject<IncomingMessage>(queuemsg);
        string instanceId = await starter.StartNewAsync("Test", msg);
        log.LogInformation($"Started orchestration with ID = '{instanceId}'.");

        var status = await starter.GetStatusAsync(instanceId);

        while (status.RuntimeStatus != OrchestrationRuntimeStatus.Completed)
        {
            System.Threading.Thread.Sleep(1000);
            status = await starter.GetStatusAsync(instanceId);
            if (status.RuntimeStatus == OrchestrationRuntimeStatus.Failed 
                || status.RuntimeStatus == OrchestrationRuntimeStatus.Terminated
                || status.RuntimeStatus == OrchestrationRuntimeStatus.Canceled)
            {
                throw new Exception("Orchestration failed with error: " + status.Output);
            }
        }

    }

しかし、私にはハックのように思えます。このタイプのコードは、MS のサンプル コードでは見たことがありません。これは、Durable Functions フレームワークで処理する必要があると思います。servicebus トリガーを耐久性のある関数で機能させる別の方法はありますか?

4

2 に答える 2