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

            string taskIdAsString = RedisConverter.ToString(taskId);

            string entityKey = RedisTaskRuntimeInfoRepository.GetEntityKey(taskIdAsString);

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

            taskInfo.Percentage   = 100;
            taskInfo.Status       = TaskStatus.Success;
            taskInfo.CompletedUtc = timestampUtc;

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

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

                transaction.Commit();
            }

            Trace.WriteLine("EXIT: Task '{0}' completed 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));
        }
        private static RedisTaskRuntimeInfo Convert(IReadOnlyDictionary <string, string> values)
        {
            if (values == null)
            {
                throw new ArgumentNullException("values");
            }

            RedisTaskRuntimeInfo result = new RedisTaskRuntimeInfo(
                RedisConverter.ParseGuid(values["Id"]),
                RedisConverter.ParseType(values["TaskType"]),
                RedisConverter.ParseDateTime(values["SubmittedUtc"]),
                RedisConverter.ParseEnum <TaskStatus>(values["Status"]));

            string value;

            if (values.TryGetValue("PollingQueue", out value))
            {
                result.PollingQueue = value;
            }

            if (values.TryGetValue("Priority", out value))
            {
                result.Priority = RedisConverter.ParseEnum <TaskPriority>(value);
            }

            if (values.TryGetValue("TaskProcessorId", out value))
            {
                result.TaskProcessorId = RedisConverter.ParseGuidOrNull(value);
            }

            if (values.TryGetValue("StartedUtc", out value))
            {
                result.StartedUtc = RedisConverter.ParseDateTimeOrNull(value);
            }

            if (values.TryGetValue("Percentage", out value))
            {
                result.Percentage = RedisConverter.ParseDouble(value);
            }

            if (values.TryGetValue("CanceledUtc", out value))
            {
                result.CanceledUtc = RedisConverter.ParseDateTimeOrNull(value);
            }

            if (values.TryGetValue("CompletedUtc", out value))
            {
                result.CompletedUtc = RedisConverter.ParseDateTimeOrNull(value);
            }

            if (values.TryGetValue("Error", out value))
            {
                result.Error = value;
            }

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

            string taskIdAsString = RedisConverter.ToString(taskId);

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

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

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

            this.provider.SetHashValue(RedisTaskRuntimeInfoRepository.ArchiveTasksHash, taskIdAsString, content);

            Trace.WriteLine("EXIT: Task '{0}' cancel completed recorded.".FormatInvariant(taskId));
        }
        /// <inheritdoc />
        public Type GetTaskType(Guid taskId)
        {
            Trace.WriteLine("ENTER: Getting task '{0}' type ...".FormatInvariant(taskId));

            string entityKey = RedisTaskRuntimeInfoRepository.GetEntityKey(taskId);

            string taskTypeAsString = this.provider.GetHashTextValue(entityKey, "TaskType");

            Type result = null;

            if (!string.IsNullOrEmpty(taskTypeAsString))
            {
#if DEBUG
                result = Type.GetType(taskTypeAsString, true);
#else
                result = Type.GetType(taskTypeAsString, false);

                if (result == null)
                {
                    Trace.TraceWarning("EXIT: Task '{0}' type '{1}' cannot be resolved.", taskId, taskTypeAsString);

                    return(null);
                }
#endif
            }
            else
            {
                RedisTaskRuntimeInfo taskInfo = this.GetById(taskId, true);

                if (taskInfo != null)
                {
                    result = taskInfo.TaskType;
                }
            }

            if (result == null)
            {
                Trace.WriteLine("EXIT: Task '{0}' type was not found neither in hash nor in archive.".FormatInvariant(taskId));
            }
            else
            {
                Trace.WriteLine("EXIT: Return task '{0}' type '{1}'.".FormatInvariant(taskId, result));
            }

            return(result);
        }