Beispiel #1
0
        /// <summary>
        /// Clears messages in a queue
        /// </summary>
        private async Task ClearMessages(MqClient client, HorseMessage message)
        {
            HorseQueue queue = _server.FindQueue(message.Target);

            if (queue == null)
            {
                if (message.WaitResponse)
                {
                    await client.SendAsync(message.CreateResponse(HorseResultCode.NotFound));
                }

                return;
            }

            string prio      = message.FindHeader(HorseHeaders.PRIORITY_MESSAGES);
            string msgs      = message.FindHeader(HorseHeaders.MESSAGES);
            bool   clearPrio = !string.IsNullOrEmpty(prio) && prio.Equals("yes", StringComparison.InvariantCultureIgnoreCase);
            bool   clearMsgs = !string.IsNullOrEmpty(msgs) && msgs.Equals("yes", StringComparison.InvariantCultureIgnoreCase);

            foreach (IAdminAuthorization authorization in _server.AdminAuthorizations)
            {
                bool grant = await authorization.CanClearQueueMessages(client, queue, clearPrio, clearMsgs);

                if (!grant)
                {
                    if (message.WaitResponse)
                    {
                        await client.SendAsync(message.CreateResponse(HorseResultCode.Unauthorized));
                    }

                    return;
                }
            }

            if (clearPrio && clearMsgs)
            {
                queue.ClearAllMessages();
            }
            else if (clearPrio)
            {
                queue.ClearHighPriorityMessages();
            }
            else if (clearMsgs)
            {
                queue.ClearRegularMessages();
            }

            //if creation successful, sends response
            if (message.WaitResponse)
            {
                await client.SendAsync(message.CreateResponse(HorseResultCode.Ok));
            }
        }
        /// <summary>
        /// Gets queue.
        /// If it's not cached, finds and caches it before returns.
        /// </summary>
        /// <returns></returns>
        private async Task <HorseQueue> GetQueue(HorseMessage message)
        {
            if (_targetQueue != null)
            {
                return(_targetQueue);
            }

            string queueName = message.FindHeader(HorseHeaders.QUEUE_NAME);

            if (queueName == null)
            {
                return(null);
            }

            HorseQueue queue = Router.Server.FindQueue(queueName);

            if (queue != null)
            {
                _targetQueue = queue;
                return(_targetQueue);
            }

            _targetQueue = await Router.Server.CreateQueue(queueName, Router.Server.Options, message, null, true, true);

            return(_targetQueue);
        }
Beispiel #3
0
        /// <summary>
        /// Reads Clear header value and returns as enum
        /// </summary>
        private static ClearDecision FindClearDecision(HorseMessage request)
        {
            string clearStr = request.FindHeader(HorseHeaders.CLEAR);

            if (string.IsNullOrEmpty(clearStr))
            {
                return(ClearDecision.None);
            }

            clearStr = clearStr.Trim();

            if (clearStr.Equals("all", StringComparison.InvariantCultureIgnoreCase))
            {
                return(ClearDecision.All);
            }

            if (clearStr.Equals("high-priority", StringComparison.InvariantCultureIgnoreCase))
            {
                return(ClearDecision.HighPriority);
            }

            if (clearStr.Equals("default-priority", StringComparison.InvariantCultureIgnoreCase))
            {
                return(ClearDecision.DefaultPriority);
            }

            return(ClearDecision.None);
        }
Beispiel #4
0
        public async Task Handle(MqClient client, HorseMessage message, bool fromNode)
        {
            HorseQueue queue = await FindQueue(client, message.Target, message);

            if (queue == null)
            {
                return;
            }

            //if there is at least one cc header
            //we need to create a clone of the message
            //clone does not have cc headers but others
            HorseMessage  clone  = null;
            List <string> ccList = null;
            List <KeyValuePair <string, string> > additionalHeaders = null;

            if (message.HasHeader && message.FindHeader(HorseHeaders.CC) != null)
            {
                additionalHeaders = message.Headers.Where(x => !x.Key.Equals(HorseHeaders.CC, StringComparison.InvariantCultureIgnoreCase)).ToList();
                ccList            = new List <string>(message.Headers.Where(x => x.Key.Equals(HorseHeaders.CC, StringComparison.InvariantCultureIgnoreCase)).Select(x => x.Value));
                clone             = message.Clone(false, true, _server.MessageIdGenerator.Create(), additionalHeaders);
            }

            await HandlePush(client, message, queue, true);

            //if there are cc headers, we will push the message to other queues
            if (clone != null)
            {
                await PushOtherQueues(client, clone, ccList, additionalHeaders);
            }
        }
Beispiel #5
0
        /// <summary>
        /// Creates new router
        /// </summary>
        private async Task CreateRouter(MqClient client, HorseMessage message)
        {
            IRouter found = _server.FindRouter(message.Target);

            if (found != null)
            {
                await client.SendAsync(message.CreateResponse(HorseResultCode.Ok));

                return;
            }

            string      methodHeader = message.FindHeader(HorseHeaders.ROUTE_METHOD);
            RouteMethod method       = RouteMethod.Distribute;

            if (!string.IsNullOrEmpty(methodHeader))
            {
                method = (RouteMethod)Convert.ToInt32(methodHeader);
            }

            //check create queue access
            foreach (IClientAuthorization authorization in _server.Authorizations)
            {
                bool grant = await authorization.CanCreateRouter(client, message.Target, method);

                if (!grant)
                {
                    await client.SendAsync(message.CreateResponse(HorseResultCode.Unauthorized));

                    return;
                }
            }

            _server.AddRouter(message.Target, method);
            await client.SendAsync(message.CreateResponse(HorseResultCode.Ok));
        }
Beispiel #6
0
        /// <summary>
        /// Reads Count header value and returns as integer
        /// </summary>
        private static int FindCount(HorseMessage request)
        {
            string countStr = request.FindHeader(HorseHeaders.COUNT);

            if (string.IsNullOrEmpty(countStr))
            {
                return(0);
            }

            return(Convert.ToInt32(countStr.Trim()));
        }
Beispiel #7
0
        /// <summary>
        /// Reads Order header value and returns as true false.
        /// If true, it's fifo (as default).
        /// If false, it's lifo.
        /// </summary>
        private static bool FindOrder(HorseMessage request)
        {
            string orderStr = request.FindHeader(HorseHeaders.ORDER);

            if (string.IsNullOrEmpty(orderStr))
            {
                return(true);
            }

            bool lifo = orderStr.Trim().Equals(HorseHeaders.LIFO, StringComparison.InvariantCultureIgnoreCase);

            return(!lifo);
        }
Beispiel #8
0
        /// <summary>
        /// Removes a router with it's bindings
        /// </summary>
        private async Task RemoveRouterBinding(MqClient client, HorseMessage message)
        {
            IRouter router = _server.FindRouter(message.Target);

            if (router == null)
            {
                await client.SendAsync(message.CreateResponse(HorseResultCode.NotFound));

                return;
            }

            string name = message.FindHeader(HorseHeaders.BINDING_NAME);

            if (string.IsNullOrEmpty(name))
            {
                await client.SendAsync(message.CreateResponse(HorseResultCode.NotFound));

                return;
            }

            Binding[] bindings = router.GetBindings();
            Binding   binding  = bindings.FirstOrDefault(x => x.Name == name);

            if (binding == null)
            {
                await client.SendAsync(message.CreateResponse(HorseResultCode.NotFound));

                return;
            }

            //check create queue access
            foreach (IClientAuthorization authorization in _server.Authorizations)
            {
                bool grant = await authorization.CanRemoveBinding(client, binding);

                if (!grant)
                {
                    await client.SendAsync(message.CreateResponse(HorseResultCode.Unauthorized));

                    return;
                }
            }

            router.RemoveBinding(binding);
            await client.SendAsync(message.CreateResponse(HorseResultCode.Ok));
        }
        public async Task InPersistentHandler()
        {
            ConfigurationFactory.Destroy();
            PersistentDeliveryHandler handler = null;
            HorseServer server = new HorseServer();
            HorseMq     mq     = server.UseHorseMq(cfg => cfg
                                                   .AddPersistentQueues(q => q.KeepLastBackup())
                                                   .UseDeliveryHandler(async builder =>
            {
                DatabaseOptions options = new DatabaseOptions
                {
                    Filename             = "redelivery-test.tdb",
                    InstantFlush         = true,
                    CreateBackupOnShrink = false,
                    ShrinkInterval       = TimeSpan.FromSeconds(60)
                };

                handler = new PersistentDeliveryHandler(builder.Queue,
                                                        options,
                                                        DeleteWhen.AfterSend,
                                                        ProducerAckDecision.None,
                                                        true);
                await handler.Initialize();
                return(handler);
            }));

            HorseQueue queue = await mq.CreateQueue("test");

            HorseMessage message = new HorseMessage(MessageType.QueueMessage, "test");

            message.SetMessageId("id");
            message.SetStringContent("Hello, World!");
            QueueMessage queueMessage = new QueueMessage(message);

            await handler.BeginSend(queue, queueMessage);

            List <KeyValuePair <string, int> > deliveries = handler.RedeliveryService.GetDeliveries();

            Assert.Single(deliveries);
            Assert.Equal("id", deliveries[0].Key);
            Assert.Equal(1, deliveries[0].Value);

            string header = message.FindHeader(HorseHeaders.DELIVERY);

            Assert.Null(header);

            await handler.BeginSend(queue, queueMessage);

            deliveries = handler.RedeliveryService.GetDeliveries();
            Assert.Single(deliveries);
            Assert.Equal("id", deliveries[0].Key);
            Assert.Equal(2, deliveries[0].Value);

            header = message.FindHeader(HorseHeaders.DELIVERY);
            Assert.NotNull(header);
            Assert.Equal(2, Convert.ToInt32(header));

            queueMessage.MarkAsSent();

            await handler.EndSend(queue, queueMessage);

            deliveries = handler.RedeliveryService.GetDeliveries();
            Assert.Empty(deliveries);
        }
Beispiel #10
0
        /// <summary>
        /// Reads Info header value and returns as boolean
        /// </summary>
        private static bool FindInfoRequest(HorseMessage request)
        {
            string infoStr = request.FindHeader(HorseHeaders.INFO);

            return(!string.IsNullOrEmpty(infoStr) && infoStr.Trim().Equals("Yes", StringComparison.InvariantCultureIgnoreCase));
        }
Beispiel #11
0
        public Task Handle(MqClient client, HorseMessage message, bool fromNode)
        {
            string eventName = message.Target;
            string queueName = message.FindHeader(HorseHeaders.QUEUE_NAME);
            bool   subscribe = message.ContentType == 1;

            HorseQueue queue = !string.IsNullOrEmpty(queueName) ? _server.FindQueue(queueName) : null;

            if (subscribe)
            {
                foreach (IClientAuthorization authorization in _server.Authorizations)
                {
                    if (!authorization.CanSubscribeEvent(client, queue))
                    {
                        return(SendResponse(client, message, false));
                    }
                }
            }

            switch (eventName)
            {
            case EventNames.MessageProduced:
                if (queue == null)
                {
                    return(SendResponse(client, message, false));
                }

                if (subscribe)
                {
                    queue.OnMessageProduced.Subscribe(client);
                }
                else
                {
                    queue.OnMessageProduced.Unsubscribe(client);
                }

                return(SendResponse(client, message, true));

            case EventNames.ClientConnected:
                if (subscribe)
                {
                    _server.OnClientConnected.Subscribe(client);
                }
                else
                {
                    _server.OnClientConnected.Unsubscribe(client);
                }

                return(SendResponse(client, message, true));

            case EventNames.ClientDisconnected:
                if (subscribe)
                {
                    _server.OnClientDisconnected.Subscribe(client);
                }
                else
                {
                    _server.OnClientDisconnected.Unsubscribe(client);
                }

                return(SendResponse(client, message, true));

            case EventNames.Subscribe:
                if (queue == null)
                {
                    return(SendResponse(client, message, false));
                }

                if (subscribe)
                {
                    queue.OnConsumerSubscribed.Subscribe(client);
                }
                else
                {
                    queue.OnConsumerSubscribed.Unsubscribe(client);
                }

                return(SendResponse(client, message, true));

            case EventNames.Unsubscribe:
                if (queue == null)
                {
                    return(SendResponse(client, message, false));
                }

                if (subscribe)
                {
                    queue.OnConsumerUnsubscribed.Subscribe(client);
                }
                else
                {
                    queue.OnConsumerUnsubscribed.Unsubscribe(client);
                }

                return(SendResponse(client, message, true));

            case EventNames.QueueCreated:
                if (subscribe)
                {
                    _server.OnQueueCreated.Subscribe(client);
                }
                else
                {
                    _server.OnQueueCreated.Unsubscribe(client);
                }

                return(SendResponse(client, message, true));

            case EventNames.QueueUpdated:
                if (subscribe)
                {
                    _server.OnQueueUpdated.Subscribe(client);
                }
                else
                {
                    _server.OnQueueUpdated.Unsubscribe(client);
                }

                return(SendResponse(client, message, true));

            case EventNames.QueueRemoved:
                if (subscribe)
                {
                    _server.OnQueueRemoved.Subscribe(client);
                }
                else
                {
                    _server.OnQueueRemoved.Unsubscribe(client);
                }

                return(SendResponse(client, message, true));
            }

            return(Task.CompletedTask);
        }
Beispiel #12
0
        internal async Task <HorseQueue> CreateQueue(string queueName,
                                                     QueueOptions options,
                                                     HorseMessage requestMessage,
                                                     Func <DeliveryHandlerBuilder, Task <IMessageDeliveryHandler> > asyncHandler,
                                                     bool hideException,
                                                     bool returnIfExists)
        {
            await _createQueueLocker.WaitAsync();

            try
            {
                if (!Filter.CheckNameEligibility(queueName))
                {
                    throw new InvalidOperationException("Invalid queue name");
                }

                if (Options.QueueLimit > 0 && Options.QueueLimit >= _queues.Count)
                {
                    throw new OperationCanceledException("Queue limit is exceeded for the server");
                }

                HorseQueue queue = _queues.Find(x => x.Name == queueName);

                if (queue != null)
                {
                    if (returnIfExists)
                    {
                        return(queue);
                    }

                    throw new DuplicateNameException($"The server has already a queue with same name: {queueName}");
                }

                string topic           = null;
                bool   statusSpecified = false; //when queue is created by subscriber, it will be initialized if status is specified
                if (requestMessage != null)
                {
                    string waitForAck = requestMessage.FindHeader(HorseHeaders.ACKNOWLEDGE);
                    if (!string.IsNullOrEmpty(waitForAck))
                    {
                        switch (waitForAck.Trim().ToLower())
                        {
                        case "none":
                            options.Acknowledge = QueueAckDecision.None;
                            break;

                        case "request":
                            options.Acknowledge = QueueAckDecision.JustRequest;
                            break;

                        case "wait":
                            options.Acknowledge = QueueAckDecision.WaitForAcknowledge;
                            break;
                        }
                    }

                    string queueStatus = requestMessage.FindHeader(HorseHeaders.QUEUE_STATUS);
                    if (queueStatus != null)
                    {
                        statusSpecified = true;
                        options.Status  = QueueStatusHelper.FindStatus(queueStatus);
                    }

                    topic = requestMessage.FindHeader(HorseHeaders.QUEUE_TOPIC);

                    string delay = requestMessage.FindHeader(HorseHeaders.DELAY_BETWEEN_MESSAGES);
                    if (!string.IsNullOrEmpty(delay))
                    {
                        options.DelayBetweenMessages = Convert.ToInt32(delay);
                    }
                }

                queue = new HorseQueue(this, queueName, options);
                if (!string.IsNullOrEmpty(topic))
                {
                    queue.Topic = topic;
                }

                DeliveryHandlerBuilder handlerBuilder = new DeliveryHandlerBuilder
                {
                    Server = this,
                    Queue  = queue
                };
                if (requestMessage != null)
                {
                    handlerBuilder.DeliveryHandlerHeader = requestMessage.FindHeader(HorseHeaders.DELIVERY_HANDLER);
                    handlerBuilder.Headers = requestMessage.Headers;
                }

                bool initialize;
                //if queue creation is triggered by consumer subscription, we might skip initialization
                if (requestMessage != null && requestMessage.Type == MessageType.Server && requestMessage.ContentType == KnownContentTypes.Subscribe)
                {
                    initialize = statusSpecified;
                }
                else
                {
                    initialize = true;
                }

                if (initialize)
                {
                    IMessageDeliveryHandler deliveryHandler = await asyncHandler(handlerBuilder);

                    queue.InitializeQueue(deliveryHandler);
                }

                _queues.Add(queue);
                foreach (IQueueEventHandler handler in _queueEventHandlers)
                {
                    await handler.OnCreated(queue);
                }

                if (initialize)
                {
                    handlerBuilder.TriggerAfterCompleted();
                }

                OnQueueCreated.Trigger(queue);
                return(queue);
            }
            catch (Exception e)
            {
                SendError("CREATE_QUEUE", e, $"QueueName:{queueName}");

                if (!hideException)
                {
                    throw;
                }

                return(null);
            }
            finally
            {
                try
                {
                    _createQueueLocker.Release();
                }
                catch
                {
                }
            }
        }