< Summary

Information
Class: Elsa.UserTasks.Services.DefaultUserTaskDueService
Assembly: Elsa.UserTasks
File(s): /home/runner/work/elsa-core/elsa-core/src/modules/Elsa.UserTasks/Services/DefaultUserTaskDueService.cs
Line coverage
63%
Covered lines: 28
Uncovered lines: 16
Coverable lines: 44
Total lines: 74
Line coverage: 63.6%
Branch coverage
42%
Covered branches: 11
Total branches: 26
Branch coverage: 42.3%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
MarkOverdueAsync()59.09%382267.74%

File(s)

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.UserTasks/Services/DefaultUserTaskDueService.cs

#LineLine coverage
 1using Elsa.Common;
 2using Elsa.UserTasks.Contracts;
 3using Elsa.UserTasks.Models;
 4using Elsa.Workflows;
 5
 6namespace Elsa.UserTasks.Services;
 7
 18public sealed class DefaultUserTaskDueService(
 19    IUserTaskRepository repository,
 110    IUserTaskManager manager,
 111    IUserTaskNotificationSink notifications,
 112    IIdentityGenerator identityGenerator,
 113    ISystemClock clock) : IUserTaskDueService
 14{
 15    public async Task<int> MarkOverdueAsync(string tenantId, DateTimeOffset? now = null, CancellationToken cancellationT
 16    {
 117        var scanNow = now ?? clock.UtcNow;
 118        var cursor = (string?)null;
 119        var marked = 0;
 20
 21        do
 22        {
 123            var due = await repository.QueryAsync(new UserTaskQuery
 124            {
 125                TenantId = tenantId,
 126                DueTo = scanNow,
 127                Cursor = cursor,
 128                Sort = "due",
 129                Limit = 200
 130            }, cancellationToken);
 31
 532            foreach (var task in due.Items.Where(x => !x.IsTerminal && x.DueAt <= scanNow))
 33            {
 134                if (task.EnableTimeoutOutcome)
 35                {
 36                    try
 37                    {
 138                        var result = await manager.TimeoutAsync(tenantId, task.Id, task.Revision, scanNow, cancellationT
 139                        if (result.Accepted)
 140                            marked++;
 141                    }
 042                    catch (Exception exception) when (exception is not OperationCanceledException)
 43                    {
 44                        // The accepted transition remains durable and is repaired by reconciliation if
 45                        // bookmark delivery failed. Continue scanning other tasks.
 046                    }
 47
 48                    continue;
 49                }
 50
 051                if (task.IsOverdue || !await repository.TryMutateAsync(tenantId, task.Id, task.Revision, current =>
 052                    {
 053                        if (current.IsOverdue || current.IsTerminal)
 054                            return false;
 055                        current.IsOverdue = true;
 056                        current.Events.Add(new UserTaskEvent(identityGenerator.GenerateId(), tenantId, current.Id, curre
 057                            "OverdueNotified", clock.UtcNow));
 058                        return true;
 059                    }, cancellationToken))
 60                    continue;
 61
 062                marked++;
 063                var committed = await repository.GetAsync(tenantId, task.Id, cancellationToken);
 064                if (committed != null)
 065                    await notifications.PublishAsync(new UserTaskOverdue(tenantId, committed.Id, committed.Status, commi
 066            }
 67
 168            cursor = due.NextCursor;
 169        }
 170        while (cursor != null);
 71
 172        return marked;
 173    }
 74}