private async Task sendMessages(Endpoint destination, PersistentMessage[] messages)
 {
     var sender = createSender(destination, messages);
     MessageBookmark[] sendHistoryBookmarks = null;
     sender.Success = () => sendHistoryBookmarks = success(messages);
     try
     {
         await sender.Send();
         _logger.DebugMessage(() => new MessagesSent(messages, destination));
     }
     catch (FailedToConnectException ex)
     {
         _logger.InfoMessage(new FailedToSend(destination, "Failed to connect", ex));
         failedToConnect(messages);
     }
     catch (QueueDoesNotExistsException)
     {
         _logger.InfoMessage(new FailedToSend(destination, "Queue doesn't exist"));
         failedToSend(messages, true);
     }
     catch (RevertSendException)
     {
         _logger.InfoMessage(new FailedToSend(destination, "Revert was received"));
         revert(sendHistoryBookmarks, messages);
     }
     catch (Exception ex)
     {
         _logger.InfoMessage(new FailedToSend(destination, "Exception was thrown", ex));
         failedToSend(messages);
     }
 }
        public void OneMessage()
        {
            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>();
            }, ObjectMother.Logger()))
            {
                reciever.Start();

                new Sender(ObjectMother.Logger())
                {
                    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.Until(() => recievedMsgs != null).ShouldBeTrue();

                recievedMsgs.ShouldHaveCount(1);
                "hello doggy".ShouldEqual(recievedMsgs[0].Queue);
                new byte[] { 1, 2, 4, 5, 6 }.ShouldEqual(recievedMsgs[0].Data);
                new DateTime(2001, 1, 1).ShouldEqual(recievedMsgs[0].SentAt);
            }
        }
예제 #3
0
 public IEnumerable<Endpoint> GetEndpointsToSend(IEnumerable<Endpoint> currentlySending, int numberOfEndpoints)
 {
     var endpoints = new HashSet<Endpoint>();
     var enumerator = outgoing.GetEnumerator();
     while (enumerator.MoveNext())
     {
         var endpoint = new Endpoint( outgoing.ForColumnType<StringColumn>().Get("address"),
             outgoing.ForColumnType<IntColumn>().Get("port"));
         if (!endpoints.Contains(endpoint) && !currentlySending.Contains(endpoint))
         {
             endpoints.Add(endpoint);
             if (endpoints.Count == numberOfEndpoints)
                 break;
         }
     }
     return endpoints;
 }
 private async Task sendMessages(Endpoint destination, PersistentMessage[] messages)
 {
     var sender = createSender(destination, messages);
     MessageBookmark[] sendHistoryBookmarks = null;
     sender.Success = () => sendHistoryBookmarks = success(messages);
     try
     {
         await sender.Send().ConfigureAwait(false);
         _logger.MessagesSent(messages, destination);
     }
     catch (FailedToConnectException ex)
     {
         _logger.FailedToSend(destination, "Failed to connect", ex);
         failedToConnect(messages);
     }
     catch (QueueDoesNotExistsException)
     {
         _logger.FailedToSend(destination, "Queue doesn't exist");
         failedToSend(messages, true);
     }
     catch (RevertSendException)
     {
         _logger.FailedToSend(destination, "Revert was received");
         revert(sendHistoryBookmarks, messages);
     }
     catch (TimeoutException)
     {
         try
         {
             _logger.FailedToSend(destination, "Timed out");
             failedToSend(messages);
         }
         catch (EsentException)
         {
             // This will occur if the task completed as the TimeoutException was thrown, and 
             // the message was moved to history.  Swallow it to prevent unobserved task exceptions.
         }
     }
     catch (Exception ex)
     {
         _logger.FailedToSend(destination, "Exception was thrown", ex);
         failedToSend(messages);
     }
 }
 private PersistentMessage[] gatherMessagesToSend(Endpoint endpoint)
 {
     return _queueStorage.Send(actions => actions.GetMessagesToSendAndMarkThemAsInFlight(100, 1024 * 1024, endpoint));
 }
예제 #6
0
        public PersistentMessage[] GetMessagesToSendAndMarkThemAsInFlight(int maxNumberOfMessage, int maxSizeOfMessagesInTotal, Endpoint endpoint)
        {
            var enumerator = outgoing.GetEnumerator();

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

            while (enumerator.MoveNext())
            {
                var msgId = outgoing.ForColumnType<GuidColumn>().Get("msg_id");
                var value = (OutgoingMessageStatus) outgoing.ForColumnType<IntColumn>().Get("send_status");
                var time = outgoing.ForColumnType<DateTimeColumn>().Get("time_to_send");

                _logger.Debug("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 deliverByTime = outgoing.ForColumnType<DateTimeColumn>().GetOrDefault("deliver_by");
                if (deliverByTime.HasValue)
                {
                    if (deliverByTime < DateTime.Now)
                    {
                        _logger.Info("Outgoing message {0} was not succesfully sent by its delivery time limit {1}", msgId, deliverByTime);
                        var numOfRetries = outgoing.ForColumnType<IntColumn>().Get("number_of_retries");
                        MoveFailedMessageToOutgoingHistory(numOfRetries, msgId);
                        continue;
                    }
                }

                var maxAttempts = outgoing.ForColumnType<IntColumn>().GetOrDefault("max_attempts");
                if (maxAttempts != null)
                {
                    var numOfRetries = outgoing.ForColumnType<IntColumn>().Get("number_of_retries");
                    if (numOfRetries > maxAttempts)
                    {
                        _logger.Info("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(
                    outgoing.ForColumnType<StringColumn>().Get("address"),
                    outgoing.ForColumnType<IntColumn>().Get("port"));

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

                var rowQueue = outgoing.ForColumnType<StringColumn>().Get("queue");

                if (queue == null)
                    queue = rowQueue;

                if(queue != rowQueue)
                    continue;

                var bookmark = enumerator.Current;

                _logger.Info("Adding message {0} to returned messages", msgId);
                messages.Add(new PersistentMessage
                {
                    Id = new MessageId
                    {
                        SourceInstanceId = instanceId,
                        MessageIdentifier = msgId
                    },
                    Headers = HttpUtility.ParseQueryString(outgoing.ForColumnType<StringColumn>().Get("headers")),
                    Queue = rowQueue,
                    SubQueue = outgoing.ForColumnType<StringColumn>().Get("subqueue"),
                    SentAt = outgoing.ForColumnType<DateTimeColumn>().Get("sent_at"),
                    Data = outgoing.ForColumnType<BytesColumn>().Get("data"),
                    Bookmark = bookmark
                });

                outgoing.Update(() => outgoing.ForColumnType<IntColumn>().Set("send_status", (int)OutgoingMessageStatus.InFlight));

                _logger.Debug("Marking output message {0} as InFlight", msgId);

                if (maxNumberOfMessage < messages.Count)
                    break;
                if (maxSizeOfMessagesInTotal < messages.Sum(x => x.Data.Length))
                    break;
            }
            return messages.ToArray();
        }
예제 #7
0
 public void MessagesSent(IList<Message> messages, Endpoint destination)
 {
     Debug(() => "Messages {0} sent to {1}".ToFormat(string.Join(", ", messages.Select(x => x.Id)), destination));
 }
예제 #8
0
        public MessageId Send(ITransaction transaction, 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.");

            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, transaction.Id);

            });

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

            _logger.QueuedForSend(message, destination);

            return messageId;
        }
예제 #9
0
 public Guid RegisterToSend(Endpoint destination, string queue, string subQueue, MessagePayload payload, Guid transactionId)
 {
     var msgId = GuidCombGenerator.Generate();
     var bookmark = outgoing.Insert(() =>
     {
         outgoing.ForColumnType<GuidColumn>().Set("msg_id", msgId);
         outgoing.ForColumnType<GuidColumn>().Set("tx_id", transactionId);
         outgoing.ForColumnType<StringColumn>().Set("address", destination.Host);
         outgoing.ForColumnType<IntColumn>().Set("port", destination.Port);
         outgoing.ForColumnType<DateTimeColumn>().Set("time_to_send", DateTime.Now);
         outgoing.ForColumnType<DateTimeColumn>().Set("sent_at", DateTime.Now);
         outgoing.ForColumnType<IntColumn>().Set("send_status", (int)OutgoingMessageStatus.NotReady);
         outgoing.ForColumnType<StringColumn>().Set("queue", queue);
         outgoing.ForColumnType<StringColumn>().Set("subqueue", subQueue);
         outgoing.ForColumnType<StringColumn>().Set("headers", payload.Headers.ToQueryString());
         outgoing.ForColumnType<BytesColumn>().Set("data", payload.Data);
         outgoing.ForColumnType<IntColumn>().Set("number_of_retries", 1);
         outgoing.ForColumnType<IntColumn>().Set("size_of_data", payload.Data.Length);
         if(payload.DeliverBy.HasValue)
             outgoing.ForColumnType<DateTimeColumn>().Set("deliver_by", payload.DeliverBy.Value);
         if(payload.MaxAttempts.HasValue)
             outgoing.ForColumnType<IntColumn>().Set("max_attempts", payload.MaxAttempts.Value);
     });
     outgoing.MoveTo(bookmark);
     _logger.Debug("Created output message '{0}' for 'lq.tcp://{1}:{2}/{3}/{4}' as NotReady",
         msgId,
         destination.Host,
         destination.Port,
         queue,
         subQueue
         );
     return msgId;
 }
예제 #10
0
 public void QueuedForSend(Message message, Endpoint destination)
 {
     _queuedForSend.Add(new QueuedForSend(message, destination));
 }
예제 #11
0
 public void MessagesSent(IList<Message> messages, Endpoint destination)
 {
     _sent.Add(new SentMessages(destination, messages));
 }
예제 #12
0
 public void FailedToSend(Endpoint destination, string reason, Exception exception = null)
 {
     _sendFailures.Add(new SendFailure(destination, reason, exception));
 }
 public MessageQueuedForSend(Endpoint destination, Message message)
 {
     Destination = destination;
     Message = message;
 }
예제 #14
0
 public MessagesSent(Message[] messages, Endpoint destination)
 {
     Messages = messages;
     Destination = destination;
 }
예제 #15
0
 public void QueuedForSend(Message message, Endpoint destination)
 {
     Debug("Message {0} queued for send to {1}", message.Id, destination);
 }
 private Sender createSender(Endpoint destination, PersistentMessage[] messages)
 {
     return new Sender(_logger)
     {
         Connected = () => _choke.SuccessfullyConnected(),
         Destination = destination,
         Messages = messages,
     };
 }
예제 #17
0
 public FailedToSend(Endpoint destination, string reason, Exception exception = null)
 {
     Destination = destination;
     Reason = reason;
     Exception = exception;
 }
예제 #18
0
 public QueuedForSend(Message message, Endpoint destination)
 {
     Message = message;
     Destination = destination;
 }
예제 #19
0
 public SendFailure(Endpoint destination, string reason, Exception exception)
 {
     Destination = destination;
     Reason = reason;
     Exception = exception;
 }
예제 #20
0
 public SentMessages(Endpoint destination, IList<Message> messages)
 {
     Destination = destination;
     Messages = messages;
 }
예제 #21
0
 public MessageEventArgs(Endpoint endpoint, Message message)
 {
     Endpoint = endpoint;
     Message = message;
 }
예제 #22
0
 public void FailedToSend(Endpoint destination, string reason, Exception exception = null)
 {
     _logger.Info("Failed to send to {0}: {1}", destination, reason);
     _logger.DebugException("Details:", exception);
 }