Beispiel #1
0
        /// <summary>
        /// Returns all messages sent given a matching Message ID.
        /// </summary>
        /// <param name="MsgID"></param>
        private RequestState[] GetStatesByID(long MsgID)
        {
            // In case the id referenced the message id
            if (PendingQueue.TryRemove(MsgID, out var state))
            {
                return new RequestState[] { state }
            }
            ;

            // In case the id is a container id
            var FromContainer = PendingQueue.Values
                                .Where(x => x.ContainerID == MsgID)
                                .Select(x => GetStatesByID(x.MessageID))
                                .Join();

            if (FromContainer.Count() > 0)
            {
                return(FromContainer);
            }

            // In case the id refers to an ack
            var AlreadySend = SentAcks.Read()
                              .Where(x => x.MessageID == MsgID)
                              .ToArray();

            if (AlreadySend.Count() > 0)
            {
                return(AlreadySend);
            }

            // When all else fails
            return(null);
        }
Beispiel #2
0
        private async Task AckHandlerMethod(CancellationToken cancellationToken)
        {
            while (!cancellationToken.IsCancellationRequested)
            {
                try
                {
                    // Send every three minutes
                    await Task.Delay(3 * 60 * 1000, cancellationToken);

                    // Don't run this time if there aren't any messages to acknowledge
                    if (!PendingAcks.Any())
                    {
                        continue;
                    }

                    // Take all the required acks out of the bag
                    var acks = new List <long>();
                    while (PendingAcks.TryTake(out var ack))
                    {
                        acks.Add(ack);
                    }

                    Logger.Log(Logger.Level.Debug, $"Found {acks.Count} messages that need acknowledgement.  Adding them to the payload.");

                    // Create a request that contains the list of acks
                    var Acks_Request = new RequestState(Schema.msgs_ack(new { msg_ids = acks }));

                    // Add the request to both the send queue (to be sent to the server) and
                    // the sent acks queue (in case we need to resend.  We don't want to place
                    // in pending since there shouldn't be a response.
                    SendQueue.Add(Acks_Request);
                    SentAcks.Put(Acks_Request);

                    // Send the acks to the server
                    // ToDo: If the user will be polling for updates, can we skip this line
                    // and let the acks be sent for us?
                    Task unawaited = Task.Run(() => ProcessSendQueue());
                }
                catch (TaskCanceledException)
                {
                    // We don't really care if the task was cancelled.
                    break;
                }
                catch (ObjectDisposedException)
                {
                    // We don't really care if the task was cancelled.
                    break;
                }
                catch (Exception ex)
                {
                    // ToDo: Do we really want to skip all acks when this happens?  Likely we
                    // will encounter the same error again if we reprocess...
                    Logger.Log(Logger.Level.Error, $"An error occurred process acks.  Skipping.\n\n{ex.Message}");
                }
            }
        }