elsa-core/src/modules/Elsa.Scheduling/ScheduledTasks/ScheduledSpecificInstantTask.cs
Sipke Schoorstra dd812645c7 Refactor imports to reduce use of Elsa.Common.Contracts
Consolidate imports by replacing Elsa.Common.Contracts with Elsa.Common and Elsa.Common.Multitenancy. This update streamlines import statements across various modules, improving code readability and maintainability.
2024-10-05 18:30:45 +02:00

80 lines
2.5 KiB
C#

using Elsa.Common;
using Elsa.Mediator.Contracts;
using Elsa.Scheduling.Commands;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Timer = System.Timers.Timer;
namespace Elsa.Scheduling.ScheduledTasks;
/// <summary>
/// A task that is scheduled to execute at a specific instant.
/// </summary>
public class ScheduledSpecificInstantTask : IScheduledTask, IDisposable
{
private readonly ITask _task;
private readonly ISystemClock _systemClock;
private readonly IServiceScopeFactory _scopeFactory;
private readonly ILogger<ScheduledSpecificInstantTask> _logger;
private readonly DateTimeOffset _startAt;
private readonly CancellationTokenSource _cancellationTokenSource;
private Timer? _timer;
/// <summary>
/// Initializes a new instance of <see cref="ScheduledSpecificInstantTask"/>.
/// </summary>
public ScheduledSpecificInstantTask(ITask task, DateTimeOffset startAt, ISystemClock systemClock, IServiceScopeFactory scopeFactory, ILogger<ScheduledSpecificInstantTask> logger)
{
_task = task;
_systemClock = systemClock;
_scopeFactory = scopeFactory;
_logger = logger;
_startAt = startAt;
_cancellationTokenSource = new CancellationTokenSource();
Schedule();
}
/// <inheritdoc />
public void Cancel() => _timer?.Dispose();
private void Schedule()
{
var now = _systemClock.UtcNow;
var delay = _startAt - now;
if (delay.Milliseconds <= 0)
delay = TimeSpan.FromMilliseconds(1);
_timer = new Timer(delay.TotalMilliseconds) { Enabled = true };
_timer.Elapsed += async (_, _) =>
{
_timer?.Dispose();
_timer = null;
using var scope = _scopeFactory.CreateScope();
var commandSender = scope.ServiceProvider.GetRequiredService<ICommandSender>();
var cancellationToken = _cancellationTokenSource.Token;
if (!cancellationToken.IsCancellationRequested)
{
try
{
await commandSender.SendAsync(new RunScheduledTask(_task), cancellationToken);
}
catch (Exception e)
{
_logger.LogError(e, "Error scheduled task");
}
}
};
}
void IDisposable.Dispose()
{
_cancellationTokenSource.Dispose();
_timer?.Dispose();
}
}