private async Task SendMessageAsync(ApolloQueue queue, Lazy <IMessageSender> sender, IMessage[] messages)
        {
            if (messages == null || !messages.Any())
            {
                return;
            }
            if (!messages.All(m => m is ServiceBusMessage))
            {
                throw new InvalidOperationException($"{GetType().Name} cannot send messages which do not inherit from {nameof(ServiceBusMessage)}");
            }
            try
            {
                await sender.Value.SendAsync(messages.Select(m => ((ServiceBusMessage)m).InnerMessage).ToArray());

                foreach (var message in messages)
                {
                    OnMessageSent(message, queue);
                }
            }
            catch (Exception ex)
            {
                Logger.Warn(ex);
                throw;
            }
        }
Пример #2
0
 private MessageStatus OnRegistrationReceived(ApolloQueue queue, IMessage m, CancellationToken?cancelToken)
 {
     Logger.Info($"Received registration request from {m.Identifier}");
     if (_storage.SaveRegistration(m.ReplyToSession, m.Properties.ToDictionary(p => p.Key, p => p.Value.ToString())))
     {
         Communicator.SendToClientsAsync(Communicator.MessageFactory.CreateAcknowledgment(m));
     }
     return(MessageStatus.Complete);
 }
        private void InvokeMessageHandlers(ApolloQueue queue, IMessage message, CancellationToken?token)
        {
            if (message == null)
            {
                return;
            }

            try
            {
                if (Handlers.TryGetValue(queue, out var handlers))
                {
                    var status = MessageStatus.Unhandled;
                    foreach (var handler in handlers.Where(h => h.PassesFilter(message)))
                    {
                        try
                        {
                            if (token?.IsCancellationRequested ?? false)
                            {
                                return;
                            }
                            status = handler.HandleMessage(queue, message, token);
                            if (status.HasFlag(MessageStatus.Handled))
                            {
                                break;
                            }
                        }
                        catch (Exception ex)
                        {
                            _service.AsyncListeningExceptions.Add(ExceptionDispatchInfo.Capture(ex));
                            _logger?.WriteLine($"{ex.Message} (This would normally be suppressed by the system)");
                            throw;
                        }
                    }
                    if (message.Label == ApolloConstants.PositiveAcknowledgement || message.Label == ApolloConstants.NegativeAcknowledgement)
                    {
                        return;
                    }
                    if (status == MessageStatus.Unhandled)
                    {
                        throw new Exception($"{_identifier} received a message from {queue} with label '{message.Label}' which no handler could handle");
                    }
                    if (!status.HasFlag(MessageStatus.MarkedForDeletion))
                    {
                        _service.Enqueue(message, queue, _identifier);
                    }
                }
                else
                {
                    Debug.Assert(false, "Received a message without having any handlers!");
                }
            }
            catch (Exception ex)
            {
                _logger?.WriteLine($"{ex.Message} (This would normally be suppressed by the system)");
                _service.AsyncListeningExceptions.Add(ExceptionDispatchInfo.Capture(ex));
            }
        }
Пример #4
0
        protected virtual MessageStatus HandlePing(ApolloQueue targetQueue, IMessage message, CancellationToken?token)
        {
            var response = MessageFactory.CreateAcknowledgment(message);

            response[nameof(PingStats.ServedBy)] = Communicator.GetState <string>(ApolloConstants.RegisteredAsKey);
            response[nameof(PingStats.TimeRequestEnqueuedUtc)] = message.EnqueuedTimeUtc;
            Communicator.SendToClientsAsync(response);
            return(MessageStatus.Complete);
        }
Пример #5
0
 public ConcurrentQueue <MockMessage> GetQueue(ApolloQueue queueType, string targetSession)
 {
     if (NormalQueues.TryGetValue(queueType, out var queue))
     {
         if (targetSession != null)
         {
             throw new InvalidOperationException("Tried to send a message to a session in a queue without sessions enabled");
         }
         return(queue);
     }
     return(GetSessionQueue(queueType, targetSession));
 }
Пример #6
0
        private MessageStatus LostOwnershipNotificationReceived(ApolloQueue queue, IMessage m, CancellationToken?cancelToken)
        {
            var alias = m.GetStringProperty(DesiredAliasKey);

            if (string.IsNullOrWhiteSpace(alias))
            {
                return(MessageStatus.Complete);
            }
            Logger.Warn($"Lost ownership of alias '{alias}'");
            LostOwnershipOfAlias?.Invoke(alias);
            return(MessageStatus.Complete);
        }
Пример #7
0
 private MessageStatus AliasOwnershipRequestReceived(ApolloQueue queue, IMessage m, CancellationToken?cancelToken)
 {
     if (_storage.CheckOwnership(m.GetStringProperty(DesiredAliasKey), Guid.Parse(m.GetStringProperty(AliasTokenKey)), m.ReplyToSession))
     {
         var reply = MessageFactory.CreateAcknowledgment(m);
         reply.CopyPropertiesFrom(m);
         Communicator.SendToClientsAsync(reply);
         Logger.Info($"{m.Identifier} granted ownership of alias '{m.GetStringProperty(DesiredAliasKey)}'");
     }
     else
     {
         Logger.Info($"{m.Identifier} denied ownership of alias '{m.GetStringProperty(DesiredAliasKey)}'");
         Communicator.SendToClientsAsync(MessageFactory.CreateNegativeAcknowledgment(m, $"Token did not match the one registered for {m.GetStringProperty(DesiredAliasKey)}"));
     }
     return(MessageStatus.Complete);
 }
        private async Task InvokeMessageHandlers(IReceiverClient receiver, ApolloQueue queue, ServiceBusMessage message, CancellationToken?token)
        {
            if (message == null)
            {
                return;
            }

            if (Handlers.TryGetValue(queue, out var handlers))
            {
                var status = MessageStatus.Unhandled;
                foreach (var handler in handlers.Where(h => h.PassesFilter(message)))
                {
                    try
                    {
                        if (token?.IsCancellationRequested ?? false)
                        {
                            return;
                        }
                        status = handler.HandleMessage(queue, message, token);
                        if (status.HasFlag(MessageStatus.Handled))
                        {
                            break;
                        }
                    }
                    catch (Exception ex)
                    {
                        Logger.Error($"Encountered an error in {handler.OnMessageReceived.Method.DeclaringType?.Name ?? "<Unknown>"}.{handler.OnMessageReceived.Method.Name} while handling a message labelled {message.Label}", ex);
                    }
                }
                if (status.HasFlag(MessageStatus.MarkedForDeletion))
                {
                    await receiver.CompleteAsync(message.InnerMessage.SystemProperties.LockToken);
                }
                else if (string.IsNullOrWhiteSpace(message.ResponseTo))
                {
                    await receiver.DeadLetterAsync(message.InnerMessage.SystemProperties.LockToken, $"{State[ApolloConstants.RegisteredAsKey]} does not have a plugin which can handle this message");
                }
                else
                {
                    await receiver.DeadLetterAsync(message.InnerMessage.SystemProperties.LockToken, $"{State[ApolloConstants.RegisteredAsKey]} is not expecting or longer waiting for this response");
                }
            }
            else
            {
                Logger.Error($"Received a message on queue {queue} without having any handlers registered for that queue! (This should not be possible and implies that something has gone wrong)");
            }
        }
Пример #9
0
        private MessageStatus AliasOwnershipClaimReceived(ApolloQueue queue, IMessage m, CancellationToken?cancelToken)
        {
            var oldOwner = _storage.TakeOwnership(m.GetStringProperty(DesiredAliasKey), Guid.Parse(m.GetStringProperty(AliasTokenKey)), m.ReplyToSession);

            if (oldOwner != null)
            {
                var lostOwnershipMessage = MessageFactory.CreateNewMessage("Lost Alias Ownership");
                lostOwnershipMessage.TargetSession    = oldOwner;
                lostOwnershipMessage[DesiredAliasKey] = m.GetStringProperty(DesiredAliasKey);
                Communicator.SendToClientsAsync(lostOwnershipMessage);
            }
            var reply = MessageFactory.CreateAcknowledgment(m);

            reply.CopyPropertiesFrom(m);
            Communicator.SendToClientsAsync(reply);
            return(MessageStatus.Complete);
        }
Пример #10
0
        private MessageStatus ForwardAliasMessage(ApolloQueue queue, IMessage m, CancellationToken?cancelToken)
        {
            var targetAlias = m.GetStringProperty(ApolloConstants.TargetAliasKey);
            var owner       = _storage.GetAliasOwner(targetAlias);

            if (owner == null)
            {
                Communicator.SendToClientsAsync(MessageFactory.CreateNegativeAcknowledgment(m, $"Alias '{targetAlias ?? "<Alias not specified>"}' is not owned or invalid"));
            }
            else
            {
                var forwardedMessage = MessageFactory.CloneMessage(m);
                forwardedMessage.TargetSession = owner;
                Communicator.SendToClientsAsync(forwardedMessage);
            }
            return(MessageStatus.Complete);
        }
 public MessageStatus HandleMessage(ApolloQueue queue, IMessage message, CancellationToken?cancelToken)
 {
     if (OnMessageReceived == null)
     {
         return(MessageStatus.Unhandled);
     }
     try
     {
         return(OnMessageReceived.Invoke(queue, message, cancelToken));
     }
     catch (Exception ex)
     {
         var logger = Plugin?.GetLogger();
         logger?.Error($"Encountered an error while processing a message with label {message.Label} ({ex.Message})");
         logger?.Debug(ex);
         OnError?.Invoke(message, ex);
         throw;
     }
 }
        protected override string GetQueueName(ApolloQueue queue)
        {
            switch (queue)
            {
            case ApolloQueue.Registrations:
                return(Configuration.RegistrationQueue);

            case ApolloQueue.ServerRequests:
                return(Configuration.ServerRequestsQueue);

            case ApolloQueue.Aliases:
                return(Configuration.ClientAliasesQueue);

            case ApolloQueue.ClientSessions:
                return(Configuration.ClientsQueue);

            default:
                throw new ArgumentOutOfRangeException(nameof(queue), queue, null);
            }
        }
Пример #13
0
 public ConcurrentQueue <MockMessage> GetSessionQueue(ApolloQueue queueType, string identifier)
 {
     return(SessionQueues.TryGetValue(queueType, out var queue)
                     ? queue.GetOrAdd(identifier, new ConcurrentQueue <MockMessage>())
                     : null);
 }
Пример #14
0
 public MockMessageSender(MockServiceBusQueues queues, ApolloQueue queueType)
 {
     QueueType = queueType;
     Queues    = queues;
 }
 private MockQueue GetSessionQueue(ApolloQueue queueType, string identifier)
 {
     return(SessionQueues.TryGetValue(queueType, out var queue)
                         ? queue.GetOrAdd(identifier, new MockQueue())
                         : null);
 }
 public MockQueue GetQueue(ApolloQueue queueType, string targetSession)
 {
     return(!NormalQueues.TryGetValue(queueType, out var queue)
                         ? GetSessionQueue(queueType, targetSession)
                         : queue);
 }