Skip to content

Lock

The UserLock class allows you to manage distributed locks, ensuring that only one process at a time can access a shared resource.

Below we have the import statement

from everysk.sdk.engines import UserLock

Example

In this example, we create a lock named my_lock with a 10-second timeout. The process acquires the lock, performs some protected work, and then releases the lock.

lock = UserLock(name='my_lock', timeout=10)

try:
    lock.acquire()
    print("Lock acquired, doing something important...")

finally:
    lock.release()

This pattern should be used whenever you need to ensure exclusive access to a resource.

Failure Case

If you attempt to release a lock after the timeout, the system will raise an error. This prevents accidental misuse of the lock mechanism.

lock = UserLock(name='my_lock', timeout=10)

try:
    lock.acquire()
    sleep(11)

finally:
    lock.release()

This code above will raise a LockNotOwnedError since the timeout already exceeded.

Combining the features of Lock and Cache

from everysk.sdk.engines import MarketData, UserCache, UserLock

cache = UserCache()
cache_key = 'raw_sector_query'

# Create a distributed lock with a 10-second timeout
lock = UserLock(name='sector_query_lock', timeout=10)

cached_result = cache.get(cache_key)

if cached_result:
    return cached_result

try:
    lock.acquire()  # Acquire lock before performing expensive operation

    # Double check the cache in case another process already set it
    cached_result = cache.get(cache_key)
    if cached_result:
        return cached_result

    market_data = MarketData()
    result = market_data.search(
        [["raw_sector", "=", "Technology"]],
        fields=["instrument_class", "name", "gics_sector"],
        limit=1,
    )

    cache.set(cache_key, result, timeout=600)
    return result

finally:
    lock.release()  # Always release the lock

This example ensures that only one process at a time can run the MarketData.search and update the cache by using a UserLock. The lock is acquired before the expensive operation, and the cache is checked again inside the lock to avoid duplicate work if another process already populated it. Finally, the lock is always released in a finally block, guaranteeing proper cleanup even if an error occurs.