diff --git a/Gofer.NET.Tests/GivenARecurringTask.cs b/Gofer.NET.Tests/GivenARecurringTask.cs index 70aeaa2..2a9116a 100644 --- a/Gofer.NET.Tests/GivenARecurringTask.cs +++ b/Gofer.NET.Tests/GivenARecurringTask.cs @@ -15,7 +15,8 @@ public class GivenARecurringTask [Fact] public void ItPersistsPropertiesWhenSerializedAndDeserialized() { - var taskKey = $"{nameof(ItPersistsPropertiesWhenSerializedAndDeserialized)}::{Guid.NewGuid().ToString()}"; + var taskKey = + new TaskKey($"{nameof(ItPersistsPropertiesWhenSerializedAndDeserialized)}::{Guid.NewGuid().ToString()}"); var testTask = GetTestTask(() => Console.WriteLine(nameof(ItPersistsPropertiesWhenSerializedAndDeserialized))); @@ -43,7 +44,7 @@ public void ItProperlyDeterminesEquivalence() var taskInfo1 = GetTestTask(() => TestMethod1("hello world")); var taskInfo2 = GetTestTask(() => TestMethod2()); - var taskKey = $"{nameof(ItPersistsPropertiesWhenSerializedAndDeserialized)}::{Guid.NewGuid().ToString()}"; + var taskKey = new TaskKey($"{nameof(ItPersistsPropertiesWhenSerializedAndDeserialized)}::{Guid.NewGuid().ToString()}"); new RecurringTask(taskInfo1, TimeSpan.FromMinutes(5), taskKey) .IsEquivalent(new RecurringTask(taskInfo1, TimeSpan.FromMinutes(5), taskKey)) @@ -71,7 +72,7 @@ public void ItProperlyDeterminesEquivalence() Action differentIdsThrow = () => new RecurringTask(taskInfo1, TimeSpan.FromMinutes(5), taskKey) - .IsEquivalent(new RecurringTask(taskInfo1, TimeSpan.FromMinutes(5), "anothertaskkey")); + .IsEquivalent(new RecurringTask(taskInfo1, TimeSpan.FromMinutes(5), new TaskKey("anothertaskkey"))); differentIdsThrow.ShouldThrow(); } diff --git a/Gofer.NET.Tests/GivenATaskScheduler.cs b/Gofer.NET.Tests/GivenATaskScheduler.cs index db556dc..a7bdaeb 100644 --- a/Gofer.NET.Tests/GivenATaskScheduler.cs +++ b/Gofer.NET.Tests/GivenATaskScheduler.cs @@ -244,7 +244,7 @@ public async Task ItDoesNotBlowUpWhenCancelingNonExistentTasks() var taskQueue = TaskQueueTestFixture.UniqueRedisTaskQueue(); var taskScheduler = new TaskScheduler(taskQueue); - (await taskScheduler.CancelTask("hello")).Should().BeFalse(); + (await taskScheduler.CancelTask(new TaskKey("hello"))).Should().BeFalse(); } [Fact] diff --git a/RecurringTask.cs b/RecurringTask.cs index 300ad4d..2112859 100644 --- a/RecurringTask.cs +++ b/RecurringTask.cs @@ -12,7 +12,7 @@ public class RecurringTask public string LockKey => $"{nameof(RecurringTask)}::{TaskKey}::ScheduleLock"; [JsonProperty] - public string TaskKey { get; private set; } + public TaskKey TaskKey { get; private set; } [JsonProperty] public DateTime StartTime { get; private set; } @@ -34,7 +34,7 @@ public RecurringTask() { } public RecurringTask( TaskInfo taskInfo, TimeSpan interval, - string taskKey) : this(taskInfo, taskKey) + TaskKey taskKey) : this(taskInfo, taskKey) { Interval = interval; @@ -44,7 +44,7 @@ public RecurringTask( public RecurringTask( TaskInfo taskInfo, string crontab, - string taskKey) : this(taskInfo, taskKey) + TaskKey taskKey) : this(taskInfo, taskKey) { ValidateCrontab(crontab); Crontab = crontab; @@ -52,7 +52,7 @@ public RecurringTask( FirstRunTime = GetNextRunTime(DateTime.UtcNow); } - private RecurringTask(TaskInfo taskInfo, string taskKey) + private RecurringTask(TaskInfo taskInfo, TaskKey taskKey) { TaskInfo = taskInfo; StartTime = DateTime.UtcNow; @@ -122,7 +122,7 @@ public bool IsEquivalent(RecurringTask comparisonRecurringTask) throw new ArgumentException("comparisonRecurringTask must not be null"); } - if (comparisonRecurringTask.TaskKey != TaskKey) + if (!comparisonRecurringTask.TaskKey.Equals(TaskKey)) { throw new Exception("Cannot compare with a recurringTask with a different TaskKey."); } diff --git a/ScheduledTask.cs b/ScheduledTask.cs index 735a822..00298aa 100644 --- a/ScheduledTask.cs +++ b/ScheduledTask.cs @@ -12,7 +12,7 @@ public class ScheduledTask public string LockKey => $"{nameof(ScheduledTask)}::{TaskKey}::ScheduleLock"; [JsonProperty] - public string TaskKey { get; private set; } + public TaskKey TaskKey { get; private set; } [JsonProperty] public long ScheduledUnixTimeMilliseconds { get; private set; } @@ -25,7 +25,7 @@ public ScheduledTask() { } public ScheduledTask( TaskInfo taskInfo, TimeSpan offset, - string taskKey) : this(taskInfo, new DateTimeOffset(DateTime.UtcNow + offset), taskKey) + TaskKey taskKey) : this(taskInfo, new DateTimeOffset(DateTime.UtcNow + offset), taskKey) { } @@ -33,14 +33,14 @@ public ScheduledTask( TaskInfo taskInfo, DateTime scheduledTime, TaskQueue taskQueue, - string taskKey) : this(taskInfo, new DateTimeOffset(scheduledTime), taskKey) + TaskKey taskKey) : this(taskInfo, new DateTimeOffset(scheduledTime), taskKey) { } public ScheduledTask( TaskInfo taskInfo, DateTimeOffset scheduledDateTimeOffset, - string taskKey) + TaskKey taskKey) { TaskKey = taskKey; TaskInfo = taskInfo; diff --git a/TaskKey.cs b/TaskKey.cs new file mode 100644 index 0000000..edb23c7 --- /dev/null +++ b/TaskKey.cs @@ -0,0 +1,55 @@ +using System; + +namespace Gofer.NET +{ + public class TaskKey + { + public string Value { get; set; } + + public string RecurringTaskName { get; set; } + + public static TaskKey CreateUnique() + { + return new TaskKey($"{DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}::{Guid.NewGuid().ToString()}"); + } + + public static TaskKey CreateRecurring(string recurringTaskName) + { + return new TaskKey($"Recurring{nameof(TaskKey)}::{recurringTaskName}", recurringTaskName); + } + + public TaskKey() {} + + public TaskKey(string value) + { + Value = value; + RecurringTaskName = null; + } + + public TaskKey(string value, string recurringTaskName) + { + Value = value; + RecurringTaskName = recurringTaskName; + } + + public override bool Equals(object obj) + { + if (obj == null || GetType() != obj.GetType()) + { + return false; + } + + return string.Equals(Value, ((TaskKey) obj).Value); + } + + public override int GetHashCode() + { + return Value.GetHashCode(); + } + + public override string ToString() + { + return Value; + } + } +} \ No newline at end of file diff --git a/TaskScheduler.cs b/TaskScheduler.cs index babb045..b1481f1 100644 --- a/TaskScheduler.cs +++ b/TaskScheduler.cs @@ -69,7 +69,7 @@ public async Task Tick(bool forceRunPromotion=false) public async Task AddScheduledTask(Expression action, TimeSpan offsetFromNow) { - var scheduledTask = new ScheduledTask(action.ToTaskInfo(), offsetFromNow, UniqueTaskKey()); + var scheduledTask = new ScheduledTask(action.ToTaskInfo(), offsetFromNow, TaskKey.CreateUnique()); await EnqueueScheduledTask(scheduledTask); @@ -78,7 +78,7 @@ public async Task AddScheduledTask(Expression action, Tim public async Task AddScheduledTask(Expression action, DateTimeOffset scheduledTime) { - var scheduledTask = new ScheduledTask(action.ToTaskInfo(), scheduledTime, UniqueTaskKey()); + var scheduledTask = new ScheduledTask(action.ToTaskInfo(), scheduledTime, TaskKey.CreateUnique()); await EnqueueScheduledTask(scheduledTask); @@ -87,7 +87,7 @@ public async Task AddScheduledTask(Expression action, Dat public async Task AddScheduledTask(Expression action, DateTime scheduledTime) { - var scheduledTask = new ScheduledTask(action.ToTaskInfo(), scheduledTime, UniqueTaskKey()); + var scheduledTask = new ScheduledTask(action.ToTaskInfo(), scheduledTime, TaskKey.CreateUnique()); await EnqueueScheduledTask(scheduledTask); @@ -96,7 +96,8 @@ public async Task AddScheduledTask(Expression action, Dat public async Task AddRecurringTask(Expression action, TimeSpan interval, string taskName) { - var recurringTask = new RecurringTask(action.ToTaskInfo(), interval, RecurringTaskKey(taskName)); + var recurringTask = new RecurringTask(action.ToTaskInfo(), interval, + TaskKey.CreateRecurring(taskName)); if (await RecurringTaskDoesNotExistOrNeedsChange(recurringTask)) { @@ -109,7 +110,8 @@ public async Task AddRecurringTask(Expression action, Tim public async Task AddRecurringTask(Expression action, string crontab, string taskName) { - var recurringTask = new RecurringTask(action.ToTaskInfo(), crontab, RecurringTaskKey(taskName)); + var recurringTask = new RecurringTask(action.ToTaskInfo(), crontab, + TaskKey.CreateRecurring(taskName)); if (await RecurringTaskDoesNotExistOrNeedsChange(recurringTask)) { @@ -124,12 +126,17 @@ public async Task CancelRecurringTask(RecurringTask recurringTask) return await CancelTask(recurringTask.TaskKey); } + public async Task CancelRecurringTask(string taskName) + { + return await CancelTask(TaskKey.CreateRecurring(taskName)); + } + public async Task CancelScheduledTask(ScheduledTask scheduledTask) { return await CancelTask(scheduledTask.TaskKey); } - public async Task CancelTask(string taskKey) + public async Task CancelTask(TaskKey taskKey) { if (LoadedCancelTaskScript == null) { @@ -142,12 +149,25 @@ public async Task CancelTask(string taskKey) (RedisKey) ScheduledTasksMapKey, }, new [] { - (RedisValue) taskKey + (RedisValue) taskKey.Value }); return (bool) didCancel; } + public async Task GetRecurringTask(TaskKey taskKey) + { + var serializedRecurringTask = await _taskQueue.Backend.GetMapField(ScheduledTasksMapKey, + $"serializedRecurringTask::{taskKey.Value}"); + + if (string.IsNullOrEmpty(serializedRecurringTask)) + return null; + + var recurringTask = JsonTaskInfoSerializer.Deserialize(serializedRecurringTask); + + return recurringTask; + } + public async Task GetRecurringTask(string taskKey) { var serializedRecurringTask = await _taskQueue.Backend.GetMapField(ScheduledTasksMapKey, @@ -198,7 +218,7 @@ private async Task EnqueueRecurringTask(RecurringTask recurringTask) { var serializedTaskInfo = JsonTaskInfoSerializer.Serialize(recurringTask.TaskInfo); await _taskQueue.Backend.SetMapFields(ScheduledTasksMapKey, - (recurringTask.TaskKey, serializedTaskInfo), + (recurringTask.TaskKey.Value, serializedTaskInfo), ($"isRecurring::{recurringTask.TaskKey}", true), ($"serializedRecurringTask::{recurringTask.TaskKey}", JsonTaskInfoSerializer.Serialize(recurringTask))); @@ -207,7 +227,7 @@ await _taskQueue.Backend.SetMapFields(ScheduledTasksMapKey, await _taskQueue.Backend.AddToOrderedSet( ScheduledTasksOrderedSetKey, nextRunTimestamp, - recurringTask.TaskKey); + recurringTask.TaskKey.Value); } private async Task EnqueueScheduledTask(ScheduledTask scheduledTask) @@ -215,13 +235,13 @@ private async Task EnqueueScheduledTask(ScheduledTask scheduledTask) var serializedTaskInfo = JsonTaskInfoSerializer.Serialize(scheduledTask.TaskInfo); await _taskQueue.Backend.SetMapFields(ScheduledTasksMapKey, - (scheduledTask.TaskKey, serializedTaskInfo), + (scheduledTask.TaskKey.Value, serializedTaskInfo), ($"isRecurring::{scheduledTask.TaskKey}", false)); await _taskQueue.Backend.AddToOrderedSet( ScheduledTasksOrderedSetKey, scheduledTask.ScheduledUnixTimeMilliseconds, - scheduledTask.TaskKey); + scheduledTask.TaskKey.Value); } private async Task RescheduleRecurringTasks() @@ -251,7 +271,7 @@ private async Task RescheduleRecurringTasks() recurringTask = JsonTaskInfoSerializer.Deserialize(serializedRecurringTask); nextRunTimestamp = recurringTask.GetNextRunTimestamp(DateTime.UtcNow); - args.Add((RedisValue) recurringTask.TaskKey); + args.Add((RedisValue) recurringTask.TaskKey.Value); args.Add((RedisValue) nextRunTimestamp); } @@ -362,15 +382,5 @@ private string LuaScriptToCancelTask() return false "; } - - private string UniqueTaskKey() - { - return $"{DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}::{Guid.NewGuid().ToString()}"; - } - - private string RecurringTaskKey(string taskName) - { - return $"{nameof(RecurringTaskKey)}::{taskName}"; - } } }