/// <inheritdoc />
        public void Add(ITaskRuntimeInfo taskInfo)
        {
            if (taskInfo == null)
            {
                throw new ArgumentNullException("taskInfo");
            }

            Trace.WriteLine("ENTER: Adding runtime information for task '{0}' of type '{1}' with priority '{2}' in polling queue '{3}' ...".FormatInvariant(taskInfo.TaskId, taskInfo.TaskType, taskInfo.Priority, taskInfo.PollingQueue));

            taskInfo.ValidateForAdd();

            string entityKey = RedisTaskRuntimeInfoRepository.GetEntityKey(taskInfo.TaskId);

            string addToListKey;

            Dictionary <string, string> values = new Dictionary <string, string>()
            {
                { "Id", RedisConverter.ToString(taskInfo.TaskId) },
                { "TaskType", RedisConverter.ToString(taskInfo.TaskType, true) },
                { "SubmittedUtc", RedisConverter.ToString(taskInfo.SubmittedUtc) },
                { "Status", RedisConverter.ToString(taskInfo.Status) }
            };

            if (string.IsNullOrEmpty(taskInfo.PollingQueue))
            {
                values.Add("Priority", RedisConverter.ToString(taskInfo.Priority));

                addToListKey = RedisTaskRuntimeInfoRepository.PendingTasksList;
            }
            else
            {
                values.Add("PollingQueue", taskInfo.PollingQueue);

                addToListKey = RedisTaskRuntimeInfoRepository.GetPollingQueueRedisKey(taskInfo.PollingQueue, TaskStatus.Pending);
            }

            using (IRedisTransaction transaction = this.Provider.CreateTransaction())
            {
                transaction.SetHashValues(entityKey, values);

                transaction.AddToList(addToListKey, RedisConverter.ToString(taskInfo.TaskId));

                transaction.Commit();
            }

            Trace.WriteLine("EXIT: Runtime information for task '{0}' of type '{1}' with priority '{2}' in polling queue '{3}' added.".FormatInvariant(taskInfo.TaskId, taskInfo.TaskType, taskInfo.Priority, taskInfo.PollingQueue));
        }
        /// <inheritdoc />
        public IEnumerable <ITaskRuntimeInfo> ReservePollingQueueTasks(string pollingQueueKey, int maxResults)
        {
            Trace.WriteLine("ENTER: Reserving {0} polling queue '{1}' tasks for execution ...".FormatInvariant(maxResults, pollingQueueKey));

            if (string.IsNullOrEmpty(pollingQueueKey))
            {
                throw new ArgumentNullException(nameof(pollingQueueKey));
            }

            if (maxResults < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(maxResults), maxResults, "Value must not be negative.");
            }

            string pollingQueueListKey = RedisTaskRuntimeInfoRepository.GetPollingQueueRedisKey(pollingQueueKey, TaskStatus.Pending);

            List <string> entityIds = new List <string>();

            using (IRedisPipeline pipeline = this.provider.CreatePipeline())
            {
                for (int i = 0; i < maxResults; i++)
                {
                    pipeline.PopFirstListElementAsText(pollingQueueListKey, value =>
                    {
                        if (!string.IsNullOrEmpty(value))
                        {
                            entityIds.Add(value);
                        }
                    });
                }

                pipeline.Flush();
            }

            ICollection <ITaskRuntimeInfo> result = this.GetAll(entityIds);

            Trace.WriteLine("EXIT: {0} polling queue '{1}' tasks reserved for execution.".FormatInvariant(result.Count, pollingQueueKey));

            return(result);
        }