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); }
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; }
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); } }; }
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; }