Hello, I am trying to use the default ABP background worker.
In my controller i have call my job; await _updateSalesDomaineService.TriggerStatsVentesMoisJob((int)PeriodeId);
Here is my Job:
using Abp.BackgroundJobs;
using Abp.Domain.Services;
using System.Threading.Tasks;
namespace DocuPro.DomainServices
{
public class UpdateSalesDomaineService : DomainService, IDomainService
{
private readonly IBackgroundJobManager _backgroundJobManager;
public UpdateSalesDomaineService(IBackgroundJobManager backgroundJobManager)
{
_backgroundJobManager = backgroundJobManager;
}
public async Task TriggerStatsVentesMoisJob(int periodeId)
{
Logger.Warn("UpdateStatsVentesMoisJob. Job STARTED");
await _backgroundJobManager.EnqueueAsync<UpdateStatsVentesMoisJob, StatsVentesMoisJobArgs>(new StatsVentesMoisJobArgs
{
PeriodeId = periodeId
});
Logger.Warn("UpdateStatsVentesMoisJob. Job ENDED");
}
// Other domain service methods...
}
public class StatsVentesMoisJobArgs
{
public int PeriodeId { get; set; }
}
}
And here is my method:
using Abp.BackgroundJobs;
using Abp.Dependency;
using Abp.Domain.Repositories;
using Abp.Domain.Uow;
using DocuPro.CommonBases;
using DocuPro.SortiesLocalesBases;
using System;
using System.Threading.Tasks;
namespace DocuPro.DomainServices
{
public class UpdateStatsVentesMoisJob : BackgroundJob<StatsVentesMoisJobArgs>, ITransientDependency
{
private readonly ISortiesLocalesesAppService _sortiesLocalesesAppService;
private readonly IRepository<Periode> _periodeRepository;
public UpdateStatsVentesMoisJob(
ISortiesLocalesesAppService sortiesLocalesesAppService,
IRepository<Periode> periodeRepository)
{
_sortiesLocalesesAppService = sortiesLocalesesAppService;
_periodeRepository = periodeRepository;
}
[UnitOfWork]
public override void Execute(StatsVentesMoisJobArgs args)
{
Logger.Warn("UpdateStatsVentesMoisJob. Job STARTED.");
var periodeId = args.PeriodeId;
if (periodeId <= 0)
{
Logger.Warn("Invalid PeriodeId provided to UpdateStatsVentesMoisJob. Job aborted.");
return;
}
try
{
_sortiesLocalesesAppService.UpdateStatsVentesMois(periodeId);
}
catch (Exception ex)
{
Logger.Error($"An error occurred while executing UpdateStatsVentesMoisJob for PeriodeId {periodeId}.", ex);
}
}
}
}
Here is my UpdateStatsVentesMois method:
public async Task UpdateStatsVentesMois(int periodeId)
{
Logger.Warn("UpdateStatsVentesMoisJob. Job STARTED. UpdateStatsVentesMois");
var statsList = await GetStatsVentesMois(periodeId); // Assuming this returns a list of VentesMoisStatsDto
await _statsVentesRepository.DeleteAllByPeriodeId(periodeId);
Logger.Warn($"UpdateStatsVentesMoisJob. NOMBRE MOIS. DELETED ");
foreach (var stat in statsList)
{
// Insert new record
var newStat = new CreateOrEditStatsVenteDto
{
Pays = stat.Pays,
Grossiste = stat.Grossiste,
GrossisteId= stat.GrossisteId,
ProduitLibelle = stat.ProduitLibelle,
Ventes = (int)stat.Ventes,
VentesMois = (int)stat.VentesMois,
Poids = stat.Poids,
VentesMoisMMinus1 = (int)stat.VentesMoisMMinus1,
TauxEvol = stat.TauxEvol,
BudgetMois = stat.BudgetMois,
TauxReal = stat.TauxReal,
BudgetAnnee = stat.BudgetAnnee,
TauxRealCumulBudget = stat.TauxRealCumulBudget,
AvgVentesLast3Months = (int)stat.AvgVentesLast3Months,
AvgVentesLast6Months = (int)stat.AvgVentesLast6Months,
AvgVentesLast12Months = (int)stat.AvgVentesLast12Months,
CAMois = (int)stat.CAMois,
CAMoisMMinus1 = (int)stat.CAMoisMMinus1,
TauxEvolCA = stat.TauxEvolCA,
BudgetMoisCA = (int)stat.BudgetMoisCA,
TauxRealCA = stat.TauxRealCA,
BudgetAnneeCA = (int)stat.BudgetAnneeCA,
CumulCA = (int)stat.CumulCA,
CumulBudgetCA = (int)stat.CumulBudgetCA,
TauxRealCumulBudgetCA = stat.TauxRealCumulBudgetCA,
PGHT = stat.PGHT,
SortieLocalesId = stat.SortieLocalesId, // Assuming this is the correct property name
PeriodeId = stat.PeriodeId,
};
await _statsVentesRepository.CreateOrEdit(newStat);
}
Logger.Warn($"UpdateStatsVentesMoisJob. FIN ");
}
On this : var statsList = await GetStatsVentesMois(periodeId);
I get an error :
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
---> Microsoft.Data.SqlClient.SqlException (0x80131904): The transaction operation cannot be performed because there are pending requests working on this transaction.
at Microsoft.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action1 wrapCloseInAction) at Microsoft.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action
1 wrapCloseInAction)
at Microsoft.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
at Microsoft.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject
I have set MultipleActiveResultSets=true;
I am sending you my application, database and Log by email
3 Answer(s)
-
0
Hi,
As I can see, your AppService method is async but the background job is sync. I suggest you 2 changes;
- Change your background job to inherit from
AsyncBackgroundJob
instead ofBackgroundJob
- Use a domain service instead of using
SortiesLocalesesAppService
in your background job.
- Change your background job to inherit from
-
0
Hello, thanks for your help.
I changed the job signature to this:
public class UpdateStatsVentesMoisJob : AsyncBackgroundJob<StatsVentesMoisJobArgs>, ITransientDependency
Then I created this under DocuPro.Application/DomainServices
using Abp.Domain.Repositories; using DocuPro.CommonBases; using Microsoft.Extensions.Logging; using Stripe; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;
namespace DocuPro.DomainServices { public class DomaineServiceDatabaseFunctions: IDomaineServiceDatabaseFunctions {
private readonly IRepository<Periode> _periodeRepository; private readonly ILogger<DomaineServiceDatabaseFunctions> _logger; public DomaineServiceDatabaseFunctions(IRepository<Periode> periodeRepository, ILogger<DomaineServiceDatabaseFunctions> logger) { _periodeRepository = periodeRepository; _logger = logger; } public async Task UpdateStatsVentesMois(int periodeId) { var periode = await _periodeRepository.GetAsync(periodeId); if (periode == null) { _logger.LogWarning($"UpdateStatsVentesMois. Periode with Id {periodeId} not found."); return; } _logger.LogInformation($"UpdateStatsVentesMois. Periode with Id {periodeId} WAS found."); // Other logic... } }
}
But when I execute I get:
WARN 2024-03-04 12:10:33,578 [38 ] .DomainServices.UpdateStatsVentesMoisJob - UpdateStatsVentesMoisJob. Job STARTED. ERROR 2024-03-04 12:10:33,756 [43 ] .DomainServices.UpdateStatsVentesMoisJob - An error occurred while executing UpdateStatsVentesMoisJob for PeriodeId 146. Abp.Domain.Entities.EntityNotFoundException: There is no such an entity. Entity type: DocuPro.CommonBases.Periode, id: 146 at Abp.Domain.Repositories.AbpRepositoryBase`2.GetAsync(TPrimaryKey id) at DocuPro.DomainServices.DomaineServiceDatabaseFunctions.UpdateStatsVentesMois(Int32 periodeId) in C:\Apps\MedicPro Fevrier\MedicPro.All\src\DocuPro.Application\DomainServices\DomaineServiceDatabaseFunctions.cs:line 28
-
0
Hi,
Is this entity
DocuPro.CommonBases.Periode, id: 146
belongs to a tenant or host ? If it belongs to a tenant, you need to switch to tenant context, see https://aspnetboilerplate.com/Pages/Documents/Multi-Tenancy#switching-between-host-and-tenants