Using transactions/UnitOfWork to delete/create jobs

Hello (:

I’m implementing HangFire on my company’s asp.net core framework, and I’m creating a few methods to make it easier for our programmers to use it.

I’m creating a method UpdateScheduledJob (shown simplified bellow), in which I do two actions:

public string UpdateScheduledJob<TArgs>(string jobId, TArgs args, DateTimeOffset dateTimeToExecute)
{
   BackgroundJob.Delete(jobId);
   var newJobId = BackgroundJob.Schedule<BackgroundJobExecutionAdapter>(adapter => adapter.Execute(args, JobCancellationToken.Null), dateTimeToExecute);
   return newJobId;
}

The problem with this, is that a I want to guarantee that either none or both operations get executed and commited to the database (I’m using Sql Server).
In case that the Schedule method thrown any exception, I want to rollback the delete operation.

I thought about doing something like this:

public string UpdateScheduledJob<TArgs>(string jobId, TArgs args, DateTimeOffset dateTimeToExecute)
{
  using (var transaction = JobStorage.Current.GetConnection().CreateWriteTransaction())
  {
    BackgroundJob.Delete(jobId);
    var newJobId = BackgroundJob.Schedule<BackgroundJobExecutionAdapter>(adapter => adapter.Execute(args, JobCancellationToken.Null), dateTimeToExecute);

    transaction.Commit();
    return newJobId;
  }
}

But when I took a look on HangFire’s code, I found that the BackgroundJobClientExtensions.Delete method already internally creates and commit the transaction.

Is there any way I can achieve this all or nothing behaviour??

I also want to implement Unit Of Work Pattern to create and commit transactions… but let’s go one step at a time…

Our framework already implements Unit Of Work on database and service bus messages, in this order.

Basically, imagine a controller method… if an entity is changed, and then a service bus message is published, after the method is executed, we commit changes to the database, and then the service bus messages are really sent. If the commit throws any exception, the service bus messages are rolled back and not sent.
I would like to add a third “layer” to this, which you be the enqueue/schedule of the background Jobs, only after the database changes are commited and the service bus messages are sent, then really commit the background jobs…

Thanks in advance!!

1 Like