Base solution for your next web application
Open Closed

HangFire job manager #4775


User avatar
0
SperseDev created

Hi

I have read documentation related to integration with HangFire like alternative job processor. Good explanation and all work correctly, but after several days of working noticed a strange behavior different from the behavior of the classic background job manager.

Simple example to explain:

[UnitOfWork]
public void TestMethod()
{
    PrepareDataForTestJob();
  
    CurrentUnitOfWork.SaveChanges();
	
    _backgroundJobManager.EnqueueAsync<TestJob, TestJobParams>(new TestJobParams()); 
	
    throw new Exception("Some Exception");
}

Method _backgroundJobManager.EnqueueAsync enqueues job immediately and HangFire job processor starts processing without committed prepared data. In a case when method TestMethod throws exception job still exists in queue processing.

First thought, that we need to rewrite HangfireBackgroundJobManager to something like that:

public Task<string> EnqueueAsync<TJob, TArgs>(TArgs args, BackgroundJobPriority priority = BackgroundJobPriority.Normal, TimeSpan? delay = null) 
    where TJob : IBackgroundJob<TArgs>
{
    string jobUniqueIdentifier = string.Empty;

    _unitOfWorkManager.Current.Completed += (sender, args) => 
    { 
        if (!delay.HasValue)
        {
            HangfireBackgroundJob.Enqueue<TJob>(job => job.Execute(args));
        }
        else
        {
            HangfireBackgroundJob.Schedule<TJob>(job => job.Execute(args), delay.Value);
        }
    }
    return Task.FromResult(jobUniqueIdentifier);  //???
}

Do you have any suggestions how to fix this correctly?

Thanks!


4 Answer(s)
  • User Avatar
    0
    alper created
    Support Team

    what I didn't understand is; when you call SaveChanges ( CurrentUnitOfWork.SaveChanges();) data should be committed. And Hangfire should go on with the committed data.

  • User Avatar
    0
    SperseDev created

    Yes, but after an exception at the end of this method all changes will be rolled back, but Hangfire job will be left.

  • User Avatar
    0
    alper created
    Support Team

    I got it!

    You can create a different and isolated transaction in another transaction.

    using (var uow = _unitOfWorkManager.Begin(TransactionScopeOption.RequiresNew))
    {              
    	/*DO YOUR WORK*/
    	await _unitOfWorkManager.Current.SaveChangesAsync();
    	await uow.CompleteAsync();
    }
    

    <a class="postlink" href="https://aspnetboilerplate.com/Pages/Documents/Unit-Of-Work?searchKey=unit%20of%20work#unit-of-work-scope">https://aspnetboilerplate.com/Pages/Doc ... work-scope</a>

  • User Avatar
    0
    SperseDev created

    Yes, you are right, but ... My point was that It is not so simple as you describe to change the default background job processor to Hangfire. After exchanging we also need to rewrite some logic to something like you offered. Currently, the documentation doesn't have warnings about this. My offer was to modify HangfireBackgroundJobManager to move enqueueing a job on transaction committing level. Thanks