public async Task ReDeliverStuckMessage(Data.DataContext _context)
        {
            DateTime DeservedTimeForError      = DateTime.Now.AddMinutes(-_config.ReDelivery.MaxTotalMinuteForError);
            DateTime DeservedTimeForInProducer = DateTime.Now.AddMinutes(-_config.ReDelivery.MaxTotalMinuteForInProducer);

            List <Message> stuckMessages = await _context.Messages.Where(m =>
                                                                         (m.Status == MessageStatuses.ERROR && m.UpdatedAt <= DeservedTimeForError) ||
                                                                         (m.Status == MessageStatuses.INPRODUCER && m.UpdatedAt <= DeservedTimeForInProducer))
                                           .ToListAsync();

            foreach (Message message in stuckMessages)
            {
                // stuck message, log it
                if (message.ReDeliveryTimes >= _config.ReDelivery.MaxRetryTimes)
                {
                    using var transaction = _context.Database.BeginTransaction();

                    StuckMessage stuckMessage = _mapper.Map <StuckMessage>(message);
                    stuckMessage.StuckReason = MessageStuckReasons.MAX_RETRY_EXCEED;
                    await _context.StuckMessages.AddAsync(stuckMessage);

                    _context.Messages.Remove(message);

                    await _context.SaveChangesAsync();

                    transaction.Commit();
                }
                else
                {
                    await _queueService.ReScheduleMessage(message);
                }
            }
        }
Пример #2
0
        private async Task HandleBasicNack(ulong DeliveryTag, bool IsMultiple)
        {
            using (var scope = _provider.CreateScope())
            {
                DataContext _context = scope.ServiceProvider.GetRequiredService <DataContext>();
                IMapper     _mapper  = scope.ServiceProvider.GetRequiredService <IMapper>();

                List <Guid>    MessageIds = GetOutstandingConfirm(DeliveryTag, IsMultiple);
                List <Message> messages   = await _context.Messages.Where(m => MessageIds.Contains(m.Id)).ToListAsync();

                List <StuckMessage> stuckMessages = new();
                foreach (Message msg in messages)
                {
                    // prepare stuck message record
                    StuckMessage stuckMessage = _mapper.Map <StuckMessage>(msg);
                    stuckMessage.StuckReason = MessageStuckReasons.QUEUE_NACK;
                    stuckMessages.Add(stuckMessage);

                    msg.Status    = MessageStatuses.LOGGED;
                    msg.UpdatedAt = DateTime.Now;
                }

                using (var transaction = _context.Database.BeginTransaction())
                {
                    if (messages.Count >= _config.DBConfig.DeservedBulk)
                    {
                        await _context.BulkDeleteAsync(messages, options => options.PropertiesToInclude = new List <string>() { nameof(Message.Status), nameof(Message.UpdatedAt) });
                    }
                    else
                    {
                        _context.Messages.RemoveRange(messages);
                    }

                    if (stuckMessages.Count >= _config.DBConfig.DeservedBulk)
                    {
                        await _context.BulkInsertAsync(stuckMessages);
                    }
                    else
                    {
                        await _context.StuckMessages.AddRangeAsync(stuckMessages);
                    }

                    await _context.SaveChangesAsync();

                    transaction.Commit();
                }
            }
            RemoveOutstandingConfirm(DeliveryTag, IsMultiple);
        }