当Azure Durable Function实例表状态为Failed时,如何触发函数写入Azure SQL DB
实现Durable Function失败状态触发SQL写入的方案
方案一:在Durable编排流程内主动发送失败消息到队列(推荐)
这种方式不需要依赖存储表监听,直接在编排函数中捕获失败,将数据发送到队列,再由队列触发函数写入SQL,实时性和可靠性更优。
步骤1:在编排函数中捕获失败并调用辅助Activity发送队列消息
编排函数本身无法直接使用队列输出绑定,需封装专门的Activity函数处理队列消息发送:
[FunctionName("MyOrchestrator")] public static async Task RunOrchestrator( [OrchestrationTrigger] IDurableOrchestrationContext context) { try { // 执行你的业务Activity逻辑 await context.CallActivityAsync("YourBusinessActivity", null); } catch (Exception ex) { // 构造包含失败详情的消息对象 var failureDetails = new { InstanceId = context.InstanceId, RuntimeStatus = "Failed", FailureReason = ex.Message, OccurredAt = DateTime.UtcNow }; // 调用Activity发送队列消息 await context.CallActivityAsync("SendFailureToQueue", failureDetails); } } [FunctionName("SendFailureToQueue")] public static void SendFailureToQueue( [ActivityTrigger] dynamic failureDetails, [Queue("durable-failure-events")] ICollector<string> queueCollector) { // 将消息序列化为JSON字符串存入队列 string jsonMsg = JsonConvert.SerializeObject(failureDetails); queueCollector.Add(jsonMsg); }
步骤2:创建队列触发函数写入Azure SQL DB
用QueueTrigger绑定目标队列,读取消息后直接插入SQL:
[FunctionName("WriteFailureToSql")] public static void Run( [QueueTrigger("durable-failure-events")] string queueMsg, [Sql("INSERT INTO DurableFunctionFailures (InstanceId, RuntimeStatus, FailureReason, OccurredAt) VALUES (@InstanceId, @RuntimeStatus, @FailureReason, @OccurredAt)", ConnectionStringSetting = "AzureSqlConnection")] out dynamic sqlData) { // 反序列化队列消息 var failureData = JsonConvert.DeserializeObject<dynamic>(queueMsg); // 构造SQL插入数据 sqlData = new { InstanceId = failureData.InstanceId, RuntimeStatus = failureData.RuntimeStatus, FailureReason = failureData.FailureReason, OccurredAt = failureData.OccurredAt }; }
方案二:监听Durable实例表的失败状态(适合无法修改现有编排代码的场景)
如果不能改动现有Durable编排逻辑,可使用Table触发器监听默认实例表(表名默认是DurableFunctionsHubInstances),过滤出状态为Failed的实体。
实现代码
[FunctionName("MonitorDurableFailuresFromTable")] public static void Run( [TableTrigger("DurableFunctionsHubInstances", Filter = "RuntimeStatus eq 'Failed'")] DurableInstanceEntity tableEntity, [Sql("INSERT INTO DurableFunctionFailures (InstanceId, RuntimeStatus, FailureReason, OccurredAt) VALUES (@InstanceId, @RuntimeStatus, @FailureReason, @OccurredAt)", ConnectionStringSetting = "AzureSqlConnection")] out dynamic sqlData) { // 从表实体提取数据(Durable实例表的RowKey即为InstanceId) sqlData = new { InstanceId = tableEntity.RowKey, RuntimeStatus = tableEntity.RuntimeStatus, FailureReason = tableEntity.Output, // 失败详情通常存于Output字段 OccurredAt = tableEntity.Timestamp }; } // 对应Durable实例表的实体类 public class DurableInstanceEntity { public string PartitionKey { get; set; } public string RowKey { get; set; } public DateTime Timestamp { get; set; } public string RuntimeStatus { get; set; } public string Output { get; set; } }
注意事项
- Table触发器为轮询模式,默认间隔1分钟,存在一定延迟;可在host.json中调整轮询频率,但过于频繁会增加存储成本。
- 需确保函数拥有存储表的读取权限,建议使用系统分配的托管身份授权。
通用注意点
- 幂等性处理:SQL插入时建议给InstanceId添加唯一性约束,避免重复写入相同失败记录。
- 连接配置:将存储账户和SQL DB的连接字符串添加到Function App的应用设置中,禁止硬编码。
- 消息序列化:确保队列消息的序列化/反序列化逻辑一致,避免解析错误。
内容的提问来源于stack exchange,提问作者Sri Azure
相关产品推荐
相关产品推荐

