using System.Runtime.CompilerServices;
using Elsa.Common;
using Elsa.Expressions.Models;
using Elsa.Extensions;
using Elsa.Scheduling.Bookmarks;
using Elsa.Workflows;
using Elsa.Workflows.Attributes;
using Elsa.Workflows.Memory;
using Elsa.Workflows.Models;
using Microsoft.Extensions.Logging;
namespace Elsa.Scheduling.Activities;
///
/// Triggers the workflow at a specific future timestamp.
///
[Activity("Elsa", "Scheduling", "Trigger execution at a specific time in the future.")]
public class StartAt : Trigger
{
private const string InputKey = "ExecuteAt";
///
public StartAt([CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) : base(source, line)
{
}
///
public StartAt(Input dateTime, [CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) : this(source, line) => DateTime = dateTime;
///
public StartAt(Func dateTime, [CallerFilePath] string? source = null, [CallerLineNumber] int? line = null)
: this(new Input(dateTime), source, line)
{
}
///
public StartAt(
Func> dateTime,
[CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) : this(new Input(dateTime), source, line)
{
}
///
public StartAt(Func> dateTime, [CallerFilePath] string? source = null, [CallerLineNumber] int? line = null)
: this(new Input(dateTime), source, line)
{
}
///
public StartAt(Func dateTime, [CallerFilePath] string? source = null, [CallerLineNumber] int? line = null)
: this(new Input(dateTime), source, line)
{
}
///
public StartAt(DateTimeOffset dateTime, [CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) : this(source, line) =>
DateTime = new Input(dateTime);
///
public StartAt(Variable dateTime, [CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) : this(source, line) =>
DateTime = new Input(dateTime);
///
/// The timestamp at which the workflow should be triggered.
///
[Input]
public Input DateTime { get; set; } = null!;
///
protected override object GetTriggerPayload(TriggerIndexingContext context)
{
var executeAt = context.ExpressionExecutionContext.Get(DateTime);
return new StartAtPayload(executeAt);
}
///
protected override async ValueTask ExecuteAsync(ActivityExecutionContext context)
{
if (context.IsTriggerOfWorkflow())
{
await context.CompleteActivityAsync();
return;
}
var executeAt = context.ExpressionExecutionContext.Get(DateTime);
var clock = context.ExpressionExecutionContext.GetRequiredService();
var now = clock.UtcNow;
var logger = context.GetRequiredService>();
context.JournalData.Add("Executed At", now);
if (executeAt <= now)
{
logger.LogDebug("Scheduled trigger time lies in the past ('{Delta}'). Completing immediately", now - executeAt);
await context.CompleteActivityAsync();
return;
}
var payload = new StartAtPayload(executeAt);
context.CreateBookmark(payload);
}
///
/// Creates a new activity set to trigger at the specified timestamp.
///
public static StartAt From(DateTimeOffset value, [CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) => new(value, source, line);
}