public void OneMessage()
        {
            var wait = new ManualResetEvent(false);

            Message[] recievedMsgs = null;
            var endPoint = new Endpoint("localhost", 23456);
            using (var reciever = new Receiver(new IPEndPoint(IPAddress.Loopback, 23456), messages =>
            {
                recievedMsgs = messages;
                return MockRepository.GenerateStub<IMessageAcceptance>();
            }))
            {
                reciever.CompletedRecievingMessages += () => wait.Set();
                reciever.Start();

                new Sender
                {
                    Destination = endPoint,
                    Messages = new[]
                    {
                        new Message
                        {
                            Data = new byte[] {1, 2, 4, 5, 6},
                            SentAt = new DateTime(2001, 1, 1),
                            Queue = "hello doggy",
                            Id = MessageId.GenerateRandom()
                        },
                    }
                }.Send();

                wait.WaitOne();

                Assert.Equal(1, recievedMsgs.Length);
                Assert.Equal("hello doggy", recievedMsgs[0].Queue);
                Assert.Equal(new byte[] { 1, 2, 4, 5, 6 }, recievedMsgs[0].Data);
                Assert.Equal(new DateTime(2001, 1, 1), recievedMsgs[0].SentAt);
            }
        }
        public MessageId Send(Uri uri, MessagePayload payload)
        {
            if (waitingForAllMessagesToBeSent)
                throw new CannotSendWhileWaitingForAllMessagesToBeSentException("Currently waiting for all messages to be sent, so we cannot send. You probably have a race condition in your application.");

            EnsureEnslistment();
            var parts = uri.AbsolutePath.Substring(1).Split('/');
            var queue = parts[0];
            string subqueue = null;
            if (parts.Length > 1)
            {
                subqueue = string.Join("/", parts.Skip(1).ToArray());
            }

            Guid msgId = Guid.Empty;

            var port = uri.Port;
            if (port == -1)
                port = 2200;
            var destination = new Endpoint(uri.Host, port);

            queueStorage.Global(actions =>
            {
                msgId = actions.RegisterToSend(destination, queue,
                                               subqueue, payload, Enlistment.Id);

                actions.Commit();
            });

            var messageId = new MessageId
                                {
                                    SourceInstanceId = queueStorage.Id,
                                    MessageIdentifier = msgId
                                };
            var message = new Message
            {
                Id = messageId,
                Data = payload.Data,
                Headers = payload.Headers,
                Queue = queue,
                SubQueue = subqueue
            };

            OnMessageQueuedForSend(new MessageEventArgs(destination, message));

            return messageId;
        }
 public void FailedToSendTo(Endpoint endpointThatWeFailedToSendTo)
 {
     var action = FailedToSendMessagesTo;
     if (action != null)
         action(endpointThatWeFailedToSendTo);
 }
Beispiel #4
0
        public Guid RegisterToSend(Endpoint destination, string queue, string subQueue, MessagePayload payload, Guid transactionId)
        {
            var bookmark = new MessageBookmark();
            var msgId = GuidCombGenerator.Generate();
            using (var update = new Update(session, outgoing, JET_prep.Insert))
            {
                Api.SetColumn(session, outgoing, outgoingColumns["msg_id"], msgId.ToByteArray());
                Api.SetColumn(session, outgoing, outgoingColumns["tx_id"], transactionId.ToByteArray());
                Api.SetColumn(session, outgoing, outgoingColumns["address"], destination.Host, Encoding.Unicode);
                Api.SetColumn(session, outgoing, outgoingColumns["port"], destination.Port);
                Api.SetColumn(session, outgoing, outgoingColumns["time_to_send"], DateTime.Now.ToOADate());
                Api.SetColumn(session, outgoing, outgoingColumns["sent_at"], DateTime.Now.ToOADate());
                Api.SetColumn(session, outgoing, outgoingColumns["send_status"], (int)OutgoingMessageStatus.NotReady);
                Api.SetColumn(session, outgoing, outgoingColumns["queue"], queue, Encoding.Unicode);
                Api.SetColumn(session, outgoing, outgoingColumns["subqueue"], subQueue, Encoding.Unicode);
                Api.SetColumn(session, outgoing, outgoingColumns["headers"], payload.Headers.ToQueryString(),
                              Encoding.Unicode);
                Api.SetColumn(session, outgoing, outgoingColumns["data"], payload.Data);
                Api.SetColumn(session, outgoing, outgoingColumns["number_of_retries"], 1);
                Api.SetColumn(session, outgoing, outgoingColumns["size_of_data"], payload.Data.Length);

                update.Save(bookmark.Bookmark, bookmark.Size, out bookmark.Size);
            }
            Api.JetGotoBookmark(session, outgoing, bookmark.Bookmark, bookmark.Size);
            logger.DebugFormat("Created output message '{0}' for 'rhino.queues://{1}:{2}/{3}/{4}' as NotReady",
                msgId,
                destination.Host,
                destination.Port,
                queue,
                subQueue
                );
            return msgId;
        }
Beispiel #5
0
        public IList<PersistentMessage> GetMessagesToSendAndMarkThemAsInFlight(int maxNumberOfMessage, int maxSizeOfMessagesInTotal, out Endpoint endPoint)
        {
            Api.MoveBeforeFirst(session, outgoing);

            endPoint = null;
            string queue = null;
            var messages = new List<PersistentMessage>();

            while (Api.TryMoveNext(session, outgoing))
            {

                var msgId = new Guid(Api.RetrieveColumn(session, outgoing, ColumnsInformation.OutgoingColumns["msg_id"]));
                var value = (OutgoingMessageStatus)Api.RetrieveColumnAsInt32(session, outgoing, ColumnsInformation.OutgoingColumns["send_status"]).Value;
                var timeAsDate = Api.RetrieveColumnAsDouble(session, outgoing, ColumnsInformation.OutgoingColumns["time_to_send"]).Value;
                var time = DateTime.FromOADate(timeAsDate);

                logger.DebugFormat("Scanning message {0} with status {1} to be sent at {2}", msgId, value, time);
                if (value != OutgoingMessageStatus.Ready)
                    continue;

                if (time > DateTime.Now)
                    continue;

                var rowEndpoint = new Endpoint(
                    Api.RetrieveColumnAsString(session, outgoing, ColumnsInformation.OutgoingColumns["address"]),
                    Api.RetrieveColumnAsInt32(session, outgoing, ColumnsInformation.OutgoingColumns["port"]).Value
                    );

                if (endPoint == null)
                    endPoint = rowEndpoint;

                if (endPoint.Equals(rowEndpoint) == false)
                    continue;

                var rowQueue = Api.RetrieveColumnAsString(session, outgoing, ColumnsInformation.OutgoingColumns["queue"], Encoding.Unicode);

                if (queue == null)
                    queue = rowQueue;

                if(queue != rowQueue)
                    continue;

                logger.DebugFormat("Adding message {0} to returned messages", msgId);

                var bookmark = new MessageBookmark();
                Api.JetGetBookmark(session, outgoing, bookmark.Bookmark, bookmark.Size, out bookmark.Size);
                var headerAsQueryString = Api.RetrieveColumnAsString(session, outgoing, ColumnsInformation.OutgoingColumns["headers"],Encoding.Unicode);
                messages.Add(new PersistentMessage
                {
                    Id = new MessageId
                    {
                        SourceInstanceId = instanceId,
                        MessageIdentifier = msgId
                    },
                    Headers = HttpUtility.ParseQueryString(headerAsQueryString),
                    Queue = rowQueue,
                    SubQueue = Api.RetrieveColumnAsString(session, outgoing, ColumnsInformation.OutgoingColumns["subqueue"], Encoding.Unicode),
                    Priority = Api.RetrieveColumnAsInt16(session, outgoing, ColumnsInformation.OutgoingColumns["priority"]).Value,
                    SentAt = DateTime.FromOADate(Api.RetrieveColumnAsDouble(session, outgoing, ColumnsInformation.OutgoingColumns["sent_at"]).Value),
                    Data = Api.RetrieveColumn(session, outgoing, ColumnsInformation.OutgoingColumns["data"]),
                    Bookmark = bookmark
                });

                using (var update = new Update(session, outgoing, JET_prep.Replace))
                {
                    Api.SetColumn(session, outgoing, ColumnsInformation.OutgoingColumns["send_status"],
                                  (int)OutgoingMessageStatus.InFlight);
                    update.Save();
                }

                logger.DebugFormat("Marking output message {0} as InFlight", msgId);

                if (maxNumberOfMessage < messages.Count)
                    break;
                if (maxSizeOfMessagesInTotal < messages.Sum(x => x.Data.Length))
                    break;
            }
            return messages;
        }
        private Action<MessageBookmark[]> OnRevert(Endpoint endpoint	)
        {
        	return bookmarksToRevert =>
			{
				queueStorage.Send(actions =>
				{
					actions.RevertBackToSend(bookmarksToRevert);

					actions.Commit();
				});
				queueManager.FailedToSendTo(endpoint);
			};
        }
 private Action OnCommit(Endpoint endpoint, IEnumerable<PersistentMessage> messages)
 {
     return () =>
     {
         foreach (var message in messages)
         {
             queueManager.OnMessageSent(new MessageEventArgs(endpoint, message));
         }
     };
 }
        private Action<Exception> OnFailure(Endpoint endpoint, IEnumerable<PersistentMessage> messages)
        {
            return exception =>
            {
                try
                {
                    queueStorage.Send(actions =>
                        {
                            foreach (var message in messages)
                            {
                                actions.MarkOutgoingMessageAsFailedTransmission(message.Bookmark,
                                                                                exception is QueueDoesNotExistsException);
                            }

                            actions.Commit();
                            queueManager.FailedToSendTo(endpoint);
                        });
                }
                finally
                {
                    Interlocked.Decrement(ref currentlySendingCount);
                }
            };
        }
Beispiel #9
0
        public IList<PersistentMessage> GetMessagesToSendAndMarkThemAsInFlight(int maxNumberOfMessage, int maxSizeOfMessagesInTotal, out Endpoint endPoint)
        {
            Api.MoveBeforeFirst(session, outgoing);

            endPoint = null;
            string queue = null;
            var messages = new List<PersistentMessage>();

            while (Api.TryMoveNext(session, outgoing))
            {
                var msgId = new Guid(Api.RetrieveColumn(session, outgoing, ColumnsInformation.OutgoingColumns["msg_id"]));
                var value = (OutgoingMessageStatus)Api.RetrieveColumnAsInt32(session, outgoing, ColumnsInformation.OutgoingColumns["send_status"]).Value;
                var timeAsDate = Api.RetrieveColumnAsDouble(session, outgoing, ColumnsInformation.OutgoingColumns["time_to_send"]).Value;
                var time = DateTime.FromOADate(timeAsDate);

                logger.DebugFormat("Scanning message {0} with status {1} to be sent at {2}", msgId, value, time);
                if (value != OutgoingMessageStatus.Ready)
                    continue;

                // Check if the message has expired, and move it to the outgoing history.
                var deliverBy = Api.RetrieveColumnAsDouble(session, outgoing, ColumnsInformation.OutgoingColumns["deliver_by"]);
                if (deliverBy != null)
                {
                    var deliverByTime = DateTime.FromOADate(deliverBy.Value);
                    if (deliverByTime < DateTime.Now)
                    {
                        logger.InfoFormat("Outgoing message {0} was not succesfully sent by its delivery time limit {1}", msgId, deliverByTime);
                        var numOfRetries = Api.RetrieveColumnAsInt32(session, outgoing, ColumnsInformation.OutgoingColumns["number_of_retries"]).Value;
                        MoveFailedMessageToOutgoingHistory(numOfRetries, msgId);
                        continue;
                    }
                }

                var maxAttempts = Api.RetrieveColumnAsInt32(session, outgoing, ColumnsInformation.OutgoingColumns["max_attempts"]);
                if (maxAttempts != null)
                {
                    var numOfRetries = Api.RetrieveColumnAsInt32(session, outgoing, ColumnsInformation.OutgoingColumns["number_of_retries"]).Value;
                    if (numOfRetries > maxAttempts)
                    {
                        logger.InfoFormat("Outgoing message {0} has reached its max attempts of {1}", msgId, maxAttempts);
                        MoveFailedMessageToOutgoingHistory(numOfRetries, msgId);
                        continue;
                    }
                }

                if (time > DateTime.Now)
                    continue;

                var rowEndpoint = new Endpoint(
                    Api.RetrieveColumnAsString(session, outgoing, ColumnsInformation.OutgoingColumns["address"]),
                    Api.RetrieveColumnAsInt32(session, outgoing, ColumnsInformation.OutgoingColumns["port"]).Value
                    );

                if (endPoint == null)
                    endPoint = rowEndpoint;

                if (endPoint.Equals(rowEndpoint) == false)
                    continue;

                var rowQueue = Api.RetrieveColumnAsString(session, outgoing, ColumnsInformation.OutgoingColumns["queue"], Encoding.Unicode);

                if (queue == null)
                    queue = rowQueue;

                if(queue != rowQueue)
                    continue;

                var bookmark = new MessageBookmark();
                Api.JetGetBookmark(session, outgoing, bookmark.Bookmark, bookmark.Size, out bookmark.Size);

                logger.DebugFormat("Adding message {0} to returned messages", msgId);
                var headerAsQueryString = Api.RetrieveColumnAsString(session, outgoing, ColumnsInformation.OutgoingColumns["headers"],Encoding.Unicode);
                messages.Add(new PersistentMessage
                {
                    Id = new MessageId
                    {
                        SourceInstanceId = instanceId,
                        MessageIdentifier = msgId
                    },
                    Headers = HttpUtility.ParseQueryString(headerAsQueryString),
                    Queue = rowQueue,
                    SubQueue = Api.RetrieveColumnAsString(session, outgoing, ColumnsInformation.OutgoingColumns["subqueue"], Encoding.Unicode),
                    SentAt = DateTime.FromOADate(Api.RetrieveColumnAsDouble(session, outgoing, ColumnsInformation.OutgoingColumns["sent_at"]).Value),
                    Data = Api.RetrieveColumn(session, outgoing, ColumnsInformation.OutgoingColumns["data"]),
                    Bookmark = bookmark
                });

                using (var update = new Update(session, outgoing, JET_prep.Replace))
                {
                    Api.SetColumn(session, outgoing, ColumnsInformation.OutgoingColumns["send_status"],
                                  (int)OutgoingMessageStatus.InFlight);
                    update.Save();
                }

                logger.DebugFormat("Marking output message {0} as InFlight", msgId);

                if (maxNumberOfMessage < messages.Count)
                    break;
                if (maxSizeOfMessagesInTotal < messages.Sum(x => x.Data.Length))
                    break;
            }
            return messages;
        }
 public MessageEventArgs(Endpoint endpoint, Message message)
 {
     Endpoint = endpoint;
     Message = message;
 }