Distributed lock service

Hi!

I’m trying to understand the distributed lock, and if I’m doing something wrong…

I’m acquiring an async lock, with a timeout of 30 seconds:

using (await _distributedLockService.AcquireLockAsync(myResource, TimeSpan.FromSeconds(30))) 
{
    // Code that takes about 3 seconds
}

This lock is acquired from a specific request. The time it takes to perform the code inside the using block takes about 3 seconds. If I send two requests at (basically) the same time, one of the locks times out after 30 seconds, even if the code inside the using block already finished 27 seconds ago. Do I misunderstand how the timeout works, or am I missing something else?

The call to the method is awaited, and the AcquireLockAsync call is also await. I even tried to call Dispose() on the IDisposable that is returned from AcquireLockAsync, but no luck here as well.

Litium version: 7.6.2

Hard to tell what might be wrong, could you add a full code sample to reproduce the issue?

As reference you can find an example on how to use the lock at: Education/ErpPriceCalculatorDecorator.cs at main · LitiumAB/Education · GitHub

I can’t really share the actual code. I’ve already read that example with no luck, I’m doing what it is telling me to do :stuck_out_tongue:

Basically, the code inside the lock is confirming an order, based on certain conditions.
The second concurrent request is a callback from a payment provider that also wants to confirm this order. The problem here is that we can’t wait for the payment provider every time, as their callback can vary from 1 second up to 5 minutes until a callback is sent to us, which forces us to make the confirmation at the time when the user places the order.

The confirmation sometimes collide, as the callback from the payment provider can come at the same time.

The actual code might not be needed, perhaps an example with the same flow can reproduce the problem?

Is it a multiserver setup? Are you using Redis?
Do you have logging to check how many requests that reach the lock, could it be more than 2?
Do you exit the lock immediately if the order is already confirmed?
Do ho have logging to verify that the lock has been exited by the first request?

Yes, multiserver with Redis. However, the problem occurs locally as well with only one server (also using redis).

I can confirm that there are only two requests to the lock.
By exit, I guess you mean stop the method from continuing? Yes, we call return immediately if we find that the order is confirmed.
How would that logging look like? I have logging after the confirm method has been awaited and fully executed.

Some pseudo code:

using (await _distributedLockService.AcquireLockAsync(paymentReference, TimeSpan.FromSeconds(10)))
{
     try 
     {
          var order = GetOrder();
          var paymentFromProvider = await GetPayment();

          if (order.OrderState == Confirmed)
          {
               // Already confirmed, just return the order
               return order;
          }

          SetPaymentStatus(ExecuteReserve);

          if (paymentFromProvider.Status == Completed)
          {
              CancelOrderAndThrowIfAnyVariantIsOutOfStock(order);

               // Confirm order
               SetPaymentStatus(Reserved);
               await UpdatePaymentProviderOrderWithAdditionalInfo();

               // Get a new fresh copy of the order as we've changed the payment status to reserved
               order = GetOrder();
               
               if (PaymentState != Reserved)
               {
                    throw new Exception("Payment could not be reserved");
               }

               if (order.OrderState != Confirmed)
               {
                    throw new Exception("Order could not transition to confirmed");
               }

               AddInfoToEachOrderRow();
          }
     }
     catch(Exception ex) 
     {
          SetPaymentStatus(ReserveFailed);
          throw;
     }
}

This is likely due to a known bug: Login

The bug was fixed in version 7.7.1, would it be possible for you to upgrade to see if that solves the issue?

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.