From dd2c14afe93df24eeb8e34986fd0ef3288c10603 Mon Sep 17 00:00:00 2001 From: axeleron007 Date: Thu, 16 Sep 2021 15:38:29 +0300 Subject: [PATCH] Faulted status added to Workflow Test --- .../Events/ActivityExecutionResultExecuted.cs | 2 +- .../Events/ActivityExecutionResultFailed.cs | 18 +++++ .../Services/Workflows/WorkflowRunner.cs | 69 +++++++++++-------- .../elsa-designer-tree/elsa-designer-tree.tsx | 17 ++++- .../elsa-workflow-properties-panel.tsx | 27 +++++++- .../src/models/domain.ts | 1 + .../ActivityExecutionResultExecutedHandler.cs | 19 ++++- .../Models/WorkflowTestMessage.cs | 1 + 8 files changed, 117 insertions(+), 37 deletions(-) create mode 100644 src/core/Elsa.Abstractions/Events/ActivityExecutionResultFailed.cs diff --git a/src/core/Elsa.Abstractions/Events/ActivityExecutionResultExecuted.cs b/src/core/Elsa.Abstractions/Events/ActivityExecutionResultExecuted.cs index 9a57eba9a..bdc44d37b 100644 --- a/src/core/Elsa.Abstractions/Events/ActivityExecutionResultExecuted.cs +++ b/src/core/Elsa.Abstractions/Events/ActivityExecutionResultExecuted.cs @@ -1,4 +1,4 @@ -using Elsa.ActivityResults; +using Elsa.ActivityResults; using Elsa.Services.Models; using MediatR; diff --git a/src/core/Elsa.Abstractions/Events/ActivityExecutionResultFailed.cs b/src/core/Elsa.Abstractions/Events/ActivityExecutionResultFailed.cs new file mode 100644 index 000000000..9d5d98dad --- /dev/null +++ b/src/core/Elsa.Abstractions/Events/ActivityExecutionResultFailed.cs @@ -0,0 +1,18 @@ +using System; +using Elsa.Services.Models; +using MediatR; + +namespace Elsa.Events +{ + public class ActivityExecutionResultFailed : INotification + { + public ActivityExecutionResultFailed(Exception exception, ActivityExecutionContext activityExecutionContext) + { + Exception = exception; + ActivityExecutionContext = activityExecutionContext; + } + + public Exception Exception { get; } + public ActivityExecutionContext ActivityExecutionContext { get; } + } +} \ No newline at end of file diff --git a/src/core/Elsa.Core/Services/Workflows/WorkflowRunner.cs b/src/core/Elsa.Core/Services/Workflows/WorkflowRunner.cs index cbaf61180..4d22587e2 100644 --- a/src/core/Elsa.Core/Services/Workflows/WorkflowRunner.cs +++ b/src/core/Elsa.Core/Services/Workflows/WorkflowRunner.cs @@ -250,39 +250,48 @@ namespace Elsa.Services.Workflows var output = outputReference != null ? await _workflowStorageService.LoadAsync(outputReference.ProviderName, new WorkflowStorageContext(workflowInstance, outputReference.ActivityId), "Output", cancellationToken) : null; var input = !burstStarted ? workflowExecutionContext.Input : scheduledActivity.Input ?? output; var activityExecutionContext = new ActivityExecutionContext(scope, workflowExecutionContext, activityBlueprint, input, resuming, cancellationToken); - var runtimeActivityInstance = await activityExecutionContext.ActivateActivityAsync(cancellationToken); - var activityType = runtimeActivityInstance.ActivityType; - using var executionScope = AmbientActivityExecutionContext.EnterScope(activityExecutionContext); - await _mediator.Publish(new ActivityActivating(activityExecutionContext), cancellationToken); - var activity = await activityType.ActivateAsync(activityExecutionContext); - if (!burstStarted) + try { - await _mediator.Publish(new WorkflowExecutionBurstStarting(workflowExecutionContext, activityExecutionContext), cancellationToken); - burstStarted = true; + var runtimeActivityInstance = await activityExecutionContext.ActivateActivityAsync(cancellationToken); + var activityType = runtimeActivityInstance.ActivityType; + using var executionScope = AmbientActivityExecutionContext.EnterScope(activityExecutionContext); + await _mediator.Publish(new ActivityActivating(activityExecutionContext), cancellationToken); + var activity = await activityType.ActivateAsync(activityExecutionContext); + + if (!burstStarted) + { + await _mediator.Publish(new WorkflowExecutionBurstStarting(workflowExecutionContext, activityExecutionContext), cancellationToken); + burstStarted = true; + } + + if (resuming) + await _mediator.Publish(new ActivityResuming(activityExecutionContext, activity), cancellationToken); + + await _mediator.Publish(new ActivityExecuting(activityExecutionContext, activity), cancellationToken); + var result = await TryExecuteActivityAsync(activityOperation, activityExecutionContext, activity, cancellationToken); + + if (result == null) + return; + + await _mediator.Publish(new ActivityExecuted(activityExecutionContext, activity), cancellationToken); + await _mediator.Publish(new ActivityExecutionResultExecuting(result, activityExecutionContext), cancellationToken); + await result.ExecuteAsync(activityExecutionContext, cancellationToken); + workflowExecutionContext.CompletePass(); + workflowInstance.LastExecutedActivityId = currentActivityId; + await _mediator.Publish(new ActivityExecutionResultExecuted(result, activityExecutionContext), cancellationToken); + await _mediator.Publish(new WorkflowExecutionPassCompleted(workflowExecutionContext, activityExecutionContext), cancellationToken); + + if (!workflowExecutionContext.HasScheduledActivities) + await _mediator.Publish(new WorkflowExecutionBurstCompleted(workflowExecutionContext, activityExecutionContext), cancellationToken); + + activityOperation = Execute; + } + catch (Exception e) + { + await _mediator.Publish(new ActivityExecutionResultFailed(e, activityExecutionContext), cancellationToken); + throw; } - - if (resuming) - await _mediator.Publish(new ActivityResuming(activityExecutionContext, activity), cancellationToken); - - await _mediator.Publish(new ActivityExecuting(activityExecutionContext, activity), cancellationToken); - var result = await TryExecuteActivityAsync(activityOperation, activityExecutionContext, activity, cancellationToken); - - if (result == null) - return; - - await _mediator.Publish(new ActivityExecuted(activityExecutionContext, activity), cancellationToken); - await _mediator.Publish(new ActivityExecutionResultExecuting(result, activityExecutionContext), cancellationToken); - await result.ExecuteAsync(activityExecutionContext, cancellationToken); - workflowExecutionContext.CompletePass(); - workflowInstance.LastExecutedActivityId = currentActivityId; - await _mediator.Publish(new ActivityExecutionResultExecuted(result, activityExecutionContext), cancellationToken); - await _mediator.Publish(new WorkflowExecutionPassCompleted(workflowExecutionContext, activityExecutionContext), cancellationToken); - - if (!workflowExecutionContext.HasScheduledActivities) - await _mediator.Publish(new WorkflowExecutionBurstCompleted(workflowExecutionContext, activityExecutionContext), cancellationToken); - - activityOperation = Execute; } workflowInstance.CurrentActivity = null; diff --git a/src/designer/elsa-workflows-studio/src/components/designers/tree/elsa-designer-tree/elsa-designer-tree.tsx b/src/designer/elsa-workflows-studio/src/components/designers/tree/elsa-designer-tree/elsa-designer-tree.tsx index c49d19136..b70340988 100644 --- a/src/designer/elsa-workflows-studio/src/components/designers/tree/elsa-designer-tree/elsa-designer-tree.tsx +++ b/src/designer/elsa-workflows-studio/src/components/designers/tree/elsa-designer-tree/elsa-designer-tree.tsx @@ -845,8 +845,21 @@ export class ElsaWorkflowDesigner { if (testActivityMessage == undefined) return ""; - const color = testActivityMessage.status == "Executed" ? "green" : "red"; - + let color = ""; + + switch (testActivityMessage.status) + { + case "Executed": + color = "green"; + break; + case "Suspended": + color = "yellow"; + break; + case "Failed": + color = "red"; + break; + } + return ` diff --git a/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-workflow-properties-panel/elsa-workflow-properties-panel.tsx b/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-workflow-properties-panel/elsa-workflow-properties-panel.tsx index 58d312782..5f9efa850 100644 --- a/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-workflow-properties-panel/elsa-workflow-properties-panel.tsx +++ b/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-workflow-properties-panel/elsa-workflow-properties-panel.tsx @@ -277,7 +277,7 @@ export class ElsaWorkflowPropertiesPanel { {t('ExecuteWorkflow')} - {this.renderActivityMessage()} + {this.renderActivityTestMessage()} @@ -285,7 +285,7 @@ export class ElsaWorkflowPropertiesPanel { } - renderActivityMessage() { + renderActivityTestMessage() { const {testActivity} = this; @@ -330,7 +330,7 @@ export class ElsaWorkflowPropertiesPanel {
-
{t('Correlation Id')}
+
{'Correlation Id'}
{testActivity.correlationId}
@@ -356,10 +356,31 @@ export class ElsaWorkflowPropertiesPanel { }
))} + {this.renderActivityTestError()}
); } + renderActivityTestError() { + + const {testActivity} = this; + + if (testActivity == undefined) + return + + const t = (x, params?) => this.i18next.t(x, params); + + if (!testActivity.error) + return; + + return ( +
+
{t('Error')}
+
{testActivity.error}
+
+ ); + } + createClient() { return createElsaClient(this.serverUrl); } diff --git a/src/designer/elsa-workflows-studio/src/models/domain.ts b/src/designer/elsa-workflows-studio/src/models/domain.ts index a2f3aea5b..d8ba848a9 100644 --- a/src/designer/elsa-workflows-studio/src/models/domain.ts +++ b/src/designer/elsa-workflows-studio/src/models/domain.ts @@ -328,6 +328,7 @@ export interface WorkflowTestActivityMessage { activityId: string; status: string; data?: any; + error?: string; } export interface WorkflowTestUpdateRequest { diff --git a/src/server/Elsa.Server.Api/Handlers/ActivityExecutionResultExecutedHandler.cs b/src/server/Elsa.Server.Api/Handlers/ActivityExecutionResultExecutedHandler.cs index 4c794eba3..f7d6c2d5d 100644 --- a/src/server/Elsa.Server.Api/Handlers/ActivityExecutionResultExecutedHandler.cs +++ b/src/server/Elsa.Server.Api/Handlers/ActivityExecutionResultExecutedHandler.cs @@ -10,7 +10,7 @@ using Newtonsoft.Json.Linq; namespace Elsa.Server.Api.Handlers { - public class ActivityExecutionResultExecutedHandler : INotificationHandler + public class ActivityExecutionResultExecutedHandler : INotificationHandler, INotificationHandler { private readonly IWorkflowTestService _workflowTestService; @@ -46,5 +46,22 @@ namespace Elsa.Server.Api.Handlers await _workflowTestService.DispatchMessage(signalRConnectionId, message); } + + public async Task Handle(ActivityExecutionResultFailed notification, CancellationToken cancellationToken) + { + var context = notification.ActivityExecutionContext; + var signalRConnectionId = context.WorkflowExecutionContext.WorkflowBlueprint.SignalRConnectionId; + if (string.IsNullOrWhiteSpace(signalRConnectionId)) return; + + var message = new WorkflowTestMessage + { + CorrelationId = context.CorrelationId, + ActivityId = context.ActivityId, + Status = "Failed", + Error = notification.Exception.InnerException?.InnerException?.ToString() + }; + + await _workflowTestService.DispatchMessage(signalRConnectionId, message); + } } } \ No newline at end of file diff --git a/src/server/Elsa.Server.Api/Models/WorkflowTestMessage.cs b/src/server/Elsa.Server.Api/Models/WorkflowTestMessage.cs index 32273be41..21b7f4849 100644 --- a/src/server/Elsa.Server.Api/Models/WorkflowTestMessage.cs +++ b/src/server/Elsa.Server.Api/Models/WorkflowTestMessage.cs @@ -6,5 +6,6 @@ namespace Elsa.Server.Api.Models public string ActivityId { get; set; } = default!; public string Status { get; set; } = default!; public object? Data { get; set; } + public string? Error { get; set; } } }