Merge branch 'main' of github.com:elsa-workflows/elsa-core

This commit is contained in:
Sipke Schoorstra 2024-07-22 14:36:43 +02:00
commit d3f9d5ef8f
26 changed files with 231 additions and 84 deletions

View file

@ -373,6 +373,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.ServerAndStudio.Web",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Studio.Web", "src\apps\Elsa.Studio.Web\Elsa.Studio.Web.csproj", "{169A82A5-2DB3-40EA-801E-14C08D743DF7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.OpenTelemetry", "src\modules\Elsa.OpenTelemetry\Elsa.OpenTelemetry.csproj", "{2CDF3E1C-267D-4198-B1C7-7E1F548FC120}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -885,6 +887,10 @@ Global
{169A82A5-2DB3-40EA-801E-14C08D743DF7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{169A82A5-2DB3-40EA-801E-14C08D743DF7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{169A82A5-2DB3-40EA-801E-14C08D743DF7}.Release|Any CPU.Build.0 = Release|Any CPU
{2CDF3E1C-267D-4198-B1C7-7E1F548FC120}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2CDF3E1C-267D-4198-B1C7-7E1F548FC120}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2CDF3E1C-267D-4198-B1C7-7E1F548FC120}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2CDF3E1C-267D-4198-B1C7-7E1F548FC120}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -1039,6 +1045,7 @@ Global
{690B0274-291F-4D9E-BA76-54EFF7D3E4BC} = {D92BEAB2-60D6-4BB4-885A-6BA681C6CCF1}
{060FD0BA-BD78-48E1-A8A7-4906A5AD5E39} = {D92BEAB2-60D6-4BB4-885A-6BA681C6CCF1}
{169A82A5-2DB3-40EA-801E-14C08D743DF7} = {D92BEAB2-60D6-4BB4-885A-6BA681C6CCF1}
{2CDF3E1C-267D-4198-B1C7-7E1F548FC120} = {5BA4A8FA-F7F4-45B3-AEC8-8886D35AAC79}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {D4B5CEAA-7D70-4FCB-A68E-B03FBE5E0E5E}

View file

@ -36,7 +36,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
rm -rf /var/lib/apt/lists/*
# Set PYTHONNET_PYDLL environment variable
ENV PYTHONNET_PYDLL /usr/lib/aarch64-linux-gnu/libpython3.11.so
ENV PYTHONNET_PYDLL=/usr/lib/aarch64-linux-gnu/libpython3.11.so
# Copy the tracer from build target
COPY --from=build /tmp/datadog-dotnet-apm.deb /tmp/datadog-dotnet-apm.deb

View file

@ -28,7 +28,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
rm -rf /var/lib/apt/lists/*
# Set PYTHONNET_PYDLL environment variable
ENV PYTHONNET_PYDLL /usr/lib/aarch64-linux-gnu/libpython3.11.so
ENV PYTHONNET_PYDLL=/usr/lib/aarch64-linux-gnu/libpython3.11.so
EXPOSE 80/tcp
EXPOSE 443/tcp

View file

@ -29,7 +29,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
rm -rf /var/lib/apt/lists/*
# Set PYTHONNET_PYDLL environment variable
ENV PYTHONNET_PYDLL /usr/lib/aarch64-linux-gnu/libpython3.11.so
ENV PYTHONNET_PYDLL=/usr/lib/aarch64-linux-gnu/libpython3.11.so
EXPOSE 80/tcp
EXPOSE 443/tcp

View file

@ -5,6 +5,7 @@
<ProjectReference Include="..\..\modules\Elsa.Caching.Distributed.MassTransit\Elsa.Caching.Distributed.MassTransit.csproj" />
<ProjectReference Include="..\..\modules\Elsa.EntityFrameworkCore.PostgreSql\Elsa.EntityFrameworkCore.PostgreSql.csproj"/>
<ProjectReference Include="..\..\modules\Elsa.MassTransit.AzureServiceBus\Elsa.MassTransit.AzureServiceBus.csproj"/>
<ProjectReference Include="..\..\modules\Elsa.OpenTelemetry\Elsa.OpenTelemetry.csproj" />
<ProjectReference Include="..\..\modules\Elsa\Elsa.csproj"/>
<ProjectReference Include="..\..\common\Elsa.DropIns\Elsa.DropIns.csproj"/>
<ProjectReference Include="..\..\modules\Elsa.Alterations.MassTransit\Elsa.Alterations.MassTransit.csproj"/>

View file

@ -21,13 +21,17 @@ using Elsa.MongoDb.Modules.Alterations;
using Elsa.MongoDb.Modules.Identity;
using Elsa.MongoDb.Modules.Management;
using Elsa.MongoDb.Modules.Runtime;
using Elsa.OpenTelemetry.Middleware;
using Elsa.Server.Web;
using Elsa.Tenants.Extensions;
using Elsa.Workflows;
using Elsa.Workflows.Api;
using Elsa.Workflows.Management.Compression;
using Elsa.Workflows.Management.Stores;
using Elsa.Workflows.Pipelines.ActivityExecution;
using Elsa.Workflows.Pipelines.WorkflowExecution;
using Elsa.Workflows.Runtime.Distributed.Extensions;
using Elsa.Workflows.Runtime.Extensions;
using Elsa.Workflows.Runtime.Stores;
using JetBrains.Annotations;
using Medallion.Threading.FileSystem;
@ -133,6 +137,11 @@ services
identity.UseConfigurationBasedRoleProvider(options => identitySection.Bind(options));
})
.UseDefaultAuthentication()
.UseWorkflows(workflows =>
{
workflows.WithDefaultWorkflowExecutionPipeline(pipeline => pipeline.UseWorkflowExecutionTracing());
workflows.WithDefaultActivityExecutionPipeline(pipeline => pipeline.UseActivityExecutionTracing());
})
.UseWorkflowManagement(management =>
{
if (persistenceProvider == PersistenceProvider.MongoDb)

View file

@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>
Provides OpenTelemetry sources for tracing workflow and activity execution.
</Description>
<PackageTags>elsa module open-telemetry</PackageTags>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Elsa.Workflows.Core\Elsa.Workflows.Core.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Extensions\" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,11 @@
using Elsa.Features.Abstractions;
using Elsa.Features.Services;
namespace Elsa.OpenTelemetry.Features;
public class OpenTelemetryFeature(IModule module) : FeatureBase(module)
{
public override void Configure()
{
}
}

View file

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait />
</Weavers>

View file

@ -0,0 +1,8 @@
using System.Diagnostics;
namespace Elsa.OpenTelemetry.Helpers;
public class ElsaOpenTelemetry
{
public static readonly ActivitySource ActivitySource = new("Elsa.Workflows");
}

View file

@ -0,0 +1,36 @@
using System.Diagnostics;
using Elsa.OpenTelemetry.Helpers;
using Elsa.Workflows;
using Elsa.Workflows.Pipelines.ActivityExecution;
using Elsa.Workflows.Pipelines.WorkflowExecution;
using JetBrains.Annotations;
using Activity = System.Diagnostics.Activity;
using ActivityKind = System.Diagnostics.ActivityKind;
namespace Elsa.OpenTelemetry.Middleware;
[UsedImplicitly]
public class OpenTelemetryTracingActivityExecutionMiddleware(ActivityMiddlewareDelegate next) : IActivityExecutionMiddleware
{
public async ValueTask InvokeAsync(ActivityExecutionContext context)
{
var activity = context.Activity;
using var span = ElsaOpenTelemetry.ActivitySource.StartActivity($"ActivityExecution {context.ActivityDescriptor.TypeName}", ActivityKind.Internal, Activity.Current?.Context ?? default);
span?.AddTag("activity.nodeId", activity.NodeId);
span?.AddTag("activity.type", activity.Type);
span?.AddTag("activity.name", activity.Name);
span?.AddTag("activityInstance.id", context.Id);
span?.AddTag("activityInstance.originalStatus", context.Status.ToString());
span?.AddEvent(new ActivityEvent("Executing"));
await next(context);
span?.AddEvent(new ActivityEvent("Executed"));
span?.AddTag("activityInstance.newStatus", context.Status.ToString());
}
}
[UsedImplicitly]
public static class OpenTelemetryTracingActivityExecutionMiddlewareExtensions
{
/// Installs the <see cref="OpenTelemetryTracingActivityExecutionMiddleware"/> component in the workflow execution pipeline.
public static IActivityExecutionPipelineBuilder UseActivityExecutionTracing(this IActivityExecutionPipelineBuilder pipelineBuilder) => pipelineBuilder.Insert<OpenTelemetryTracingActivityExecutionMiddleware>(0);
}

View file

@ -0,0 +1,38 @@
using System.Diagnostics;
using Elsa.OpenTelemetry.Helpers;
using Elsa.Workflows;
using Elsa.Workflows.Pipelines.WorkflowExecution;
using JetBrains.Annotations;
using Activity = System.Diagnostics.Activity;
using ActivityKind = System.Diagnostics.ActivityKind;
namespace Elsa.OpenTelemetry.Middleware;
[UsedImplicitly]
public class OpenTelemetryTracingWorkflowExecutionMiddleware(WorkflowMiddlewareDelegate next) : WorkflowExecutionMiddleware(next)
{
public override async ValueTask InvokeAsync(WorkflowExecutionContext context)
{
var workflowInstanceId = context.Id;
var workflow = context.Workflow;
using var activity = ElsaOpenTelemetry.ActivitySource.StartActivity($"WorkflowExecution {workflow.WorkflowMetadata.Name}", ActivityKind.Internal, Activity.Current?.Context ?? default);
activity?.AddTag("workflowInstance.id", workflowInstanceId);
activity?.AddTag("workflowDefinition.definitionId", workflow.Identity.DefinitionId);
activity?.AddTag("workflowDefinition.version", workflow.Identity.Version);
activity?.AddTag("tenantId", workflow.Identity.TenantId);
activity?.AddTag("workflowInstance.originalStatus", context.Status.ToString());
activity?.AddTag("workflowInstance.originalSubStatus", context.SubStatus.ToString());
activity?.AddEvent(new ActivityEvent("Executing"));
await Next(context);
activity?.AddEvent(new ActivityEvent("Executed"));
activity?.AddTag("workflowInstance.newStatus", context.Status.ToString());
activity?.AddTag("workflowInstance.newSubStatus", context.SubStatus.ToString());
}
}
[UsedImplicitly]
public static class OpenTelemetryWorkflowExecutionMiddlewareExtensions
{
/// Installs the <see cref="OpenTelemetryTracingWorkflowExecutionMiddleware"/> component in the workflow execution pipeline.
public static IWorkflowExecutionPipelineBuilder UseWorkflowExecutionTracing(this IWorkflowExecutionPipelineBuilder pipelineBuilder) => pipelineBuilder.Insert<OpenTelemetryTracingWorkflowExecutionMiddleware>(0);
}

View file

@ -1,4 +1,5 @@
using Elsa.WorkflowContexts.Middleware;
using Elsa.Workflows;
using Elsa.Workflows.Contracts;
using Elsa.Workflows.Pipelines.ActivityExecution;
using Elsa.Workflows.Pipelines.WorkflowExecution;

View file

@ -1,4 +1,4 @@
namespace Elsa.Workflows.Contracts;
namespace Elsa.Workflows;
public interface IActivityExecutionMiddleware
{

View file

@ -1,6 +1,6 @@
using Elsa.Workflows.Pipelines.ActivityExecution;
namespace Elsa.Workflows.Contracts;
namespace Elsa.Workflows;
/// <summary>
/// Builds an activity execution pipeline.
@ -19,6 +19,9 @@ public interface IActivityExecutionPipelineBuilder
/// <returns>The current <see cref="IActivityExecutionPipelineBuilder"/>.</returns>
IActivityExecutionPipelineBuilder Use(Func<ActivityMiddlewareDelegate, ActivityMiddlewareDelegate> middleware);
/// Inserts the middleware component at the specified index.
IActivityExecutionPipelineBuilder Insert(int index, Func<ActivityMiddlewareDelegate, ActivityMiddlewareDelegate> middleware);
/// <summary>
/// Constructs the final <see cref="ActivityMiddlewareDelegate"/> delegate that invokes each installed middleware component.
/// </summary>

View file

@ -1,41 +1,30 @@
using Elsa.Workflows.Pipelines.WorkflowExecution;
namespace Elsa.Workflows.Contracts;
namespace Elsa.Workflows;
/// <summary>
/// Builds a workflow execution pipeline.
/// </summary>
public interface IWorkflowExecutionPipelineBuilder
{
/// <summary>
/// A general-purpose dictionary of values that can be used by middleware components.
/// </summary>
public IDictionary<object, object?> Properties { get; }
/// <summary>
/// The middleware components that have been installed.
/// </summary>
public IEnumerable<Func<WorkflowMiddlewareDelegate, WorkflowMiddlewareDelegate>> Components { get; }
/// <summary>
/// The current service provider to resolve services from.
/// </summary>
IServiceProvider ServiceProvider { get; }
/// <summary>
/// Installs the specified delegate as a middleware component.
/// </summary>
IWorkflowExecutionPipelineBuilder Use(Func<WorkflowMiddlewareDelegate, WorkflowMiddlewareDelegate> middleware);
/// <summary>
/// Constructs the final <see cref="WorkflowMiddlewareDelegate"/> delegate that invokes each installed middleware component.
/// </summary>
public WorkflowMiddlewareDelegate Build();
/// <summary>
/// Clears the current pipeline.
/// </summary>
IWorkflowExecutionPipelineBuilder Reset();
/// Inserts the middleware component at the specified index.
IWorkflowExecutionPipelineBuilder Insert(int index, Func<WorkflowMiddlewareDelegate, WorkflowMiddlewareDelegate> middleware);
/// <summary>
/// Replaces the middleware component at the specified index with the specified delegate.

View file

@ -1,20 +1,37 @@
using Elsa.Workflows.Contracts;
using System.Diagnostics.CodeAnalysis;
using Microsoft.Extensions.DependencyInjection;
namespace Elsa.Workflows.Pipelines.ActivityExecution;
public static class ActivityExecutionMiddlewareExtensions
{
public static IActivityExecutionPipelineBuilder UseMiddleware<TMiddleware>(this IActivityExecutionPipelineBuilder pipelineBuilder, params object[] args) where TMiddleware : IActivityExecutionMiddleware
public static IActivityExecutionPipelineBuilder UseMiddleware<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TMiddleware>(this IActivityExecutionPipelineBuilder pipelineBuilder, params object[] args) where TMiddleware : IActivityExecutionMiddleware
{
var delegateFactory = CreateMiddlewareDelegateFactory<TMiddleware>(pipelineBuilder, args);
return pipelineBuilder.Use(delegateFactory);
}
public static IActivityExecutionPipelineBuilder Insert<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]TMiddleware>(this IActivityExecutionPipelineBuilder pipelineBuilder, int index, params object[] args) where TMiddleware : IActivityExecutionMiddleware
{
var delegateFactory = CreateMiddlewareDelegateFactory<TMiddleware>(pipelineBuilder, args);
return pipelineBuilder.Insert(index, delegateFactory);
}
/// Creates a middleware delegate for the specified middleware component.
public static Func<ActivityMiddlewareDelegate, ActivityMiddlewareDelegate> CreateMiddlewareDelegateFactory<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TMiddleware>(
this IActivityExecutionPipelineBuilder pipelineBuilder, params object[] args) where TMiddleware : IActivityExecutionMiddleware
{
var middleware = typeof(TMiddleware);
return pipelineBuilder.Use(next =>
return next =>
{
var invokeMethod = MiddlewareHelpers.GetInvokeMethod(middleware);
var ctorArgs = new[] { next }.Concat(args).Select(x => x!).ToArray();
var ctorArgs = new[]
{
next
}.Concat(args).Select(x => x).ToArray();
var instance = ActivatorUtilities.CreateInstance(pipelineBuilder.ServiceProvider, middleware, ctorArgs);
return (ActivityMiddlewareDelegate)invokeMethod.CreateDelegate(typeof(ActivityMiddlewareDelegate), instance);
});
};
}
}

View file

@ -1,22 +1,12 @@
using Elsa.Workflows.Contracts;
namespace Elsa.Workflows.Pipelines.ActivityExecution;
/// <inheritdoc />
public class ActivityExecutionPipelinePipelineBuilder : IActivityExecutionPipelineBuilder
public class ActivityExecutionPipelinePipelineBuilder(IServiceProvider serviceProvider) : IActivityExecutionPipelineBuilder
{
private readonly IList<Func<ActivityMiddlewareDelegate, ActivityMiddlewareDelegate>> _components = new List<Func<ActivityMiddlewareDelegate, ActivityMiddlewareDelegate>>();
/// <summary>
/// Initializes a new instance of the <see cref="ActivityExecutionPipelinePipelineBuilder"/> class.
/// </summary>
public ActivityExecutionPipelinePipelineBuilder(IServiceProvider serviceProvider)
{
ServiceProvider = serviceProvider;
}
/// <inheritdoc />
public IServiceProvider ServiceProvider { get; }
public IServiceProvider ServiceProvider { get; } = serviceProvider;
/// <inheritdoc />
public IActivityExecutionPipelineBuilder Use(Func<ActivityMiddlewareDelegate, ActivityMiddlewareDelegate> middleware)
@ -25,6 +15,12 @@ public class ActivityExecutionPipelinePipelineBuilder : IActivityExecutionPipeli
return this;
}
public IActivityExecutionPipelineBuilder Insert(int index, Func<ActivityMiddlewareDelegate, ActivityMiddlewareDelegate> middleware)
{
_components.Insert(index, middleware);
return this;
}
/// <inheritdoc />
public ActivityMiddlewareDelegate Build()
{

View file

@ -4,44 +4,42 @@ using Microsoft.Extensions.DependencyInjection;
namespace Elsa.Workflows.Pipelines.WorkflowExecution;
/// <summary>
/// Provides extensions to <see cref="IWorkflowExecutionPipelineBuilder"/> that adds support for installing <see cref="IWorkflowExecutionMiddleware"/> components.
/// </summary>
public static class WorkflowExecutionMiddlewareExtensions
{
/// <summary>
/// Installs the specified middleware component into the pipeline being built.
/// </summary>
public static IWorkflowExecutionPipelineBuilder UseMiddleware<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TMiddleware>(
this IWorkflowExecutionPipelineBuilder pipelineBuilder, params object[] args) where TMiddleware : IWorkflowExecutionMiddleware
{
var delegateFactory = CreateMiddlewareDelegateFactory<TMiddleware>(pipelineBuilder, args);
return pipelineBuilder.Use(delegateFactory);
}
/// Installs the specified middleware component into the pipeline being built.
public static IWorkflowExecutionPipelineBuilder Insert<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TMiddleware>(
this IWorkflowExecutionPipelineBuilder pipelineBuilder, int index, params object[] args) where TMiddleware : IWorkflowExecutionMiddleware
{
var delegateFactory = CreateMiddlewareDelegateFactory<TMiddleware>(pipelineBuilder, args);
return pipelineBuilder.Insert(index, delegateFactory);
}
/// <summary>
/// Replaces the terminal middleware component with the specified middleware component.
/// </summary>
public static IWorkflowExecutionPipelineBuilder ReplaceTerminal<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TMiddleware>(
this IWorkflowExecutionPipelineBuilder pipelineBuilder, params object[] args) where TMiddleware : IWorkflowExecutionMiddleware
{
var index = pipelineBuilder.Components.Count() - 1;
return pipelineBuilder.Replace<TMiddleware>(index, args);
}
/// <summary>
/// Replaces the middleware component at the specified index with the specified middleware component.
/// </summary>
public static IWorkflowExecutionPipelineBuilder Replace<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TMiddleware>(
this IWorkflowExecutionPipelineBuilder pipelineBuilder, int index, params object[] args) where TMiddleware : IWorkflowExecutionMiddleware
{
var delegateFactory = CreateMiddlewareDelegateFactory<TMiddleware>(pipelineBuilder, args);
return pipelineBuilder.Replace(index, delegateFactory);
}
/// <summary>
/// Creates a middleware delegate for the specified middleware component.
/// </summary>
public static Func<WorkflowMiddlewareDelegate, WorkflowMiddlewareDelegate> CreateMiddlewareDelegateFactory<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TMiddleware>(
this IWorkflowExecutionPipelineBuilder pipelineBuilder, params object[] args) where TMiddleware : IWorkflowExecutionMiddleware
{

View file

@ -1,5 +1,3 @@
using Elsa.Workflows.Contracts;
namespace Elsa.Workflows.Pipelines.WorkflowExecution;
/// <inheritdoc />
@ -54,6 +52,12 @@ public class WorkflowExecutionPipelineBuilder : IWorkflowExecutionPipelineBuilde
return this;
}
public IWorkflowExecutionPipelineBuilder Insert(int index, Func<WorkflowMiddlewareDelegate, WorkflowMiddlewareDelegate> middleware)
{
_components.Insert(index, middleware);
return this;
}
public IWorkflowExecutionPipelineBuilder Replace(int index, Func<WorkflowMiddlewareDelegate, WorkflowMiddlewareDelegate> middleware)
{
_components[index] = middleware;

View file

@ -1,3 +1,4 @@
using Elsa.Workflows;
using Elsa.Workflows.Contracts;
using Elsa.Workflows.Pipelines.ActivityExecution;
using Elsa.Workflows.Runtime.Middleware.Activities;

View file

@ -0,0 +1,36 @@
using Elsa.Extensions;
using Elsa.Workflows.Features;
using Elsa.Workflows.Middleware.Activities;
// ReSharper disable once CheckNamespace
namespace Elsa.Workflows.Runtime.Extensions;
/// Adds an extension method to the <see cref="WorkflowsFeature"/> that installs a default workflow runtime execution pipeline.
public static class PipelineWorkflowsFeatureExtensions
{
/// Installs a default workflow runtime execution pipeline.
public static WorkflowsFeature WithDefaultWorkflowExecutionPipeline(this WorkflowsFeature workflowsFeature, Action<IWorkflowExecutionPipelineBuilder>? configurePipeline = null)
{
return workflowsFeature.WithWorkflowExecutionPipeline(pipeline =>
{
pipeline.UseDefaultPipeline();
configurePipeline?.Invoke(pipeline);
});
}
/// Installs an activity invoker that can run activities asynchronously in the background.
public static WorkflowsFeature WithDefaultActivityExecutionPipeline(this WorkflowsFeature workflowsFeature, Action<IActivityExecutionPipelineBuilder>? configurePipeline = null)
{
return workflowsFeature.WithActivityExecutionPipeline(pipeline =>
{
pipeline
.UseExceptionHandling()
.UseExecutionLogging()
.UseNotifications()
.UseBackgroundActivityInvoker();
configurePipeline?.Invoke(pipeline);
});
}
}

View file

@ -1,4 +1,4 @@
using Elsa.Workflows.Contracts;
using Elsa.Workflows;
using Elsa.Workflows.Middleware.Workflows;
using Elsa.Workflows.Pipelines.WorkflowExecution;
using Elsa.Workflows.Runtime.Middleware.Workflows;

View file

@ -1,30 +0,0 @@
using Elsa.Extensions;
using Elsa.Workflows.Features;
using Elsa.Workflows.Middleware.Activities;
// ReSharper disable once CheckNamespace
namespace Elsa.Workflows.Runtime.Extensions;
/// <summary>
/// Adds an extension method to the <see cref="WorkflowsFeature"/> that installs a default workflow runtime execution pipeline.
/// </summary>
public static class WorkflowsFeatureExtensions
{
/// <summary>
/// Installs a default workflow runtime execution pipeline.
/// </summary>
public static WorkflowsFeature WithDefaultWorkflowExecutionPipeline(this WorkflowsFeature workflowsFeature) =>
workflowsFeature.WithWorkflowExecutionPipeline(pipeline =>
pipeline.UseDefaultPipeline());
/// <summary>
/// Installs an activity invoker that can run activities asynchronously in the background.
/// </summary>
public static WorkflowsFeature WithBackgroundActivityExecutionPipeline(this WorkflowsFeature workflowsFeature) =>
workflowsFeature.WithActivityExecutionPipeline(pipeline =>
pipeline
.UseExceptionHandling()
.UseExecutionLogging()
.UseNotifications()
.UseBackgroundActivityInvoker());
}

View file

@ -1,3 +1,4 @@
using Elsa.Workflows;
using Elsa.Workflows.Contracts;
using Microsoft.Extensions.DependencyInjection;

View file

@ -37,7 +37,7 @@ public class ElsaFeature : FeatureBase
Module
.UseWorkflows(workflows => workflows
.WithDefaultWorkflowExecutionPipeline()
.WithBackgroundActivityExecutionPipeline())
.WithDefaultActivityExecutionPipeline())
.UseWorkflowManagement(management =>
{
if (!DisableAutomaticActivityRegistration)