Fix TimerEvent and CronEvent

This commit is contained in:
Sipke Schoorstra 2020-11-17 22:13:55 +01:00
parent 4474d9cdc2
commit 0b81bba3d4
5 changed files with 62 additions and 35 deletions

View file

@ -2,6 +2,8 @@ using Elsa.ActivityResults;
using Elsa.Attributes;
using Elsa.Services;
using Elsa.Services.Models;
using NCrontab;
using NodaTime;
// ReSharper disable once CheckNamespace
namespace Elsa.Activities.Timers
@ -13,10 +15,39 @@ namespace Elsa.Activities.Timers
)]
public class CronEvent : Activity
{
private readonly IClock _clock;
public CronEvent(IClock clock)
{
_clock = clock;
}
[ActivityProperty(Hint = "Specify a CRON expression. See https://crontab.guru/ for help.")]
public string CronExpression { get; set; } = "* * * * *";
public Instant ExecuteAt
{
get => GetState<Instant>();
set => SetState(value);
}
protected override IActivityExecutionResult OnExecute(ActivityExecutionContext context)
{
if (context.WorkflowExecutionContext.IsFirstPass)
return Done();
ExecuteAt = GetNextOccurrence(CronExpression);
return Suspend();
}
protected override IActivityExecutionResult OnExecute(ActivityExecutionContext context) => context.WorkflowExecutionContext.IsFirstPass ? (IActivityExecutionResult) Done() : Suspend();
protected override IActivityExecutionResult OnResume() => Done();
private Instant GetNextOccurrence(string cronExpression)
{
var schedule = CrontabSchedule.Parse(cronExpression);
var now = _clock.GetCurrentInstant();
return Instant.FromDateTimeUtc(schedule.GetNextOccurrence(now.ToDateTimeUtc()));
}
}
}

View file

@ -10,10 +10,31 @@ namespace Elsa.Activities.Timers
[Trigger(Category = "Timers", Description = "Triggers at a specified interval.")]
public class TimerEvent : Activity
{
private readonly IClock _clock;
public TimerEvent(IClock clock)
{
_clock = clock;
}
[ActivityProperty(Hint = "An expression that evaluates to a Duration value.")]
public Duration Timeout { get; set; } = default!;
protected override IActivityExecutionResult OnExecute(ActivityExecutionContext context) => context.WorkflowExecutionContext.IsFirstPass ? (IActivityExecutionResult)Done() : Suspend();
public Instant ExecuteAt
{
get => GetState<Instant>();
set => SetState(value);
}
protected override IActivityExecutionResult OnExecute(ActivityExecutionContext context)
{
if (context.WorkflowExecutionContext.IsFirstPass)
return Done();
ExecuteAt = _clock.GetCurrentInstant().Plus(Timeout);
return Suspend();
}
protected override IActivityExecutionResult OnResume() => Done();
}
}

View file

@ -13,29 +13,14 @@ namespace Elsa.Activities.Timers.Triggers
public class CronEventTriggerProvider : TriggerProvider<CronEventTrigger, CronEvent>
{
private readonly IClock _clock;
public CronEventTriggerProvider(IClock clock)
{
_clock = clock;
}
public override async ValueTask<ITrigger> GetTriggerAsync(TriggerProviderContext<CronEvent> context, CancellationToken cancellationToken)
{
var cron = await context.GetActivity<CronEvent>().GetPropertyValueAsync(x => x.CronExpression, cancellationToken);
var executeAt = GetNextOccurrence(cron);
var executeAt = context.GetActivity<CronEvent>().GetState(x => x.ExecuteAt);
return new TimerEventTrigger
{
ExecuteAt = executeAt
};
}
private Instant GetNextOccurrence(string cronExpression)
{
var schedule = CrontabSchedule.Parse(cronExpression);
var now = _clock.GetCurrentInstant();
return Instant.FromDateTimeUtc(schedule.GetNextOccurrence(now.ToDateTimeUtc()));
}
}
}

View file

@ -1,6 +1,4 @@
using System.Threading;
using System.Threading.Tasks;
using Elsa.Triggers;
using Elsa.Triggers;
using NodaTime;
namespace Elsa.Activities.Timers.Triggers
@ -12,18 +10,9 @@ namespace Elsa.Activities.Timers.Triggers
public class TimerEventTriggerProvider : TriggerProvider<TimerEventTrigger, TimerEvent>
{
private readonly IClock _clock;
public TimerEventTriggerProvider(IClock clock)
public override ITrigger GetTrigger(TriggerProviderContext<TimerEvent> context)
{
_clock = clock;
}
public override async ValueTask<ITrigger> GetTriggerAsync(TriggerProviderContext<TimerEvent> context, CancellationToken cancellationToken)
{
var duration = await context.GetActivity<TimerEvent>().GetPropertyValueAsync(x => x.Timeout, cancellationToken);
var now = _clock.GetCurrentInstant();
var executeAt = now.Plus(duration);
var executeAt = context.GetActivity<TimerEvent>().GetState(x => x.ExecuteAt);
return new TimerEventTrigger
{

View file

@ -41,7 +41,7 @@ namespace Elsa
return (T)value!;
}
public static T GetActivityState<TActivity, T>(
public static T? GetActivityState<TActivity, T>(
this IWorkflowBlueprint workflowBlueprint,
Expression<Func<TActivity, T>> propertyExpression,
ActivityExecutionContext activityExecutionContext) where TActivity : IActivity
@ -51,13 +51,14 @@ namespace Elsa
return GetActivityState<T>(propertyName, activityExecutionContext);
}
public static T GetActivityState<T>(
public static T? GetActivityState<T>(
string propertyName,
ActivityExecutionContext activityExecutionContext)
{
var activity = activityExecutionContext.ActivityInstance;
var serializer = activityExecutionContext.GetService<JsonSerializer>();
return activity.Data[propertyName]!.ToObject<T>(serializer)!;
var value = activity.Data[propertyName];
return value != null ? value.ToObject<T>(serializer) : default;
}
public static IEnumerable<IWorkflowBlueprint> WithVersion(