using System.Collections.Generic; using System.Linq; using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Elsa.Jobs.Schedules; using Elsa.Jobs.Services; using Elsa.Scheduling.Activities; using Elsa.Scheduling.Jobs; using Elsa.Scheduling.Services; using Elsa.Workflows.Core.Models; using Elsa.Workflows.Persistence.Entities; using Elsa.Workflows.Persistence.Extensions; namespace Elsa.Scheduling.Implementations; public class WorkflowBookmarkScheduler : IWorkflowBookmarkScheduler { private const string RootGroupKey = "WorkflowInstance"; private readonly IJobScheduler _jobScheduler; public WorkflowBookmarkScheduler(IJobScheduler jobScheduler) { _jobScheduler = jobScheduler; } public async Task ScheduleBookmarksAsync(string workflowInstanceId, IEnumerable bookmarks, CancellationToken cancellationToken = default) { var bookmarkList = bookmarks.ToList(); // Select all Delay bookmarks. var delayBookmarks = bookmarkList.Filter().ToList(); // Select all StartAt bookmarks. var startAtBookmarks = bookmarkList.Filter().ToList(); var groupKeys = new[] { RootGroupKey, workflowInstanceId }; // Schedule a trigger for each Delay bookmark. foreach (var bookmark in delayBookmarks) { var payload = JsonSerializer.Deserialize(bookmark.Data!)!; var resumeAt = payload.ResumeAt; var job = new ResumeWorkflowJob(workflowInstanceId, bookmark.Id); var schedule = new SpecificInstantSchedule(resumeAt); await _jobScheduler.ScheduleAsync(job, bookmark.Id, schedule, groupKeys, cancellationToken); } // Schedule a trigger for each StartAt bookmark. foreach (var bookmark in startAtBookmarks) { var payload = JsonSerializer.Deserialize(bookmark.Data!)!; var executeAt = payload.ExecuteAt; var job = new ResumeWorkflowJob(workflowInstanceId, bookmark.Id); var schedule = new SpecificInstantSchedule(executeAt); await _jobScheduler.ScheduleAsync(job, bookmark.Id, schedule, groupKeys, cancellationToken); } } public async Task UnscheduleBookmarksAsync(string workflowInstanceId, IEnumerable bookmarks, CancellationToken cancellationToken = default) { var bookmarkList = bookmarks.ToList(); var delayBookmarks = bookmarkList.Filter().ToList(); var startAtBookmarks = bookmarkList.Filter().ToList(); var bookmarksToUnSchedule = delayBookmarks.Concat(startAtBookmarks).ToList(); foreach (var bookmark in bookmarksToUnSchedule) await _jobScheduler.UnscheduleAsync(bookmark.Id, cancellationToken); } }