Locking of single entity in MongoDB to allow atomic processing only once

While working on a project with a MongoDB as a database and some operations that were handling some financial transactions which needs to be atomic I sometime find it hard to work without the SQL Server transactions. MongoDB is fast and reliable and you can mostly live without the transactions and only in some cases handle the failures (by deleting the extra records or similar approaches), there are cases when you need only one update to get through. For example in cases of payment processing by automated task. Only the first attempt should succeed. The next (even if almost simultaneous) should be blocked. Having said that, the following scenario might be useful for SQL-based databases as well, basically anytime you want to “lock” a record for an exclusive processing.

This will no block other code from accessing the records (it is not defensive enough), but will allow the locking functionality to the code aware of the workflow that needs to be followed.

I achieved this, by defining a “lock” interface:

Lock object contains only these fields:

The logic is supposed to work in a way that as long as the DB entity has the Locked = true and LockUtcTime < a given expiration period we should not access and work with this entity. The expiration is here mostly for the cases when the processing code hangs and would not set the Locked to false after the processing (having said that, all the logic should be in a proper try-catch-finally, to make sure all cases are handled).

Now what we need to do in the (let’s say payment) processing code instead of a plain retrieval of the object from the DB, we use a FindOneAndUpdate command like this:

This way we only get the entity for the first time. The second time it is not returned, because it is already locked.

At the end of the operation (finally block of the operation) we must not forget to to set the Locked back to false:

 

Send a Comment

Your email address will not be published.