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); }
public async Task <PushResult> Push(QueueMessage message) { try { QueueClient cc; if (_queue.Options.Acknowledge == QueueAckDecision.WaitForAcknowledge) { Tuple <QueueClient, int> tuple = await _queue.GetNextAvailableRRClient(_roundRobinIndex); cc = tuple.Item1; if (cc != null) { _roundRobinIndex = tuple.Item2; } } else { cc = _queue.GetNextRRClient(ref _roundRobinIndex); } /* * //if to process next message is requires previous message acknowledge, wait here * if (_queue.Options.Acknowledge == QueueAckDecision.WaitForAcknowledge) * await _queue.WaitForAcknowledge(message); */ if (cc == null) { _queue.AddMessage(message, false); return(PushResult.NoConsumers); } ProcessingMessage = message; PushResult result = await ProcessMessage(message, cc); ProcessingMessage = null; return(result); } catch (Exception e) { _queue.Server.SendError("PUSH", e, $"QueueName:{_queue.Name}, State:RoundRobin"); return(PushResult.Error); } }
private async Task <bool> SendOnlyFirst(HorseMessage message) { if (_queues.Length < 1) { 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); }
public async Task <PullResult> Pull(QueueClient client, HorseMessage request) { int index = 1; int count = FindCount(request); if (count < 1) { await client.Client.SendAsync(MessageBuilder.CreateNoContentPullResponse(request, HorseHeaders.UNACCEPTABLE)); return(PullResult.Unacceptable); } ClearDecision clear = FindClearDecision(request); bool sendInfo = FindInfoRequest(request); bool fifo = FindOrder(request); Tuple <QueueMessage, int, int> messageTuple = await DequeueMessage(fifo, sendInfo, count == index?clear : ClearDecision.None); //there is no pullable message if (messageTuple.Item1 == null) { await client.Client.SendAsync(MessageBuilder.CreateNoContentPullResponse(request, HorseHeaders.EMPTY)); return(PullResult.Empty); } List <KeyValuePair <string, string> > headers = new List <KeyValuePair <string, string> >(); KeyValuePair <string, string> requestId = new KeyValuePair <string, string>(HorseHeaders.REQUEST_ID, request.MessageId); KeyValuePair <string, string> countHeader = new KeyValuePair <string, string>(HorseHeaders.COUNT, count.ToString()); while (index <= count) { QueueMessage message = messageTuple.Item1; if (message == null) { break; } try { headers.Add(requestId); headers.Add(countHeader); headers.Add(new KeyValuePair <string, string>(HorseHeaders.INDEX, index.ToString())); if (sendInfo) { headers.Add(new KeyValuePair <string, string>(HorseHeaders.PRIORITY_MESSAGES, messageTuple.Item2.ToString())); headers.Add(new KeyValuePair <string, string>(HorseHeaders.MESSAGES, messageTuple.Item3.ToString())); } bool processed = await ProcessPull(client, request, message, headers); if (!processed) { break; } index++; messageTuple = await DequeueMessage(fifo, sendInfo, count == index?clear : ClearDecision.None); headers.Clear(); } catch (Exception ex) { _queue.Info.AddError(); try { Decision decision = await _queue.DeliveryHandler.ExceptionThrown(_queue, message, ex); await _queue.ApplyDecision(decision, message); if (!message.IsInQueue) { if (decision.PutBack == PutBackDecision.Start) { _queue.AddMessage(message, false); } else if (decision.PutBack == PutBackDecision.End) { _queue.AddMessage(message); } } } catch //if developer does wrong operation, we should not stop { } } } await client.Client.SendAsync(MessageBuilder.CreateNoContentPullResponse(request, HorseHeaders.END)); return(PullResult.Success); }
private async Task <PushResult> ProcessMessage(QueueMessage message) { //if we need acknowledge from receiver, it has a deadline. DateTime?ackDeadline = null; if (_queue.Options.Acknowledge != QueueAckDecision.None) { ackDeadline = DateTime.UtcNow.Add(_queue.Options.AcknowledgeTimeout); } //if to process next message is requires previous message acknowledge, wait here if (_queue.Options.Acknowledge == QueueAckDecision.WaitForAcknowledge) { await _queue.WaitForAcknowledge(message); } //if there are not receivers, complete send operation List <QueueClient> clients = _queue.ClientsClone; if (clients.Count == 0) { _queue.AddMessage(message, false); return(PushResult.NoConsumers); } if (message.CurrentDeliveryReceivers.Count > 0) { message.CurrentDeliveryReceivers.Clear(); } message.Decision = await _queue.DeliveryHandler.BeginSend(_queue, message); if (!await _queue.ApplyDecision(message.Decision, message)) { return(PushResult.Success); } //create prepared message data byte[] messageData = HmqWriter.Create(message.Message); Decision final = new Decision(false, false, PutBackDecision.No, DeliveryAcknowledgeDecision.None); bool messageIsSent = false; //to all receivers foreach (QueueClient client in clients) { //to only online receivers if (!client.Client.IsConnected) { continue; } //call before send and check decision Decision ccrd = await _queue.DeliveryHandler.CanConsumerReceive(_queue, message, client.Client); final = HorseQueue.CreateFinalDecision(final, ccrd); if (!ccrd.Allow) { continue; } //create delivery object MessageDelivery delivery = new MessageDelivery(message, client, ackDeadline); //send the message bool sent = await client.Client.SendAsync(messageData); if (sent) { if (_queue.Options.Acknowledge != QueueAckDecision.None) { client.CurrentlyProcessing = message; client.ProcessDeadline = ackDeadline ?? DateTime.UtcNow; } messageIsSent = true; message.CurrentDeliveryReceivers.Add(client); //adds the delivery to time keeper to check timing up _queue.TimeKeeper.AddAcknowledgeCheck(delivery); //mark message is sent delivery.MarkAsSent(); //do after send operations for per message _queue.Info.AddDelivery(); Decision d = await _queue.DeliveryHandler.ConsumerReceived(_queue, delivery, client.Client); final = HorseQueue.CreateFinalDecision(final, d); } else { Decision d = await _queue.DeliveryHandler.ConsumerReceiveFailed(_queue, delivery, client.Client); final = HorseQueue.CreateFinalDecision(final, d); } } message.Decision = final; if (!await _queue.ApplyDecision(final, message)) { return(PushResult.Success); } //after all sending operations completed, calls implementation send completed method and complete the operation if (messageIsSent) { _queue.Info.AddMessageSend(); } message.Decision = await _queue.DeliveryHandler.EndSend(_queue, message); await _queue.ApplyDecision(message.Decision, message); if (message.Decision.Allow && message.Decision.PutBack == PutBackDecision.No) { _queue.Info.AddMessageRemove(); _ = _queue.DeliveryHandler.MessageDequeued(_queue, message); } return(PushResult.Success); }