From bc8eb1ac0d44bf22282aaddf55bb5cc23109265a Mon Sep 17 00:00:00 2001 From: Mira <56395159+TheXorog@users.noreply.github.com> Date: Sun, 6 Aug 2023 19:13:35 +0200 Subject: [PATCH] refactor!: Use Func for scheduled tasks --- Entities/ScheduledTask.cs | 35 ++++++++++++ EventArgs/ScheduledTaskStartedEventArgs.cs | 22 ++++++++ Extensions/ScheduledTaskExtensions.cs | 65 ++++++++++++---------- Global.cs | 2 - Internal/Internal.cs | 40 ++----------- 5 files changed, 98 insertions(+), 66 deletions(-) create mode 100644 Entities/ScheduledTask.cs create mode 100644 EventArgs/ScheduledTaskStartedEventArgs.cs diff --git a/Entities/ScheduledTask.cs b/Entities/ScheduledTask.cs new file mode 100644 index 0000000..7c78eb6 --- /dev/null +++ b/Entities/ScheduledTask.cs @@ -0,0 +1,35 @@ +namespace Xorog.UniversalExtensions.Entities; + +public class ScheduledTask +{ + internal ScheduledTask() + { + this.Uid = Guid.NewGuid().ToString(); + } + + /// + /// The unique identifier of this task. + /// + public string Uid { get; internal set; } + + /// + /// The custom data asscociated with this task. + /// + public object? CustomData { get; internal set; } + + /// + /// The time this task will run. + /// + public DateTime? RunTime { get; internal set; } + + /// + /// The to prematurely dequeue this task. + /// + internal CancellationTokenSource? TokenSource { get; set; } = new(); + + /// + /// Delete this task. + /// + public void Delete() => + ScheduledTaskExtensions.DeleteScheduledTask(Uid); +} diff --git a/EventArgs/ScheduledTaskStartedEventArgs.cs b/EventArgs/ScheduledTaskStartedEventArgs.cs new file mode 100644 index 0000000..f8e3471 --- /dev/null +++ b/EventArgs/ScheduledTaskStartedEventArgs.cs @@ -0,0 +1,22 @@ +using Xorog.UniversalExtensions.Entities; + +namespace Xorog.UniversalExtensions.EventArgs; + +public class ScheduledTaskStartedEventArgs : System.EventArgs +{ + internal ScheduledTaskStartedEventArgs(ScheduledTask details, Task task) + { + this.Details = details; + this.Task = task; + } + + /// + /// The details of this scheduled task. + /// + public ScheduledTask Details { get; internal set; } + + /// + /// The task that was executed. + /// + public Task Task { get; internal set; } +} diff --git a/Extensions/ScheduledTaskExtensions.cs b/Extensions/ScheduledTaskExtensions.cs index 74f675c..a9473d9 100644 --- a/Extensions/ScheduledTaskExtensions.cs +++ b/Extensions/ScheduledTaskExtensions.cs @@ -1,52 +1,61 @@ -namespace Xorog.UniversalExtensions; +using Xorog.UniversalExtensions.Entities; +using Xorog.UniversalExtensions.EventArgs; + +namespace Xorog.UniversalExtensions; public static class ScheduledTaskExtensions { + /// + /// Fired when a log message has been sent. + /// + public static event EventHandler? TaskStarted; + /// /// Create a scheduled task /// - /// The task to run + /// The task to run /// The time to run the task /// Any custom data you wish to provide. /// An unique identifier of the task - public static string CreateScheduledTask(this Task task, DateTime runTime, object? customData = null) + public static string CreateScheduledTask(this Func taskFunc, DateTime runTime, object? customData = null) { - if (task.Status != TaskStatus.Created) - throw new InvalidOperationException("The task is already being executed or has been scheduled for execution.") - .AttachData("Task", task) - .AttachData("RunTime", runTime) - .AttachData("CustomData", customData); - string UID = Guid.NewGuid().ToString(); CancellationTokenSource CancellationToken = new CancellationTokenSource(); if (Math.Ceiling(runTime.GetTimespanUntil().TotalMilliseconds) < 0) runTime = DateTime.UtcNow.AddSeconds(1); + var scheduledTask = new ScheduledTask + { + Uid = UID, + RunTime = runTime, + TokenSource = CancellationToken, + CustomData = customData, + }; + _ = LongDelay(runTime.GetTimespanUntil(), CancellationToken).ContinueWith(x => { - lock (RegisteredScheduledTasks) + lock (InternalScheduler.RegisteredScheduledTasks) { - RegisteredScheduledTasks.Remove(UID); + InternalScheduler.RegisteredScheduledTasks.Remove(UID); } _logger?.LogDebug("Running scheduled task with UID '{UID}'", UID, runTime.GetTimespanUntil().GetHumanReadable()); if (x.IsCompletedSuccessfully) - task.Start(); + { + var task = Task.Run(taskFunc); + _ = Task.Run(() => + { + ScheduledTaskExtensions.TaskStarted?.Invoke(null, new ScheduledTaskStartedEventArgs(scheduledTask, task)); + }); + } }); - lock (RegisteredScheduledTasks) + lock (InternalScheduler.RegisteredScheduledTasks) { _logger?.LogDebug("Creating scheduled task with UID '{UID}' running in {RunTime}", UID, runTime.GetTimespanUntil().GetHumanReadable()); - - RegisteredScheduledTasks.Add(UID, new ScheduledTask - { - Uid = UID, - RunTime = runTime, - TokenSource = CancellationToken, - CustomData = customData, - }); + InternalScheduler.RegisteredScheduledTasks.Add(UID, scheduledTask); } return UID; } @@ -60,18 +69,18 @@ public static class ScheduledTaskExtensions /// Throws if the task hasn't been found or if an internal error occurred public static void DeleteScheduledTask(string UID) { - if (!RegisteredScheduledTasks.ContainsKey(UID)) + if (!InternalScheduler.RegisteredScheduledTasks.ContainsKey(UID)) throw new KeyNotFoundException($"No scheduled task has been found with UID '{UID}'"); - if (RegisteredScheduledTasks[UID].TokenSource is null) + if (InternalScheduler.RegisteredScheduledTasks[UID].TokenSource is null) throw new Exception($"Internal: There is no token source registered the specified task."); _logger?.LogDebug("Deleting scheduled task with UID '{UID}'", UID); - lock (RegisteredScheduledTasks) + lock (InternalScheduler.RegisteredScheduledTasks) { - RegisteredScheduledTasks[UID].TokenSource?.Cancel(); - RegisteredScheduledTasks.Remove(UID); + InternalScheduler.RegisteredScheduledTasks[UID].TokenSource?.Cancel(); + InternalScheduler.RegisteredScheduledTasks.Remove(UID); } return; } @@ -83,7 +92,7 @@ public static class ScheduledTaskExtensions /// /// A list of all registered tasks public static IReadOnlyList? GetScheduledTasks() - => RegisteredScheduledTasks.Select(x => x.Value).ToList().AsReadOnly(); + => InternalScheduler.RegisteredScheduledTasks.Select(x => x.Value).ToList().AsReadOnly(); /// /// Gets a specific task @@ -92,7 +101,7 @@ public static class ScheduledTaskExtensions /// The task /// Throws if the task has not been found public static ScheduledTask GetScheduledTask(string UID) - => RegisteredScheduledTasks[UID]; + => InternalScheduler.RegisteredScheduledTasks[UID]; internal static async Task LongDelay(TimeSpan delay, CancellationTokenSource token) { diff --git a/Global.cs b/Global.cs index 05154bc..1d92821 100644 --- a/Global.cs +++ b/Global.cs @@ -9,6 +9,4 @@ global using System.Drawing; global using Microsoft.Extensions.Logging; global using Xorog.UniversalExtensions.Enums; -global using static Xorog.UniversalExtensions.Internal; -global using static Xorog.UniversalExtensions.InternalSheduler; global using static Xorog.UniversalExtensions.Log; \ No newline at end of file diff --git a/Internal/Internal.cs b/Internal/Internal.cs index 69b4697..da5267d 100644 --- a/Internal/Internal.cs +++ b/Internal/Internal.cs @@ -1,4 +1,6 @@ -namespace Xorog.UniversalExtensions; +using Xorog.UniversalExtensions.Entities; + +namespace Xorog.UniversalExtensions; internal static class Internal { @@ -79,43 +81,9 @@ internal static class Internal } } -public class InternalSheduler +internal class InternalScheduler { public static Dictionary RegisteredScheduledTasks { get; internal set; } = new Dictionary(); - - public class ScheduledTask - { - public ScheduledTask() - { - this.Uid = Guid.NewGuid().ToString(); - } - - /// - /// The unique identifier of this task. - /// - public string Uid { get; internal set; } - - /// - /// The custom data asscociated with this task. - /// - public object? CustomData { get; internal set; } - - /// - /// The time this task will run. - /// - public DateTime? RunTime { get; internal set; } - - /// - /// The to prematurely dequeue this task. - /// - internal CancellationTokenSource? TokenSource { get; set; } = new(); - - /// - /// Delete this task. - /// - public void Delete() => - ScheduledTaskExtensions.DeleteScheduledTask(Uid); - } } public class HumanReadableTimeFormatConfig