public async Task AsyncFunc(string semaphoreFile) { // Wait to ensure async waiting is happening. await Task.Delay(1000); TaskQueueTestFixture.WriteSemaphoreValue(semaphoreFile, "async"); }
public async Task ItAllowsForRecurringTasksTaskInfoToBeChanged() { var taskName = Guid.NewGuid().ToString(); var taskQueue = TaskQueueTestFixture.UniqueRedisTaskQueue(); var taskScheduler = new TaskScheduler(taskQueue); var recurringTask = await taskScheduler.AddRecurringTask(() => TaskQueueTestFixture.WriteSemaphore("afile"), $"*/{IntervalSeconds} * * * * *", taskName); var fetchedRecurringTask = await taskScheduler.GetRecurringTask(recurringTask.TaskKey); fetchedRecurringTask.TaskInfo.MethodName.Should().Be("WriteSemaphore"); fetchedRecurringTask.Interval.Should().BeNull(); fetchedRecurringTask.Crontab.Should().Be($"*/{IntervalSeconds} * * * * *"); fetchedRecurringTask.TaskInfo.Args[0].Should().Be("afile"); // Different Argument await taskScheduler.AddRecurringTask(() => TaskQueueTestFixture.WriteSemaphore("bfile"), $"*/{IntervalSeconds} * * * * *", taskName); fetchedRecurringTask = await taskScheduler.GetRecurringTask(recurringTask.TaskKey); fetchedRecurringTask.TaskInfo.MethodName.Should().Be("WriteSemaphore"); fetchedRecurringTask.Interval.Should().BeNull(); fetchedRecurringTask.Crontab.Should().Be($"*/{IntervalSeconds} * * * * *"); fetchedRecurringTask.TaskInfo.Args[0].Should().Be("bfile"); // Different Interval await taskScheduler.AddRecurringTask(() => TaskQueueTestFixture.WriteSemaphore("bfile"), TimeSpan.FromSeconds(IntervalSeconds), taskName); fetchedRecurringTask = await taskScheduler.GetRecurringTask(recurringTask.TaskKey); fetchedRecurringTask.TaskInfo.MethodName.Should().Be("WriteSemaphore"); fetchedRecurringTask.Interval.Should().Be(TimeSpan.FromSeconds(IntervalSeconds)); fetchedRecurringTask.Crontab.Should().BeNull(); fetchedRecurringTask.TaskInfo.Args[0].Should().Be("bfile"); // Different Target Method await taskScheduler.AddRecurringTask(() => TaskQueueTestFixture.WriteSemaphoreValue("bfile", "avalue"), TimeSpan.FromSeconds(IntervalSeconds), taskName); fetchedRecurringTask = await taskScheduler.GetRecurringTask(recurringTask.TaskKey); fetchedRecurringTask.TaskInfo.MethodName.Should().Be("WriteSemaphoreValue"); fetchedRecurringTask.Interval.Should().Be(TimeSpan.FromSeconds(IntervalSeconds)); fetchedRecurringTask.Crontab.Should().BeNull(); fetchedRecurringTask.TaskInfo.Args[0].Should().Be("bfile"); fetchedRecurringTask.TaskInfo.Args[1].Should().Be("avalue"); }
public void ArrayFunc3(int?[] nums, string semaphoreFile) { var str = ""; var first = true; foreach (var num in nums) { if (!first) { str += ","; } str += num?.ToString() ?? "null"; first = false; } TaskQueueTestFixture.WriteSemaphoreValue(semaphoreFile, str); }
public async Task ItExecutesImmediateAndScheduledTasksInOrder() { const int immediateTasks = 5; const int scheduledTasks = 20; const int scheduledTasksStart = -100; const int scheduledTasksIncrement = 50; var taskQueue = TaskQueueTestFixture.UniqueRedisTaskQueue(); var taskClient = new TaskClient(taskQueue); var semaphoreFile = Path.GetTempFileName(); File.Delete(semaphoreFile); File.Exists(semaphoreFile).Should().BeFalse(); for (var i = 0; i < immediateTasks; ++i) { await taskClient.TaskQueue.Enqueue(() => TaskQueueTestFixture.WriteSemaphoreValue(semaphoreFile, (i + 1).ToString())); } for (var i = 0; i < scheduledTasks; ++i) { await taskClient.TaskScheduler.AddScheduledTask( () => TaskQueueTestFixture.WriteSemaphoreValue(semaphoreFile, (immediateTasks + i + 1).ToString()), TimeSpan.FromMilliseconds(scheduledTasksStart + (scheduledTasksIncrement *i))); } var task = Task.Run(async() => await taskClient.Listen()); Thread.Sleep(scheduledTasks * scheduledTasksIncrement + 2000); var expectedFileContents = Enumerable .Range(1, immediateTasks + scheduledTasks) .Aggregate("", (acc, v) => acc + v.ToString()); File.Exists(semaphoreFile).Should().BeTrue(); File.ReadAllText(semaphoreFile).Should().Be(expectedFileContents); taskClient.CancelListen(); await task; }
public void ArrayFunc2(int[] nums, string semaphoreFile) { TaskQueueTestFixture.WriteSemaphoreValue(semaphoreFile, string.Join(",", nums)); }
public void TypeFunc(Type typeArg, string semaphoreFile) { TaskQueueTestFixture.WriteSemaphoreValue(semaphoreFile, typeArg?.ToString() ?? "null"); }
public void ExceptionFunc(Exception exc, string semaphoreFile) { TaskQueueTestFixture.WriteSemaphoreValue(semaphoreFile, exc); }
public void ObjectFunc(object num, string semaphoreFile) { TaskQueueTestFixture.WriteSemaphoreValue(semaphoreFile, num); }
public void StringFunc(string num, string semaphoreFile) { TaskQueueTestFixture.WriteSemaphoreValue(semaphoreFile, num); }
public void DoubleFunc(double num, string semaphoreFile) { TaskQueueTestFixture.WriteSemaphoreValue(semaphoreFile, num); }
public void BoolFunc(bool num, string semaphoreFile) { TaskQueueTestFixture.WriteSemaphoreValue(semaphoreFile, num); }
public void FloatFunc(float num, string semaphoreFile) { TaskQueueTestFixture.WriteSemaphoreValue(semaphoreFile, num); }
public void NullableIntFunc(int?num, string semaphoreFile) { TaskQueueTestFixture.WriteSemaphoreValue(semaphoreFile, num ?? -1); }
public void DateTimeFunc(DateTime dateTime, string semaphoreFile) { TaskQueueTestFixture.WriteSemaphoreValue(semaphoreFile, dateTime); }
public async Task ItExecutesScheduledTasksOnlyOnce() { const int numberOfTasks = 1000; const int tasksPerTimeInterval = 25; const int timeInterval = 1000; const int numberOfSchedulerThreads = 4; TimeSpan promotionFrequency = TimeSpan.FromMilliseconds(100); ThreadPool.SetMinThreads(numberOfSchedulerThreads * 4, 200); var taskQueue = TaskQueueTestFixture.UniqueRedisTaskQueue(); var taskScheduler = new TaskScheduler(taskQueue, promotionFrequency); var canceled = false; var taskSchedulerTasks = new List <Task>(); var taskRunnerTasks = new List <Task>(); for (var s = 0; s < numberOfSchedulerThreads; ++s) { taskSchedulerTasks.Add(Task.Run(async() => { var inThreadTaskScheduler = new TaskScheduler(taskQueue); while (!canceled) { await inThreadTaskScheduler.Tick(forceRunPromotion: true); } })); taskRunnerTasks.Add(Task.Run(async() => { while (!canceled) { await taskQueue.ExecuteNext(); } })); } var tasks = new List <(ScheduledTask, string, string)>(); System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew(); for (var i = 0; i < numberOfTasks / tasksPerTimeInterval; ++i) { for (var k = 0; k < tasksPerTimeInterval; ++k) { var semaphoreFile = Path.GetTempFileName(); File.Delete(semaphoreFile); semaphoreFile = semaphoreFile + Guid.NewGuid().ToString(); var semaphoreValue = Guid.NewGuid().ToString(); var scheduledTask = await taskScheduler.AddScheduledTask( () => TaskQueueTestFixture.WriteSemaphoreValue(semaphoreFile, semaphoreValue), TimeSpan.FromMilliseconds((i + 1) * timeInterval)); tasks.Add((scheduledTask, semaphoreFile, semaphoreValue)); } } _testOutputHelper.WriteLine(sw.ElapsedMilliseconds.ToString()); var precisionAllowanceFactorMs = promotionFrequency.TotalMilliseconds + 10; long now; for (var i = 0; i < numberOfTasks / tasksPerTimeInterval; ++i) { Thread.Sleep(timeInterval); // EACH TASK, 3 Cases // CASE 1: Scheduled Time should have run, allowing for precision loss // CASE 2: Scheduled Time should definitely not have run // CASE 3: Scheduled Time is past, but within precision allowance (may have run or not) foreach (var task in tasks) { now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); if (task.Item1.ScheduledUnixTimeMilliseconds <= (now - precisionAllowanceFactorMs)) { File.Exists(task.Item2).Should().BeTrue(); File.ReadAllText(task.Item2).Should().Be(task.Item3); } else if (task.Item1.ScheduledUnixTimeMilliseconds > now) { File.Exists(task.Item2).Should().BeFalse(); } } } Thread.Sleep((int)precisionAllowanceFactorMs); foreach (var task in tasks) { File.Exists(task.Item2).Should().BeTrue(); File.ReadAllText(task.Item2).Should().Be(task.Item3); } canceled = true; await Task.WhenAll(taskSchedulerTasks); await Task.WhenAll(taskRunnerTasks); }
public async Task ItExecutesCrontabRecurringTasksAccordingToTheirSchedules() { const int numberOfTasks = 10; const int timeInterval = 1000; const int testIntervals = 10; const int numberOfSchedulerThreads = 4; const int precisionAllowanceFactorMs = 800; ThreadPool.SetMinThreads(numberOfSchedulerThreads * 4, 200); var taskQueue = TaskQueueTestFixture.UniqueRedisTaskQueue(); var taskScheduler = new TaskScheduler(taskQueue); var canceled = false; var taskSchedulerTasks = new List <Task>(); var taskRunnerTasks = new List <Task>(); for (var s = 0; s < numberOfSchedulerThreads; ++s) { taskSchedulerTasks.Add(Task.Run(async() => { var inThreadTaskScheduler = new TaskScheduler(taskQueue); while (!canceled) { await inThreadTaskScheduler.Tick(forceRunPromotion: true); } })); taskRunnerTasks.Add(Task.Run(async() => { while (!canceled) { await taskQueue.ExecuteNext(); } })); } var tasks = new List <(RecurringTask, string, string)>(); for (var i = 0; i < numberOfTasks; ++i) { var semaphoreFile = Path.GetTempFileName(); File.Delete(semaphoreFile); semaphoreFile = semaphoreFile + Guid.NewGuid().ToString(); var semaphoreValue = Guid.NewGuid().ToString(); var recurringTask = await taskScheduler.AddRecurringTask( () => TaskQueueTestFixture.WriteSemaphoreValue(semaphoreFile, semaphoreValue), $"*/{timeInterval / 1000} * * * * *", Guid.NewGuid().ToString()); tasks.Add((recurringTask, semaphoreFile, semaphoreValue)); } var synchronizationFactor = DateTime.UtcNow.ToUnixTimeMilliseconds() - DateTime.UtcNow.ToUnixTimeSeconds() * 1000; Thread.Sleep((int)synchronizationFactor + 100); for (var i = 0; i < testIntervals; ++i) { Thread.Sleep(timeInterval); foreach (var task in tasks) { var diff = DateTime.UtcNow.ToUnixTimeMilliseconds() - (task.Item1.FirstRunTime.ToUnixTimeMilliseconds() - timeInterval); var elapsedIntervalsMax = diff / timeInterval; var elapsedIntervalsMin = (diff % timeInterval) <= precisionAllowanceFactorMs ? elapsedIntervalsMax - 1 : elapsedIntervalsMax; _testOutputHelper.WriteLine(diff.ToString()); elapsedIntervalsMax.Should().BeGreaterThan(i); var expectedStringMax = ""; for (var e = 0; e < elapsedIntervalsMax; ++e) { expectedStringMax += task.Item3; } var expectedStringMin = ""; for (var e = 0; e < elapsedIntervalsMin; ++e) { expectedStringMin += task.Item3; } File.Exists(task.Item2).Should().BeTrue(elapsedIntervalsMax.ToString()); var fileText = File.ReadAllText(task.Item2); if (fileText != expectedStringMax) { fileText.Should().Be(expectedStringMin); } } } canceled = true; await Task.WhenAll(taskSchedulerTasks); await Task.WhenAll(taskRunnerTasks); }