********************* Простое использование ********************* Простые примеры использования модуля ==================================== В качестве примера работы с m3-mutex реализуем небольшой класс-семафор, который будет блокировать повторное редактирование уже заданного объекта:: class ObjEditMutex(object): u"""Класс-семафор, блокирующий повторное редактирование объекта """ Добавим метод, который позволит нам получать id объекта:: def get_obj_id(self, obj_id): u"""Подмена obj_id, для возможности переопределения класса. Позволяет использовать свой уникальный obj_id без изменения логики родительского класса. """ return obj_id Добавим метод, который позволит нам получать семафор по типу и id объекта:: def get_mutex_id(self, mode, obj_id): u"""Возвращает id семафора для указанного типа и id объекта :param basestring mode: Тип объекта :param int obj_id: id объекта :rtype: int """ return m3_mutex.MutexID(mode=mode, id=str(obj_id)) Добавим метод, который позволит нам проверять наличие семафора:: def check(self, obj_id, mode, request_id): u"""Проверка на наличие семафора. Возвращает True, если объект не заблокирован или заблокирован нами. В противном случае возвращает False """ obj_id = self.get_obj_id(obj_id) mutex_id = self.get_mutex_id(mode=mode, obj_id=obj_id) # По умолчанию семафор занят is_free = False state, mt = m3_mutex.request_mutex(mutex_id) # Проверяем свободен ли семафор if state == m3_mutex.MutexState.FREE: is_free = True # Если семафорт занят нами в текущем запросе, то тоже все ОК elif state == m3_mutex.MutexState.CAPTURED_BY_ME: is_free = True return is_free Добавим метод, который позволит нам создавать семафор для последующей его блокировки:: def block(self, obj_id, mode, request_id): u"""Создание семафора и его блокировка. Передаётся id объекта, тип объекта и id запроса. :param int obj_id: id объекта :param basestring mode: тип объекта :param int request_id: id запроса :rtype: basestring or None """ blocker = None obj_id = self.get_obj_id(obj_id) mutex_id = self.get_mutex_id(mode=mode, obj_id=obj_id) try: # Получаем состояние state, mt = m3_mutex.request_mutex(mutex_id) # Если mutex никем не занят, в том числе нами из другого места if state == m3_mutex.MutexState.FREE: # Захватываем mutex m3_mutex.capture_mutex(mutex_id, status_data=request_id) # Иначе блокируем else: # Получаем владельца mutex blocker = mt.owner.name # Если занят except m3_mutex.MutexBusy: blocker = u'Блокировщик неизвестен' return blocker Добавим метод, который позволит нам обновлять блокировку семафора:: def refresh(self, obj_id, mode, request_id): u"""Обновление блокировки семафора, чтобы он не освободился по тайм-ауту. Передаётся id объекта, тип объекта и id запроса. :param int obj_id: id объекта :param basestring mode: тип объекта :param int request_id: id запроса :rtype: basestring or None """ obj_id = self.get_obj_id(obj_id) mutex_id = self.get_mutex_id(mode=mode, obj_id=obj_id) # Получаем состояние state, mt = m3_mutex.request_mutex(mutex_id) # Если заблокирован нами и не из другого запроса if (state == m3_mutex.MutexState.CAPTURED_BY_ME and mt.status_data == request_id): # Обновляем блокировку для повторного захвата m3_mutex.capture_mutex(mutex_id, status_data=request_id) else: return u"Блокировка объекта снята!" return None Добавим метод, который позволит нам освобождать семафор:: def release(self, obj_id, mode, request_id): u"""Освобождение семафора. Передаётся id объекта, тип объекта и id запроса. """ obj_id = self.get_obj_id(obj_id) mutex_id = m3_mutex.MutexID(mode=mode, id=obj_id) state, mt = m3_mutex.request_mutex(mutex_id) if state == m3_mutex.MutexState.CAPTURED_BY_ME: mt = m3_mutex.capture_mutex(mutex_id) try: if mt.status_data == request_id: m3_mutex.release_mutex(mutex_id) except m3_mutex.MutexBusy: pass return None После этого, данный семафор можно использовать следующим образом:: # создаем семафор mutex = ObjEditMutex() # создаем или получаем каким - либо образом объект some_obj = SomeObjClass() # блокируем объект blocker = mutex.block(some_obj.id, some_obj.type, some_obj.uuid) # если нам удалось заблокировать объект if blocker is None: # делаем что - то с объектом do_something(some_obj) # освобождаем объект mutex.release(some_obj.id, some_obj.type, some_obj.uuid) print 'Операция с объектом завершена' else: # говорим, что объект занят print u'Объект занят'