Ejemplo n.º 1
0
        public async Task ItDoesNotDelayScheduledTaskPromotionWhenRunningLongTasks()
        {
            var waitTime = 4000;

            var taskQueue  = TaskQueueTestFixture.UniqueRedisTaskQueue();
            var taskClient = new TaskClient(taskQueue);

            var semaphoreFile = Path.GetTempFileName();

            File.Delete(semaphoreFile);
            File.Exists(semaphoreFile).Should().BeFalse();

            await taskClient.TaskQueue.Enqueue(() => Wait(waitTime));

            await taskClient.TaskScheduler.AddScheduledTask(
                () => TaskQueueTestFixture.WriteSemaphore(semaphoreFile),
                TimeSpan.FromMilliseconds(waitTime / 4));

            var task = Task.Run(async() => await taskClient.Listen());

            await Task.Delay(waitTime / 2);

            // Ensure we did not run the scheduled task
            File.Exists(semaphoreFile).Should().BeFalse();

            var dequeuedScheduledTask = await taskQueue.Dequeue();

            File.Exists(semaphoreFile).Should().BeFalse();
            dequeuedScheduledTask.Should().NotBeNull();
            dequeuedScheduledTask.MethodName.Should().Be(nameof(TaskQueueTestFixture.WriteSemaphore));

            taskClient.CancelListen();
            await task;
        }
Ejemplo n.º 2
0
        public async Task ItAllowsForRecurringTaskCrontabSchedulesToBeChanged()
        {
            var taskName = Guid.NewGuid().ToString();

            Func <string, TaskScheduler, Task> configureSchedulerAction = async(semaphoreFile, taskScheduler) =>
            {
                var crontab = $"*/{IntervalSeconds} * * * * *";
                TaskSchedulerTestHelpers.SynchronizeToCrontabNextStart(crontab);
                Thread.Sleep(10);

                await taskScheduler.AddRecurringTask(() => TaskQueueTestFixture.WriteSemaphore(semaphoreFile),
                                                     crontab, taskName);
            };

            Func <string, TaskScheduler, Task> reconfigureRecurringTaskIntervalAction = async(semaphoreFile, taskScheduler) =>
            {
                // Must synchronize to next start time or test becomes flaky
                var newCrontab = $"*/{IntervalSeconds*2} * * * * *";
                TaskSchedulerTestHelpers.SynchronizeToCrontabNextStart(newCrontab);
                Thread.Sleep(10);

                await taskScheduler.AddRecurringTask(() => TaskQueueTestFixture.WriteSemaphore(semaphoreFile),
                                                     newCrontab, taskName);
            };

            await TaskSchedulerTestHelpers.AssertTaskSchedulerWritesSemaphoreTwiceAfterReconfiguringInterval(
                IntervalSeconds,
                configureSchedulerAction,
                reconfigureRecurringTaskIntervalAction);
        }
        public async Task ItExecutesAScheduledTaskAtTheSpecifiedOffsetOnlyOnce()
        {
            Func <string, TaskScheduler, Task> configureSchedulerAction = async(semaphoreFile, taskScheduler) =>
            {
                await taskScheduler.AddScheduledTask(() => TaskQueueTestFixture.WriteSemaphore(semaphoreFile),
                                                     TimeSpan.FromSeconds(IntervalSeconds), RandomTaskName);
            };

            await AssertTaskSchedulerWritesSemaphoreOnlyOnce(configureSchedulerAction);
        }
        public async Task ItExecutesARecurringTaskAtTheSpecifiedCrontabInterval()
        {
            Func <string, TaskScheduler, Task> configureSchedulerAction = async(semaphoreFile, taskScheduler) =>
            {
                await taskScheduler.AddRecurringTask(() => TaskQueueTestFixture.WriteSemaphore(semaphoreFile),
                                                     $"*/{IntervalSeconds} * * * * *", RandomTaskName);
            };

            await AssertTaskSchedulerWritesSemaphoreTwice(configureSchedulerAction);
        }
Ejemplo n.º 5
0
        public async Task ItExecutesARecurringTaskAtTheSpecifiedInterval()
        {
            Func <string, TaskScheduler, Task> configureSchedulerAction = async(semaphoreFile, taskScheduler) =>
            {
                await taskScheduler.AddRecurringTask(() => TaskQueueTestFixture.WriteSemaphore(semaphoreFile),
                                                     TimeSpan.FromSeconds(IntervalSeconds), RandomTaskName);
            };

            await TaskSchedulerTestHelpers.AssertTaskSchedulerWritesSemaphoreTwice(
                IntervalSeconds,
                configureSchedulerAction);
        }
Ejemplo n.º 6
0
        public async Task ItExecutesAScheduledTaskAtTheSpecifiedDateTimeOnlyOnce()
        {
            Func <string, TaskScheduler, Task> configureSchedulerAction = async(semaphoreFile, taskScheduler) =>
            {
                await taskScheduler.AddScheduledTask(() => TaskQueueTestFixture.WriteSemaphore(semaphoreFile),
                                                     DateTime.UtcNow + TimeSpan.FromSeconds(IntervalSeconds));
            };

            await TaskSchedulerTestHelpers.AssertTaskSchedulerWritesSemaphoreOnlyOnce(
                IntervalSeconds,
                configureSchedulerAction);
        }
Ejemplo n.º 7
0
        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");
        }
Ejemplo n.º 8
0
        public async Task ItExecutesARecurringTaskAtTheSpecifiedCrontabInterval()
        {
            Func <string, TaskScheduler, Task> configureSchedulerAction = async(semaphoreFile, taskScheduler) =>
            {
                var crontab = $"*/{IntervalSeconds} * * * * *";
                TaskSchedulerTestHelpers.SynchronizeToCrontabNextStart(crontab);
                Thread.Sleep(10);

                await taskScheduler.AddRecurringTask(() => TaskQueueTestFixture.WriteSemaphore(semaphoreFile),
                                                     crontab, RandomTaskName);
            };

            await TaskSchedulerTestHelpers.AssertTaskSchedulerWritesSemaphoreTwice(IntervalSeconds,
                                                                                   configureSchedulerAction);
        }
Ejemplo n.º 9
0
        public async Task ItsTasksAreConsumedOnlyOnceByMultipleConsumers()
        {
            // Higher numbers here increase confidence
            var numberOfJobs      = 16;
            var numberOfConsumers = 4;

            var sharedTaskQueueName = nameof(ItsTasksAreConsumedOnlyOnceByMultipleConsumers);
            var consumers           = Enumerable.Range(0, numberOfConsumers)
                                      .Select(_ => new TaskQueueTestFixture(sharedTaskQueueName)).ToList();

            var semaphoreFiles = new List <string>();

            for (int i = 0; i < numberOfJobs; ++i)
            {
                var path = Path.GetTempFileName();
                File.Delete(path);
                semaphoreFiles.Add(path);

                var sharedTaskQueue = consumers[0].TaskQueue;
                await sharedTaskQueue.Enqueue(() => TaskQueueTestFixture.WriteSemaphore(path));
            }

            var tasks = new List <Task>();

            // Purposely executing more times than the number of tasks we have
            // Specifically numberOfJobs * numberOfConsumers times.
            for (var i = 0; i < numberOfJobs; i += 1)
            {
                foreach (var consumer in consumers)
                {
                    var task = Task.Run(() => consumer.TaskQueue.ExecuteNext());
                    tasks.Add(task);
                }
            }

            await Task.WhenAll(tasks);

            foreach (var semaphoreFile in semaphoreFiles)
            {
                File.ReadAllText(semaphoreFile).Should()
                .Be(TaskQueueTestFixture.SemaphoreText);
            }
        }
Ejemplo n.º 10
0
        public async Task ItDoesNotOverwriteOriginalRecurringTaskWhenDuplicatesAreAdded()
        {
            var taskName      = Guid.NewGuid().ToString();
            var taskQueue     = TaskQueueTestFixture.UniqueRedisTaskQueue();
            var taskScheduler = new TaskScheduler(taskQueue);

            var originalRecurringTask = await taskScheduler.AddRecurringTask(() => TaskQueueTestFixture.WriteSemaphore("a"),
                                                                             TimeSpan.FromSeconds(IntervalSeconds), taskName);

            var duplicateRecurringTask = await taskScheduler.AddRecurringTask(() => TaskQueueTestFixture.WriteSemaphore("a"),
                                                                              TimeSpan.FromSeconds(IntervalSeconds), taskName);

            originalRecurringTask.Should().NotBeNull();
            duplicateRecurringTask.Should().BeNull();

            var recurringTask = await taskScheduler.GetRecurringTask(originalRecurringTask.TaskKey);

            recurringTask.StartTime.Should().Be(originalRecurringTask.StartTime);
        }
Ejemplo n.º 11
0
        public async Task ItContinuesListeningWhenATaskThrowsAnException()
        {
            var waitTime = 5000;

            var taskQueue     = TaskQueueTestFixture.UniqueRedisTaskQueue();
            var taskClient    = new TaskClient(taskQueue);
            var semaphoreFile = Path.GetTempFileName();

            await taskClient.TaskQueue.Enqueue(() => Throw());

            await taskClient.TaskQueue.Enqueue(() => TaskQueueTestFixture.WriteSemaphore(semaphoreFile));

            var task = Task.Run(async() => await taskClient.Listen());
            await Task.Delay(waitTime);

            taskClient.CancelListen();
            await task;

            TaskQueueTestFixture.EnsureSemaphore(semaphoreFile);
        }
Ejemplo n.º 12
0
        public async Task ItAllowsForScheduledTasksToBeCanceled()
        {
            var           taskName      = Guid.NewGuid().ToString();
            ScheduledTask scheduledTask = null;

            Func <string, TaskScheduler, Task> configureSchedulerAction = async(semaphoreFile, taskScheduler) =>
            {
                scheduledTask = await taskScheduler.AddScheduledTask(() => TaskQueueTestFixture.WriteSemaphore(semaphoreFile),
                                                                     DateTime.UtcNow + TimeSpan.FromSeconds(IntervalSeconds));
            };

            Func <TaskScheduler, Task> cancelTaskAction = async(taskScheduler) =>
            {
                (await taskScheduler.CancelScheduledTask(scheduledTask)).Should().BeTrue();
            };

            await TaskSchedulerTestHelpers.AssertTaskSchedulerDoesNotWriteSemaphore(
                IntervalSeconds,
                configureSchedulerAction,
                cancelTaskAction);
        }
Ejemplo n.º 13
0
        public async Task ItAllowsForRecurringTasksToBeCanceled()
        {
            var           taskName      = Guid.NewGuid().ToString();
            RecurringTask recurringTask = null;

            Func <string, TaskScheduler, Task> configureSchedulerAction = async(semaphoreFile, taskScheduler) =>
            {
                recurringTask = await taskScheduler.AddRecurringTask(() => TaskQueueTestFixture.WriteSemaphore(semaphoreFile),
                                                                     $"*/{IntervalSeconds} * * * * *", taskName);
            };

            Func <TaskScheduler, Task> cancelTaskAction = async(taskScheduler) =>
            {
                (await taskScheduler.CancelRecurringTask(recurringTask)).Should().BeTrue();
            };

            await TaskSchedulerTestHelpers.AssertTaskSchedulerDoesNotWriteSemaphore(
                IntervalSeconds,
                configureSchedulerAction,
                cancelTaskAction);
        }
Ejemplo n.º 14
0
        public async Task ItAllowsForRecurringTaskTimespanSchedulesToBeChanged()
        {
            var taskName = Guid.NewGuid().ToString();

            Func <string, TaskScheduler, Task> configureSchedulerAction = async(semaphoreFile, taskScheduler) =>
            {
                await taskScheduler.AddRecurringTask(() => TaskQueueTestFixture.WriteSemaphore(semaphoreFile),
                                                     TimeSpan.FromSeconds(IntervalSeconds), taskName);
            };

            Func <string, TaskScheduler, Task> reconfigureRecurringTaskIntervalAction = async(semaphoreFile, taskScheduler) =>
            {
                await taskScheduler.AddRecurringTask(() => TaskQueueTestFixture.WriteSemaphore(semaphoreFile),
                                                     TimeSpan.FromSeconds(IntervalSeconds * 2), taskName);
            };

            await TaskSchedulerTestHelpers.AssertTaskSchedulerWritesSemaphoreTwiceAfterReconfiguringInterval(
                IntervalSeconds,
                configureSchedulerAction,
                reconfigureRecurringTaskIntervalAction);
        }
Ejemplo n.º 15
0
        public async Task ItContinuesListeningWhenATaskThrowsAnException()
        {
            var waitTime = 5000;

            var taskClient = new TaskClient(
                TaskQueue.Redis(TaskQueueTestFixture.RedisConnectionString, nameof(ItContinuesListeningWhenATaskThrowsAnException)),
                restoreScheduleFromBackup: false);
            var semaphoreFile = Path.GetTempFileName();

            await taskClient.TaskQueue.Enqueue(() => Throw());

            await taskClient.TaskQueue.Enqueue(() => TaskQueueTestFixture.WriteSemaphore(semaphoreFile));

            var task = Task.Run(async() => await taskClient.Listen());
            await Task.Delay(waitTime);

            taskClient.CancelListen();
            await task;

            TaskQueueTestFixture.EnsureSemaphore(semaphoreFile);
        }
Ejemplo n.º 16
0
        public async Task ItExecutesTasksOnlyOnceWhenUsingMultipleConsumers(string taskType)
        {
            var semaphoreFile = Path.GetTempFileName();

            File.Delete(semaphoreFile);
            File.Create(semaphoreFile).Close();

            var intervalSeconds = 5;
            var taskQueue       = TaskQueueTestFixture.UniqueRedisTaskQueue();

            var schedulingTaskScheduler = new TaskScheduler(taskQueue);

            var taskSchedulers = new[]
            {
                new TaskScheduler(taskQueue),
                new TaskScheduler(taskQueue),
                new TaskScheduler(taskQueue),
                new TaskScheduler(taskQueue),
            };

            if (taskType == "scheduled")
            {
                await schedulingTaskScheduler.AddScheduledTask(() => TaskQueueTestFixture.WriteSemaphore(semaphoreFile),
                                                               TimeSpan.FromSeconds(intervalSeconds));
            }

            if (taskType == "recurring")
            {
                await schedulingTaskScheduler.AddRecurringTask(() => TaskQueueTestFixture.WriteSemaphore(semaphoreFile),
                                                               TimeSpan.FromSeconds(intervalSeconds), RandomTaskName);
            }

            Thread.Sleep(((intervalSeconds) * 1000) + 50);

            // Ran only once
            await Task.WhenAll(
                taskSchedulers.Select(
                    taskScheduler =>
                    Task.Run(async() =>
            {
                await taskScheduler.Tick();
                await taskQueue.ExecuteNext();
            })));

            File.Exists(semaphoreFile).Should().Be(true);
            File.ReadAllText(semaphoreFile).Should().Be(TaskQueueTestFixture.SemaphoreText);


            // Ran only twice (or once if scheduled)
            Thread.Sleep(((intervalSeconds) * 1000) + 50);
            await Task.WhenAll(
                taskSchedulers.Select(
                    taskScheduler =>
                    Task.Run(async() =>
            {
                await taskScheduler.Tick();
                await taskQueue.ExecuteNext();
            })));

            if (taskType == "recurring")
            {
                File.ReadAllText(semaphoreFile).Should()
                .Be(TaskQueueTestFixture.SemaphoreText + TaskQueueTestFixture.SemaphoreText);
            }
            if (taskType == "scheduled")
            {
                File.ReadAllText(semaphoreFile).Should()
                .Be(TaskQueueTestFixture.SemaphoreText);
            }
        }