/// <summary> /// Pushes a message to a queue /// </summary> public async Task <HorseResult> PushJson(string queue, object jsonObject, string messageId, bool waitAcknowledge, IEnumerable <KeyValuePair <string, string> > messageHeaders = null) { TypeDeliveryDescriptor descriptor = _client.DeliveryContainer.GetDescriptor(jsonObject.GetType()); HorseMessage message = descriptor.CreateMessage(MessageType.QueueMessage, queue, 0); if (!string.IsNullOrEmpty(messageId)) { message.SetMessageId(messageId); } message.WaitResponse = waitAcknowledge; if (messageHeaders != null) { foreach (KeyValuePair <string, string> pair in messageHeaders) { message.AddHeader(pair.Key, pair.Value); } } message.Serialize(jsonObject, _client.JsonSerializer); if (string.IsNullOrEmpty(message.MessageId) && waitAcknowledge) { message.SetMessageId(_client.UniqueIdGenerator.Create()); } return(await _client.WaitResponse(message, waitAcknowledge)); }
/// <summary> /// Sends a request to target with a JSON model, waits response /// </summary> public async Task <HorseResult <TResponse> > RequestJson <TResponse>(string target, ushort?contentType, object model, IEnumerable <KeyValuePair <string, string> > messageHeaders = null) { TypeDeliveryDescriptor descriptor = _client.DeliveryContainer.GetDescriptor(model.GetType()); HorseMessage message = descriptor.CreateMessage(MessageType.DirectMessage, target, contentType); message.Serialize(model, _client.JsonSerializer); if (messageHeaders != null) { foreach (KeyValuePair <string, string> pair in messageHeaders) { message.AddHeader(pair.Key, pair.Value); } } HorseMessage responseMessage = await _client.Request(message); if (responseMessage.ContentType == 0) { TResponse response = responseMessage.Deserialize <TResponse>(_client.JsonSerializer); return(new HorseResult <TResponse>(response, message, HorseResultCode.Ok)); } return(new HorseResult <TResponse>(default, responseMessage, (HorseResultCode)responseMessage.ContentType));
/// <summary> /// Sends a JSON message by full name /// </summary> public async Task <HorseResult> SendJsonById <T>(string id, ushort contentType, T model, bool waitAcknowledge, IEnumerable <KeyValuePair <string, string> > messageHeaders = null) { HorseMessage message = new HorseMessage(); message.SetTarget(id); message.Type = MessageType.DirectMessage; message.ContentType = contentType; message.Serialize(model, _client.JsonSerializer); if (messageHeaders != null) { foreach (KeyValuePair <string, string> pair in messageHeaders) { message.AddHeader(pair.Key, pair.Value); } } if (waitAcknowledge) { return(await _client.SendAndGetAck(message)); } return(await _client.SendAsync(message)); }
/// <summary> /// Sends all routers /// </summary> private async Task ListRouters(MqClient client, HorseMessage message) { List <RouterInformation> items = new List <RouterInformation>(); foreach (IRouter router in _server.Routers) { RouterInformation info = new RouterInformation { Name = router.Name, IsEnabled = router.IsEnabled }; if (router is Router r) { info.Method = r.Method; } items.Add(info); } HorseMessage response = message.CreateResponse(HorseResultCode.Ok); response.Serialize(items, new NewtonsoftContentSerializer()); await client.SendAsync(response); }
/// <summary> /// Sends a JSON message by full name /// </summary> public async Task <HorseResult> SendJson <T>(T model, bool waitAcknowledge, IEnumerable <KeyValuePair <string, string> > messageHeaders = null) { TypeDeliveryDescriptor descriptor = _client.DeliveryContainer.GetDescriptor(model.GetType()); HorseMessage message = descriptor.CreateMessage(MessageType.DirectMessage, null, null); if (string.IsNullOrEmpty(message.Target)) { return(new HorseResult(HorseResultCode.SendError)); } message.WaitResponse = waitAcknowledge; message.Serialize(model, _client.JsonSerializer); if (messageHeaders != null) { foreach (KeyValuePair <string, string> pair in messageHeaders) { message.AddHeader(pair.Key, pair.Value); } } if (waitAcknowledge) { return(await _client.SendAndGetAck(message)); } return(await _client.SendAsync(message)); }
/// <summary> /// Adds new binding to a router /// </summary> /// <param name="routerName">Router name of the binding</param> /// <param name="type">Binding type</param> /// <param name="name">Binding name</param> /// <param name="target">Binding target. Queue name, tag name, direct receiver id, name, type, etc.</param> /// <param name="interaction">Binding interaction</param> /// <param name="bindingMethod">Binding method is used when multiple receivers available in same binding. It's used for Direct and Tag bindings.</param> /// <param name="contentType">Overwritten content type if specified</param> /// <param name="priority">Binding priority</param> /// <returns></returns> public async Task <HorseResult> AddBinding(string routerName, BindingType type, string name, string target, BindingInteraction interaction, RouteMethod bindingMethod = RouteMethod.Distribute, ushort?contentType = null, int priority = 1) { HorseMessage message = new HorseMessage(); message.Type = MessageType.Server; message.ContentType = KnownContentTypes.AddBinding; message.SetTarget(routerName); message.WaitResponse = true; message.SetMessageId(_client.UniqueIdGenerator.Create()); BindingInformation info = new BindingInformation { Name = name, Target = target, Interaction = interaction, ContentType = contentType, Priority = priority, BindingType = type, Method = bindingMethod }; message.Serialize(info, new NewtonsoftContentSerializer()); return(await _client.WaitResponse(message, true)); }
/// <summary> /// Publishes a JSON object to a router /// </summary> public async Task <HorseResult> PublishJson(string routerName, object model, string messageId = null, bool waitForAcknowledge = false, ushort?contentType = null, IEnumerable <KeyValuePair <string, string> > messageHeaders = null) { TypeDeliveryDescriptor descriptor = _client.DeliveryContainer.GetDescriptor(model.GetType()); HorseMessage message = descriptor.CreateMessage(MessageType.Router, routerName, contentType); if (!string.IsNullOrEmpty(messageId)) { message.SetMessageId(messageId); } else { message.SetMessageId(_client.UniqueIdGenerator.Create()); } message.WaitResponse = waitForAcknowledge; message.Serialize(model, _client.JsonSerializer); if (messageHeaders != null) { foreach (KeyValuePair <string, string> pair in messageHeaders) { message.AddHeader(pair.Key, pair.Value); } } return(await _client.WaitResponse(message, waitForAcknowledge)); }
/// <summary> /// Gets connected instance list /// </summary> private async Task GetInstanceList(MqClient client, HorseMessage message) { foreach (IAdminAuthorization authorization in _server.AdminAuthorizations) { bool grant = await authorization.CanManageInstances(client, message); if (!grant) { if (message.WaitResponse) { await client.SendAsync(message.CreateResponse(HorseResultCode.Unauthorized)); } return; } } List <NodeInformation> list = new List <NodeInformation>(); //slave instances List <MqClient> slaves = _server.NodeManager.Clients.GetAsClone(); foreach (MqClient slave in slaves) { list.Add(new NodeInformation { IsSlave = true, Host = slave.RemoteHost, IsConnected = slave.IsConnected, Id = slave.UniqueId, Name = slave.Name, Lifetime = slave.ConnectedDate.LifetimeMilliseconds() }); } //master instances foreach (HmqStickyConnector connector in _server.NodeManager.Connectors) { NodeOptions options = connector.Tag as NodeOptions; HorseClient c = connector.GetClient(); list.Add(new NodeInformation { IsSlave = false, Host = options?.Host, IsConnected = connector.IsConnected, Id = c.ClientId, Name = options?.Name, Lifetime = Convert.ToInt64(connector.Lifetime.TotalMilliseconds) }); } HorseMessage response = message.CreateResponse(HorseResultCode.Ok); message.ContentType = KnownContentTypes.InstanceList; response.Serialize(list, _server.MessageContentSerializer); await client.SendAsync(response); }
/// <summary> /// Triggers event and sends message to subscribers /// </summary> protected void Trigger(object model) { try { if (_subscribers.Count == 0) { return; } HorseMessage message = new HorseMessage(MessageType.Event, Target); message.SetSource(Name); if (model != null) { message.Serialize(model, _server.MessageContentSerializer); } byte[] data = HmqWriter.Create(message); List <MqClient> removing = null; lock (_subscribers) foreach (MqClient subscriber in _subscribers) { //if client is disconnected, add it into removing list if (!subscriber.IsConnected) { //removing list is created when it's needed if (removing == null) { removing = new List <MqClient>(); } removing.Add(subscriber); } else { _ = subscriber.SendAsync(data); } } //if there are some removing clients from subscribers list, remove them if (removing != null) { lock (_subscribers) foreach (MqClient remove in removing) { _subscribers.Remove(remove); } } } catch (Exception e) { _server.SendError("EVENT_TRIGGER", e, $"Name:{Name}, Type:{GetType().Name}"); } }
/// <summary> /// Fills JSON object data to the queue. /// Creates new HorseMessage and before writing content and adding into queue calls the action. /// </summary> public PushResult FillJson <T>(IEnumerable <T> items, bool createAsSaved, Action <HorseMessage, T> action) where T : class { try { if (_queue.Status == QueueStatus.Stopped) { return(PushResult.StatusNotSupported); } int max = _queue.PriorityMessagesList.Count + _queue.MessagesList.Count + items.Count(); if (_queue.Options.MessageLimit > 0 && max > _queue.Options.MessageLimit) { return(PushResult.LimitExceeded); } foreach (T item in items) { HorseMessage message = new HorseMessage(MessageType.QueueMessage, _queue.Name); message.WaitResponse = _queue.Options.Acknowledge != QueueAckDecision.None; if (_queue.Options.UseMessageId) { message.SetMessageId(_queue.Server.MessageIdGenerator.Create()); } action(message, item); message.Serialize(item, _queue.Server.MessageContentSerializer); QueueMessage qm = new QueueMessage(message, createAsSaved); if (message.HighPriority) { lock (_queue.PriorityMessagesList) _queue.PriorityMessagesList.AddLast(qm); } else { lock (_queue.MessagesList) _queue.MessagesList.AddLast(qm); } } _queue.Info.UpdateHighPriorityMessageCount(_queue.PriorityMessagesList.Count); _queue.Info.UpdateRegularMessageCount(_queue.MessagesList.Count); _ = _queue.Trigger(); return(PushResult.Success); } catch (Exception e) { _queue.Server.SendError("FILL_JSON", e, $"QueueName:{_queue.Name}"); return(PushResult.Error); } }
/// <summary> /// Gets all connected clients /// </summary> public async Task GetClients(MqClient client, HorseMessage message) { foreach (IAdminAuthorization authorization in _server.AdminAuthorizations) { bool grant = await authorization.CanReceiveClients(client); if (!grant) { if (message.WaitResponse) { await client.SendAsync(message.CreateResponse(HorseResultCode.Unauthorized)); } return; } } List <ClientInformation> list = new List <ClientInformation>(); string filter = null; if (!string.IsNullOrEmpty(message.Target)) { filter = message.Target; } foreach (MqClient mc in _server.Clients) { if (!string.IsNullOrEmpty(filter)) { if (string.IsNullOrEmpty(mc.Type) || !Filter.CheckMatch(mc.Type, filter)) { continue; } } list.Add(new ClientInformation { Id = mc.UniqueId, Name = mc.Name, Type = mc.Type, IsAuthenticated = mc.IsAuthenticated, Online = mc.ConnectedDate.LifetimeMilliseconds(), }); } HorseMessage response = message.CreateResponse(HorseResultCode.Ok); message.ContentType = KnownContentTypes.ClientList; response.Serialize(list, _server.MessageContentSerializer); await client.SendAsync(response); }
/// <summary> /// Sends all bindings of a router /// </summary> private async Task ListRouterBindings(MqClient client, HorseMessage message) { IRouter router = _server.FindRouter(message.Target); if (router == null) { await client.SendAsync(message.CreateResponse(HorseResultCode.NotFound)); return; } List <BindingInformation> items = new List <BindingInformation>(); foreach (Binding binding in router.GetBindings()) { BindingInformation info = new BindingInformation { Name = binding.Name, Target = binding.Target, Priority = binding.Priority, ContentType = binding.ContentType, Interaction = binding.Interaction }; if (binding is QueueBinding) { info.BindingType = BindingType.Queue; } else if (binding is DirectBinding directBinding) { info.Method = directBinding.RouteMethod; info.BindingType = BindingType.Direct; } else if (binding is TopicBinding topicBinding) { info.Method = topicBinding.RouteMethod; info.BindingType = BindingType.Topic; } else if (binding is HttpBinding) { info.BindingType = BindingType.Http; } items.Add(info); } HorseMessage response = message.CreateResponse(HorseResultCode.Ok); response.Serialize(items, new NewtonsoftContentSerializer()); await client.SendAsync(response); }
/// <summary> /// Sends decision to all connected master nodes /// </summary> public void SendDecisionToNodes(QueueMessage queueMessage, Decision decision) { HorseMessage msg = new HorseMessage(MessageType.Server, null, 10); DecisionOverNode model = new DecisionOverNode { Queue = Name, MessageId = queueMessage.Message.MessageId, Acknowledge = decision.Acknowledge, Allow = decision.Allow, PutBack = decision.PutBack, SaveMessage = decision.SaveMessage }; msg.Serialize(model, Server.MessageContentSerializer); Server.NodeManager.SendMessageToNodes(msg); }
/// <summary> /// Gets active consumers of the queue /// </summary> public async Task GetQueueConsumers(MqClient client, HorseMessage message) { HorseQueue queue = _server.FindQueue(message.Target); if (queue == null) { await client.SendAsync(message.CreateResponse(HorseResultCode.NotFound)); return; } foreach (IAdminAuthorization authorization in _server.AdminAuthorizations) { bool grant = await authorization.CanReceiveQueueConsumers(client, queue); if (!grant) { if (message.WaitResponse) { await client.SendAsync(message.CreateResponse(HorseResultCode.Unauthorized)); } return; } } List <ClientInformation> list = new List <ClientInformation>(); foreach (QueueClient cc in queue.ClientsClone) { list.Add(new ClientInformation { Id = cc.Client.UniqueId, Name = cc.Client.Name, Type = cc.Client.Type, IsAuthenticated = cc.Client.IsAuthenticated, Online = cc.JoinDate.LifetimeMilliseconds(), }); } HorseMessage response = message.CreateResponse(HorseResultCode.Ok); message.ContentType = KnownContentTypes.QueueConsumers; response.Serialize(list, _server.MessageContentSerializer); await client.SendAsync(response); }
public override async Task Execute(HorseClient client, HorseMessage message, object model) { Exception exception = null; IConsumerFactory consumerFactory = null; bool respond = false; try { TRequest requestModel = (TRequest)model; IHorseRequestHandler <TRequest, TResponse> handler; if (_handler != null) { handler = _handler; } else if (_handlerFactoryCreator != null) { consumerFactory = _handlerFactoryCreator(); object consumerObject = await consumerFactory.CreateConsumer(_handlerType); handler = (IHorseRequestHandler <TRequest, TResponse>)consumerObject; } else { throw new ArgumentNullException("There is no consumer defined"); } try { TResponse responseModel = await Handle(handler, requestModel, message, client); HorseResultCode code = responseModel is null ? HorseResultCode.NoContent : HorseResultCode.Ok; HorseMessage responseMessage = message.CreateResponse(code); if (responseModel != null) { responseMessage.Serialize(responseModel, client.JsonSerializer); } respond = true; await client.SendAsync(responseMessage); } catch (Exception e) { ErrorResponse errorModel = await handler.OnError(e, requestModel, message, client); if (errorModel.ResultCode == HorseResultCode.Ok) { errorModel.ResultCode = HorseResultCode.Failed; } HorseMessage responseMessage = message.CreateResponse(errorModel.ResultCode); if (!string.IsNullOrEmpty(errorModel.Reason)) { responseMessage.SetStringContent(errorModel.Reason); } respond = true; await client.SendAsync(responseMessage); throw; } } catch (Exception e) { if (!respond) { try { HorseMessage response = message.CreateResponse(HorseResultCode.InternalServerError); await client.SendAsync(response); } catch { } } await SendExceptions(message, client, e); exception = e; } finally { if (consumerFactory != null) { consumerFactory.Consumed(exception); } } }
/// <summary> /// Finds all queues in the server /// </summary> private async Task GetQueueList(MqClient client, HorseMessage message) { foreach (IAdminAuthorization authorization in _server.AdminAuthorizations) { bool grant = await authorization.CanReceiveQueues(client); if (!grant) { if (message.WaitResponse) { await client.SendAsync(message.CreateResponse(HorseResultCode.Unauthorized)); } return; } } List <QueueInformation> list = new List <QueueInformation>(); foreach (HorseQueue queue in _server.Queues) { if (queue == null) { continue; } string ack = "none"; if (queue.Options.Acknowledge == QueueAckDecision.JustRequest) { ack = "just"; } else if (queue.Options.Acknowledge == QueueAckDecision.WaitForAcknowledge) { ack = "wait"; } list.Add(new QueueInformation { Name = queue.Name, Topic = queue.Topic, Status = queue.Status.ToString().Trim().ToLower(), PriorityMessages = queue.PriorityMessagesList.Count, Messages = queue.MessagesList.Count, Acknowledge = ack, AcknowledgeTimeout = Convert.ToInt32(queue.Options.AcknowledgeTimeout.TotalMilliseconds), MessageTimeout = Convert.ToInt32(queue.Options.MessageTimeout.TotalMilliseconds), HideClientNames = queue.Options.HideClientNames, ReceivedMessages = queue.Info.ReceivedMessages, SentMessages = queue.Info.SentMessages, Deliveries = queue.Info.Deliveries, NegativeAcks = queue.Info.NegativeAcknowledge, Acks = queue.Info.Acknowledges, TimeoutMessages = queue.Info.TimedOutMessages, SavedMessages = queue.Info.MessageSaved, RemovedMessages = queue.Info.MessageRemoved, Errors = queue.Info.ErrorCount, LastMessageReceived = queue.Info.GetLastMessageReceiveUnix(), LastMessageSent = queue.Info.GetLastMessageSendUnix(), MessageLimit = queue.Options.MessageLimit, MessageSizeLimit = queue.Options.MessageSizeLimit, DelayBetweenMessages = queue.Options.DelayBetweenMessages }); } HorseMessage response = message.CreateResponse(HorseResultCode.Ok); message.ContentType = KnownContentTypes.QueueList; response.Serialize(list, _server.MessageContentSerializer); await client.SendAsync(response); }