Distributed lock management
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 the value at nearly the same time and both read it as 1
, then each will write the value back as 2
when in reality you need the first read to complete its write before the next client reads, leading to an incremented value of 3
. This scenario is an example of a race condition, which is undesirable 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 to be done correctly. 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 parameter mutex
that uniquely identifies this lock and an optional timeout. If no timeout is provided, the default value is 1000ms.
const distLock = await squid.acquireLock('YOUR_MUTEX_STRING', 5000); // Setting the timeout to 5000ms
This method returns a promise that resolves 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 until the given timeout is reached.
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', 5000, 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.