Distributed locks
Manage access to your shared resources in real-time to transact data in the desired order
On some occasions, there are resources shared between application instances that need to take turns accessing resources. For example, when incrementing a value, if two clients read a value at the same time as 1
, then each will increment the value to 2
, even though the desired behavior would be for the value to be incremented twice to a result of 3
.
This scenario is an example of a race condition, a situation that occurs when a system attempts to perform two or more operations at the same time. But because of the nature of the system, the operations must be done in the proper sequence.
Squid provides a distributed lock for developers to use to properly synchronize shared data and resolve race conditions.
Creating a distributed lock
To synchronize access to a shared resource, you can use the acquireLock
method, passing a string value for the mutex
parameter that uniquely identifies this lock:
const distLock = await squid.acquireLock('YOUR_MUTEX_STRING');
This method returns a promise that resolves to a distributed lock for the given mutex. If the lock is not available because another client has secured it, then the promise waits to resolve until the lock is released or when the connection with the server is lost.
Releasing the lock
The lock is released when the release()
method is called or when the connection to the server is lost. If the client disconnects, the lock is released automatically.
// Release the lock when the work is completed
distLock.release();
Putting these methods together, your workflow could look like the following:
const distLock = await squid.acquireLock('YOUR_MUTEX_STRING', 5000);
try {
// Take action on a shared resource
} catch (e) {
// Catch errors like timeout
} finally {
distLock.release(); // Release the lock when no longer needed
}
To check if a lock has been released, use the isReleased()
method. This method returns a boolean that is true
if the lock has been released.
console.log(distLock.isReleased()); // true or false
You can take actions upon lock release using the observeRelease()
method. This returns an observable that emits when the lock is released.
distLock.observeRelease().subscribe(() => {
// Do something upon releasing the lock
});
Managing a distributed lock with a callback
You can also use the withLock()
method to manage a distributed lock. This method executes a given callback while holding a lock for the given mutex. The lock is released when the callback finishes, so the release()
method is not required when using `withLock().
squid.withLock('YOUR_MUTEX_STRING', async () => {
// Complete tasks like reading and/or updating data
return; // Can also return a function
});
Securing distributed locks
By default, distributed locks are fully secured and can only be invoked if a Squid backend security function allows it. To learn more, view the backend documentation on securing distributed locks.