/// <inheritdoc />
        public void RequestCancel(Guid taskId, DateTime timestampUtc)
        {
            Trace.WriteLine("ENTER: Record task '{0}' cancel request ...".FormatInvariant(taskId));

            string taskIdAsString = RedisConverter.ToString(taskId);

            string entityKey = RedisTaskRuntimeInfoRepository.GetEntityKey(taskIdAsString);

            RedisTaskRuntimeInfo taskInfo = this.GetById(taskId, false);

            taskInfo.Status      = TaskStatus.Canceled;
            taskInfo.CanceledUtc = timestampUtc;

            byte[] content = this.serializer.Serialize(taskInfo);

            using (IRedisTransaction transaction = this.Provider.CreateTransaction())
            {
                transaction.RemoveKey(entityKey);
                transaction.RemoveFromList(RedisTaskRuntimeInfoRepository.PendingTasksList, taskIdAsString);
                transaction.RemoveFromList(RedisTaskRuntimeInfoRepository.ActiveTasksList, taskIdAsString);

                transaction.SetHashValue(RedisTaskRuntimeInfoRepository.ArchiveTasksHash, taskIdAsString, content);

                transaction.Commit();
            }

            Trace.WriteLine("EXIT: Task '{0}' cancel request recorded.".FormatInvariant(taskId));
        }
        /// <inheritdoc />
        public void Fail(Guid taskId, DateTime timestampUtc, Exception error)
        {
            if (error == null)
            {
                throw new ArgumentNullException(nameof(error));
            }

            Trace.WriteLine("ENTER: Record task '{0}' failed with error '{1}' ...".FormatInvariant(taskId, error.Message));

            string taskIdAsString = RedisConverter.ToString(taskId);

            string entityKey = RedisTaskRuntimeInfoRepository.GetEntityKey(taskIdAsString);

            RedisTaskRuntimeInfo taskInfo = this.GetById(taskId, false);

            taskInfo.Status       = TaskStatus.Failed;
            taskInfo.CompletedUtc = timestampUtc;
            taskInfo.Error        = error.ToString();

            byte[] content = this.serializer.Serialize(taskInfo);

            using (IRedisTransaction transaction = this.Provider.CreateTransaction())
            {
                transaction.RemoveKey(entityKey);
                transaction.RemoveFromList(RedisTaskRuntimeInfoRepository.ActiveTasksList, taskIdAsString);
                transaction.AddToList(RedisTaskRuntimeInfoRepository.FailedTasksList, taskIdAsString);
                transaction.SetHashValue(RedisTaskRuntimeInfoRepository.ArchiveTasksHash, taskIdAsString, content);

                transaction.Commit();
            }

            Trace.WriteLine("EXIT: Task '{0}' failed with error '{1}' recorded.".FormatInvariant(taskId, error.Message));
        }
        /// <inheritdoc />
        public void Start(Guid taskId, Guid taskProcessorId, DateTime timestampUtc)
        {
            Trace.WriteLine("ENTER: Recording task '{0}' started by processor '{1}' ...".FormatInvariant(taskId, taskProcessorId));

            string entityKey = RedisTaskRuntimeInfoRepository.GetEntityKey(taskId);

            Dictionary <string, string> values = new Dictionary <string, string>()
            {
                { "Status", RedisConverter.ToString(TaskStatus.InProgress) },
                { "TaskProcessorId", RedisConverter.ToString(taskProcessorId) },
                { "StartedUtc", RedisConverter.ToString(timestampUtc) }
            };

            using (IRedisTransaction transaction = this.Provider.CreateTransaction())
            {
                transaction.SetHashValues(entityKey, values);
                transaction.RemoveFromList(RedisTaskRuntimeInfoRepository.PendingTasksList, RedisConverter.ToString(taskId));
                transaction.AddToList(RedisTaskRuntimeInfoRepository.ActiveTasksList, RedisConverter.ToString(taskId));

                transaction.Commit();
            }

            Trace.WriteLine("EXIT: Task '{0}' assigned to processor '{1}' recorded.".FormatInvariant(taskId, taskProcessorId));
        }