Esempio n. 1
0
        public void ItExecutesTasksAtTheSpecifiedInterval()
        {
            var semaphoreFile = Path.GetTempFileName();

            File.Delete(semaphoreFile);

            var intervalSeconds = 2;

            var taskScheduler = new TaskScheduler(TaskQueue.Redis("localhost:6379"));

            taskScheduler.AddScheduledTask(() => TaskQueueTestFixture.WriteSempaphore(semaphoreFile),
                                           TimeSpan.FromSeconds(intervalSeconds), "test");
            taskScheduler.Tick();

            File.Exists(semaphoreFile).Should().Be(false);

            // Confirm Scheduled Task Ran once
            Thread.Sleep(((intervalSeconds) * 1000) + 10);
            taskScheduler.Tick();
            File.Exists(semaphoreFile).Should().Be(true);
            File.ReadAllText(semaphoreFile).Should().Be(TaskQueueTestFixture.SemaphoreText);

            // Confirm Ran TWICE
            Thread.Sleep(((intervalSeconds) * 1000) + 10);
            taskScheduler.Tick();
            File.Exists(semaphoreFile).Should().Be(true);
            File.ReadAllText(semaphoreFile).Should()
            .Be(TaskQueueTestFixture.SemaphoreText + TaskQueueTestFixture.SemaphoreText);
        }
Esempio n. 2
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);
            }
        }
Esempio n. 3
0
        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);
        }