Skip to content

Instantly share code, notes, and snippets.

@TylerHendrickson
Last active April 19, 2019 06:01
Show Gist options
  • Select an option

  • Save TylerHendrickson/1c7eac348076f6bf44e17568fe600f10 to your computer and use it in GitHub Desktop.

Select an option

Save TylerHendrickson/1c7eac348076f6bf44e17568fe600f10 to your computer and use it in GitHub Desktop.
Distributed lock decorator backed by DynamoDB (or DLDBBDDB for short)
import functools
import sys
import time
import boto3
import botocore
from python_dynamodb_lock.python_dynamodb_lock import DynamoDBLockClient
lock_client = DynamoDBLockClient(boto3.resource('dynamodb'))
# This may be done in infra config (terraform, cloudformation, etc) instead:
try:
lock_client.create_dynamodb_table(boto3.client('dynamodb'))
except botocore.exceptions.ClientError as e:
if 'ResourceInUseException' not in str(e):
raise
else:
print('DDB Table already exists')
def distributed_lock(fn):
"""Decorator that waits until any other instances
of the decorated function (in a distributed system)
have finished executing before allowing local execution.
"""
key = f'{fn.__module__}.{fn.__qualname__}'
@functools.wraps(fn)
def wrapper(*args, **kwargs):
with lock_client.acquire_lock(key):
return fn(*args, **kwargs)
return wrapper
@distributed_lock
def foo(seconds: int):
"""A function that must be executed in an exclusive manner,
within a distributed system.
This just sleeps.
"""
time.sleep(seconds)
def main() -> int:
"""Runs the example, expecting a single positional int argument
that defines the sleep duration. Program execution time will be at
least slightly higher than this value, plus whatever time was spent
waiting to acquire the lock.
"""
try:
duration = int(sys.argv[1])
except (IndexError, ValueError):
print('Bad/missing positional argument for duration!')
return 1
start = time.time()
foo(duration)
runtime = time.time() - start
print(f'foo({duration}) returned after {runtime} seconds')
return 0
if __name__ == '__main__':
sys.exit(main())
boto3==1.9.133
python-dynamodb-lock==0.9.1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment