public async Task GivenValidTasks_WhenTaskHostingStart_ThenTasksShouldBeExecute() { int taskCount = 10; string resultMessage = "success"; List <TaskInfo> taskInfos = new List <TaskInfo>(); for (int i = 0; i < taskCount; ++i) { TaskInfo taskInfo = new TaskInfo(); taskInfo.TaskId = Guid.NewGuid().ToString(); taskInfo.TaskTypeId = 0; taskInfos.Add(taskInfo); } int executedTaskCount = 0; TestTaskConsumer consumer = new TestTaskConsumer(taskInfos.ToArray()); TestTaskFactory factory = new TestTaskFactory(t => { return(new TestTask( async() => { Interlocked.Increment(ref executedTaskCount); await Task.Delay(TimeSpan.FromMilliseconds(20)); return new TaskResultData(TaskResult.Success, resultMessage); }, null)); }); TaskHosting taskHosting = new TaskHosting(consumer, factory, _logger); taskHosting.PollingFrequencyInSeconds = 0; taskHosting.MaxRunningTaskCount = 5; CancellationTokenSource tokenSource = new CancellationTokenSource(); tokenSource.CancelAfter(TimeSpan.FromSeconds(10)); await taskHosting.StartAsync(tokenSource); Assert.Equal(taskCount, executedTaskCount); foreach (string resultString in taskInfos.Select(t => t.Result)) { TaskResultData result = JsonConvert.DeserializeObject <TaskResultData>(resultString); Assert.Equal(TaskResult.Success, result.Result); Assert.Equal(resultMessage, result.ResultData); } }
public async Task GivenAnLongRunningTask_WhenTaskHostingStop_ThenTaskShouldBeCompleted() { TaskInfo taskInfo0 = new TaskInfo(); taskInfo0.TaskId = Guid.NewGuid().ToString(); taskInfo0.TaskTypeId = 0; taskInfo0.Status = TaskStatus.Running; AutoResetEvent autoResetEvent = new AutoResetEvent(false); int executeCount0 = 0; TestTaskConsumer consumer = new TestTaskConsumer(new TaskInfo[] { taskInfo0 }); TestTaskFactory factory = new TestTaskFactory(t => { return(new TestTask( async() => { autoResetEvent.Set(); await Task.Delay(TimeSpan.FromSeconds(10)); Interlocked.Increment(ref executeCount0); return new TaskResultData(TaskResult.Success, string.Empty); }, null)); }); TaskHosting taskHosting = new TaskHosting(consumer, factory, _logger); taskHosting.PollingFrequencyInSeconds = 0; taskHosting.MaxRunningTaskCount = 1; taskHosting.TaskHeartbeatTimeoutThresholdInSeconds = 2; CancellationTokenSource tokenSource = new CancellationTokenSource(); Task hostingTask = taskHosting.StartAsync(tokenSource); autoResetEvent.WaitOne(); tokenSource.Cancel(); await hostingTask; Assert.Equal(1, executeCount0); // If task failcount > MaxRetryCount + 1, the Task should failed with error message. TaskResultData taskResult0 = JsonConvert.DeserializeObject <TaskResultData>(taskInfo0.Result); Assert.Equal(TaskResult.Success, taskResult0.Result); Assert.Equal(1, executeCount0); }
public async Task GivenTaskRunning_WhenCancel_ThenTaskShouldBeCompleteWithCancelledStatus() { TaskInfo taskInfo0 = new TaskInfo(); taskInfo0.TaskId = Guid.NewGuid().ToString(); taskInfo0.TaskTypeId = 0; TestTaskConsumer consumer = new TestTaskConsumer(new TaskInfo[] { taskInfo0 }); CancellationTokenSource tokenSource = new CancellationTokenSource(); AutoResetEvent autoResetEvent1 = new AutoResetEvent(false); AutoResetEvent autoResetEvent2 = new AutoResetEvent(false); TestTaskFactory factory = new TestTaskFactory(t => { return(new TestTask( () => { autoResetEvent2.Set(); autoResetEvent1.WaitOne(); tokenSource.Cancel(); return Task.FromResult(new TaskResultData(TaskResult.Canceled, string.Empty)); }, () => { autoResetEvent1.Set(); })); }); TaskHosting taskHosting = new TaskHosting(consumer, factory, _logger); taskHosting.PollingFrequencyInSeconds = 0; taskHosting.MaxRunningTaskCount = 1; Task hostingTask = taskHosting.StartAsync(tokenSource); autoResetEvent2.WaitOne(); taskInfo0.IsCanceled = true; await hostingTask; TaskResultData taskResult = JsonConvert.DeserializeObject <TaskResultData>(taskInfo0.Result); Assert.Equal(TaskResult.Canceled, taskResult.Result); }
public async Task GivenTaskCrash_WhenTaskHostingRepickupTask_ThenFirstTasksShouldBeCancelled() { string resultMessage = "success"; List <TaskInfo> taskInfos = new List <TaskInfo>(); TaskInfo taskInfo = new TaskInfo(); taskInfo.TaskId = Guid.NewGuid().ToString(); taskInfo.TaskTypeId = 0; taskInfos.Add(taskInfo); TestTaskConsumer consumer = new TestTaskConsumer(taskInfos.ToArray()); bool isCancelled = false; CancellationTokenSource tokenSource = new CancellationTokenSource(); TestTaskFactory factory = new TestTaskFactory(t => { return(new TestTask( async() => { await Task.Delay(TimeSpan.FromSeconds(10)); return new TaskResultData(TaskResult.Success, resultMessage); }, async() => { await Task.Delay(TimeSpan.FromMilliseconds(20)); isCancelled = true; tokenSource.Cancel(); }) { RunId = Guid.NewGuid().ToString(), }); }); TaskHosting taskHosting = new TaskHosting(consumer, factory, _logger); taskHosting.PollingFrequencyInSeconds = 0; taskHosting.TaskHeartbeatTimeoutThresholdInSeconds = 0; tokenSource.CancelAfter(TimeSpan.FromSeconds(5)); await taskHosting.StartAsync(tokenSource); Assert.True(isCancelled); }
public async Task GivenTaskWithCriticalException_WhenTaskHostingStart_ThenTaskShouldFailWithErrorMessage() { string errorMessage = "Test error"; TaskInfo taskInfo0 = new TaskInfo(); taskInfo0.TaskId = Guid.NewGuid().ToString(); taskInfo0.TaskTypeId = 0; int executeCount0 = 0; TestTaskConsumer consumer = new TestTaskConsumer(new TaskInfo[] { taskInfo0 }); TestTaskFactory factory = new TestTaskFactory(t => { return(new TestTask( () => { Interlocked.Increment(ref executeCount0); throw new Exception(errorMessage); }, null)); }); TaskHosting taskHosting = new TaskHosting(consumer, factory, _logger); taskHosting.PollingFrequencyInSeconds = 0; taskHosting.MaxRunningTaskCount = 1; CancellationTokenSource tokenSource = new CancellationTokenSource(); tokenSource.CancelAfter(TimeSpan.FromSeconds(1)); await taskHosting.StartAsync(tokenSource); Assert.Equal(1, executeCount0); // If task failcount > MaxRetryCount + 1, the Task should failed with error message. TaskResultData taskResult0 = JsonConvert.DeserializeObject <TaskResultData>(taskInfo0.Result); Assert.Equal(TaskResult.Fail, taskResult0.Result); Assert.Equal(errorMessage, taskResult0.ResultData); }
public async Task GivenTempUnavailableConsumer_WhenTaskHostingStart_ThenTaskHostingShouldKeepRunning() { Random random = new Random(); int taskCount = 1000; List <TaskInfo> taskInfos = new List <TaskInfo>(); for (int i = 0; i < taskCount; ++i) { TaskInfo taskInfo = new TaskInfo(); taskInfo.TaskId = Guid.NewGuid().ToString(); taskInfo.TaskTypeId = (short)(i % 10 == 0 ? 1 : 0); taskInfos.Add(taskInfo); } int faultInjected = 0; TestTaskConsumer consumer = new TestTaskConsumer( taskInfos.ToArray(), faultInjectionAction: (method) => { if (random.NextDouble() < 0.1) { Interlocked.Increment(ref faultInjected); throw new Exception($"Injected Exception in {method}"); } }); TestTaskFactory factory = new TestTaskFactory(t => { if (t.TaskTypeId == 0) { return(new TestTask( async() => { await Task.Delay(TimeSpan.FromMilliseconds(1)); return new TaskResultData(TaskResult.Success, string.Empty); }, null)); } else { return(new TestTask( () => { throw new Exception(); }, null)); } }); TaskHosting taskHosting = new TaskHosting(consumer, factory, _logger); taskHosting.PollingFrequencyInSeconds = 0; taskHosting.MaxRunningTaskCount = 20; taskHosting.TaskHeartbeatTimeoutThresholdInSeconds = 1; CancellationTokenSource tokenSource = new CancellationTokenSource(); tokenSource.CancelAfter(TimeSpan.FromSeconds(20)); await taskHosting.StartAsync(tokenSource); foreach (TaskInfo taskInfo in taskInfos) { TaskResultData taskResult = JsonConvert.DeserializeObject <TaskResultData>(taskInfo.Result); if (taskInfo.TaskTypeId == 0) { Assert.Equal(TaskResult.Success, taskResult.Result); } else { Assert.Equal(TaskResult.Fail, taskResult.Result); } } }
public async Task GivenTaskThrowException_WhenTaskHostingStart_ThenTaskHostingShouldKeepRunning() { int taskCount = 1000; List <TaskInfo> taskInfos = new List <TaskInfo>(); for (int i = 0; i < taskCount; ++i) { TaskInfo taskInfo = new TaskInfo(); taskInfo.TaskId = Guid.NewGuid().ToString(); taskInfo.TaskTypeId = (short)(i % 10 == 0 ? 1 : 0); taskInfos.Add(taskInfo); } int executedTaskCount = 0; int failedTaskCount = 0; TestTaskConsumer consumer = new TestTaskConsumer(taskInfos.ToArray()); TestTaskFactory factory = new TestTaskFactory(t => { if (t.TaskTypeId == 0) { return(new TestTask( async() => { Interlocked.Increment(ref executedTaskCount); await Task.Delay(TimeSpan.FromMilliseconds(10)); return new TaskResultData(TaskResult.Success, string.Empty); }, null)); } else { return(new TestTask( () => { Interlocked.Increment(ref failedTaskCount); throw new Exception(); }, null)); } }); TaskHosting taskHosting = new TaskHosting(consumer, factory, _logger); taskHosting.PollingFrequencyInSeconds = 0; taskHosting.MaxRunningTaskCount = 5; CancellationTokenSource tokenSource = new CancellationTokenSource(); tokenSource.CancelAfter(TimeSpan.FromSeconds(20)); await taskHosting.StartAsync(tokenSource); Assert.Equal(900, executedTaskCount); Assert.Equal(100, failedTaskCount); foreach (TaskInfo taskInfo in taskInfos) { TaskResultData taskResult = JsonConvert.DeserializeObject <TaskResultData>(taskInfo.Result); if (taskInfo.TaskTypeId == 0) { Assert.Equal(TaskResult.Success, taskResult.Result); } else { Assert.Equal(TaskResult.Fail, taskResult.Result); } } }
public async Task GivenTaskWithRetriableException_WhenTaskHostingStart_ThenTaskShouldBeRetry() { string errorMessage = "Test error"; short maxRetryCount = 2; TaskInfo taskInfo0 = new TaskInfo(); taskInfo0.TaskId = Guid.NewGuid().ToString(); taskInfo0.TaskTypeId = 0; taskInfo0.MaxRetryCount = maxRetryCount; TaskInfo taskInfo1 = new TaskInfo(); taskInfo1.TaskId = Guid.NewGuid().ToString(); taskInfo1.TaskTypeId = 1; taskInfo1.MaxRetryCount = maxRetryCount; int executeCount0 = 0; int executeCount1 = 0; TestTaskConsumer consumer = new TestTaskConsumer(new TaskInfo[] { taskInfo0, taskInfo1 }); TestTaskFactory factory = new TestTaskFactory(t => { if (t.TaskTypeId == 0) { return(new TestTask( () => { Interlocked.Increment(ref executeCount0); throw new RetriableTaskException(errorMessage); }, null)); } else { return(new TestTask( () => { Interlocked.Increment(ref executeCount1); if (executeCount1 < maxRetryCount + 1) { throw new RetriableTaskException(errorMessage); } return Task.FromResult <TaskResultData>(new TaskResultData(TaskResult.Success, string.Empty)); }, null)); } }); TaskHosting taskHosting = new TaskHosting(consumer, factory, _logger); taskHosting.PollingFrequencyInSeconds = 0; taskHosting.MaxRunningTaskCount = 1; CancellationTokenSource tokenSource = new CancellationTokenSource(); tokenSource.CancelAfter(TimeSpan.FromSeconds(5)); await taskHosting.StartAsync(tokenSource); Assert.Equal(maxRetryCount + 1, executeCount0); Assert.Equal(maxRetryCount + 1, executeCount1); // If task failcount > MaxRetryCount + 1, the Task should failed with error message. TaskResultData taskResult0 = JsonConvert.DeserializeObject <TaskResultData>(taskInfo0.Result); Assert.Equal(TaskResult.Fail, taskResult0.Result); Assert.Equal(errorMessage, taskResult0.ResultData); // If task failcount < MaxRetryCount + 1, the Task should success. TaskResultData taskResult1 = JsonConvert.DeserializeObject <TaskResultData>(taskInfo1.Result); Assert.Equal(TaskResult.Success, taskResult1.Result); }
public async Task GivenBatchTaskMoreThanMaxConcurrentLimit_WhenExecuteTasks_ThenRunningTaskCountShouldLessThanLimit() { string resultMessage = "success"; List <TaskInfo> taskInfos = new List <TaskInfo>(); int count = 10; short maxConcurrentCount = 2; for (int i = 0; i < count; ++i) { TaskInfo taskInfo = new TaskInfo(); taskInfo.TaskId = Guid.NewGuid().ToString(); taskInfo.TaskTypeId = 0; taskInfos.Add(taskInfo); } ILogger <TaskHosting> logger = Substitute.For <ILogger <TaskHosting> >(); TestTaskConsumer consumer = new TestTaskConsumer(taskInfos.ToArray()); int runningTaskCount = 0; int maxRunningTaskCount = 0; bool runningTaskCountLargeThanLimit = false; TestTaskFactory factory = new TestTaskFactory(t => { return(new TestTask( async() => { Interlocked.Increment(ref runningTaskCount); maxRunningTaskCount = Math.Max(runningTaskCount, maxRunningTaskCount); try { await Task.Delay(TimeSpan.FromMilliseconds(10)); return new TaskResultData(TaskResult.Success, resultMessage); } finally { Interlocked.Decrement(ref runningTaskCount); } }, null)); }); TaskHosting taskHosting = new TaskHosting(consumer, factory, logger); taskHosting.PollingFrequencyInSeconds = 0; taskHosting.MaxRunningTaskCount = maxConcurrentCount; CancellationTokenSource tokenSource = new CancellationTokenSource(); tokenSource.CancelAfter(TimeSpan.FromSeconds(10)); await taskHosting.StartAsync(tokenSource); Assert.False(runningTaskCountLargeThanLimit); Assert.Equal(2, maxRunningTaskCount); foreach (ICall call in logger.ReceivedCalls()) { if (call.GetMethodInfo().Name.Equals("Log")) { Assert.NotEqual(LogLevel.Error, call.GetArguments()[0]); } } }