/// <summary> /// Submits a task with the specified parameters. /// </summary> /// <param name="taskId">The unique ID of the task.</param> /// <param name="task">The task to submit.</param> /// <param name="summary">The summary to associated with the task, if any.</param> /// <param name="priority">The priority of the task.</param> internal void SubmitTask(Guid taskId, ITask task, ITaskSummary summary, TaskPriority priority) { if (task == null) { throw new ArgumentNullException("task"); } Trace.WriteLine("ENTER: Submitting '{0}' with priority '{1}' ...".FormatInvariant(task.GetType().Name, priority)); string pollingQueueKey = this.configuration.GetPollingQueueKey(task.GetType()); this.repository.Tasks.Add(taskId, task); if (summary != null) { this.repository.TaskSummary.Add(taskId, summary); } ITaskRuntimeInfo taskInfo = this.repository.TaskRuntimeInfo.Create(taskId, task.GetType(), this.dateTimeProvider.UtcNow, priority, pollingQueueKey); this.repository.TaskRuntimeInfo.Add(taskInfo); ITaskMessageBusSender taskMessageBus = this.messageBus.Tasks.GetSender(task.GetType()); taskMessageBus.NotifyTaskSubmitted(taskId, this.dateTimeProvider.UtcNow, !string.IsNullOrEmpty(pollingQueueKey)); Trace.WriteLine("EXIT: Task '{0}' submitted with ID '{1}' ...".FormatInvariant(task, taskId)); }
/// <inheritdoc /> public void CancelTask(Guid taskId) { Trace.WriteLine("ENTER: Cancelling task '{0}' ...".FormatInvariant(taskId)); Lazy <DateTime> timestampUtc = new Lazy <DateTime>(() => this.dateTimeProvider.UtcNow); ITaskRuntimeInfo taskInfo = this.repository.TaskRuntimeInfo.GetById(taskId); if (taskInfo == null) { throw new KeyNotFoundException("Task '{0}' was not found.".FormatInvariant(taskId)); } switch (taskInfo.Status) { case TaskStatus.Canceled: case TaskStatus.Failed: case TaskStatus.Success: throw new InvalidOperationException("Task '{0}' status is {1} and will not be canceled.".FormatInvariant(taskId, taskInfo.Status)); } ITaskMessageBusSender taskMessageBus = this.messageBus.Tasks.GetSender(taskInfo.TaskType); taskMessageBus.NotifyTaskCancelRequest(taskId, timestampUtc.Value); this.repository.TaskRuntimeInfo.RequestCancel(taskId, timestampUtc.Value); Trace.WriteLine("EXIT: Task '{0}' canceled.".FormatInvariant(taskId)); }
private bool AssignTaskToProcessor(Guid taskId, Type taskType, Guid taskProcessorId) { Trace.WriteLine("ENTER: Assigning task '{0}' to processor '{1}' ...".FormatInvariant(taskId, taskProcessorId)); this.repository.TaskRuntimeInfo.Assign(taskId, taskProcessorId); using (ManualResetEventSlim blocker = new ManualResetEventSlim()) { this.assignTaskWaitHandlers.TryAdd(taskId, blocker); ITaskMessageBusSender taskMessageBus = this.messageBus.Tasks.GetSender(taskType); ThreadPool.QueueUserWorkItem(state => { taskMessageBus.NotifyTaskAssigned(taskId, taskProcessorId); }); bool result = blocker.Wait(this.assignTaskTimeout); ManualResetEventSlim blocker1; this.assignTaskWaitHandlers.TryRemove(taskId, out blocker1); if (result) { Trace.WriteLine("EXIT: Task '{0}' assigned successfully to processor '{1}'.".FormatInvariant(taskId, taskProcessorId)); } else { Trace.WriteLine("EXIT: Failed to assign task '{0}' to processor '{1}'. Response was not receive after {2} timeout.".FormatInvariant(taskId, taskProcessorId, this.assignTaskTimeout)); } return(result); } }
public void GetTaskSender() { CompositeTaskMessageBus composite = new CompositeTaskMessageBus(); composite.Senders.Add(new FakeTaskMessageBus()); composite.Senders.Add(new FakeTaskMessageBus()); composite.Senders.OfType <FakeTaskMessageBus>().First().PredefineResult(false, mb => mb.IsSupported(typeof(FakeTask))); composite.Senders.OfType <FakeTaskMessageBus>().Last().PredefineResult(true, mb => mb.IsSupported(typeof(FakeTask))); ITaskMessageBusSender result = composite.GetSender <FakeTask>(); result.NotifyTaskProgress(Guid.Empty, 0); composite.Senders.OfType <FakeTaskMessageBus>().First().AssertNoMethodCall(mb => mb.NotifyTaskProgress(Guid.Empty, 0)); composite.Senders.OfType <FakeTaskMessageBus>().Last().AssertMethodCallOnce(mb => mb.NotifyTaskProgress(Guid.Empty, 0)); }
public void StartTask(Guid taskId) { ITask task = this.repository.Tasks.GetById(taskId); if (task == null) { throw new ArgumentException("Task '{0}' was not found in storage.".FormatInvariant(taskId), "taskId"); } ITaskWorker taskWorker = this.taskFactory.CreateTaskWorker(task); ITaskMessageBusSender taskMessageBus = this.messageBus.Tasks.GetSender(task.GetType()); taskWorker.ReportProgress += (sender, e) => { this.repository.TaskRuntimeInfo.Progress(taskId, e.Percentage); taskMessageBus.NotifyTaskProgress(taskId, e.Percentage); }; this.messageBus.Tasks.Receiver.SubscribeForChannels(MessageBusChannel.TaskCancelRequest); bool isCanceled = false; this.messageBus.Tasks.Receiver.TaskCancelRequested += (_, e1) => { if (!isCanceled && (e1.TaskId == taskId)) { isCanceled = true; taskWorker.CancelTask(); } }; ITaskJobSettings settings = null; ITaskWorkerConfiguration config = this.configuration[task.GetType()]; if ((config != null) && config.HasTaskJobSettings) { settings = this.repository.TaskJobSettings.Get(task.GetType()); } ITaskRuntimeInfo taskInfo = this.repository.TaskRuntimeInfo.GetById(taskId); if (taskInfo == null) { throw new ArgumentException("Task '{0}' not found in storage.".FormatInvariant(taskId), "taskId"); } switch (taskInfo.Status) { case TaskStatus.Pending: case TaskStatus.InProgress: break; case TaskStatus.Canceled: throw new OperationCanceledException(); default: throw new ArgumentException("Task '{0}' status is '{1}'.".FormatInvariant(taskId, taskInfo.Status), "taskId"); } try { try { taskWorker.StartTask(task, settings); } catch (Exception ex) { this.repository.TaskRuntimeInfo.Fail(taskId, this.dateTimeProvider.UtcNow, ex); throw; } } finally { this.messageBus.Tasks.Receiver.UnsubscribeFromAllChannels(); if (taskWorker is IDisposable) { ((IDisposable)taskWorker).Dispose(); } } }