Refactor runAsynchronously logic and remove TaskActivityAttribute

Replaced `TaskActivityAttribute` with `RunAsynchronously` property in `ActivityDescriptor`, simplifying activity configurations. Updated references across code to adopt this new approach, ensuring consistent behavior for asynchronous task activities. Minor changes to naming conventions and style settings were also included.
This commit is contained in:
Sipke Schoorstra 2025-12-14 13:44:06 +01:00
parent 6f64739d83
commit 33af795704
No known key found for this signature in database
GPG key ID: 5C10502B28A4268F
6 changed files with 16 additions and 48 deletions

View file

@ -10,17 +10,17 @@ public record ActivityDescriptor
/// <summary>
/// The fully qualified name of the activity type.
/// </summary>
public string TypeName { get; init; } = default!;
public string TypeName { get; init; } = null!;
/// <summary>
/// The namespace of the activity type.
/// </summary>
public string Namespace { get; init; } = default!;
public string Namespace { get; init; } = null!;
/// <summary>
/// The name of the activity type.
/// </summary>
public string Name { get; init; } = default!;
public string Name { get; init; } = null!;
/// <summary>
/// The version of the activity type.
@ -30,7 +30,7 @@ public record ActivityDescriptor
/// <summary>
/// The category of the activity type.
/// </summary>
public string Category { get; init; } = default!;
public string Category { get; init; } = null!;
/// <summary>
/// The display name of the activity type.

View file

@ -8,21 +8,21 @@ public class ActivityAttribute : Attribute
// Default constructor.
}
public ActivityAttribute(string @namespace, string? category, string? description = default)
public ActivityAttribute(string @namespace, string? category, string? description = null)
{
Namespace = @namespace;
Description = description;
Category = category;
}
public ActivityAttribute(string @namespace, string? description = default)
public ActivityAttribute(string @namespace, string? description = null)
{
Namespace = @namespace;
Description = description;
Category = @namespace;
}
public ActivityAttribute(string @namespace, string? type, int version = 1, string? description = default, string? category = default)
public ActivityAttribute(string @namespace, string? type, int version = 1, string? description = null, string? category = null)
{
Namespace = @namespace;
Type = type;
@ -38,4 +38,5 @@ public class ActivityAttribute : Attribute
public string? DisplayName { get; set; }
public string? Category { get; set; }
public ActivityKind Kind { get; set; } = ActivityKind.Action;
public bool RunAsynchronously { get; set; }
}

View file

@ -1,19 +0,0 @@
namespace Elsa.Workflows.Attributes;
[AttributeUsage(AttributeTargets.Class)]
public class TaskActivityAttribute : ActivityAttribute
{
public TaskActivityAttribute()
{
Kind = ActivityKind.Task;
}
public TaskActivityAttribute(string @namespace, string? category, string? description = null, bool runAsynchronously = false)
: base(@namespace, category, description)
{
Kind = ActivityKind.Task;
RunAsynchronously = runAsynchronously;
}
public bool RunAsynchronously { get; set; }
}

View file

@ -49,24 +49,13 @@ public static class JsonActivityConstructorContextHelper
// 7) Pull out your boolean flags from the cleaned element
var canStartWorkflow = GetBoolean(cleanedElement, "canStartWorkflow");
var runAsynchronously = GetNullableBoolean(cleanedElement, "runAsynchronously");
if (runAsynchronously is null)
{
if (activityDescriptor.Attributes.OfType<TaskActivityAttribute>().FirstOrDefault() is { } taskActivityAttribute)
{
runAsynchronously = taskActivityAttribute.RunAsynchronously;
}
else
{
runAsynchronously = false;
}
}
var runAsynchronously = GetNullableBoolean(cleanedElement, "runAsynchronously") ?? activityDescriptor.RunAsynchronously;
// 8) If composite, setup
if (activity is IComposite composite)
composite.Setup();
// 9) Your existing synthetic inputs/outputs routines, using the cleanedElement
// 9) Existing synthetic inputs/outputs routines, using the cleanedElement
ReadSyntheticInputs(activityDescriptor, activity, cleanedElement, serializerOptions);
ReadSyntheticOutputs(activityDescriptor, activity, cleanedElement);

View file

@ -76,6 +76,11 @@ public class ActivityDescriptor
/// </summary>
public ActivityKind Kind { get; set; } = ActivityKind.Action;
/// <summary>
/// Whether the activity should be executed asynchronously. Applies only when the Kind is set to Task and as a default when not set on the activity itself.
/// </summary>
public bool RunAsynchronously { get; set; }
/// <summary>
/// The ports of the activity type.
/// </summary>

View file

@ -117,15 +117,7 @@ public class BackgroundActivityInvokerMiddleware(
return false;
var runAsynchronously = activity.GetRunAsynchronously();
if (runAsynchronously is null)
{
var taskActivityAttribute = activityDescriptor.Attributes.OfType<TaskActivityAttribute>().FirstOrDefault();
return taskActivityAttribute is { RunAsynchronously: true };
}
return (bool)runAsynchronously;
return runAsynchronously ?? activityDescriptor.RunAsynchronously;
}
private static bool GetIsBackgroundExecution(ActivityExecutionContext context) => context.TransientProperties.ContainsKey(BackgroundActivityExecutionContextExtensions.IsBackgroundExecution);