Source code for utils.views.cobalt_lock

import datetime
import os

from django.db import transaction
from django.utils import timezone

from utils.models import Lock


[docs] class CobaltLock: """handle running one thing at a time in a multi-node environment""" def __init__(self, topic: str, expiry: int = 15): """ Args: topic: name of this lock expiry: time in minutes to keep the lock closed for. After this even if open it will be considered expired (assume process died) """ self.topic = topic self.expiry = expiry self._locked = False
[docs] @transaction.atomic def get_lock(self): """Try to get a lock, returns True or False""" lock = Lock.objects.select_for_update().filter(topic=self.topic).first() if lock: # Lock found if lock.lock_open_time and lock.lock_open_time > timezone.now(): return False lock.lock_created_time = timezone.now() open_time = timezone.now() + datetime.timedelta(minutes=self.expiry) hostname = os.popen("hostname 2>/dev/null").read().strip() lock.lock_open_time = open_time lock.owner = hostname lock.save() else: # Create lock open_time = timezone.now() + datetime.timedelta(minutes=self.expiry) hostname = os.popen("hostname 2>/dev/null").read().strip() Lock(lock_open_time=open_time, topic=self.topic, owner=hostname).save() self._locked = True return True
[docs] @transaction.atomic def free_lock(self): """Release lock""" if not self._locked: return lock = Lock.objects.select_for_update().filter(topic=self.topic).first() if not lock: return lock.lock_open_time = None lock.save() self._locked = False
[docs] @transaction.atomic def delete_lock(self): """Delete the lock record, returning success. Will only delete an expired or freed lock. COB_965""" lock = Lock.objects.select_for_update().filter(topic=self.topic).first() if not lock: return True if lock.lock_open_time and lock.lock_open_time > timezone.now(): return False lock.delete() self._locked = False return True