I'm developing a singleton calss in Python to keep one node at time as primary node using the PySyncObj library:
class PhiRaft():
__instance = None
def __new__(
cls,
logger: PhiLogger = None,
node: str = None,
nodes: list = None,
timeout: float = None
):
if cls.__instance is None:
cls.__instance = super(PhiRaft, cls).__new__(cls)
if logger and node and nodes and timeout:
cls._init_singleton(cls, logger, node, nodes, timeout)
return cls.__instance
def _init_singleton(self, logger: PhiLogger, node: str, nodes: list, timeout: float):
self.__log = logger
lock_manager = ReplLockManager(autoUnlockTime=timeout)
sync_obj = SyncObj(node, nodes, consumers=[lock_manager])
self.__lockThread = LockThread(logger, lock_manager, sync_obj)
self.__lockThread.start()
def is_node_primary(self):
return self.__lockThread.getLockStatus()
class LockThread(threading.Thread):
def __init__(self, logger: PhiLogger, lock_manager: ReplLockManager, sync_obj: SyncObj):
self.__log = logger
self.__lock_manager = lock_manager
self.__sync_obj = sync_obj
self.__callbacks = []
self.__lockAcquired = False
threading.Thread.__init__(self)
def run(self):
while True:
try:
self.__lockAcquired = self.__lock_manager.tryAcquire('leader', sync=True, timeout=1)
except Exception as e:
self.__log.info(f'Error lock: {vars(e)}')
self.__log.info(f'lockAcquired: {self.__lock_manager.isAcquired("leader")}, amILeader: {self.__sync_obj._isLeader()}, leader: {self.__sync_obj._getLeader()}')
time.sleep(3)
So with that only one node at time can be the primary node and in every place of my code I can check if I'm the primary node. I'm testing this code and it works with 4+ nodes cluster but with 3 nodes only I'm facing a problem. If the raft-leader node crashes the remaing two doesn't start an election and they won't be able to acquire the lock. The tryAcquire method also throws an Exception of "Timeout". Maybe I'm not implementing it in the righ way, can anyone help me?