Last active
April 3, 2019 15:08
-
-
Save shevron/316eee5e8024dc5f488b27ba5a027553 to your computer and use it in GitHub Desktop.
Examples: MySQL named locks and Python context managers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""same logic as in above, but using a locking context manager | |
""" | |
from app_services import db_session | |
from locking_context import named_lock | |
def single_running_func(): | |
"""this code should never execute in parallel | |
""" | |
with named_lock(db_session, 'my_lock', 5): | |
# Do some stuff that should not run in parallel | |
pass # <-- here for syntax correctness |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from app_services import db_session | |
def single_running_func(): | |
"""this code should never execute in parallel | |
""" | |
lock = db_session.execute("SELECT GET_LOCK('my_lock', 5)").scalar() | |
if not lock: | |
raise RuntimeError("Could not obtain lock for 5 seconds") | |
# Do some stuff that should not run in parallel | |
db_session.execute("SELECT RELEASE_LOCK('my_lock')") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""locking_context - locking related context managers | |
""" | |
import contextlib | |
@contextlib.contextmanager | |
def named_lock(db_session, name, timeout): | |
"""Get a named mysql lock on a DB session | |
""" | |
lock = db_session.execute("SELECT GET_LOCK(:lock_name, :timeout)", | |
{"lock_name": name, "timeout": timeout}).scalar() | |
if lock: | |
try: | |
yield db_session | |
finally: | |
db_session.execute("SELECT RELEASE_LOCK(:name)", {"name": name}) | |
else: | |
e = "Could not obtain named lock {} within {} seconds".format( | |
name, timeout) | |
raise RuntimeError(e) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment