mirror of
https://github.com/outbackdingo/patroni.git
synced 2026-08-25 14:53:37 +00:00
In addition, use the RLock instead of the Lock in async executor to make sure the lock can be acquired more than once from a single thread.
56 lines
1.5 KiB
Python
56 lines
1.5 KiB
Python
import logging
|
|
from threading import RLock, Thread
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class AsyncExecutor(object):
|
|
|
|
def __init__(self):
|
|
self._busy = False
|
|
self._thread_lock = RLock()
|
|
self._scheduled_action = None
|
|
self._scheduled_action_lock = RLock()
|
|
|
|
@property
|
|
def busy(self):
|
|
return self._busy
|
|
|
|
def schedule(self, action, immediately=False):
|
|
with self._scheduled_action_lock:
|
|
if self._scheduled_action is not None:
|
|
return self._scheduled_action
|
|
self._scheduled_action = action
|
|
self._busy = immediately
|
|
return None
|
|
|
|
@property
|
|
def scheduled_action(self):
|
|
with self._scheduled_action_lock:
|
|
return self._scheduled_action
|
|
|
|
def reset_scheduled_action(self):
|
|
with self._scheduled_action_lock:
|
|
self._scheduled_action = None
|
|
self._busy = False
|
|
|
|
def run(self, func, args=()):
|
|
try:
|
|
return func(*args) if args else func()
|
|
except:
|
|
logger.exception('Exception during execution of long running task %s', self.scheduled_action)
|
|
finally:
|
|
with self:
|
|
self._busy = False
|
|
self.reset_scheduled_action()
|
|
|
|
def run_async(self, func, args=()):
|
|
self._busy = True
|
|
Thread(target=self.run, args=(func, args)).start()
|
|
|
|
def __enter__(self):
|
|
self._thread_lock.acquire()
|
|
|
|
def __exit__(self, *args):
|
|
self._thread_lock.release()
|