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()); }
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()); }
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); } }