using System.Runtime.CompilerServices;
using Elsa.Common.Contracts;
using Elsa.Extensions;
using Elsa.Scheduling.Bookmarks;
using Elsa.Workflows.Core;
using Elsa.Workflows.Core.Attributes;
using Elsa.Workflows.Core.Models;
namespace Elsa.Scheduling.Activities;
///
/// Represents a timer to periodically trigger the workflow.
///
[Activity("Elsa", "Scheduling", "Trigger workflow execution at a specific interval.")]
public class Timer : EventGenerator
{
///
public Timer([CallerFilePath] string? source = default, [CallerLineNumber] int? line = default) : base(source, line)
{
}
///
public Timer(TimeSpan interval, [CallerFilePath] string? source = default, [CallerLineNumber] int? line = default) : this(new Input(interval), source, line)
{
}
///
public Timer(Input interval, [CallerFilePath] string? source = default, [CallerLineNumber] int? line = default) : this(source, line)
{
Interval = interval;
}
///
/// The interval at which the timer should execute.
///
[Input(Description = "The interval at which the timer should execute.", DefaultValue = "00:01:00")]
public Input Interval { get; set; } = default!;
///
protected override async ValueTask ExecuteAsync(ActivityExecutionContext context)
{
if(context.IsTriggerOfWorkflow())
{
await context.CompleteActivityAsync();
return;
}
var clock = context.ExpressionExecutionContext.GetRequiredService();
var timeSpan = context.ExpressionExecutionContext.Get(Interval);
var resumeAt = clock.UtcNow.Add(timeSpan);
context.JournalData.Add("ResumeAt", resumeAt);
context.CreateBookmark(new TimerBookmarkPayload(resumeAt));
}
///
protected override object GetTriggerPayload(TriggerIndexingContext context)
{
var interval = context.ExpressionExecutionContext.Get(Interval);
var clock = context.ExpressionExecutionContext.GetRequiredService();
var executeAt = clock.UtcNow.Add(interval);
return new TimerTriggerPayload(executeAt, interval);
}
///
/// Creates a new activity set to trigger at the specified interval.
///
public static Timer FromTimeSpan(TimeSpan value, [CallerFilePath] string? source = default, [CallerLineNumber] int? line = default) => new(value, source, line);
///
/// Creates a new activity set to trigger at the specified interval in seconds.
///
public static Timer FromSeconds(double value, [CallerFilePath] string? source = default, [CallerLineNumber] int? line = default) => FromTimeSpan(TimeSpan.FromSeconds(value), source, line);
}