Как сделать недействительным ресурс, выпущенный через менеджер контекста в python? - PullRequest
0 голосов
/ 29 мая 2019

Мой вопрос относится к Kazoo / Zookeeper, но в более общем плане речь идет о выделении ресурса, а затем разрешении вызывающей стороне этого ресурса не делать паузу.Из документов Kazoo:

Настоятельно рекомендуется добавить прослушиватель состояний с помощью add_listener (), отслеживать изменения состояния LOST и SUSPENDED и действовать соответствующим образом.В случае возникновения состояния LOST наверняка потеряна блокировка и / или аренда.

Я использую диспетчер контекста для выделения блокировок:

@contextmanager
def lock(self, path, identifier):
  lock = zk.Lock(path, identifier)
  lock.acquire()
  yield lock      <--- how to communicate connection loss from client?
  finally: 
    lock.release()

Используется следующим образом:

with lock('/some_op/') as lck:
  # do something with lock, but pause in case of connection loss? 

Как распределить блокировку, но отозвать доступ в случае потери соединения?

Вот как Kazoo рекомендует реализовать слушатель состояния соединения :

def my_listener(state):
    if state == KazooState.LOST:
        # Register somewhere that the session was lost
    elif state == KazooState.SUSPENDED:
        # Handle being disconnected from Zookeeper
    else:
        # Handle being connected/reconnected to Zookeeper

1 Ответ

1 голос
/ 29 мая 2019

Возможно, это не лучший дизайн, но вы можете предоставить ссылку на блокировку для тела оператора with:

@contextmanager
def acquire_lock(self, path, identifier):
  lock = zk.Lock(path, identifier)
  try: 
    retry = KazooRetry()
    retry(lock.acquire)
    yield lock
  finally: 
    lock.release()

with acquire_lock('/some_op/') as lock:
    ...
    if necessary:
        lock.release()
    ...

В зависимости от вашего вопроса (я не знаком с Kazoo), вы можете определить my_listener в менеджере контекста, где он может закрываться через блокировку.

@contextmanager
def acquire_lock(self, path, identifier):
    lock = zk.Lock(path, identifier)
    def my_listener(state):
        if state == KazooState.LOST:
            lock.release()
        elif state == KazooState.SUSPENDED:
            ...

    try:
        retry = KazooRetry()
    # etc

Вашему контексту может потребоваться выдать слушателя или зарегистрировать его (или что бы вы ни делали со слушателями), но что бы вы ни делали с ним, он получит доступ к блокировке, созданной вами в диспетчере контекста.

...