/// <summary>
        /// Sends the standard message.
        /// </summary>
        /// <param name="commandSend">The command send.</param>
        /// <returns></returns>
        /// <exception cref="DotNetWorkQueueException">Failed to enqueue a record. The LUA enqueue script returned null</exception>
        private async Task <string> SendStandardMessageAsync(SendMessageCommand commandSend)
        {
            var messageId  = _messageIdFactory.Create().Create().ToString();
            var meta       = new RedisMetaData(_unixTimeFactory.Create().GetCurrentUnixTimestampMilliseconds());
            var serialized = _serializer.Serializer.MessageToBytes(new MessageBody {
                Body = commandSend.MessageToSend.Body
            }, commandSend.MessageToSend.Headers);

            commandSend.MessageToSend.SetHeader(_headers.StandardHeaders.MessageInterceptorGraph, serialized.Graph);

            var jobName       = _jobSchedulerMetaData.GetJobName(commandSend.MessageData);
            var scheduledTime = DateTimeOffset.MinValue;
            var eventTime     = DateTimeOffset.MinValue;

            if (!string.IsNullOrWhiteSpace(jobName))
            {
                scheduledTime = _jobSchedulerMetaData.GetScheduledTime(commandSend.MessageData);
                eventTime     = _jobSchedulerMetaData.GetEventTime(commandSend.MessageData);
            }

            var result = await _enqueueLua.ExecuteAsync(messageId,
                                                        serialized.Output, _serializer.InternalSerializer.ConvertToBytes(commandSend.MessageToSend.Headers), _serializer.InternalSerializer.ConvertToBytes(meta), jobName, scheduledTime, eventTime, commandSend.MessageData.Route).ConfigureAwait(false);

            if (string.IsNullOrWhiteSpace(result))
            {
                throw new DotNetWorkQueueException("Failed to enqueue a record. The LUA enqueue script returned null");
            }
            messageId = result;
            return(messageId);
        }
        /// <summary>
        /// Creates the messages to send.
        /// </summary>
        /// <param name="redisHeaders">The redis headers.</param>
        /// <param name="messages">The messages.</param>
        /// <param name="meta">The meta data, already serialized.</param>
        /// <param name="unixTimeFactory">The unix time factory.</param>
        /// <param name="messageIdFactory">The message identifier factory.</param>
        /// <param name="serializer">The composite serializer.</param>
        /// <returns></returns>
        public static List <EnqueueBatchLua.MessageToSend> CreateMessagesToSend(RedisHeaders redisHeaders,
                                                                                IReadOnlyCollection <QueueMessage <IMessage, IAdditionalMessageData> > messages,
                                                                                byte[] meta,
                                                                                IUnixTimeFactory unixTimeFactory,
                                                                                IGetMessageIdFactory messageIdFactory,
                                                                                ICompositeSerialization serializer)
        {
            var messagesToSend = new ConcurrentBag <EnqueueBatchLua.MessageToSend>();

            Parallel.ForEach(messages, m =>
            {
                //the correlation ID must be saved as a message header
                m.Message.SetHeader(redisHeaders.CorrelationId, new RedisQueueCorrelationIdSerialized((Guid)m.MessageData.CorrelationId.Id.Value));

                //check for delay and expiration
                long unixTimeStampDelay      = 0;
                long unixTimeStampExpiration = 0;
                if (m.MessageData.GetDelay().HasValue)
                {
                    // ReSharper disable once PossibleInvalidOperationException
                    unixTimeStampDelay = unixTimeFactory.Create().GetAddDifferenceMilliseconds(m.MessageData.GetDelay().Value);
                }
                // ReSharper disable once PossibleInvalidOperationException
                if (m.MessageData.GetExpiration().HasValue&& m.MessageData.GetExpiration().Value != TimeSpan.Zero)
                {
                    var unixTime = unixTimeFactory.Create();
                    var timeSpan = m.MessageData.GetExpiration();
                    if (timeSpan != null)
                    {
                        var timespan            = timeSpan.Value;
                        unixTimeStampExpiration = unixTime.GetAddDifferenceMilliseconds(timespan);
                    }
                }

                var serialized = serializer.Serializer.MessageToBytes(new MessageBody {
                    Body = m.Message.Body
                }, m.Message.Headers);
                m.Message.SetHeader(redisHeaders.Headers.StandardHeaders.MessageInterceptorGraph, serialized.Graph);

                messagesToSend.Add(new EnqueueBatchLua.MessageToSend
                {
                    Message         = serialized.Output,
                    Headers         = serializer.InternalSerializer.ConvertToBytes(m.Message.Headers),
                    MessageId       = messageIdFactory.Create().Create().ToString(),
                    MetaData        = meta,
                    CorrelationId   = m.MessageData.CorrelationId.ToString(),
                    TimeStamp       = unixTimeStampDelay,
                    ExpireTimeStamp = unixTimeStampExpiration,
                    Route           = m.MessageData.Route
                });
            });
            return(messagesToSend.ToList());
        }
        /// <summary>
        /// Creates the messages to send.
        /// </summary>
        /// <param name="redisHeaders">The redis headers.</param>
        /// <param name="messages">The messages.</param>
        /// <param name="meta">The meta data, already serialized.</param>
        /// <param name="unixTimeFactory">The unix time factory.</param>
        /// <param name="messageIdFactory">The message identifier factory.</param>
        /// <param name="serializer">The composite serializer.</param>
        /// <returns></returns>
        public static List<EnqueueBatchLua.MessageToSend> CreateMessagesToSend(RedisHeaders redisHeaders, 
            IReadOnlyCollection<QueueMessage<IMessage, IAdditionalMessageData>> messages,
            byte[] meta, 
            IUnixTimeFactory unixTimeFactory,
            IGetMessageIdFactory messageIdFactory,
            ICompositeSerialization serializer)
        {
            var messagesToSend = new ConcurrentBag<EnqueueBatchLua.MessageToSend>();
            Parallel.ForEach(messages, m =>
            {
                //the correlation ID must be saved as a message header
                m.Message.SetHeader(redisHeaders.CorelationId, new RedisQueueCorrelationIdSerialized((Guid)m.MessageData.CorrelationId.Id.Value));

                //check for delay and expiration
                long unixTimeStampDelay = 0;
                long unixTimeStampExpiration = 0;
                if (m.MessageData.GetDelay().HasValue)
                {
                    // ReSharper disable once PossibleInvalidOperationException
                    unixTimeStampDelay = unixTimeFactory.Create().GetAddDifferenceMilliseconds(m.MessageData.GetDelay().Value);
                }
                // ReSharper disable once PossibleInvalidOperationException
                if (m.MessageData.GetExpiration().HasValue && m.MessageData.GetExpiration().Value != TimeSpan.Zero)
                {
                    var unixTime = unixTimeFactory.Create();
                    var timeSpan = m.MessageData.GetExpiration();
                    if (timeSpan != null)
                    {
                        var timespan = timeSpan.Value;
                        unixTimeStampExpiration = unixTime.GetAddDifferenceMilliseconds(timespan);
                    }
                }

                var serialized = serializer.Serializer.MessageToBytes(new MessageBody { Body = m.Message.Body });
                m.Message.SetHeader(redisHeaders.Headers.StandardHeaders.MessageInterceptorGraph, serialized.Graph);

                messagesToSend.Add(new EnqueueBatchLua.MessageToSend()
                {
                    Message = serialized.Output,
                    Headers = serializer.InternalSerializer.ConvertToBytes(m.Message.Headers),
                    MessageId = messageIdFactory.Create().Create().ToString(),
                    MetaData = meta,
                    CorrelationId = m.MessageData.CorrelationId.ToString(),
                    TimeStamp = unixTimeStampDelay,
                    ExpireTimeStamp = unixTimeStampExpiration
                });
            });
            return messagesToSend.ToList();
        }