From a8b3cbab749239b79aed93e41a8ee843e11244e9 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Sun, 10 Sep 2023 21:31:57 +0200 Subject: [PATCH] Add request exception handling to SendHttpRequest activity --- .../Elsa.Http/Activities/FlowSendHttpRequest.cs | 8 +++++++- .../Elsa.Http/Activities/SendHttpRequest.cs | 17 +++++++++++------ .../Elsa.Http/Activities/SendHttpRequestBase.cs | 11 +++++++++++ 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/modules/Elsa.Http/Activities/FlowSendHttpRequest.cs b/src/modules/Elsa.Http/Activities/FlowSendHttpRequest.cs index 017a87803..afc2ce4d3 100644 --- a/src/modules/Elsa.Http/Activities/FlowSendHttpRequest.cs +++ b/src/modules/Elsa.Http/Activities/FlowSendHttpRequest.cs @@ -36,11 +36,17 @@ public class FlowSendHttpRequest : SendHttpRequestBase await context.CompleteActivityWithOutcomesAsync(outcome); } + /// + protected override async ValueTask HandleRequestExceptionAsync(ActivityExecutionContext context, HttpRequestException exception) + { + await context.CompleteActivityWithOutcomesAsync("Failed to connect"); + } + private static ValueTask> GetExpectedStatusCodesOptionsAsync(PropertyInfo property, CancellationToken cancellationToken = default) { var options = new Dictionary { - [nameof(DynamicOutcomesOptions)] = new DynamicOutcomesOptions(new[]{"Unmatched status code", "Done"}) + [nameof(DynamicOutcomesOptions)] = new DynamicOutcomesOptions(new[]{"Unmatched status code", "Failed to connect", "Done"}) }; return new(options); diff --git a/src/modules/Elsa.Http/Activities/SendHttpRequest.cs b/src/modules/Elsa.Http/Activities/SendHttpRequest.cs index cd966c245..eacbd0834 100644 --- a/src/modules/Elsa.Http/Activities/SendHttpRequest.cs +++ b/src/modules/Elsa.Http/Activities/SendHttpRequest.cs @@ -33,6 +33,11 @@ public class SendHttpRequest : SendHttpRequestBase [Port] public IActivity? UnmatchedStatusCode { get; set; } + /// + /// The activity to execute when the HTTP request fails to connect. + /// + public IActivity? FailedToConnect { get; set; } + /// protected override async ValueTask HandleResponseAsync(ActivityExecutionContext context, HttpResponseMessage response) { @@ -41,15 +46,15 @@ public class SendHttpRequest : SendHttpRequestBase var matchingCase = expectedStatusCodes.FirstOrDefault(x => x.StatusCode == statusCode); var activity = matchingCase != null ? matchingCase.Activity : UnmatchedStatusCode; - if (activity == null) - { - await context.CompleteActivityAsync(); - return; - } - await context.ScheduleActivityAsync(activity, OnChildActivityCompletedAsync); } + /// + protected override async ValueTask HandleRequestExceptionAsync(ActivityExecutionContext context, HttpRequestException exception) + { + await context.ScheduleActivityAsync(FailedToConnect, 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 59c5a5df2..b24161e83 100644 --- a/src/modules/Elsa.Http/Activities/SendHttpRequestBase.cs +++ b/src/modules/Elsa.Http/Activities/SendHttpRequestBase.cs @@ -84,6 +84,11 @@ public abstract class SendHttpRequestBase : Activity /// protected abstract ValueTask HandleResponseAsync(ActivityExecutionContext context, HttpResponseMessage response); + /// + /// Handles an exception that occurred while sending the request. + /// + protected abstract ValueTask HandleRequestExceptionAsync(ActivityExecutionContext context, HttpRequestException exception); + private async Task TrySendAsync(ActivityExecutionContext context) { var request = PrepareRequest(context); @@ -100,6 +105,12 @@ public abstract class SendHttpRequestBase : Activity await HandleResponseAsync(context, response); } + catch(HttpRequestException e) + { + context.AddExecutionLogEntry("Error", e.Message, payload: new { StackTrace = e.StackTrace }); + context.JournalData.Add("Error", e.Message); + await HandleRequestExceptionAsync(context, e); + } catch (TaskCanceledException e) { context.JournalData.Add("Cancelled", true);