2024-05-29 08:34:44 +00:00
|
|
|
using Elsa.Common.Contracts;
|
2023-04-11 18:17:15 +00:00
|
|
|
using Elsa.Common.Models;
|
|
|
|
|
using Elsa.Extensions;
|
|
|
|
|
using Elsa.Scheduling.Activities;
|
2023-08-06 15:03:36 +00:00
|
|
|
using Elsa.Scheduling.Bookmarks;
|
2023-04-11 18:17:15 +00:00
|
|
|
using Elsa.Scheduling.Contracts;
|
|
|
|
|
using Elsa.Workflows.Runtime.Entities;
|
2023-07-19 22:05:43 +00:00
|
|
|
using Elsa.Workflows.Runtime.Requests;
|
2024-02-09 18:37:06 +00:00
|
|
|
using Microsoft.Extensions.Logging;
|
2023-04-11 18:17:15 +00:00
|
|
|
|
|
|
|
|
namespace Elsa.Scheduling.Services;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// A default implementation of <see cref="ITriggerScheduler"/> that schedules triggers using <see cref="IWorkflowScheduler"/>.
|
|
|
|
|
/// </summary>
|
2024-05-29 08:34:44 +00:00
|
|
|
public class DefaultTriggerScheduler(IWorkflowScheduler workflowScheduler, ISystemClock systemClock, ILogger<DefaultTriggerScheduler> logger)
|
|
|
|
|
: ITriggerScheduler
|
2023-04-11 18:17:15 +00:00
|
|
|
{
|
|
|
|
|
/// <inheritdoc />
|
|
|
|
|
public async Task ScheduleAsync(IEnumerable<StoredTrigger> triggers, CancellationToken cancellationToken = default)
|
|
|
|
|
{
|
2023-04-12 19:10:07 +00:00
|
|
|
// Select Timer, StartAt and Cron triggers.
|
2023-07-19 22:05:43 +00:00
|
|
|
var triggerList = triggers.ToList();
|
|
|
|
|
var timerTriggers = triggerList.Filter<Activities.Timer>();
|
|
|
|
|
var startAtTriggers = triggerList.Filter<StartAt>();
|
|
|
|
|
var cronTriggers = triggerList.Filter<Cron>();
|
2024-05-29 08:34:44 +00:00
|
|
|
var now = systemClock.UtcNow;
|
2023-04-11 18:17:15 +00:00
|
|
|
|
|
|
|
|
// Schedule each Timer trigger.
|
|
|
|
|
foreach (var trigger in timerTriggers)
|
|
|
|
|
{
|
2023-04-16 22:11:58 +00:00
|
|
|
var (startAt, interval) = trigger.GetPayload<TimerTriggerPayload>();
|
2023-04-11 18:17:15 +00:00
|
|
|
var input = new { StartAt = startAt, Interval = interval }.ToDictionary();
|
|
|
|
|
var request = new DispatchWorkflowDefinitionRequest
|
|
|
|
|
{
|
|
|
|
|
DefinitionId = trigger.WorkflowDefinitionId,
|
|
|
|
|
VersionOptions = VersionOptions.Published,
|
|
|
|
|
TriggerActivityId = trigger.ActivityId,
|
|
|
|
|
Input = input
|
|
|
|
|
};
|
2024-05-29 08:34:44 +00:00
|
|
|
await workflowScheduler.ScheduleRecurringAsync(trigger.Id, request, startAt, interval, cancellationToken);
|
2023-04-11 18:17:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Schedule each StartAt trigger.
|
|
|
|
|
foreach (var trigger in startAtTriggers)
|
|
|
|
|
{
|
2023-04-16 22:11:58 +00:00
|
|
|
var executeAt = trigger.GetPayload<StartAtPayload>().ExecuteAt;
|
2024-05-29 08:34:44 +00:00
|
|
|
|
|
|
|
|
// If the trigger is in the past, log info and skip scheduling.
|
|
|
|
|
if (executeAt < now)
|
|
|
|
|
{
|
|
|
|
|
logger.LogInformation("StartAt trigger is in the past. TriggerId: {TriggerId}. ExecuteAt: {ExecuteAt}. Skipping scheduling", trigger.Id, executeAt);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-11 18:17:15 +00:00
|
|
|
var input = new { ExecuteAt = executeAt }.ToDictionary();
|
|
|
|
|
var request = new DispatchWorkflowDefinitionRequest
|
|
|
|
|
{
|
|
|
|
|
DefinitionId = trigger.WorkflowDefinitionId,
|
|
|
|
|
VersionOptions = VersionOptions.Published,
|
|
|
|
|
TriggerActivityId = trigger.ActivityId,
|
|
|
|
|
Input = input
|
|
|
|
|
};
|
2023-04-16 22:11:58 +00:00
|
|
|
|
2024-05-29 08:34:44 +00:00
|
|
|
await workflowScheduler.ScheduleAtAsync(trigger.Id, request, executeAt, cancellationToken);
|
2023-04-11 18:17:15 +00:00
|
|
|
}
|
2023-04-16 22:11:58 +00:00
|
|
|
|
2023-04-12 19:10:07 +00:00
|
|
|
// Schedule each Cron trigger.
|
|
|
|
|
foreach (var trigger in cronTriggers)
|
|
|
|
|
{
|
2023-04-21 10:12:28 +00:00
|
|
|
var payload = trigger.GetPayload<CronTriggerPayload>();
|
|
|
|
|
var cronExpression = payload.CronExpression;
|
2024-05-29 21:49:40 +00:00
|
|
|
|
|
|
|
|
if (string.IsNullOrWhiteSpace(cronExpression))
|
|
|
|
|
{
|
|
|
|
|
_logger.LogWarning("Cron expression is empty. TriggerId: {TriggerId}. Skipping scheduling of this trigger", trigger.Id);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-21 10:12:28 +00:00
|
|
|
var input = new { CronExpression = cronExpression }.ToDictionary();
|
2023-04-12 19:10:07 +00:00
|
|
|
var request = new DispatchWorkflowDefinitionRequest
|
|
|
|
|
{
|
|
|
|
|
DefinitionId = trigger.WorkflowDefinitionId,
|
|
|
|
|
VersionOptions = VersionOptions.Published,
|
|
|
|
|
TriggerActivityId = trigger.ActivityId,
|
|
|
|
|
Input = input
|
|
|
|
|
};
|
2024-02-09 18:37:06 +00:00
|
|
|
try
|
|
|
|
|
{
|
2024-05-29 08:34:44 +00:00
|
|
|
await workflowScheduler.ScheduleCronAsync(trigger.Id, request, cronExpression, cancellationToken);
|
2024-02-09 18:37:06 +00:00
|
|
|
}
|
|
|
|
|
catch (FormatException ex)
|
|
|
|
|
{
|
2024-05-29 08:34:44 +00:00
|
|
|
logger.LogWarning($"Cron expression format error: {ex.Message}. CronExpression: {cronExpression}");
|
2024-02-09 18:37:06 +00:00
|
|
|
}
|
2023-04-12 19:10:07 +00:00
|
|
|
}
|
2023-04-11 18:17:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <inheritdoc />
|
|
|
|
|
public async Task UnscheduleAsync(IEnumerable<StoredTrigger> triggers, CancellationToken cancellationToken = default)
|
|
|
|
|
{
|
2023-07-20 09:57:20 +00:00
|
|
|
var triggerList = triggers.ToList();
|
2024-02-09 18:37:06 +00:00
|
|
|
|
2023-04-11 18:17:15 +00:00
|
|
|
// Select all Timer triggers.
|
2023-07-20 09:57:20 +00:00
|
|
|
var timerTriggers = triggerList.Filter<Activities.Timer>();
|
2023-04-11 18:17:15 +00:00
|
|
|
|
|
|
|
|
// Select all StartAt triggers.
|
2023-07-20 09:57:20 +00:00
|
|
|
var startAtTriggers = triggerList.Filter<StartAt>();
|
2023-04-16 22:11:58 +00:00
|
|
|
|
2023-06-22 09:50:43 +00:00
|
|
|
// Select all Cron triggers.
|
2023-07-20 09:57:20 +00:00
|
|
|
var cronTriggers = triggerList.Filter<Cron>();
|
2023-06-22 09:50:43 +00:00
|
|
|
|
2023-04-11 18:17:15 +00:00
|
|
|
// Concatenate the filtered triggers.
|
2023-06-23 16:38:57 +00:00
|
|
|
var filteredTriggers = timerTriggers.Concat(startAtTriggers).Concat(cronTriggers);
|
2023-04-11 18:17:15 +00:00
|
|
|
|
|
|
|
|
// Unschedule each trigger.
|
|
|
|
|
foreach (var trigger in filteredTriggers)
|
2024-05-29 08:34:44 +00:00
|
|
|
await workflowScheduler.UnscheduleAsync(trigger.Id, cancellationToken);
|
2023-04-11 18:17:15 +00:00
|
|
|
}
|
2023-06-22 09:50:43 +00:00
|
|
|
}
|