Python DynamoDB Lock

0.9.1 · maintenance · verified Tue Apr 14

Python DynamoDB Lock is a general-purpose distributed locking library built on top of DynamoDB. It supports both coarse-grained and fine-grained locking, heavily inspired by the Java-based AmazonDynamoDBLockClient. The current version is 0.9.1, with the last release in October 2018. While functional, its development appears to be in maintenance mode.

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to acquire and release a distributed lock using `DynamoDBLockClient` as a context manager for a specific resource. It includes basic setup for a DynamoDB table and shows how to handle the critical section.

import boto3
from python_dynamodb_lock import DynamoDBLockClient
import os
import time

# Configure AWS credentials and region (e.g., via environment variables or ~/.aws/credentials)
# For local testing, you might use 'local' endpoint_url
dynamodb_resource = boto3.resource(
    'dynamodb',
    region_name=os.environ.get('AWS_REGION', 'us-east-1'),
    endpoint_url=os.environ.get('DYNAMODB_ENDPOINT_URL', None)
)

table_name = os.environ.get('DYNAMODB_LOCK_TABLE_NAME', 'MyDistributedLockTable')

# It's recommended to create the table beforehand with a 'lock_key' primary key and TTL enabled
# For demonstration, we'll try to create it if it doesn't exist
try:
    table = dynamodb_resource.Table(table_name)
    table.load()
except dynamodb_resource.meta.client.exceptions.ResourceNotFoundException:
    print(f"Creating DynamoDB table: {table_name}")
    dynamodb_resource.create_table(
        TableName=table_name,
        KeySchema=[{'AttributeName': 'lock_key', 'KeyType': 'HASH'}],
        AttributeDefinitions=[{'AttributeName': 'lock_key', 'AttributeType': 'S'}],
        BillingMode='PAY_PER_REQUEST'
    )
    # Wait for the table to be active
    dynamodb_resource.meta.client.get_waiter('table_exists').wait(TableName=table_name)
    print(f"Table {table_name} created.")

# Instantiate the lock client
# The 'owner_name' helps identify who holds the lock (e.g., hostname + process ID)
lock_client = DynamoDBLockClient(
    dynamodb_resource,
    table_name=table_name,
    owner_name=f"{os.uname()[1]}-{os.getpid()}"
)

lock_key = "my-critical-resource"

try:
    print(f"Attempting to acquire lock for {lock_key}...")
    # Use the 'lock' method as a context manager for a specific lock
    with lock_client.lock(lock_key):
        print(f"Successfully acquired lock for {lock_key}. Performing critical section...")
        # Simulate work
        time.sleep(5)
        print(f"Finished critical section for {lock_key}.")
    print(f"Lock for {lock_key} automatically released.")
except Exception as e:
    print(f"Failed to acquire or process with lock for {lock_key}: {e}")
finally:
    # It's important to close the client to stop background heartbeat threads
    print("Closing lock client...")
    lock_client.close() 
    print("Lock client closed.")

view raw JSON →