using Elsa.Common;
using Elsa.Common.Multitenancy;
using Elsa.Common.Models;
using Elsa.Scheduling.Options;
using Elsa.Workflows.Runtime;
using Elsa.Workflows.Runtime.Filters;
using Elsa.Workflows.Runtime.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
namespace Elsa.Scheduling.StartupTasks;
///
/// Enqueues schedule creation when using the default scheduler, which doesn't have its own persistence layer like Quartz or Hangfire.
///
[TaskDependency(typeof(PopulateRegistriesStartupTask))]
public class CreateSchedulesStartupTask(IServiceProvider serviceProvider, IOptions options) : IStartupTask
{
public async Task ExecuteAsync(CancellationToken cancellationToken)
{
var workQueue = serviceProvider.GetService();
if (workQueue != null)
await workQueue.EnqueueAsync(CreateSchedulesAsync, cancellationToken);
else
await CreateSchedulesAsync(serviceProvider, cancellationToken);
}
private async Task CreateSchedulesAsync(IServiceProvider serviceProvider, CancellationToken cancellationToken)
{
var triggerStore = serviceProvider.GetRequiredService();
var bookmarkStore = serviceProvider.GetRequiredService();
var triggerScheduler = serviceProvider.GetRequiredService();
var bookmarkScheduler = serviceProvider.GetRequiredService();
var pageSize = Math.Max(1, options.Value.StartupSchedulePageSize);
var stimulusNames = new[]
{
SchedulingStimulusNames.Cron, SchedulingStimulusNames.Timer, SchedulingStimulusNames.StartAt, SchedulingStimulusNames.Delay,
};
var triggerFilter = new TriggerFilter
{
Names = stimulusNames
};
var bookmarkFilter = new BookmarkFilter
{
Names = stimulusNames
};
await ScheduleTriggersAsync(triggerStore, triggerScheduler, triggerFilter, pageSize, cancellationToken);
await ScheduleBookmarksAsync(bookmarkStore, bookmarkScheduler, bookmarkFilter, pageSize, cancellationToken);
}
private static async Task ScheduleTriggersAsync(ITriggerStore triggerStore, ITriggerScheduler triggerScheduler, TriggerFilter triggerFilter, int pageSize, CancellationToken cancellationToken)
{
var pageArgs = PageArgs.FromRange(0, pageSize);
while (true)
{
var page = await triggerStore.FindManyAsync(triggerFilter, pageArgs, cancellationToken);
if (page.Items.Count == 0)
break;
await triggerScheduler.ScheduleAsync(page.Items, cancellationToken);
var nextOffset = pageArgs.Offset.GetValueOrDefault() + page.Items.Count;
if (nextOffset >= page.TotalCount)
break;
pageArgs = pageArgs.Next();
}
}
private static async Task ScheduleBookmarksAsync(IBookmarkStore bookmarkStore, IBookmarkScheduler bookmarkScheduler, BookmarkFilter bookmarkFilter, int pageSize, CancellationToken cancellationToken)
{
var pageArgs = PageArgs.FromRange(0, pageSize);
while (true)
{
var page = await bookmarkStore.FindManyAsync(bookmarkFilter, pageArgs, cancellationToken);
if (page.Items.Count == 0)
break;
await bookmarkScheduler.ScheduleAsync(page.Items, cancellationToken);
var nextOffset = pageArgs.Offset.GetValueOrDefault() + page.Items.Count;
if (nextOffset >= page.TotalCount)
break;
pageArgs = pageArgs.Next();
}
}
}