/// <summary> /// Removes a router with it's bindings /// </summary> private async Task RemoveRouter(MqClient client, HorseMessage message) { IRouter found = _server.FindRouter(message.Target); if (found == null) { await client.SendAsync(message.CreateResponse(HorseResultCode.Ok)); return; } //check create queue access foreach (IClientAuthorization authorization in _server.Authorizations) { bool grant = await authorization.CanRemoveRouter(client, found); if (!grant) { await client.SendAsync(message.CreateResponse(HorseResultCode.Unauthorized)); return; } } _server.RemoveRouter(found); await client.SendAsync(message.CreateResponse(HorseResultCode.Ok)); }
/// <summary> /// Reads a data message object from the stream /// </summary> public async Task <DataMessage> Read(Stream stream) { DataType type = ReadType(stream); string id = await ReadId(stream); if (string.IsNullOrEmpty(id)) { return(new DataMessage(DataType.Empty, null)); } if (type == DataType.Delete) { return(new DataMessage(DataType.Delete, id)); } int size = await ReadLength(stream); if (size == 0) { return(new DataMessage(DataType.Empty, id)); } HorseMessage msg = await _reader.Read(stream); return(new DataMessage(DataType.Insert, id, msg)); }
/// <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> /// 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); }
/// <summary> /// Sends the message to binding receivers /// </summary> public override Task <bool> Send(MqClient sender, HorseMessage message) { try { if (DateTime.UtcNow - _queueUpdateTime > _queueCacheDuration) { RefreshQueueCache(); } message.WaitResponse = Interaction == BindingInteraction.Response; switch (RouteMethod) { case RouteMethod.Distribute: return(SendDistribute(message)); case RouteMethod.OnlyFirst: return(SendOnlyFirst(message)); case RouteMethod.RoundRobin: return(SendRoundRobin(message)); default: return(Task.FromResult(false)); } } catch (Exception e) { Router.Server.SendError("BINDING_SEND", e, $"Type:Topic, Binding:{Name}"); return(Task.FromResult(false)); } }
/// <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); }
public async Task WithAcknowledge() { TestHorseMq server = new TestHorseMq(); await server.Initialize(); int port = server.Start(); HorseClient client1 = new HorseClient(); HorseClient client2 = new HorseClient(); client1.ClientId = "client-1"; client2.ClientId = "client-2"; client2.AutoAcknowledge = true; client1.ResponseTimeout = TimeSpan.FromSeconds(14); await client1.ConnectAsync("hmq://localhost:" + port); await client2.ConnectAsync("hmq://localhost:" + port); Assert.True(client1.IsConnected); Assert.True(client2.IsConnected); bool received = false; client2.MessageReceived += (c, m) => received = m.Source == "client-1"; HorseMessage message = new HorseMessage(MessageType.DirectMessage, "client-2"); message.SetStringContent("Hello, World!"); HorseResult sent = await client1.SendAndGetAck(message); Assert.Equal(HorseResultCode.Ok, sent.Code); Assert.True(received); }
/// <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 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> /// Sends a memory stream message by full name /// </summary> private async Task <HorseResult> SendById(string id, ushort contentType, MemoryStream content, bool waitAcknowledge, IEnumerable <KeyValuePair <string, string> > messageHeaders = null) { HorseMessage message = new HorseMessage(); message.SetTarget(id); message.ContentType = contentType; message.Content = content; message.Type = MessageType.DirectMessage; 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)); }
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); } }
public async Task Handle(MqClient client, HorseMessage message, bool fromNode) { try { HorseQueue queue = _server.FindQueue(message.Target); //if auto creation active, try to create queue if (queue == null && _server.Options.AutoQueueCreation) { QueueOptions options = QueueOptions.CloneFrom(_server.Options); queue = await _server.CreateQueue(message.Target, options, message, _server.DeliveryHandlerFactory, true, true); } if (queue == null) { if (!string.IsNullOrEmpty(message.MessageId)) { await client.SendAsync(message.CreateResponse(HorseResultCode.NotFound)); } return; } await HandlePullRequest(client, message, queue); } catch (Exception e) { _server.SendError("PULL_REQUEST", e, $"QueueName:{message.Target}"); } }
/// <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> /// Pushes new message into the queue /// </summary> public Task <PushResult> Push(HorseMessage message) { message.Type = MessageType.QueueMessage; message.SetTarget(Name); return(Push(new QueueMessage(message), null)); }
public Task Consume(HorseMessage message, string serializedException, HorseClient client) { Exception exception = JsonConvert.DeserializeObject <Exception>(serializedException); Console.WriteLine(exception.Message); return(Task.CompletedTask); }
/// <summary> /// Sends a message to connected master nodes /// </summary> public void SendMessageToNodes(HorseMessage message) { foreach (HmqStickyConnector connector in Connectors) { _ = connector.GetClient()?.SendAsync(message); } }
internal Task TriggerEvents(HorseClient client, HorseMessage message) { string eventName = message.Source; string queue = message.Target; List <EventDescriptor> list = _descriptors[eventName]; EventDescriptor descriptor; lock (list) descriptor = list.FirstOrDefault(x => x.Queue == queue); if (descriptor == null) { return(Task.CompletedTask); } List <Delegate> methods; lock (descriptor.Methods) methods = new List <Delegate>(descriptor.Methods); object param = message.Deserialize(descriptor.ParameterType, client.JsonSerializer); foreach (var m in methods) { m.DynamicInvoke(param); } return(Task.CompletedTask); }
public async Task WithoutAnyResponse() { TestHorseMq server = new TestHorseMq(); await server.Initialize(); int port = server.Start(); HorseClient client1 = new HorseClient(); HorseClient client2 = new HorseClient(); client1.ClientId = "client-1"; client2.ClientId = "client-2"; await client1.ConnectAsync("hmq://localhost:" + port); await client2.ConnectAsync("hmq://localhost:" + port); Assert.True(client1.IsConnected); Assert.True(client2.IsConnected); bool received = false; client2.MessageReceived += (c, m) => received = m.Source == "client-1"; HorseMessage message = new HorseMessage(MessageType.DirectMessage, "client-2"); message.SetStringContent("Hello, World!"); HorseResult sent = await client1.SendAsync(message); Assert.Equal(HorseResultCode.Ok, sent.Code); await Task.Delay(1000); Assert.True(received); }
/// <summary> /// Sends negative ack /// </summary> protected Task SendNegativeAck(HorseMessage message, HorseClient client, Exception exception) { string reason; switch (NackReason) { case NackReason.Error: reason = HorseHeaders.NACK_REASON_ERROR; break; case NackReason.ExceptionType: reason = exception.GetType().Name; break; case NackReason.ExceptionMessage: reason = exception.Message; break; default: reason = HorseHeaders.NACK_REASON_NONE; break; } return(client.SendNegativeAck(message, reason)); }
/// <summary> /// Sends the message to binding receivers /// </summary> public override async Task <bool> Send(MqClient sender, HorseMessage message) { try { HorseQueue queue = await GetQueue(message); if (queue == null) { return(false); } string messageId = Interaction == BindingInteraction.None ? Router.Server.MessageIdGenerator.Create() : message.MessageId; HorseMessage msg = message.Clone(true, true, messageId); msg.Type = MessageType.QueueMessage; msg.SetTarget(Target); msg.WaitResponse = Interaction == BindingInteraction.Response; QueueMessage queueMessage = new QueueMessage(msg); queueMessage.Source = sender; PushResult result = await queue.Push(queueMessage, sender); return(result == PushResult.Success); } catch (Exception e) { Router.Server.SendError("BINDING_SEND", e, $"Type:AutoQueue, Binding:{Name}"); return(false); } }
/// <summary> /// Pushes a message to router /// </summary> public Task <RouterPublishResult> Publish(MqClient sender, HorseMessage message) { try { if (!IsEnabled) { return(Task.FromResult(RouterPublishResult.Disabled)); } if (Bindings.Length == 0) { return(Task.FromResult(RouterPublishResult.NoBindings)); } switch (Method) { case RouteMethod.Distribute: return(Distribute(sender, message)); case RouteMethod.OnlyFirst: return(OnlyFirst(sender, message)); case RouteMethod.RoundRobin: return(RoundRobin(sender, message)); default: return(Task.FromResult(RouterPublishResult.Disabled)); } } catch (Exception e) { Server.SendError("PUBLISH", e, $"Router:{Name}, Binding:{Name}"); return(Task.FromResult(RouterPublishResult.NoBindings)); } }
private async Task <bool> SendRoundRobin(HorseMessage message) { Interlocked.Increment(ref _roundRobinIndex); int i = _roundRobinIndex; if (i >= _queues.Length) { _roundRobinIndex = 0; i = 0; } if (_queues.Length == 0) { return(false); } HorseQueue queue = Router.Server.FindQueue(message.Target); if (queue == null) { if (!Router.Server.Options.AutoQueueCreation) { return(false); } queue = await Router.Server.CreateQueue(message.Target, Router.Server.Options, message, Router.Server.DeliveryHandlerFactory, true, true); } QueueMessage queueMessage = new QueueMessage(message); queue.AddMessage(queueMessage); return(true); }
/// <summary> /// Sends the message to only first binding /// </summary> private async Task <RouterPublishResult> OnlyFirst(MqClient sender, HorseMessage message) { int index = 0; bool sent; RouterPublishResult result = RouterPublishResult.NoReceivers; do { if (index >= Bindings.Length) { return(RouterPublishResult.NoReceivers); } Binding binding = Bindings[index]; sent = await binding.Send(sender, message); if (sent) { result = binding.Interaction != BindingInteraction.None ? RouterPublishResult.OkAndWillBeRespond : RouterPublishResult.OkWillNotRespond; } index++; }while (!sent); return(result); }
/// <summary> /// Processes the client message which has single receiver (message by unique id) /// </summary> private async Task ProcessSingleReceiverClientMessage(MqClient client, HorseMessage message) { //find the receiver MqClient other = _server.FindClient(message.Target); if (other == null) { await client.SendAsync(message.CreateResponse(HorseResultCode.NotFound)); return; } //check sending message authority foreach (IClientAuthorization authorization in _server.Authorizations) { bool grant = await authorization.CanDirectMessage(client, message, other); if (!grant) { await client.SendAsync(message.CreateResponse(HorseResultCode.Unauthorized)); return; } } //send the message await other.SendAsync(message); }
/// <summary> /// Distributes the message to all bindings /// </summary> private async Task <RouterPublishResult> Distribute(MqClient sender, HorseMessage message) { RouterPublishResult result = RouterPublishResult.NoReceivers; foreach (Binding binding in Bindings) { bool oldWaitResponse = message.WaitResponse; bool sent = await binding.Send(sender, message); message.WaitResponse = oldWaitResponse; if (sent) { if (binding.Interaction != BindingInteraction.None) { result = RouterPublishResult.OkAndWillBeRespond; } else if (result == RouterPublishResult.NoReceivers) { result = RouterPublishResult.OkWillNotRespond; } } } return(result); }
/// <summary> /// Clears messages in a queue. /// Required administration permission. /// If server has no implementation for administration authorization, request is not allowed. /// </summary> public Task <HorseResult> ClearMessages(string queue, bool clearPriorityMessages, bool clearMessages) { if (!clearPriorityMessages && !clearMessages) { return(Task.FromResult(HorseResult.Failed())); } HorseMessage message = new HorseMessage(); message.Type = MessageType.Server; message.ContentType = KnownContentTypes.ClearMessages; message.SetTarget(queue); message.WaitResponse = true; message.SetMessageId(_client.UniqueIdGenerator.Create()); message.AddHeader(HorseHeaders.QUEUE_NAME, queue); if (clearPriorityMessages) { message.AddHeader(HorseHeaders.PRIORITY_MESSAGES, "yes"); } if (clearMessages) { message.AddHeader(HorseHeaders.MESSAGES, "yes"); } return(_client.WaitResponse(message, true)); }
/// <summary> /// Sends the message to only one binding within round robin algorithm /// </summary> private async Task <RouterPublishResult> RoundRobin(MqClient sender, HorseMessage message) { int len = Bindings.Length; for (int i = 0; i < len; i++) { Interlocked.Increment(ref _lastRoutedIndex); if (_lastRoutedIndex >= Bindings.Length) { Interlocked.Exchange(ref _lastRoutedIndex, 0); } Binding binding = Bindings[_lastRoutedIndex]; bool waitResponse = message.WaitResponse; bool sent = await binding.Send(sender, message); message.WaitResponse = waitResponse; if (sent) { return(binding.Interaction != BindingInteraction.None ? RouterPublishResult.OkAndWillBeRespond : RouterPublishResult.OkWillNotRespond); } } return(RouterPublishResult.NoReceivers); }
/// <summary> /// Pushes a message to a queue /// </summary> public async Task <HorseResult> Push(string queue, MemoryStream content, string messageId, bool waitAcknowledge, IEnumerable <KeyValuePair <string, string> > messageHeaders = null) { HorseMessage message = new HorseMessage(MessageType.QueueMessage, queue, 0); message.Content = content; message.WaitResponse = waitAcknowledge; if (!string.IsNullOrEmpty(messageId)) { message.SetMessageId(messageId); } if (messageHeaders != null) { foreach (KeyValuePair <string, string> pair in messageHeaders) { message.AddHeader(pair.Key, pair.Value); } } if (string.IsNullOrEmpty(message.MessageId) && waitAcknowledge) { message.SetMessageId(_client.UniqueIdGenerator.Create()); } return(await _client.WaitResponse(message, waitAcknowledge)); }
/// <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)); }