Exemplo n.º 1
0
        public async Task MessageReceived(Message message, IQueuedMessageContext context,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            var messageContext = new BusMessageContext(_bus, context.Headers, context.SenderPrincipal);
            await MessageHandler.HandleMessage(_messageNamingService, _serializationService, _messageHandlers,
                message, messageContext, cancellationToken);

            if (messageContext.MessageAcknowledged)
            {
                await context.Acknowledge();
            }
        }
Exemplo n.º 2
0
        public ISentMessage CreateSentMessage(Message message)
        {
            CheckDisposed();

            var messageId = message.Headers.MessageId;
            var replyStreamExpiration = DateTime.UtcNow.Add(_replyTimeout);
            var newReplyStream = new ReplyStream();
            var replyStream = (ReplyStream) _cache.AddOrGetExisting(messageId, newReplyStream, replyStreamExpiration);
            // ReSharper disable once ConvertIfStatementToNullCoalescingExpression
            if (replyStream == null)
            {
                // MemoryCache.AddOrGetExisting returns null if the key does not
                // already exist, so use the one we just created. See:
                // http://msdn.microsoft.com/en-us/library/dd988741%28v=vs.110%29.aspx
                replyStream = newReplyStream;
            }
            return new SentMessageWithCachedReplies(messageId, replyStream);
        }
Exemplo n.º 3
0
        public static async Task HandleMessage(IMessageNamingService messageNamingService,
            ISerializationService serializationService, IEnumerable<IMessageHandler> messageHandlers, Message message,
            IMessageContext messageContext, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (message.Headers.Expires < DateTime.UtcNow)
            {
                Log.WarnFormat("Discarding expired \"{0}\" message (ID {1}, expired {2})", message.Headers.MessageName,
                    message.Headers.MessageId, message.Headers.Expires);

                messageContext.Acknowledge();
                return;
            }

            var messageType = messageNamingService.GetTypeForName(message.Headers.MessageName);
            var serializer = serializationService.GetSerializer(message.Headers.ContentType);
            var messageContent = serializer.Deserialize(message.Content, messageType);
            var handlingTasks =
                messageHandlers.Select(
                    handler => handler.HandleMessage(messageContent, messageContext, cancellationToken));

            await Task.WhenAll(handlingTasks);
        }
Exemplo n.º 4
0
 public async Task PublishMessage(Message message, TopicName topicName, CancellationToken cancellationToken)
 {
     await Task.Run(() => _accept(message, Thread.CurrentPrincipal), cancellationToken);
 }
Exemplo n.º 5
0
 public async Task SendMessage(Message message, IEndpointCredentials credentials = null,
     CancellationToken cancellationToken = new CancellationToken())
 {
     await Task.Run(() => _accept(message, Thread.CurrentPrincipal), cancellationToken);
 }
Exemplo n.º 6
0
        private async Task NotifyReplyReceived(Message message)
        {
            // TODO: Handle special "last reply" message.  Presently we only support a single reply.
            // This will probably be a special function of the ITransportService and will likely
            // be, for example, an empty POST to {baseUri}/message/{messageId}?lastReply=true, which
            // will trigger the OnComplete event in the IObservable reply stream.  However, we need
            // to put some thought into potential issues around the sequence and timing of replies
            // vs. the final lastReply POST to ensure that all replies are processed before the
            // OnComplete event is triggered.  One possibility is a reply sequence number header
            // and an indication of the total number of replies in the lastReply POST.  If the
            // number of replies received is less than the number expected, then the OnComplete
            // event can be deferred.

            var relatedToMessageId = message.Headers.RelatedTo;
            var messageType = _messageNamingService.GetTypeForName(message.Headers.MessageName);
            var serializer = _serializationService.GetSerializer(message.Headers.ContentType);
            var messageContent = serializer.Deserialize(message.Content, messageType);

            await _replyHub.ReplyReceived(messageContent, relatedToMessageId);
            await _replyHub.NotifyLastReplyReceived(relatedToMessageId);
        }
Exemplo n.º 7
0
        private async Task HandleMessageImmediately(Message message, SenderPrincipal senderPrincipal, bool isReply)
        {
            var messageContext = new BusMessageContext(this, message.Headers, senderPrincipal);
            var handlers = _handlingRules
                .Where(r => r.Specification.IsSatisfiedBy(message))
                .Select(rule => rule.MessageHandler)
                .ToList();

            if (!handlers.Any() && isReply)
            {
                // TODO: Figure out what to do here.
                return;
            }

            await MessageHandler.HandleMessage(_messageNamingService, _serializationService,
                handlers, message, messageContext, _cancellationTokenSource.Token);

            if (!messageContext.MessageAcknowledged)
            {
                throw new MessageNotAcknowledgedException();
            }
        }
Exemplo n.º 8
0
        /// <summary>
        /// Called by the host when a new message arrives to handle the message
        /// </summary>
        /// <param name="message">The new message</param>
        /// <param name="principal">The sender principal</param>
        /// <returns>Returns a task that completes when message handling is complete</returns>
        public async Task HandleMessage(Message message, IPrincipal principal)
        {
            if (_messageJournalingService != null)
            {
                await _messageJournalingService.MessageReceived(message);
            }

            // Make sure that the principal is serializable before enqueuing
            var senderPrincipal = principal as SenderPrincipal;
            if (senderPrincipal == null && principal != null)
            {
                senderPrincipal = new SenderPrincipal(principal);
            }

            var tasks = new List<Task>();

            var relatedToMessageId = message.Headers.RelatedTo;
            var isReply = relatedToMessageId != default(MessageId);
            if (isReply)
            {
                tasks.Add(NotifyReplyReceived(message));
            }

            var importance = message.Headers.Importance;
            if (importance.RequiresQueueing)
            {
                // Message expiration handled in MessageHandlingListener
                tasks.AddRange(_handlingRules
                    .Where(r => r.Specification.IsSatisfiedBy(message))
                    .Select(rule => rule.QueueName)
                    .Distinct()
                    .Select(q => _messageQueueingService.EnqueueMessage(q, message, senderPrincipal)));
            }
            else
            {
                tasks.Add(HandleMessageImmediately(message, senderPrincipal, isReply));
            }

            await Task.WhenAll(tasks);
        }
Exemplo n.º 9
0
 private IEnumerable<KeyValuePair<EndpointName, IEndpoint>> GetEndpointsForMessage(Message message)
 {
     return _sendRules
         .Where(rule => rule.Specification.IsSatisfiedBy(message))
         .SelectMany(rule => rule.Endpoints)
         .Join(_endpoints,
             endpointName => endpointName,
             endpointEntry => endpointEntry.Key,
             (_, endpointEntry) => endpointEntry);
 }
Exemplo n.º 10
0
        /// <summary>
        ///     Sends a <paramref name="content" /> to default configured endpoints.
        /// </summary>
        /// <param name="content">The content to send.</param>
        /// <param name="options">Optional settings that influence how the message is sent.</param>
        /// <param name="cancellationToken">An optional cancellation token</param>
        public async Task<ISentMessage> Send(object content, SendOptions options = default(SendOptions),
            CancellationToken cancellationToken = default(CancellationToken))
        {
            CheckDisposed();

            if (content == null) throw new ArgumentNullException("content");

            var prototypicalMessage = BuildMessage(content, options: options);
            var endpoints = GetEndpointsForMessage(prototypicalMessage);
            var transportTasks = new List<Task>();

            // Create the sent message before transporting it in order to ensure that the
            // reply stream is cached before any replies arrive.
            var sentMessage = _replyHub.CreateSentMessage(prototypicalMessage);

            // ReSharper disable once LoopCanBeConvertedToQuery
            foreach (var kvp in endpoints)
            {
                var endpointName = kvp.Key;
                var endpoint = kvp.Value;
                var credentials = endpoint.Credentials;
                var perEndpointHeaders = new MessageHeaders(prototypicalMessage.Headers)
                {
                    Destination = endpoint.Address
                };

                Log.DebugFormat("Sending message ID {0} to endpoint \"{1}\" ({2})...",
                    prototypicalMessage.Headers.MessageId, endpointName, endpoint.Address);

                var addressedMessage = new Message(perEndpointHeaders, prototypicalMessage.Content);
                transportTasks.Add(_transportService.SendMessage(addressedMessage, credentials, cancellationToken));
            }
            await Task.WhenAll(transportTasks);
            return sentMessage;
        }