< Summary

Information
Class: Elsa.Scheduling.Services.SchedulingBookmarkReconciler
Assembly: Elsa.Scheduling
File(s): /home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Scheduling/Services/SchedulingBookmarkReconciler.cs
Line coverage
100%
Covered lines: 39
Uncovered lines: 0
Coverable lines: 39
Total lines: 82
Line coverage: 100%
Branch coverage
93%
Covered branches: 15
Total branches: 16
Branch coverage: 93.7%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
ClassifyAsync()91.66%1212100%
PurgeAsync()100%44100%

File(s)

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Scheduling/Services/SchedulingBookmarkReconciler.cs

#LineLine coverage
 1using Elsa.Workflows;
 2using Elsa.Workflows.Management;
 3using Elsa.Workflows.Management.Filters;
 4using Elsa.Workflows.Runtime;
 5using Elsa.Workflows.Runtime.Entities;
 6using Elsa.Workflows.Runtime.Filters;
 7
 8namespace Elsa.Scheduling.Services;
 9
 10/// <summary>
 11/// Classifies Delay/Timer/Cron/StartAt stored bookmarks against the workflow-instance store so startup
 12/// schedule rebuild can skip and purge bookmarks whose instance is missing or finished.
 13/// </summary>
 10514public class SchedulingBookmarkReconciler(IWorkflowInstanceStore workflowInstanceStore, IBookmarkManager? bookmarkManage
 15{
 16    /// <summary>
 17    /// Splits bookmarks into those that may be scheduled and those whose instance is missing or terminal.
 18    /// </summary>
 19    public async Task<SchedulingBookmarkClassification> ClassifyAsync(IEnumerable<StoredBookmark> bookmarks, Cancellatio
 20    {
 2421        var bookmarkList = bookmarks as IReadOnlyList<StoredBookmark> ?? bookmarks.ToList();
 22
 2423        if (bookmarkList.Count == 0)
 124            return new SchedulingBookmarkClassification([], []);
 25
 2326        var instanceIds = bookmarkList
 4827            .Select(x => x.WorkflowInstanceId)
 4828            .Where(x => !string.IsNullOrWhiteSpace(x))
 2329            .Distinct(StringComparer.Ordinal)
 2330            .ToList();
 31
 2332        var liveInstanceIds = instanceIds.Count == 0
 2333            ? new HashSet<string>(StringComparer.Ordinal)
 2334            : (await workflowInstanceStore.FindManyIdsAsync(new WorkflowInstanceFilter
 2335            {
 2336                Ids = instanceIds,
 2337                WorkflowStatus = WorkflowStatus.Running
 2338            }, cancellationToken)).ToHashSet(StringComparer.Ordinal);
 39
 2340        var schedulable = new List<StoredBookmark>(bookmarkList.Count);
 2341        var orphans = new List<StoredBookmark>();
 42
 14243        foreach (var bookmark in bookmarkList)
 44        {
 4845            if (!string.IsNullOrWhiteSpace(bookmark.WorkflowInstanceId) && liveInstanceIds.Contains(bookmark.WorkflowIns
 1446                schedulable.Add(bookmark);
 47            else
 3448                orphans.Add(bookmark);
 49        }
 50
 2351        return new SchedulingBookmarkClassification(schedulable, orphans);
 2452    }
 53
 54    /// <summary>
 55    /// Revalidates candidates against the workflow-instance store, then deletes bookmarks that are still orphans.
 56    /// </summary>
 57    public async Task PurgeAsync(IEnumerable<StoredBookmark> candidateBookmarks, CancellationToken cancellationToken = d
 58    {
 959        if (bookmarkManager == null)
 260            return;
 61
 762        var remainingOrphans = (await ClassifyAsync(candidateBookmarks, cancellationToken)).Orphans;
 763        var bookmarkIds = remainingOrphans
 1064            .Select(x => x.Id)
 1065            .Where(x => !string.IsNullOrWhiteSpace(x))
 766            .Distinct(StringComparer.Ordinal)
 767            .ToList();
 68
 769        if (bookmarkIds.Count == 0)
 270            return;
 71
 572        await bookmarkManager.DeleteManyAsync(new BookmarkFilter
 573        {
 574            BookmarkIds = bookmarkIds
 575        }, cancellationToken);
 976    }
 77}
 78
 79/// <summary>
 80/// The schedulable vs orphan split for a batch of scheduling bookmarks.
 81/// </summary>
 82public record SchedulingBookmarkClassification(IReadOnlyList<StoredBookmark> Schedulable, IReadOnlyList<StoredBookmark>