Esempio n. 1
0
        /// <summary>
        /// Constructs a group and stores it in this Message object
        /// </summary>
        /// <param name="grpNoFld"></param>
        /// <param name="msgstr"></param>
        /// <param name="pos"></param>
        /// <param name="fieldMap"></param>
        /// <param name="dd"></param>
        /// <param name="sessionDataDictionary"></param>
        /// <param name="appDD"></param>
        /// <param name="msgFactory">if this is null, then this method will use the generic Group class constructor</param>
        /// <returns></returns>
        protected int SetGroup(StringField grpNoFld, string msgstr, int pos, FieldMap fieldMap, DataDictionary.IGroupSpec dd, DataDictionary.DataDictionary sessionDataDictionary, DataDictionary.DataDictionary appDD, IMessageFactory msgFactory)
        {
            int delim = dd.Delim;
            int grpPos = pos;
            Group grp = null;

            while (pos < msgstr.Length)
            {
                grpPos = pos;
                StringField f = ExtractField(msgstr, ref pos, sessionDataDictionary, appDD);
                if (f.Tag == delim)
                {
                    if (grp != null)
                    {
                        fieldMap.AddGroup(grp, false);
                    }

                    if (msgFactory != null)
                        grp = msgFactory.Create(Message.ExtractBeginString(msgstr), Message.GetMsgType(msgstr), grpNoFld.Tag);

                    //If above failed, just use a generic Group.
                    if (grp == null)
                        grp = new Group(grpNoFld.Tag, delim);
                }
                else if (!dd.IsField(f.Tag))
                {
                    if (grp != null)
                    {
                        fieldMap.AddGroup(grp, false);
                    }
                    return grpPos;
                }

                grp.SetField(f);

                if (dd.IsGroup(f.Tag))
                {

                    if (FixMessageDescriptorEnabled)
                    {
                        var oldCurrField = _currentGroupField;

                        _currentGroupField = new GroupFixFieldInfo();

                        _currentGroupField.Tag = f.Tag;

                        DataDictionary.DDField field = null;

                        if (appDD != null && appDD.FieldsByTag.TryGetValue(f.Tag, out field))
                        {
                            _currentGroupField.Name = field.Name;
                        }
                        else if (sessionDataDictionary != null && sessionDataDictionary.FieldsByTag.TryGetValue(f.Tag, out field))
                        {
                            _currentGroupField.Name = field.Name;
                        }
                        _currentGroupField.Value = f.getValue();

                        _currentGroupField.EnumValue = GetEnumValueFromField(f, field);

                        oldCurrField.Fields.Add(_currentGroupField);
                    }

                    pos = SetGroup(f, msgstr, pos, grp, dd.GetGroupSpec(f.Tag), sessionDataDictionary, appDD, msgFactory);

                }
                else
                {
                    if (FixMessageDescriptorEnabled)
                    {
                        FixFieldInfo fi = new FixFieldInfo();

                        fi.Tag = f.Tag;

                        DataDictionary.DDField field = null;

                        if (appDD != null && appDD.FieldsByTag.TryGetValue(f.Tag, out field))
                        {
                            _currentGroupField.Name = field.Name;
                        }
                        else if (sessionDataDictionary != null && sessionDataDictionary.FieldsByTag.TryGetValue(f.Tag, out field))
                        {
                            _currentGroupField.Name = field.Name;
                        }

                        fi.Value = f.getValue();

                        fi.EnumValue = GetEnumValueFromField(f, field);

                        _currentGroupField.Fields.Add(fi);

                    }

                }
            }

            return grpPos;
        }
Esempio n. 2
0
        /// <summary>
        /// Constructs a group and stores it in this Message object
        /// </summary>
        /// <param name="grpNoFld">the group's counter field</param>
        /// <param name="msgstr">full message string</param>
        /// <param name="pos">starting character position of group</param>
        /// <param name="fieldMap">full message as FieldMap</param>
        /// <param name="dd">group definition structure from dd</param>
        /// <param name="sessionDataDictionary"></param>
        /// <param name="appDD"></param>
        /// <param name="msgFactory">if null, then this method will use the generic Group class constructor</param>
        /// <returns></returns>
        protected int SetGroup(
            StringField grpNoFld, string msgstr, int pos, FieldMap fieldMap, DataDictionary.IGroupSpec dd,
            DataDictionary.DataDictionary sessionDataDictionary, DataDictionary.DataDictionary appDD, IMessageFactory msgFactory)
        {
            int grpEntryDelimiterTag = dd.Delim;
            int grpPos = pos;
            Group grp = null; // the group entry being constructed

            while (pos < msgstr.Length)
            {
                grpPos = pos;
                StringField f = ExtractField(msgstr, ref pos, sessionDataDictionary, appDD);
                if (f.Tag == grpEntryDelimiterTag)
                {
                    // This is the start of a group entry.

                    if (grp != null)
                    {
                        // We were already building an entry, so the delimiter means it's done.
                        fieldMap.AddGroup(grp, false);
                        grp = null; // prepare for new Group
                    }

                    // Create a new group!
                    if (msgFactory != null)
                        grp = msgFactory.Create(Message.ExtractBeginString(msgstr), Message.GetMsgType(msgstr), grpNoFld.Tag);

                    //If above failed (shouldn't ever happen), just use a generic Group.
                    if (grp == null)
                        grp = new Group(grpNoFld.Tag, grpEntryDelimiterTag);
                }
                else if (!dd.IsField(f.Tag))
                {
                    // This field is not in the group, thus the repeating group is done.

                    if (grp != null)
                    {
                        fieldMap.AddGroup(grp, false);
                    }
                    return grpPos;
                }

                if (grp == null)
                {
                    // This means we got into the group's fields without finding a delimiter tag.
                    throw new GroupDelimiterTagException(grpNoFld.Tag, grpEntryDelimiterTag);
                }

                // f is just a field in our group entry.  Add it and iterate again.
                grp.SetField(f);
                if(dd.IsGroup(f.Tag))
                {
                    // f is a counter for a nested group.  Recurse!
                    pos = SetGroup(f, msgstr, pos, grp, dd.GetGroupSpec(f.Tag), sessionDataDictionary, appDD, msgFactory);
                }
            }

            return grpPos;
        }
Esempio n. 3
0
        /// <summary>
        /// Constructs a group and stores it in this Message object
        /// </summary>
        /// <param name="grpNoFld">the group's counter field</param>
        /// <param name="msgstr">full message string</param>
        /// <param name="pos">starting character position of group</param>
        /// <param name="fieldMap">full message as FieldMap</param>
        /// <param name="dd">group definition structure from dd</param>
        /// <param name="sessionDataDictionary"></param>
        /// <param name="appDD"></param>
        /// <param name="msgFactory">if null, then this method will use the generic Group class constructor</param>
        /// <returns></returns>
        protected int SetGroup(
            StringField grpNoFld, string msgstr, int pos, FieldMap fieldMap, DataDictionary.IGroupSpec dd,
            DataDictionary.DataDictionary sessionDataDictionary, DataDictionary.DataDictionary appDD, IMessageFactory msgFactory)
        {
            int   grpEntryDelimiterTag = dd.Delim;
            int   grpPos = pos;
            Group grp    = null; // the group entry being constructed

            while (pos < msgstr.Length)
            {
                grpPos = pos;
                StringField f = ExtractField(msgstr, ref pos, sessionDataDictionary, appDD);
                if (f.Tag == grpEntryDelimiterTag)
                {
                    // This is the start of a group entry.

                    if (grp != null)
                    {
                        // We were already building an entry, so the delimiter means it's done.
                        fieldMap.AddGroup(grp, false);
                        grp = null; // prepare for new Group
                    }

                    // Create a new group!
                    if (msgFactory != null)
                    {
                        grp = msgFactory.Create(Message.ExtractBeginString(msgstr), Message.GetMsgType(msgstr), grpNoFld.Tag);
                    }

                    //If above failed (shouldn't ever happen), just use a generic Group.
                    if (grp == null)
                    {
                        grp = new Group(grpNoFld.Tag, grpEntryDelimiterTag);
                    }
                }
                else if (!dd.IsField(f.Tag))
                {
                    // This field is not in the group, thus the repeating group is done.

                    if (grp != null)
                    {
                        fieldMap.AddGroup(grp, false);
                    }
                    return(grpPos);
                }

                if (grp == null)
                {
                    // This means we got into the group's fields without finding a delimiter tag.
                    throw new GroupDelimiterTagException(grpNoFld.Tag, grpEntryDelimiterTag);
                }

                // f is just a field in our group entry.  Add it and iterate again.
                grp.SetField(f);
                if (dd.IsGroup(f.Tag))
                {
                    // f is a counter for a nested group.  Recurse!
                    pos = SetGroup(f, msgstr, pos, grp, dd.GetGroupSpec(f.Tag), sessionDataDictionary, appDD, msgFactory);
                }
            }

            return(grpPos);
        }
Esempio n. 4
0
        /// <summary>
        /// Constructs a group and stores it in this Message object
        /// </summary>
        /// <param name="grpNoFld"></param>
        /// <param name="msgstr"></param>
        /// <param name="pos"></param>
        /// <param name="fieldMap"></param>
        /// <param name="dd"></param>
        /// <param name="sessionDataDictionary"></param>
        /// <param name="appDD"></param>
        /// <param name="msgFactory">if this is null, then this method will use the generic Group class constructor</param>
        /// <returns></returns>
        protected int SetGroup(StringField grpNoFld, string msgstr, int pos, FieldMap fieldMap, DataDictionary.IGroupSpec dd, DataDictionary.DataDictionary sessionDataDictionary, DataDictionary.DataDictionary appDD, IMessageFactory msgFactory)
        {
            int delim = dd.Delim;
            int grpPos = pos;
            Group grp = null;

            while (pos < msgstr.Length)
            {
                grpPos = pos;
                StringField f = ExtractField(msgstr, ref pos, sessionDataDictionary, appDD);
                if (f.Tag == delim)
                {
                    if (grp != null)
                    {
                        fieldMap.AddGroup(grp, false);
                    }

                    if (msgFactory != null)
                        grp = msgFactory.Create(Message.ExtractBeginString(msgstr), Message.GetMsgType(msgstr), grpNoFld.Tag);

                    //If above failed, just use a generic Group.
                    if (grp == null)
                        grp = new Group(grpNoFld.Tag, delim);
                }
                else if (!dd.IsField(f.Tag))
                {
                    if (grp != null)
                    {
                        fieldMap.AddGroup(grp, false);
                    }
                    return grpPos;
                }
                grp.SetField(f);
                if(dd.IsGroup(f.Tag))
                {
                    pos = SetGroup(f, msgstr, pos, grp, dd.GetGroupSpec(f.Tag), sessionDataDictionary, appDD, msgFactory);
                }
            }

            return grpPos;
        }
Esempio n. 5
0
 public MessageViewModel CreateMessage(IMessageDelegate delegato, Message message)
 {
     return(_messageFactory.Create(delegato, message));
 }
Esempio n. 6
0
        /// <inheritdoc />
        public RedisMessage Handle(ReceiveMessageQuery query)
        {
            byte[] message = null;
            byte[] headers = null;
            string messageId;
            var    poisonMessage = false;
            RedisQueueCorrelationIdSerialized correlationId = null;

            try
            {
                var          unixTimestamp = _unixTimeFactory.Create().GetCurrentUnixTimestampMilliseconds();
                RedisValue[] result        = _dequeueLua.Execute(unixTimestamp);

                if (result == null || result.Length == 1 && !result[0].HasValue || !result[0].HasValue)
                {
                    return(null);
                }

                if (!result[1].HasValue)
                {
                    //at this point, the record has been de-queued, but it can't be processed.
                    poisonMessage = true;
                }

                messageId = result[0];
                var id = new RedisQueueId(messageId);
                query.MessageContext.SetMessageAndHeaders(id, null);
                if (!poisonMessage)
                {
                    message = result[1];
                    headers = result[2];
                    if (result[3].HasValue)
                    {
                        if (result[3].TryParse(out long messageExpiration))
                        {
                            if (messageExpiration - unixTimestamp < 0)
                            {
                                //message has expired
                                var allHeaders = _serializer.InternalSerializer.ConvertBytesTo <IDictionary <string, object> >(headers);
                                query.MessageContext.SetMessageAndHeaders(id, new ReadOnlyDictionary <string, object>(allHeaders));
                                _removeMessage.Remove(query.MessageContext, RemoveMessageReason.Expired);
                                return(new RedisMessage(messageId, null, true));
                            }
                        }
                    }
                }
            }
            catch (Exception error)
            {
                throw new ReceiveMessageException("Failed to dequeue a message", error);
            }

            if (poisonMessage)
            {
                //at this point, the record has been de-queued, but it can't be processed.
                throw new PoisonMessageException(
                          "An error has occurred trying to re-assemble a message de-queued from Redis; a messageId was returned, but the LUA script returned a null message. The message payload has most likely been lost.", null,
                          new RedisQueueId(messageId), new RedisQueueCorrelationId(Guid.Empty),
                          null, null);
            }

            try
            {
                var allHeaders = _serializer.InternalSerializer.ConvertBytesTo <IDictionary <string, object> >(headers);
                correlationId = (RedisQueueCorrelationIdSerialized)allHeaders[_redisHeaders.CorrelationId.Name];
                var messageGraph = (MessageInterceptorsGraph)allHeaders[_redisHeaders.Headers.StandardHeaders.MessageInterceptorGraph.Name];
                var messageData  = _serializer.Serializer.BytesToMessage <MessageBody>(message, messageGraph, allHeaders);

                var newMessage = _messageFactory.Create(messageData.Body, allHeaders);
                query.MessageContext.SetMessageAndHeaders(query.MessageContext.MessageId, new ReadOnlyDictionary <string, object>(allHeaders));

                return(new RedisMessage(
                           messageId,
                           _receivedMessageFactory.Create(
                               newMessage,
                               new RedisQueueId(messageId),
                               new RedisQueueCorrelationId(correlationId.Id)), false));
            }
            catch (Exception error)
            {
                //at this point, the record has been de-queued, but it can't be processed.
                throw new PoisonMessageException(
                          "An error has occurred trying to re-assemble a message de-queued from redis", error,
                          new RedisQueueId(messageId), new RedisQueueCorrelationId(correlationId),
                          message, headers);
            }
        }
Esempio n. 7
0
    public async Task Run([ServiceBusTrigger("message", Connection = "ServiceBus")] Message mySbMsg, ILogger log)
    {
        LogDetails logDetails = new LogDetails()
        {
            Queue = "Message"
        };

        logDetails.Started       = DateTime.Now;
        logDetails.MessageId     = mySbMsg.MessageId;
        logDetails.DeliveryCount = mySbMsg.SystemProperties.DeliveryCount;

        SendMessageRequest sendMessageRequest = null;

        bool emailAlreadySent = await _cosmosDbService.EmailSent(mySbMsg.MessageId);

        if (emailAlreadySent)
        {
            logDetails.Status = "email already sent";
        }
        else
        {
            try
            {
                string converted = Encoding.UTF8.GetString(mySbMsg.Body, 0, mySbMsg.Body.Length);

                sendMessageRequest = JsonConvert.DeserializeObject <SendMessageRequest>(converted);

                logDetails.Job             = Enum.GetName(typeof(CommunicationJobTypes), sendMessageRequest.CommunicationJobType);
                logDetails.RecipientUserId = sendMessageRequest.RecipientUserID;

                IMessage message = _messageFactory.Create(sendMessageRequest);

                EmailBuildData emailBuildData = await message.PrepareTemplateData(sendMessageRequest.BatchID, sendMessageRequest.RecipientUserID, sendMessageRequest.JobID, sendMessageRequest.GroupID, sendMessageRequest.RequestID, sendMessageRequest.AdditionalParameters, sendMessageRequest.TemplateName);

                if (emailBuildData != null)
                {
                    emailBuildData.JobID           = emailBuildData.JobID.HasValue ? emailBuildData.JobID : sendMessageRequest.JobID;
                    emailBuildData.GroupID         = emailBuildData.GroupID.HasValue ? emailBuildData.GroupID : sendMessageRequest.GroupID;
                    emailBuildData.RecipientUserID = sendMessageRequest.RecipientUserID;
                    emailBuildData.RequestID       = emailBuildData.RequestID.HasValue ? emailBuildData.RequestID : sendMessageRequest.RequestID;
                    var result = await _connectSendGridService.SendDynamicEmail(mySbMsg.MessageId, sendMessageRequest.TemplateName, message.GetUnsubscriptionGroupName(sendMessageRequest.RecipientUserID), emailBuildData);

                    logDetails.Status = $"SendDynamicEmail: {result}";
                }
                else
                {
                    logDetails.Status = "no emailBuildData";
                }
            }
            catch (AggregateException exc)
            {
                RetryHandler(mySbMsg, sendMessageRequest, exc.InnerException, log);
            }
            catch (Exception ex)
            {
                log.LogInformation($"Calling retry handler...");

                // Manage retries using our message retry handler
                RetryHandler(mySbMsg, sendMessageRequest, ex, log);
            }
        }

        logDetails.Finished = DateTime.Now;
        string json = JsonConvert.SerializeObject(logDetails);

        log.LogInformation(json);
    }
Esempio n. 8
0
 /// <summary>
 ///     Creates an empty message
 /// </summary>
 /// <param name="opCode"></param>
 /// <returns></returns>
 public static IMessage Create(short opCode)
 {
     return(_factory.Create(opCode));
 }
Esempio n. 9
0
        internal IReceivedMessageInternal HandleMessage(IDbConnection connection, IDbTransaction transaction, IDataReader reader, CommandString commandString)
        {
            if (!reader.Read())
            {
                return(null);
            }

            //load up the message from the DB
            long id            = 0;
            var  correlationId = Guid.Empty;

            byte[] headerPayload  = null;
            byte[] messagePayload = null;
            try
            {
                id = (long)reader["QueueID"];
                var cId = (string)reader["CorrelationID"];
                headerPayload  = (byte[])reader["Headers"];
                messagePayload = (byte[])reader["Body"];

                //before we continue, run the commands and commit the transaction
                //otherwise, poison messages will conflict
                foreach (var additionalCommand in commandString.AdditionalCommands)
                {
                    using (var command = connection.CreateCommand())
                    {
                        command.Transaction = transaction;
                        command.CommandText = additionalCommand;
                        command.ExecuteNonQuery();
                    }
                }
                transaction.Commit();

                correlationId = new Guid(cId);
                var headers =
                    _serialization.InternalSerializer
                    .ConvertBytesTo <IDictionary <string, object> >(
                        headerPayload);

                var messageGraph =
                    (MessageInterceptorsGraph)
                    headers[_headers.StandardHeaders.MessageInterceptorGraph.Name];

                var message =
                    _serialization.Serializer.BytesToMessage <MessageBody>(
                        messagePayload,
                        messageGraph, headers).Body;
                var newMessage = _messageFactory.Create(message, headers);

                return(_receivedMessageFactory.Create(newMessage,
                                                      new MessageQueueId <long>(id),
                                                      new MessageCorrelationId <Guid>(correlationId)));
            }
            catch (Exception err)
            {
                //at this point, the record has been de-queued, but it can't be processed.
                throw new PoisonMessageException(
                          "An error has occurred trying to re-assemble a message de-queued from SQLite",
                          err, new MessageQueueId <long>(id),
                          new MessageCorrelationId <Guid>(correlationId),
                          messagePayload,
                          headerPayload);
            }
        }
Esempio n. 10
0
 public virtual void Cancel()
 {
     _eventAggregator.PublishOnUIThreadAsync(_messageFactory.Create(typeof(DeviceSelectedMessage)));
 }
        /// <inheritdoc />
        public IReceivedMessageInternal Handle(ReceiveMessageQuery <NpgsqlConnection, NpgsqlTransaction> query)
        {
            using (var selectCommand = query.Connection.CreateCommand())
            {
                selectCommand.Transaction = query.Transaction;
                if (query.MessageId != null && query.MessageId.HasValue)
                {
                    selectCommand.CommandText =
                        ReceiveMessage.GetDeQueueCommand(_commandCache, _tableNameHelper, _options.Value, true, query.Routes);
                    selectCommand.Parameters.Add("@QueueID", NpgsqlDbType.Bigint);
                    selectCommand.Parameters["@QueueID"].Value = query.MessageId.Id.Value;
                }
                else
                {
                    selectCommand.CommandText =
                        ReceiveMessage.GetDeQueueCommand(_commandCache, _tableNameHelper, _options.Value, false, query.Routes);
                }

                selectCommand.Parameters.Add("@CurrentDate", NpgsqlDbType.Bigint);
                selectCommand.Parameters["@CurrentDate"].Value = _getTime.GetCurrentUtcDate().Ticks;

                if (_options.Value.EnableRoute && query.Routes != null && query.Routes.Count > 0)
                {
                    var routeCounter = 1;
                    foreach (var route in query.Routes)
                    {
                        selectCommand.Parameters.Add("@Route" + routeCounter, NpgsqlDbType.Varchar);
                        selectCommand.Parameters["@Route" + routeCounter].Value = route;
                        routeCounter++;
                    }
                }

                using (var reader = selectCommand.ExecuteReader())
                {
                    if (!reader.Read())
                    {
                        return(null);
                    }

                    //load up the message from the DB
                    long   id             = 0;
                    var    correlationId  = Guid.Empty;
                    byte[] headerPayload  = null;
                    byte[] messagePayload = null;
                    try
                    {
                        id             = (long)reader["queueid"];
                        correlationId  = (Guid)reader["CorrelationID"];
                        headerPayload  = (byte[])reader["Headers"];
                        messagePayload = (byte[])reader["body"];

                        var headers      = _serialization.InternalSerializer.ConvertBytesTo <IDictionary <string, object> >(headerPayload);
                        var messageGraph = (MessageInterceptorsGraph)headers[_headers.StandardHeaders.MessageInterceptorGraph.Name];
                        var message      = _serialization.Serializer.BytesToMessage <MessageBody>(messagePayload, messageGraph).Body;
                        var newMessage   = _messageFactory.Create(message, headers);

                        return(_receivedMessageFactory.Create(newMessage,
                                                              new MessageQueueId(id),
                                                              new MessageCorrelationId(correlationId)));
                    }
                    catch (Exception error)
                    {
                        //at this point, the record has been de-queued, but it can't be processed.
                        throw new PoisonMessageException(
                                  "An error has occurred trying to re-assemble a message de-queued from the server ", error, new MessageQueueId(id), new MessageCorrelationId(correlationId), messagePayload, headerPayload);
                    }
                }
            }
        }
Esempio n. 12
0
        public async ValueTask <IMessage <TMessage> > Receive(CancellationToken cancellationToken)
        {
            using (await _lock.Lock(cancellationToken).ConfigureAwait(false))
            {
                while (true)
                {
                    if (_sendWhenZero == 0)
                    {
                        await SendFlow(cancellationToken).ConfigureAwait(false);
                    }

                    _sendWhenZero--;

                    var message = _batchHandler.GetNext();

                    if (message is not null)
                    {
                        return(message);
                    }

                    var messagePackage = await _queue.Dequeue(cancellationToken).ConfigureAwait(false);

                    if (!messagePackage.ValidateMagicNumberAndChecksum())
                    {
                        await RejectPackage(messagePackage, CommandAck.ValidationErrorType.ChecksumMismatch, cancellationToken).ConfigureAwait(false);

                        continue;
                    }

                    var metadataSize = messagePackage.GetMetadataSize();
                    var metadata     = messagePackage.ExtractMetadata(metadataSize);
                    var data         = messagePackage.ExtractData(metadataSize);

                    if (metadata.Compression != CompressionType.None)
                    {
                        var decompressor = _decompressors[(int)metadata.Compression];
                        if (decompressor is null)
                        {
                            throw new CompressionException($"Support for {metadata.Compression} compression was not found");
                        }

                        try
                        {
                            data = decompressor.Decompress(data, (int)metadata.UncompressedSize);
                        }
                        catch
                        {
                            await RejectPackage(messagePackage, CommandAck.ValidationErrorType.DecompressionError, cancellationToken).ConfigureAwait(false);

                            continue;
                        }
                    }

                    var messageId       = messagePackage.MessageId;
                    var redeliveryCount = messagePackage.RedeliveryCount;

                    if (metadata.ShouldSerializeNumMessagesInBatch())
                    {
                        try
                        {
                            return(_batchHandler.Add(messageId, redeliveryCount, metadata, data));
                        }
                        catch
                        {
                            await RejectPackage(messagePackage, CommandAck.ValidationErrorType.BatchDeSerializeError, cancellationToken).ConfigureAwait(false);

                            continue;
                        }
                    }

                    return(_messageFactory.Create(messageId.ToMessageId(), redeliveryCount, data, metadata));
                }
            }
        }
Esempio n. 13
0
        /// <inheritdoc />
        public IReceivedMessageInternal GetNextMessage(List <string> routes, TimeSpan timeout)
        {
            if (_complete)
            {
                return(null);
            }

            if (routes != null && routes.Count > 0)
            {
                throw new NotSupportedException("The in-memory transport does not support routes");
            }

            using (CancellationTokenSource linkedCts =
                       CancellationTokenSource.CreateLinkedTokenSource(_cancelToken.CancelWorkToken,
                                                                       _cancelToken.StopWorkToken))
            {
                Guid id = Guid.Empty;
                try
                {
                    if (!Queues[_connectionInformation].TryTake(out id, Convert.ToInt32(timeout.TotalMilliseconds), linkedCts.Token))
                    {
                        return(null);
                    }
                }
                catch (OperationCanceledException)
                {
                    return(null);
                }

                if (!QueueData[_connectionInformation].TryRemove(id, out var item))
                {
                    return(null);
                }

                var hasError = false;
                try
                {
                    var newMessage = _messageFactory.Create(item.Body, item.Headers);

                    if (!string.IsNullOrEmpty(item.JobName))
                    {
                        var key = GenerateKey(item.JobName);

                        //add it to the cache
                        JobLastEventCache.Execute(context => item.JobEventTime, new Context(key));
                    }

                    Interlocked.Increment(ref DequeueCounts[_connectionInformation].ProcessedCount);

                    return(_receivedMessageFactory.Create(newMessage,
                                                          new MessageQueueId(id),
                                                          new MessageCorrelationId(item.CorrelationId)));
                }
                catch (Exception error)
                {
                    hasError = true;
                    //at this point, the record has been de-queued, but it can't be processed.
                    throw new PoisonMessageException(
                              "An error has occurred trying to re-assemble a message", error,
                              new MessageQueueId(id), null, null, null);
                }
                finally
                {
                    if (!hasError)
                    {
                        QueueWorking[_connectionInformation].TryAdd(item.Id, item);
                    }
                }
            }
        }