コード例 #1
0
        private async Task <int> recoverFrom(Uri destination, IDocumentSession session)
        {
            try
            {
                var channel = _channels.GetOrBuildChannel(destination);

                if (channel.Latched)
                {
                    return(0);
                }

                var outgoing = await session.Connection.CreateCommand(_findOutgoingEnvelopesSql)
                               .With("destination", destination.ToString(), NpgsqlDbType.Varchar)
                               .ExecuteToEnvelopes();

                var filtered = filterExpired(session, outgoing);

                // 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 (channel.Latched || !filtered.Any())
                {
                    return(0);
                }

                session.MarkOwnership(_marker.Outgoing, _marker.CurrentNodeId, filtered);

                await session.SaveChangesAsync();

                _logger.RecoveredOutgoing(filtered);

                foreach (var envelope in filtered)
                {
                    try
                    {
                        await channel.QuickSend(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 DeleteFromOutgoingEnvelopes(session, TransportConstants.AnyNode, destination);

                await session.SaveChangesAsync();

                return(0);
            }
        }
コード例 #2
0
        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);
            }
        }
コード例 #3
0
        private async Task <int> recoverFrom(Uri destination, SqlConnection conn)
        {
            try
            {
                Envelope[]      filtered = null;
                List <Envelope> outgoing = null;

                if (_subscribers.GetOrBuild(destination).Latched)
                {
                    return(0);
                }

                var tx = conn.BeginTransaction();

                try
                {
                    outgoing = await conn.CreateCommand(tx, _findOutgoingEnvelopesSql)
                               .With("destination", destination.ToString(), SqlDbType.VarChar)
                               .ExecuteToEnvelopes();

                    filtered = await filterExpired(conn, tx, outgoing);

                    // 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 (_subscribers.GetOrBuild(destination).Latched || !filtered.Any())
                    {
                        tx.Rollback();
                        return(0);
                    }

                    await markOwnership(conn, tx, filtered);


                    tx.Commit();
                }
                catch (Exception)
                {
                    tx.Rollback();
                    throw;
                }

                _logger.RecoveredOutgoing(filtered);

                foreach (var envelope in filtered)
                {
                    try
                    {
                        await _subscribers.GetOrBuild(destination).QuickSend(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}");

                var tx = conn.BeginTransaction();
                await DeleteFromOutgoingEnvelopes(conn, TransportConstants.AnyNode, destination, tx);

                tx.Commit();

                return(0);
            }
        }