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

This commit is contained in:
Sipke Schoorstra 2024-03-30 21:25:14 +01:00
commit ee2fdbe698
7 changed files with 146 additions and 9 deletions

View file

@ -0,0 +1,23 @@
namespace Elsa.Api.Client.Resources.WorkflowDefinitions.Enums;
/// <summary>
/// Define the Log Persistence mode to store information
/// </summary>
public enum LogPersistenceMode
{
/// <summary>
/// Persist using the Parent mode
/// </summary>
Default,
/// <summary>
/// Include property to store
/// </summary>
Include,
/// <summary>
/// Exclude Property to store
/// </summary>
Exclude
}

View file

@ -29,7 +29,9 @@ public class RabbitMqServiceBusFeature : FeatureBase
/// A RabbitMQ connection string.
public string? ConnectionString { get; set; }
/// <summary>
/// Configures the RabbitMQ transport options.
/// </summary>
public Action<RabbitMqTransportOptions>? TransportOptions { get; set; }
/// <summary>

View file

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Elsa.Workflows.Enums;
/// <summary>
/// Define the Log Persistence mode to store information
/// </summary>
public enum LogPersistenceMode
{
/// <summary>
/// Persist using the Parent mode
/// </summary>
Default,
/// <summary>
/// Include property to store
/// </summary>
Include,
/// <summary>
/// Exclude Property to store
/// </summary>
Exclude
}

View file

@ -9,6 +9,7 @@ using Elsa.Features.Abstractions;
using Elsa.Features.Attributes;
using Elsa.Features.Services;
using Elsa.Workflows.Contracts;
using Elsa.Workflows.Enums;
using Elsa.Workflows.Features;
using Elsa.Workflows.Management.Activities.WorkflowDefinitionActivity;
using Elsa.Workflows.Management.Compression;
@ -42,7 +43,7 @@ public class WorkflowManagementFeature : FeatureBase
private const string DynamicCategory = "Dynamic";
private string CompressionAlgorithm { get; set; } = nameof(None);
private LogPersistenceMode LogPersistenceMode { get; set; } = LogPersistenceMode.Include;
/// <inheritdoc />
public WorkflowManagementFeature(IModule module) : base(module)
{
@ -161,6 +162,16 @@ public class WorkflowManagementFeature : FeatureBase
return this;
}
/// <summary>
/// Set the default Log Persistence mode to use for worflow state (default is Include)
/// </summary>
/// <param name="logPersistenceMode">The mode persistence value</param>
public WorkflowManagementFeature SetDefaultLogPersistenceMode(LogPersistenceMode logPersistenceMode)
{
LogPersistenceMode = logPersistenceMode;
return this;
}
/// <inheritdoc />
[RequiresUnreferencedCode("The assembly containing the specified marker type will be scanned for activity types.")]
public override void Configure()
@ -211,6 +222,7 @@ public class WorkflowManagementFeature : FeatureBase
options.VariableDescriptors.Add(descriptor);
options.CompressionAlgorithm = CompressionAlgorithm;
options.LogPersistenceMode = LogPersistenceMode;
});
}
}

View file

@ -1,3 +1,4 @@
using Elsa.Workflows.Enums;
using Elsa.Workflows.Management.Models;
namespace Elsa.Workflows.Management.Options;
@ -20,5 +21,10 @@ public class ManagementOptions
/// <summary>
/// The format to use for compressing workflow state.
/// </summary>
public string? CompressionAlgorithm { get; set; }
public string? CompressionAlgorithm { get; set; }
/// <summary>
/// The default Log Persistence Mode to use for all the system
/// </summary>
public LogPersistenceMode LogPersistenceMode { get; set; }
}

View file

@ -215,7 +215,7 @@ public class WorkflowRuntimeFeature : FeatureBase
.AddScoped<IBookmarkManager, DefaultBookmarkManager>()
.AddScoped<IActivityExecutionManager, DefaultActivityExecutionManager>()
.AddScoped<IActivityExecutionStatsService, ActivityExecutionStatsService>()
.AddScoped<IActivityExecutionMapper, DefaultActivityExecutionMapper>()
.AddScoped<IActivityExecutionMapper, DefaultActivityExecutionMapper>()
.AddScoped<IWorkflowDefinitionStorePopulator, DefaultWorkflowDefinitionStorePopulator>()
.AddScoped<IRegistriesPopulator, DefaultRegistriesPopulator>()
.AddScoped<IWorkflowRegistry, DefaultWorkflowRegistry>()

View file

@ -1,17 +1,49 @@
using Elsa.Extensions;
using Elsa.Workflows.Enums;
using Elsa.Workflows.Management.Options;
using Elsa.Workflows.Models;
using Elsa.Workflows.Runtime.Contracts;
using Elsa.Workflows.Runtime.Entities;
using Elsa.Workflows.State;
using Humanizer;
using Microsoft.Extensions.Options;
namespace Elsa.Workflows.Runtime.Services;
/// <inheritdoc />
public class DefaultActivityExecutionMapper : IActivityExecutionMapper
{
{
private LogPersistenceMode _serverLogPersistenceMode;
private const string LogPersistenceModeKey = "logPersistenceMode";
public DefaultActivityExecutionMapper(IOptions<ManagementOptions> options)
{
_serverLogPersistenceMode = options.Value.LogPersistenceMode;
}
/// <inheritdoc />
public ActivityExecutionRecord Map(ActivityExecutionContext source)
{
{
/*
* {
* "logPersistenceMode": {
* "default": "default",
* "inputs": { k : v },
* "outputs": { k: v }
* }
* }
*/
var workflowPersistenceProperty =
GetDefaultPersistenceMode(source.WorkflowExecutionContext.Workflow.CustomProperties, () => _serverLogPersistenceMode);
var activityPersistenceProperties = source.Activity.CustomProperties
.GetValueOrDefault<IDictionary<string, object?>>(LogPersistenceModeKey, () => new Dictionary<string, object?>());
var activityPersistencePropertyDefault =
GetDefaultPersistenceMode(source.Activity.CustomProperties, () => workflowPersistenceProperty);
// Get any outcomes that were added to the activity execution context.
var outcomes = source.JournalData.TryGetValue("Outcomes", out var resultValue) ? resultValue as string[] : default;
var payload = new Dictionary<string, object>();
@ -40,7 +72,10 @@ public class DefaultActivityExecutionMapper : IActivityExecutionMapper
return default;
});
outputs = StorePropertyUsingPersistanceMode(outputs, activityPersistenceProperties!.GetValueOrDefault("outputs", () => new Dictionary<string, object>())!, activityPersistencePropertyDefault);
var activityState = StorePropertyUsingPersistanceMode(source.ActivityState, activityPersistenceProperties!.GetValueOrDefault("inputs", () => new Dictionary<string, object>())!, activityPersistencePropertyDefault );
return new ActivityExecutionRecord
{
Id = source.Id,
@ -49,7 +84,7 @@ public class DefaultActivityExecutionMapper : IActivityExecutionMapper
WorkflowInstanceId = source.WorkflowExecutionContext.Id,
ActivityType = source.Activity.Type,
ActivityName = source.Activity.Name,
ActivityState = source.ActivityState,
ActivityState = activityState,
Outputs = outputs,
Properties = source.Properties,
Payload = payload,
@ -60,8 +95,39 @@ public class DefaultActivityExecutionMapper : IActivityExecutionMapper
Status = GetAggregateStatus(source),
CompletedAt = source.CompletedAt
};
}
}
private static LogPersistenceMode GetDefaultPersistenceMode(IDictionary<string, object> customProperties,Func<LogPersistenceMode> defaultFactory)
{
var properties = customProperties
.GetValueOrDefault<IDictionary<string, object?>>(LogPersistenceModeKey, () => new Dictionary<string, object?>());
var persistencePropertyDefault = properties!
.GetValueOrDefault("default", defaultFactory);
if(persistencePropertyDefault == LogPersistenceMode.Default)
return defaultFactory();
return persistencePropertyDefault;
}
private static Dictionary<string,object?> StorePropertyUsingPersistanceMode(IDictionary<string,object?> inputs
, IDictionary<string,object> persistenceModeConfiguration
, LogPersistenceMode defaultLogPersistenceMode = LogPersistenceMode.Exclude)
{
var result = new Dictionary<string, object?>();
foreach (var input in inputs)
{
var persistence = persistenceModeConfiguration.GetValueOrDefault(input.Key.Camelize(), () => defaultLogPersistenceMode);
if (persistence.Equals(LogPersistenceMode.Include)
|| (persistence.Equals(LogPersistenceMode.Default) && defaultLogPersistenceMode == LogPersistenceMode.Include)
)
result.Add(input.Key, input.Value);
}
return result;
}
private ActivityStatus GetAggregateStatus(ActivityExecutionContext context)
{
// If any child activity is faulted, the aggregate status is faulted.