Product Version 8.0.0 Product Type: Angular Framework: .NET Core 3.0 ABP Framework: 5.0
I'm currently using the BackgroundJob class successfully. Some jobs execute in few seconds. Other jobs execute in minutes or hours. Each job is independent, with no dependency on previously executed jobs. Jobs are initiated by user actions. Long running jobs cause fast running jobs to wait until the long running job has finished because BackgroundJob executes queued jobs sequentially. This causes one user's job to wait until all other jobs have run to completion. How can I implement "fire and forget" jobs (or Tasks) that execute in parallel? I want a user's job to begin execution immediately.
Below are code snippets of the current implementation:
[AbpAuthorize(AppPermissions.Pages_Exams)]
public class ExamsAppService : ngTTMAppServiceBase, IExamsAppService
{
.
.
.
[AbpAuthorize(AppPermissions.Pages_Exams_Create)]
private async Task<ServiceStatusDto> CreateExamJob(string examGuid)
{
ServiceStatusDto status = new ServiceStatusDto(L("Exams"), L("Success"));
long UserId = (long)AbpSession.UserId;
string workingDirectory = _webHostEnvironment.ContentRootPath;
try
{
CreatJobArgs args =
new CreatJobArgs
{
tenantId = AbpSession.TenantId,
userId = UserId,
jobGuid = examGuid,
folder = StorageLibrary.Storage.FILES_FOLDER,
operation = JobOps.JOB_OP_CREATE,
workingDirectory = workingDirectory
};
using (_abpSession.Use(AbpSession.TenantId, UserId))
{
status.BackgroundJobId = await
_backgroundJobManager.EnqueueAsync<CreateExamJob, CreatJobArgs>(args);
}
status.Guid = examGuid;
return status;
}
catch (Exception ex)
{
ExceptionUtility.LogException(UserId, ex);
status.Success = false;
status.FailureReason = ex.Message;
return status;
}
}
}
=============================================
public class CreateExamJob : BackgroundJob<CreatJobArgs>, ITransientDependency, IApplicationService
{
private readonly ITempFileCacheManager _tempFileCacheManager;
private readonly IWebHostEnvironment _hostingEnvironment;
private readonly ISettingManager _settingManager;
private readonly ILocalizationManager _localizationManager;
private readonly IAbpSession _abpSession;
private readonly IBinaryObjectManager _binaryObjectManager;
private DateTime jobStartTime;
public CreateExamJob(
ITempFileCacheManager tempFileCacheManager,
ISettingManager settingManager,
IWebHostEnvironment hostingEnvironment,
ILocalizationManager localizationManager,
IBinaryObjectManager binaryObjectManager,
IAbpSession abpSession
)
{
_settingManager = settingManager;
_hostingEnvironment = hostingEnvironment;
_tempFileCacheManager = tempFileCacheManager;
_localizationManager = localizationManager;
_binaryObjectManager = binaryObjectManager;
_abpSession = abpSession;
}
[UnitOfWork]
public override void Execute(CreatJobArgs args)
{
jobStartTime = DateTime.Now;
using (CurrentUnitOfWork.SetTenantId(args.tenantId))
{
using (_abpSession.Use(args.tenantId, args.userId))
{
UserIdentifier _userId = new UserIdentifier(args.tenantId, (long)args.userId);
string userLanguage = _settingManager.GetSettingValueForUser(LocalizationSettingNames.DefaultLanguage, _userId);
CultureInfo culture = CultureHelper.GetCultureInfoByChecking(userLanguage);
Thread.CurrentThread.CurrentUICulture = culture;
LocalizationSourceName = ngTTMConsts.LocalizationSourceName;
Execute_MyCode(args); // How to "fire and forget" this? Or an instance of the CreateExamJob class?
}
}
}
}
==========================================
[Serializable]
public class CreatJobArgs
{
public string fileToken { get; set; }
public string folder { get; set; }
public string jobGuid { get; set; }
public string operation { get; set; }
public int? tenantId { get; set; }
public long? userId { get; set; }
public string workingDirectory { get; set; }
}
5 Answer(s)
-
0
Hi timmackey, The default background job manager of ABP is blocking, it can only execute one job at a time. Currently, there is no implementation of the
CancellationToken
mechanism, so long-blocking jobs cannot be interrupted. You can set different priorities for different tasks to alleviate this situation. If you want to execute tasks in parallel, or temporarily cancel tasks, you can useAbp.Hangfire
. Hangfire reference: -
0
@zony I'm not seeing a path forward due to the limitations of Hangfire Background Methods, described here: https://docs.hangfire.io/en/latest/background-methods/index.html ...which states
Local variables, instance and static fields and other information isn’t available in our background jobs.
My background process requires injected dependencies for ILocalizationManager, IBinaryObjectManager, and others. (Usage is not shown in the code snippets posted) Unless there is something I'm not understanding, Hangfire doesn't appear to be a viable option.
-
0
Hi @timmackey,
You can use dependency injection in Hagfire, see https://docs.hangfire.io/en/latest/background-methods/using-ioc-containers.html
-
0
Hi @ismcagdas, Thanks for the link.
In thinking more about my requirements, I'm coming to the conclusion that deferring one job over another depending on demand and job type, may not be the optimal solution. Plus, the solutions recommended require Hangfire.Ace, annual license fee $1500.
I'm considering Azure Functions, which is an elastic on-demand pay-as-you-go n-instance service; more like what I'm looking for.
-
0
Hi @timmackey
This is the first time I see Hangfire.Ace. You can also take a look at https://www.quartz-scheduler.net/, this is also a very nice library.