From cb4637fe19daae6189561418ad12a68e4fef86ba Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Mon, 18 Sep 2023 15:56:38 +0200 Subject: [PATCH] Add timeout outcome to SendHttpRequest activities Issue #4456 --- .../Elsa.Http/Activities/FlowSendHttpRequest.cs | 8 +++++++- src/modules/Elsa.Http/Activities/SendHttpRequest.cs | 11 +++++++++++ .../Elsa.Http/Activities/SendHttpRequestBase.cs | 7 +++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/modules/Elsa.Http/Activities/FlowSendHttpRequest.cs b/src/modules/Elsa.Http/Activities/FlowSendHttpRequest.cs index afc2ce4d3..1a9158378 100644 --- a/src/modules/Elsa.Http/Activities/FlowSendHttpRequest.cs +++ b/src/modules/Elsa.Http/Activities/FlowSendHttpRequest.cs @@ -42,11 +42,17 @@ public class FlowSendHttpRequest : SendHttpRequestBase await context.CompleteActivityWithOutcomesAsync("Failed to connect"); } + /// + protected override async ValueTask HandleTaskCanceledExceptionAsync(ActivityExecutionContext context, TaskCanceledException exception) + { + await context.CompleteActivityWithOutcomesAsync("Timeout"); + } + private static ValueTask> GetExpectedStatusCodesOptionsAsync(PropertyInfo property, CancellationToken cancellationToken = default) { var options = new Dictionary { - [nameof(DynamicOutcomesOptions)] = new DynamicOutcomesOptions(new[]{"Unmatched status code", "Failed to connect", "Done"}) + [nameof(DynamicOutcomesOptions)] = new DynamicOutcomesOptions(new[]{"Unmatched status code", "Failed to connect", "Timeout", "Done"}) }; return new(options); diff --git a/src/modules/Elsa.Http/Activities/SendHttpRequest.cs b/src/modules/Elsa.Http/Activities/SendHttpRequest.cs index eacbd0834..40c3a0a92 100644 --- a/src/modules/Elsa.Http/Activities/SendHttpRequest.cs +++ b/src/modules/Elsa.Http/Activities/SendHttpRequest.cs @@ -37,6 +37,11 @@ public class SendHttpRequest : SendHttpRequestBase /// The activity to execute when the HTTP request fails to connect. /// public IActivity? FailedToConnect { get; set; } + + /// + /// The activity to execute when the HTTP request times out. + /// + public IActivity? Timeout { get; set; } /// protected override async ValueTask HandleResponseAsync(ActivityExecutionContext context, HttpResponseMessage response) @@ -55,6 +60,12 @@ public class SendHttpRequest : SendHttpRequestBase await context.ScheduleActivityAsync(FailedToConnect, OnChildActivityCompletedAsync); } + /// + protected override async ValueTask HandleTaskCanceledExceptionAsync(ActivityExecutionContext context, TaskCanceledException exception) + { + await context.ScheduleActivityAsync(Timeout, OnChildActivityCompletedAsync); + } + private async ValueTask OnChildActivityCompletedAsync(ActivityCompletedContext context) { await context.TargetContext.CompleteActivityAsync(); diff --git a/src/modules/Elsa.Http/Activities/SendHttpRequestBase.cs b/src/modules/Elsa.Http/Activities/SendHttpRequestBase.cs index b24161e83..ad7fc90d0 100644 --- a/src/modules/Elsa.Http/Activities/SendHttpRequestBase.cs +++ b/src/modules/Elsa.Http/Activities/SendHttpRequestBase.cs @@ -88,6 +88,11 @@ public abstract class SendHttpRequestBase : Activity /// Handles an exception that occurred while sending the request. /// protected abstract ValueTask HandleRequestExceptionAsync(ActivityExecutionContext context, HttpRequestException exception); + + /// + /// Handles that occurred while sending the request. + /// + protected abstract ValueTask HandleTaskCanceledExceptionAsync(ActivityExecutionContext context, TaskCanceledException exception); private async Task TrySendAsync(ActivityExecutionContext context) { @@ -113,7 +118,9 @@ public abstract class SendHttpRequestBase : Activity } catch (TaskCanceledException e) { + context.AddExecutionLogEntry("Error", e.Message, payload: new { StackTrace = e.StackTrace }); context.JournalData.Add("Cancelled", true); + await HandleTaskCanceledExceptionAsync(context, e); } }