/// <inheritdoc />
 public ITaskImplementation LocateAndCreate(TaskDescription taskDescription)
 {
     if (_registeredTaskTypes.TryGetValue(taskDescription.TaskType, out var taskImplementationType))
     {
         return((ITaskImplementation)JsonConvert.DeserializeObject(taskDescription.TaskPayload, taskImplementationType));
     }
     return(null);
 }
        public static TaskDescription ToTaskDescription(ITaskImplementation taskImplementation)
        {
            if (taskImplementation == null)
            {
                throw new ArgumentNullException(nameof(taskImplementation));
            }
            var description = new TaskDescription(Guid.NewGuid(), taskImplementation.GetType().FullName, JsonConvert.SerializeObject(taskImplementation));

            return(description);
        }
        /// <inheritdoc />
        protected override async Task RunAsync(CancellationToken cancellationToken)
        {
            var queue = await TimeoutRetryHelper.Execute(
                (token, state) => StateManager.GetOrAddAsync <IReliableQueue <MessageWrapper> >(_queueName),
                cancellationToken : cancellationToken)
                        .ConfigureAwait(false);

            while (true)
            {
                try
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    //peek task description
                    var taskDescriptionMessage = await TimeoutRetryHelper
                                                 .ExecuteInTransaction(StateManager,
                                                                       (tran, token, state) => queue.TryPeekAsync(tran, TimeSpan.FromSeconds(4), token), cancellationToken : cancellationToken)
                                                 .ConfigureAwait(false);

                    if (!taskDescriptionMessage.HasValue)
                    {
                        continue;
                    }

                    //deserialize task description, create task implementation
                    var description    = taskDescriptionMessage.Value.CreateMessage <TaskDescription>();
                    var implementation = TaskDescription.ToTaskImplementation(_typeLocator, description);
                    if (implementation == null)
                    {
                        ServiceEventSourceMessageCallback?
                        .Invoke($"Received TaskDescription message with type {description.TaskType} and id {description.TaskId} that could not be transformed into a TaskImplementation type.");

                        continue;
                    }

                    //run task
                    ServiceEventSourceMessageCallback?
                    .Invoke($"Processing TaskDescription message with type {description.TaskType} and id {description.TaskId}, using implementation {implementation.GetType().Name}.");

                    await implementation.ExecuteAsync().ConfigureAwait(false);

                    var taskDescriptionMessageDequeued = await TimeoutRetryHelper
                                                         .ExecuteInTransaction(StateManager,
                                                                               (tran, token, state) => queue.TryDequeueAsync(tran, TimeSpan.FromSeconds(4), token), cancellationToken : cancellationToken)
                                                         .ConfigureAwait(false);

                    //dequeue task, compare it with the peeked task
                    if (taskDescriptionMessageDequeued.HasValue &&
                        taskDescriptionMessageDequeued.Value.Payload.GetHashCode()
                        == taskDescriptionMessage.Value.Payload.GetHashCode())
                    {
                        ServiceEventSourceMessageCallback?
                        .Invoke($"Processed TaskDescription message with type {description.TaskType} and id {description.TaskId}, using implementation {implementation.GetType().Name}.");
                    }
                    else
                    {
                        ServiceEventSourceMessageCallback?
                        .Invoke($"Unexpected error. The peeked message is not the dequeued message.");
                    }
                }
                catch (TaskCanceledException)
                {//swallow and move on..
                }
                catch (OperationCanceledException)
                {//swallow and move on..
                }
                catch (ObjectDisposedException)
                {//swallow and move on..
                }
                catch (Exception ex)
                {
                    ServiceEventSourceMessageCallback?.Invoke($"Exception caught while processing messages:'{ex.Message}'");
                    //swallow and move on..
                }
                finally
                {
                    await Task.Delay(Period, cancellationToken).ConfigureAwait(false);
                }
            }
        }
 public static ITaskImplementation ToTaskImplementation(ITypeLocator typeLocator, TaskDescription taskDescription)
 {
     return(typeLocator.LocateAndCreate(taskDescription));
 }