abp icon indicating copy to clipboard operation
abp copied to clipboard

Locking on UoW lifetime

Open puschie286 opened this issue 2 months ago • 2 comments

Is there an existing issue for this?

  • [x] I have searched the existing issues

Is your feature request related to a problem? Please describe the problem.

We have some cases where database changes need to be persistent in order when parallel access/updates happen.

This is tricky, because database changes (usually) happen when the UoW completes and this is in most cases after the method has finished / exit. So most locking methods are not usable (when the automatic UoW handling is used). And its gets more complicated when multiple UoW levels are involved.

A example would be a data string, that needs to be processed and updated with the result of each processing step.

Using a distributed lock would work, but only if the lock release is bonded to UoW lifetime. If multiple actions can happen in the same UoW, you need to check if this lock is already acquired by this UoW or this might cause a deadlock.

(a solution for the example would be to split it up to multiple entities but that approach has other synchronization issues)

Describe the solution you'd like

A extension for IAbpDistributedLock to lock on UoW level and release when its completed / failed.

Additional context

No response

puschie286 avatar Oct 24 '25 10:10 puschie286

I believe that for a scenario with such strict demands, implementing a queue is essential.

gdlcf88 avatar Oct 24 '25 15:10 gdlcf88

A (command) queue is a good solution for complex features that are used by multiple services. For a simple "i need to interact with a shared resource", it might be overkill and is not simple to implement either.

Because of that, i think it would be a great addition to the abp framework for a simple way to connect DistributedLocks with UnitOfWork.

Generally, you try to design systems to be lock free or minimize collision points but its often much more complex than to acquire a lock in these cases. For many small features/systems, these cases are 'edge cases' and happen very rarely - which means that a complete redesign (that might be required to solve those cases by design) is not worth it or very risky. I think that the correct resource handling (either by locking or atomic actions) in a distributed environment is one of the keys for high reliability.

Currently, you would request the DistributedLock in the outer method and execute the resource interaction within a new UoW. This makes changes to the resource safe and is enough for most cases - one of the most used pattern in our task/jobs.

A naive implementation could be a distributed lock name for the AsyncPeriodicBackgroundWorkerBase that acquire the lock before the scope is created. A more complete implementation would be a option on AbpUnitOfWorkOptions (and UoW attribute). (UoW should make actions, especially db related actions, atomic like and distributed locking can help to ensure this behavior in a distributed environment )

puschie286 avatar Oct 27 '25 11:10 puschie286