Skip to content

Use TaskKey object rather than string #36

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions Gofer.NET.Tests/GivenARecurringTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)));
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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<Exception>();
}
Expand Down
2 changes: 1 addition & 1 deletion Gofer.NET.Tests/GivenATaskScheduler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
10 changes: 5 additions & 5 deletions RecurringTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
Expand All @@ -34,7 +34,7 @@ public RecurringTask() { }
public RecurringTask(
TaskInfo taskInfo,
TimeSpan interval,
string taskKey) : this(taskInfo, taskKey)
TaskKey taskKey) : this(taskInfo, taskKey)
{
Interval = interval;

Expand All @@ -44,15 +44,15 @@ public RecurringTask(
public RecurringTask(
TaskInfo taskInfo,
string crontab,
string taskKey) : this(taskInfo, taskKey)
TaskKey taskKey) : this(taskInfo, taskKey)
{
ValidateCrontab(crontab);
Crontab = crontab;

FirstRunTime = GetNextRunTime(DateTime.UtcNow);
}

private RecurringTask(TaskInfo taskInfo, string taskKey)
private RecurringTask(TaskInfo taskInfo, TaskKey taskKey)
{
TaskInfo = taskInfo;
StartTime = DateTime.UtcNow;
Expand Down Expand Up @@ -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.");
}
Expand Down
8 changes: 4 additions & 4 deletions ScheduledTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
Expand All @@ -25,22 +25,22 @@ 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)
{
}

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;
Expand Down
55 changes: 55 additions & 0 deletions TaskKey.cs
Original file line number Diff line number Diff line change
@@ -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;
}
}
}
54 changes: 32 additions & 22 deletions TaskScheduler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public async Task Tick(bool forceRunPromotion=false)

public async Task<ScheduledTask> AddScheduledTask(Expression<Action> action, TimeSpan offsetFromNow)
{
var scheduledTask = new ScheduledTask(action.ToTaskInfo(), offsetFromNow, UniqueTaskKey());
var scheduledTask = new ScheduledTask(action.ToTaskInfo(), offsetFromNow, TaskKey.CreateUnique());

await EnqueueScheduledTask(scheduledTask);

Expand All @@ -78,7 +78,7 @@ public async Task<ScheduledTask> AddScheduledTask(Expression<Action> action, Tim

public async Task<ScheduledTask> AddScheduledTask(Expression<Action> action, DateTimeOffset scheduledTime)
{
var scheduledTask = new ScheduledTask(action.ToTaskInfo(), scheduledTime, UniqueTaskKey());
var scheduledTask = new ScheduledTask(action.ToTaskInfo(), scheduledTime, TaskKey.CreateUnique());

await EnqueueScheduledTask(scheduledTask);

Expand All @@ -87,7 +87,7 @@ public async Task<ScheduledTask> AddScheduledTask(Expression<Action> action, Dat

public async Task<ScheduledTask> AddScheduledTask(Expression<Action> action, DateTime scheduledTime)
{
var scheduledTask = new ScheduledTask(action.ToTaskInfo(), scheduledTime, UniqueTaskKey());
var scheduledTask = new ScheduledTask(action.ToTaskInfo(), scheduledTime, TaskKey.CreateUnique());

await EnqueueScheduledTask(scheduledTask);

Expand All @@ -96,7 +96,8 @@ public async Task<ScheduledTask> AddScheduledTask(Expression<Action> action, Dat

public async Task<RecurringTask> AddRecurringTask(Expression<Action> 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))
{
Expand All @@ -109,7 +110,8 @@ public async Task<RecurringTask> AddRecurringTask(Expression<Action> action, Tim

public async Task<RecurringTask> AddRecurringTask(Expression<Action> 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))
{
Expand All @@ -124,12 +126,17 @@ public async Task<bool> CancelRecurringTask(RecurringTask recurringTask)
return await CancelTask(recurringTask.TaskKey);
}

public async Task<bool> CancelRecurringTask(string taskName)
{
return await CancelTask(TaskKey.CreateRecurring(taskName));
}

public async Task<bool> CancelScheduledTask(ScheduledTask scheduledTask)
{
return await CancelTask(scheduledTask.TaskKey);
}

public async Task<bool> CancelTask(string taskKey)
public async Task<bool> CancelTask(TaskKey taskKey)
{
if (LoadedCancelTaskScript == null)
{
Expand All @@ -142,12 +149,25 @@ public async Task<bool> CancelTask(string taskKey)
(RedisKey) ScheduledTasksMapKey,
},
new [] {
(RedisValue) taskKey
(RedisValue) taskKey.Value
});

return (bool) didCancel;
}

public async Task<RecurringTask> GetRecurringTask(TaskKey taskKey)
{
var serializedRecurringTask = await _taskQueue.Backend.GetMapField(ScheduledTasksMapKey,
$"serializedRecurringTask::{taskKey.Value}");

if (string.IsNullOrEmpty(serializedRecurringTask))
return null;

var recurringTask = JsonTaskInfoSerializer.Deserialize<RecurringTask>(serializedRecurringTask);

return recurringTask;
}

public async Task<RecurringTask> GetRecurringTask(string taskKey)
{
var serializedRecurringTask = await _taskQueue.Backend.GetMapField(ScheduledTasksMapKey,
Expand Down Expand Up @@ -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)));

Expand All @@ -207,21 +227,21 @@ await _taskQueue.Backend.SetMapFields(ScheduledTasksMapKey,
await _taskQueue.Backend.AddToOrderedSet(
ScheduledTasksOrderedSetKey,
nextRunTimestamp,
recurringTask.TaskKey);
recurringTask.TaskKey.Value);
}

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()
Expand Down Expand Up @@ -251,7 +271,7 @@ private async Task RescheduleRecurringTasks()
recurringTask = JsonTaskInfoSerializer.Deserialize<RecurringTask>(serializedRecurringTask);
nextRunTimestamp = recurringTask.GetNextRunTimestamp(DateTime.UtcNow);

args.Add((RedisValue) recurringTask.TaskKey);
args.Add((RedisValue) recurringTask.TaskKey.Value);
args.Add((RedisValue) nextRunTimestamp);
}

Expand Down Expand Up @@ -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}";
}
}
}