Run code in lock inside handler with outbox

Hello,

I need to run some code in DistributedLock for specific message inside the handler.

   public abstract class MyHandler : IHandleMessages<MyMessage>
   {
      public Task Handle(TRequest request, IMessageHandlerContext context)
      {
	  await using (await myDistributedLock.AcquireAsync())
	  {
		// update database using transaction from the NServiceBus Context
 	  }
      }
   }

And it’s important that we use an outbox feature, which means that the data will be committed long after the lock is released - this is a problem for us because another transaction will get a lock before the updated data is available.
We need the lock to be released after the potbox transaction is committed.

I know that it is possible to rewrite the behavior, but I can not find information on which step the outbox transaction is created.
For example:

public class HandlerTimerBehavior : Behavior<IIncomingLogicalMessageContext>
   {
      public override async Task Invoke(IIncomingLogicalMessageContext context, Func<Task> next)
      {
         if (context.Message.Instance is MyMessage myEntity)
         {
            await using (await myDistributedLock.AcquireAsync())
            {
               await next().ConfigureAwait(false);
               // the transaction should be committed at this step
            }
         }
         else
         {
            await next().ConfigureAwait(false);
         }
      }
   }

Will this approach work correctly?

Hi @ElenaShlykova

the Outbox transaction is opened and committed in a pipeline connector just after transport receive stage. You’ll need an ITransportReceiveContext behavior releasing the distributed lock.

Can you share a bit more information on your business scenario? Why is it that you need a distributed lock?

Cheers,
Tomek