Example #1
0
        private async Task enqueueForRetry(OutgoingMessageBatch batch)
        {
            if (_settings.Cancellation.IsCancellationRequested)
            {
                return;
            }

            var expiredInQueue = Queued.Where(x => x.IsExpired()).ToArray();
            var expiredInBatch = batch.Messages.Where(x => x.IsExpired()).ToArray();

            var expired = expiredInBatch.Concat(expiredInQueue).ToArray();
            var all     = Queued.Where(x => !expiredInQueue.Contains(x))
                          .Concat(batch.Messages.Where(x => !expiredInBatch.Contains(x)))
                          .ToList();

            var reassigned = new Envelope[0];

            if (all.Count > Endpoint.MaximumEnvelopeRetryStorage)
            {
                reassigned = all.Skip(Endpoint.MaximumEnvelopeRetryStorage).ToArray();
            }

            await _persistence.DiscardAndReassignOutgoing(expired, reassigned, TransportConstants.AnyNode);

            _logger.DiscardedExpired(expired);

            Queued = all.Take(Endpoint.MaximumEnvelopeRetryStorage).ToList();
        }
        private Envelope[] filterExpired(IDocumentSession session, IEnumerable <Envelope> outgoing)
        {
            var expiredMessages = outgoing.Where(x => x.IsExpired()).ToArray();

            _logger.DiscardedExpired(expiredMessages);

            session.DeleteEnvelopes(_marker.Outgoing, expiredMessages);

            return(outgoing.Where(x => !x.IsExpired()).ToArray());
        }
Example #3
0
        private async Task <Envelope[]> filterExpired(SqlConnection conn, SqlTransaction tx, IEnumerable <Envelope> outgoing)
        {
            var expiredMessages = outgoing.Where(x => x.IsExpired()).ToArray();

            _logger.DiscardedExpired(expiredMessages);

            var cmd = conn.CreateCommand(tx, $"{_mssqlSettings.SchemaName}.uspDeleteOutgoingEnvelopes");

            cmd.CommandType = CommandType.StoredProcedure;
            var list = cmd.Parameters.AddWithValue("IDLIST", SqlServerEnvelopePersistor.BuildIdTable(expiredMessages));

            list.SqlDbType = SqlDbType.Structured;
            list.TypeName  = $"{_mssqlSettings.SchemaName}.EnvelopeIdList";

            await cmd.ExecuteNonQueryAsync();

            return(outgoing.Where(x => !x.IsExpired()).ToArray());
        }
Example #4
0
        public override async Task EnqueueForRetry(OutgoingMessageBatch batch)
        {
            var expiredInQueue = Queued.Where(x => x.IsExpired()).ToArray();
            var expiredInBatch = batch.Messages.Where(x => x.IsExpired()).ToArray();

            var expired = expiredInBatch.Concat(expiredInQueue).ToArray();
            var all     = Queued.Where(x => !expiredInQueue.Contains(x))
                          .Concat(batch.Messages.Where(x => !expiredInBatch.Contains(x)))
                          .ToList();

            var reassigned = new Envelope[0];

            if (all.Count > _settings.MaximumEnvelopeRetryStorage)
            {
                reassigned = all.Skip(_settings.MaximumEnvelopeRetryStorage).ToArray();
            }


            try
            {
                await _persistor.DiscardAndReassignOutgoing(expired, reassigned, TransportConstants.AnyNode);

                _logger.DiscardedExpired(expired);

                Queued = all.Take(_settings.MaximumEnvelopeRetryStorage).ToList();
            }
            catch (Exception e)
            {
                _logger.LogException(e, message: "Failed while trying to enqueue a message batch for retries");


#pragma warning disable 4014
                Task.Delay(100).ContinueWith(async _ => await EnqueueForRetry(batch));
#pragma warning restore 4014
            }
        }
        private async Task <int> recoverFrom(Uri destination, IDurabilityAgentStorage storage)
        {
            try
            {
                Envelope[] filtered = null;
                Envelope[] outgoing = null;

                if (_runtime.GetOrBuildSendingAgent(destination).Latched)
                {
                    return(0);
                }

                await storage.Session.Begin();

                try
                {
                    outgoing = await storage.Outgoing.Load(destination : destination);

                    var expiredMessages = outgoing.Where(x => x.IsExpired()).ToArray();
                    _logger.DiscardedExpired(expiredMessages);


                    await storage.Outgoing.Delete(expiredMessages.ToArray());

                    filtered = outgoing.Where(x => !expiredMessages.Contains(x)).ToArray();

                    // Might easily try to do this in the time between starting
                    // and having the data fetched. Was able to make that happen in
                    // (contrived) testing
                    if (_runtime.GetOrBuildSendingAgent(destination).Latched || !filtered.Any())
                    {
                        await storage.Session.Rollback();

                        return(0);
                    }

                    await storage.Outgoing.Reassign(_settings.UniqueNodeId, filtered);


                    await storage.Session.Commit();
                }
                catch (Exception)
                {
                    await storage.Session.Rollback();

                    throw;
                }

                _logger.RecoveredOutgoing(filtered);

                foreach (var envelope in filtered)
                {
                    try
                    {
                        await _runtime.GetOrBuildSendingAgent(destination).EnqueueOutgoing(envelope);
                    }
                    catch (Exception e)
                    {
                        _logger.LogException(e, message: $"Unable to enqueue {envelope} for sending");
                    }
                }

                return(outgoing.Count());
            }
            catch (UnknownTransportException e)
            {
                _logger.LogException(e, message: $"Could not resolve a channel for {destination}");

                await storage.Session.Begin();

                await storage.Outgoing.DeleteByDestination(destination);

                await storage.Session.Commit();

                return(0);
            }
        }