using System.Runtime.CompilerServices;
using System.Text.Json.Serialization;
using Elsa.Expressions.Models;
using Elsa.Extensions;
using Elsa.Workflows.Core.Attributes;
using Elsa.Workflows.Core.Models;
using Elsa.Workflows.Core.Services;
using Elsa.Workflows.Runtime.Bookmarks;
using Elsa.Workflows.Runtime.Notifications;
using Elsa.Workflows.Runtime.Services;
namespace Elsa.Workflows.Runtime.Activities;
///
/// Notifies the application that a task with a given name i requested to start.
/// When the application fulfilled the task, it is expected to report back to the workflow engine in order to resume the workflow.
///
[Activity("Elsa", "Primitives", "Requests a given task to be run. ", Kind = ActivityKind.Action)]
public class RunTask : Activity, IBookmarksPersistedHandler
{
private static readonly object BookmarkPropertyKey = new();
///
/// The key that is used for sending and receiving activity input.
///
public const string InputKey = "RunTaskInput";
///
/// The name of the task being requested.
///
[Input(Description = "The name of the task being requested.")]
public Input TaskName { get; set; } = default!;
///
/// The name of the task being requested.
///
[Input(Description = "AnyAsync additional parameters to send to the task.")]
public Input TaskParams { get; set; } = default!;
///
[JsonConstructor]
public RunTask()
{
}
///
public RunTask(MemoryBlockReference output, [CallerFilePath] string? source = default, [CallerLineNumber] int? line = default) : base(output, source, line)
{
}
///
public RunTask(Output? output, [CallerFilePath] string? source = default, [CallerLineNumber] int? line = default) : base(output, source, line)
{
}
///
public RunTask(string taskName, [CallerFilePath] string? source = default, [CallerLineNumber] int? line = default) : this(new Literal(taskName), source, line)
{
}
///
public RunTask(Func taskName, [CallerFilePath] string? source = default, [CallerLineNumber] int? line = default)
: this(new DelegateBlockReference(taskName), source, line)
{
}
///
public RunTask(Func taskName, [CallerFilePath] string? source = default, [CallerLineNumber] int? line = default)
: this(new DelegateBlockReference(taskName), source, line)
{
}
///
public RunTask(Variable taskName, [CallerFilePath] string? source = default, [CallerLineNumber] int? line = default) : base(source, line) => TaskName = new Input(taskName);
///
public RunTask(Literal taskName, [CallerFilePath] string? source = default, [CallerLineNumber] int? line = default) : base(source, line) => TaskName = new Input(taskName);
///
protected override void Execute(ActivityExecutionContext context)
{
var taskName = TaskName.Get(context);
var identityGenerator = context.GetRequiredService();
var taskId = identityGenerator.GenerateId();
var payload = new RunTaskBookmarkPayload(taskId);
context.CreateBookmark(payload, ResumeAsync);
context.TransientProperties[BookmarkPropertyKey] = payload;
}
private async ValueTask ResumeAsync(ActivityExecutionContext context)
{
var input = context.GetInput(InputKey);
context.Set(Result, input);
await context.CompleteActivityAsync();
}
async ValueTask IBookmarksPersistedHandler.BookmarksPersistedAsync(ActivityExecutionContext context)
{
var bookmark = (RunTaskBookmarkPayload)context.TransientProperties[BookmarkPropertyKey];
var taskParams = TaskParams.TryGet(context);
var taskName = TaskName.Get(context);
var notification = new RunTaskRequest(bookmark.TaskId, taskName, taskParams);
var dispatcher = context.GetRequiredService();
await dispatcher.DispatchAsync(notification, context.CancellationToken);
}
}