Base solution for your next web application
Open Closed

AbpBackgroundJobs is not deleted after the job runs #8212


User avatar
0
datalab created

Hello, i have write a BackgroundJob for send email to some user, but after the job is completed with out exception it remain in queue in DB table AbpBackgroundJobs, so the emails are sent continuously until I delete manually the record from the database. My Version: ABP.Zero 8.0, Angular, AspNet Core 3.0

	[AbpAuthorize(AppPermissions.Pages_Surveies_SendRequest)]
        public async Task SendSurvey(SendSurveyInput input)
        {
            string jobId = await _backgroundJobManager.EnqueueAsync<SendSurveyJob, SendSurveyJobArgs>(
            new SendSurveyJobArgs
            {
                 Contacts = input.Contacts,
                 SurveyId = input.SurveyId,
                 TenantId = AbpSession.TenantId.Value,
                 User = AbpSession.ToUserIdentifier(),

            });
        }

 public class SendSurveyJob : BackgroundJob<SendSurveyJobArgs>, ITransientDependency
    {
        private readonly IAppNotifier _appNotifier;
        private readonly ILocalizationSource _localizationSource;
        private readonly IObjectMapper _objectMapper;
        private readonly IRepository<Survey> _surveyRepository;
        private readonly IRepository<Contact> _contactRepository;
        private readonly EMailTemplateManager _eMailTemplateManager;
        private readonly TenantManager _tenantManager;
        private readonly SurveyManager _surveyManager;
        private readonly IRepository<SurveyRequest> _surveyRequestRepository;
        private readonly IUserEmailer _userEmailer;

        public SendSurveyJob(
            IRepository<Survey> surveyRepository,
            IRepository<Contact> contactRepository,
            EMailTemplateManager eMailTemplateManager,
            IAppNotifier appNotifier,
            ILocalizationManager localizationManager,
            IObjectMapper objectMapper,
            TenantManager tenantManager,
            SurveyManager surveyManager,
            IRepository<SurveyRequest> surveyRequestRepository,
            IUserEmailer userEmailer)
        {
            _contactRepository = contactRepository;
            _appNotifier = appNotifier;
            _objectMapper = objectMapper;
            _localizationSource = localizationManager.GetSource(GerecoConsts.LocalizationSourceName);
            _tenantManager = tenantManager;
            _surveyRepository = surveyRepository;
            _eMailTemplateManager = eMailTemplateManager;
            _surveyManager = surveyManager;
            _surveyRequestRepository = surveyRequestRepository;
            _userEmailer = userEmailer;

        }

        [UnitOfWork]
        public override void Execute(SendSurveyJobArgs args)
        {
            using (CurrentUnitOfWork.SetTenantId(args.TenantId))
            {
                Survey survey = _surveyRepository.Get(args.SurveyId);
                SendSurveyRequest(args, survey);
            }
        }

        private void SendSurveyRequest(SendSurveyJobArgs args, Survey survey)
        {
           
            string invalidSendMessage = "Non è stato possibile inviare il messaggio al seguente destinatario {0} per il seguente motivo {1}";

            List<Contact> recipients = _contactRepository
            .GetAll()
            .Include(c => c.Location)
            .Where(c => args.Contacts.Select(cs => cs.Id).Contains(c.Id))
            .ToList();

            EmailTemplate emailTemplate = _eMailTemplateManager.GetDefaultEMailTemplate();

            Tenant tenant = _tenantManager.GetById(args.TenantId);


            foreach (var recipient in recipients)
            {
                try
                {
                    var PendingOrVisitedRequest = _surveyRequestRepository
                   .GetAll()
                   .Where(r => r.ContactId == recipient.Id & r.SurveyId == survey.Id & (r.Status == SurveyRequestStatus.Pending | r.Status == SurveyRequestStatus.Visited));

                    //Imposto lo status su cancelled se il contatto ha già aperte delle richieste per il questionario che si sta inviano nello stato di Pending o Visited
                    foreach (var request in PendingOrVisitedRequest)
                    {
                        request.Status = SurveyRequestStatus.Cancelled;
                    }

                    //Inserisco la survey request in pending 
                    SurveyRequest surveyRequest = new SurveyRequest()
                    {
                        SurveyLinkId = Guid.NewGuid(),
                        SurveyId = survey.Id,
                        ContactId = recipient.Id,
                        EmailTo = recipient.EMail,
                        Status = SurveyRequestStatus.Pending
                    };

                    _surveyRequestRepository.Insert(surveyRequest);

                    _userEmailer.TryToSendEmailSurveyRequest(survey, recipient, tenant, surveyRequest, emailTemplate);

                    CurrentUnitOfWork.SaveChanges();
                }
                catch (UserFriendlyException exception)
                {
                    SendInvalidEmailNotification(args, string.Format(invalidSendMessage, recipient.FullCompanyName, exception.Message));
                }
                catch (Exception exception)
                {
                    SendInvalidEmailNotification(args, string.Format(invalidSendMessage, recipient.FullCompanyName, exception.ToString()));
                }
            }

            SendSurveyCompletedNotification(args, string.Format("L'invio del questionario {0} è stato completato.", survey.Name));
        }
 
        private void SendInvalidSurveyNotification(SendSurveyJobArgs args)
        {
            _appNotifier.SendMessageAsync(
                args.User,
                _localizationSource.GetString("SendInvalidSurveyNotification"),
                Abp.Notifications.NotificationSeverity.Warn);
        }

        private void SendInvalidEmailNotification(SendSurveyJobArgs args, string message)
        {
            _appNotifier.SendMessageAsync(
                args.User,
                message,
                Abp.Notifications.NotificationSeverity.Warn);
        }

        private void SendSurveyCompletedNotification(SendSurveyJobArgs args, string message)
        {
            _appNotifier.SendMessageAsync(
                args.User,
                message,
                Abp.Notifications.NotificationSeverity.Success);
        }
    }
         
       public async Task TryToSendEmailSurveyRequest(Survey survey, Contact recipient, Tenant tenant, SurveyRequest surveyRequest, EmailTemplate emailBodyTemplate = null)
        {
            try
            {
                var emailTemplate = new StringBuilder(_emailTemplateProvider.GetSurveyRequestTemplate(tenant.Id));
                emailTemplate.Replace("{EMAIL_TITLE}", L("SendSurveyRequestMessageEmail_Title"));
                emailTemplate.Replace("{EMAIL_SUB_TITLE}", L("SendSurveyRequestMessageEmail_SubTitle"));
                                 
                var surveyRequestMessage = GetSurveyRequestMessage(survey, recipient, emailBodyTemplate, tenant, surveyRequest);
                var surveyRequestSubject = GetSurveyRequestSubject(survey, recipient, emailBodyTemplate, tenant);

                await ReplaceBodyAndSend(recipient.EMail, surveyRequestSubject.ToString(), emailTemplate, surveyRequestMessage);                  
                             
            }
            catch (Exception exception)
            {
                Logger.Error(exception.Message, exception);
            }
        }

4 Answer(s)
  • User Avatar
    0
    musa.demir created

    Can you please download the collected data and check if this leaves rows in the AbpBackgroundJobs table?

  • User Avatar
    0
    datalab created

    Hi, no rows remains in the AbpBackgroundJobs table after download collected data.

  • User Avatar
    0
    datalab created

    Hello, I solved, there was a bug generated by asynchronous methods, I solved using AsyncHelper.RunSync for these methods. The bug could also involve ABP.ModulZero ImportUsersToExcelJob Current

    [UnitOfWork]
            public override void Execute(ImportUsersFromExcelJobArgs args)
            {
                using (CurrentUnitOfWork.SetTenantId(args.TenantId))
                {
                    var users = GetUserListFromExcelOrNull(args);
                    if (users == null || !users.Any())
                    {
                        SendInvalidExcelNotification(args);
                        return;
                    }
    
                    CreateUsers(args, users);
                }
            }
            
            private void SendInvalidExcelNotification(ImportUsersFromExcelJobArgs args)
            {
                _appNotifier.SendMessageAsync(
                    args.User,
                    _localizationSource.GetString("FileCantBeConvertedToUserList"),
                    Abp.Notifications.NotificationSeverity.Warn);
            }
    

    Rewrite

    [UnitOfWork]
            public override void Execute(ImportUsersFromExcelJobArgs args)
            {
                using (CurrentUnitOfWork.SetTenantId(args.TenantId))
                {
                    var users = GetUserListFromExcelOrNull(args);
                    if (users == null || !users.Any())
                    {
                         AsyncHelper.RunSync(() =>SendInvalidExcelNotification(args));
                        return;
                    }
    
                    CreateUsers(args, users);
                }
            }
            
            private async Task SendInvalidExcelNotification(ImportUsersFromExcelJobArgs args)
            {
               await  _appNotifier.SendMessageAsync(
                    args.User,
                    _localizationSource.GetString("FileCantBeConvertedToUserList"),
                    Abp.Notifications.NotificationSeverity.Warn);
            }
    
  • User Avatar
    0
    maliming created
    Support Team

    hi datalab Thanks for your feedback, I will update the zero code.