diff --git a/app.py b/app.py index a45e734..6def60d 100644 --- a/app.py +++ b/app.py @@ -11,7 +11,7 @@ from consumerlocator import ConsumerLocator from messagesender import MessageSender """ -Main entrypoint +Main entry point, This module builds the producer from the submodules. """ __author__ = "@tormakris" @@ -29,6 +29,11 @@ LOGGER = logging.getLogger(__name__) KNOWNCONSUMER = os.getenv("PRODUCER_KNOWNCONSUMER",'10.69.42.1') +""" +This is the producers entry point, initializes all the components (:class:'communicator.Communicator', +:class:'consumerlocator.ConsumerLocator' and :class:'messagesender.MessageSender') and sends infinite random +messages. +""" if __name__ == "__main__": LOGGER.info("Producer started") generateduuid = str(uuid.uuid4()) diff --git a/communicator.py b/communicator.py index 8ca528e..e009f73 100644 --- a/communicator.py +++ b/communicator.py @@ -20,19 +20,17 @@ class Communicator: """ def __init__(self, currentconsumer: str, uuid: str): - """ - Initialize object - :param consumerlocator: - :param uuid: + """Initialize object + :param consumerlocator: the current consumer's IP address as a string + :param uuid: string typed UUID. """ self.currenctconsumer=currentconsumer self.uuid = uuid def sendmessage(self, message: str) -> None: - """ - Send message to consumer. - :param message: - :return: none + """Send message to the current consumer. Logs the process. + :param message: the message of type string that will be sent. + :return: None """ currentconsumer=self.currenctconsumer LOGGER.info(f"Sending message to {currentconsumer}") @@ -40,9 +38,8 @@ class Communicator: LOGGER.debug(f"Message status code is:{postresponse.status_code}") def discoveravailableconsumers(self) -> list: - """ - Get the list of available consumer from the current primary consumer. - :return: + """Get the list of available consumer from the current primary consumer. Logs the received list. + :return: list of consumers' IP addresses """ try: currentconsumer = self.currenctconsumer @@ -55,9 +52,8 @@ class Communicator: return [] def isconsumeravailable(self) -> bool: - """ - Readiness probe primary consumer. - :return: + """Readiness probe current consumer. Logs the result. + :return: True if available, False otherwise """ currentconsumer = self.currenctconsumer try: @@ -70,10 +66,9 @@ class Communicator: return isavailable def checkconsumer(self, consumer: str) -> bool: - """ - Readiness probe of a prticular consumer. - :param consumer: - :return: + """Readiness probe of a particular consumer. Logs the result. + :param consumer: the consumer's IP address + :return: True if available, False otherwise """ try: response = requests.get(f'http://{consumer}/consumers') @@ -84,10 +79,9 @@ class Communicator: LOGGER.info(f"Consumer {consumer} availability: {isavailable}") return isavailable - def set_currentconsumer(self,currenctconsumer): - """ - Set current consumer - :param currenctconsumer: - :return: + def set_currentconsumer(self,currenctconsumer) -> None: + """Set current consumer + :param currenctconsumer: the consumer's IP address + :return: None """ self.currenctconsumer=currenctconsumer diff --git a/consumerlocator.py b/consumerlocator.py index 83988b4..b005c7f 100644 --- a/consumerlocator.py +++ b/consumerlocator.py @@ -18,20 +18,25 @@ KNOWNCONSUMER = os.getenv("PRODUCER_KNOWNCONSUMER",'10.69.42.1') class ConsumerLocator: """ - Manages the list of consumers. + Component responsible for managing the list of consumers. Requires an instance of :class:'communicator.Communicator' """ def __init__(self, uuid: str, communicator: Communicator): - """ - Initialize class. + """Initializes the object. + Gets the known consumer's IP address from the PRODUCER_KNOWNCONSUMER envar. + :param: uuid: Not used + :param: communicator: the :class:'communicator.Communicator' instance that will be used for the low level + communication. """ self.consumerlist = [{"Host": KNOWNCONSUMER, "State": True, "LastOk": datetime.datetime.now()}] self.currentconsumer = self.consumerlist[0] self.communicator = communicator def learnconsumerlist(self) -> None: - """" - Learns the list of consumers. + """"Learns the list of consumers from the current consumer. + Calls :func:'~communicator.Communicator.didiscoveravailableconsumers', adds the learned consumers to the list + if are not present, and then calls :func:'~consumerlocator.ConsumerLocator.updateconsumerlist' + :return: None """ recievedconsumerlist = self.communicator.discoveravailableconsumers() if recievedconsumerlist is None: @@ -48,8 +53,10 @@ class ConsumerLocator: self.updateconsumerlist() def updateconsumerlist(self) -> None: - """ - Updates the consumer list based on their availability. + """ Updates the consumer list based on their availability. + Marks for each consumer if they are available or not. If a consumer is not available for some time (1 hour), + the it will be deleted from the list. + :return: None """ removelist = [] for consumer in self.consumerlist: @@ -64,8 +71,10 @@ class ConsumerLocator: self.consumerlist.remove(rem) def updateconsumer(self): - """ - If the current consumer is not available, checks all the consumers in the list and updates the current one. + """If the current consumer is not available, checks all the consumers in the list and updates the current one. + Calls :func:'~consumerlocator.ConsumerLocator.checkcurrentconsumer' and if needed + :func:'~consumerlocator.ConsumerLocator.updateconsumerlist'. Sets the :class:'communicator.Communicator' + current instance with :func:'~communicator.Communicator.set_currentconsumer'. :return: the current consumer or None if there are no available customers at the moment. """ @@ -90,14 +99,14 @@ class ConsumerLocator: def getcurrentconsumer(self) -> str: """ - Returns the currently selected consumer. + Returns the currently selected consumer's IP address. :return: the current consumer """ return self.currentconsumer["Host"] def checkcurrentconsumer(self) -> bool: """ - Check the consumers health. + Check the current consumer's health. :return: True if OK, False if fail """ if self.currentconsumer is None: diff --git a/messagesender.py b/messagesender.py index 27992ae..881cde3 100644 --- a/messagesender.py +++ b/messagesender.py @@ -19,25 +19,31 @@ LOGGER = logging.getLogger(__name__) class MessageSender: """ - Üzenetek küldéséért felelős komponens. + Component responsible for sending the messages. Requires an instance of :class:'communicator.Communicator' """ def __init__(self, communicator: Communicator): - """ - Inicializálja az osztályt. + """Initializes the object. + :param: communicator: an instance of :class:'communicator.Communicator' """ self.communicator = communicator def randomstring(self, stringlength: int) -> str: - """Generate a random string of fixed length """ + """ + Generate a random string of fixed length + :param stringlength: the length of the string + :return: the generated string + """ letters = string.ascii_lowercase return ''.join(random.choice(letters) for i in range(stringlength)) def sendmessage(self, message: str = "") -> None: - """ - Uzenet letrehozasa - :param message: - :return: str tipus + """Sends the given message. + If the message is omitted (empty), then a random message will be generated with length 23 (with + :func:'~messagesender.MessageSender.randomstring'. Calls :func:'~communicator.Communicator.sendmessage' + to send the message. + :param message: the message of type string that will be sent + :return: None """ if not message: data = self.randomstring(32) diff --git a/test.py b/test.py index 8e053af..f20cd6d 100644 --- a/test.py +++ b/test.py @@ -18,6 +18,10 @@ generateduuid = 'c959ad81-58f9-4445-aab4-8f3d68aee1ad' def test_generate_string(mocker): + """ + Tests :func:'~messagesender.MessageSender.randomstring'. + :param: mocker: + """ mocker.patch('communicator.Communicator') comm = communicator.Communicator( currentconsumer="localhost", @@ -29,6 +33,11 @@ def test_generate_string(mocker): def test_sendmessage(httpserver): + """ + Tests :func:'~communicator.Communicator.sendmessage'. + :param httpserver: simple HTTP server + :return: None + """ httpserver.expect_oneshot_request( uri="/log", method='POST', @@ -46,6 +55,11 @@ def test_sendmessage(httpserver): def test_send_message(mocker): + """ + Tests :func:'~messagesender.MessageSender.sendmessage'. + :param mocker: + :return: None + """ mocker.patch('communicator.Communicator') comm = communicator.Communicator( currentconsumer="127.0.0.1", @@ -57,6 +71,11 @@ def test_send_message(mocker): def test_discoveravailableconsumers(httpserver): + """ + Tests :func:'~communicator.Communicator.discoveravailableconsumers' + :param httpserver: simple HTTP server + :return: None + """ httpserver.expect_oneshot_request( uri="/consumers", method='GET', @@ -73,6 +92,11 @@ def test_discoveravailableconsumers(httpserver): def test_isconsumeravailable(httpserver): + """ + Tests :func:'~communicator.Communicator.isconsumeravailable' + :param httpserver: simple HTTP server + :return: None + """ httpserver.expect_oneshot_request( uri="/consumers", method='GET', @@ -101,6 +125,11 @@ def test_isconsumeravailable(httpserver): def test_checkconsumer(httpserver): + """ + Tests :func:'~communicator.Communicator.checkconsumer' + :param httpserver: simple HTTP server + :return: None + """ httpserver.expect_oneshot_request( uri="/consumers", method='GET', @@ -129,6 +158,10 @@ def test_checkconsumer(httpserver): def test_setcurrentconsumer(): + """ + Tests :func:'~communicator.Communicator.set_currentconsumer' + :return: None + """ comm = communicator.Communicator( currentconsumer="127.0.0.1", uuid=generateduuid) @@ -137,6 +170,11 @@ def test_setcurrentconsumer(): def test_learnconsumerlist(httpserver): + """ + Tests :func:'~consumerlocator.ConsumerLocator.learnconsumerlist' + :param httpserver: simple HTTP server + :return: None + """ httpserver.expect_request( uri="/consumers", method='GET', @@ -155,6 +193,11 @@ def test_learnconsumerlist(httpserver): def test_getcurrentconsumer(mocker): + """ + Tests :func:'~consumerlocator.ConsumerLocator.getcurrentconsumer' + :param mocker: + :return: None + """ mocker.patch('communicator.Communicator') comm = communicator.Communicator( currentconsumer="127.0.0.1", @@ -165,6 +208,11 @@ def test_getcurrentconsumer(mocker): def test_checkcurrentconsumer(httpserver): + """ + Tests :func:'~consumerlocator.ConsumerLocator.checkcurrentconsumer' + :param httpserver: simple HTTP server + :return: None + """ httpserver.expect_oneshot_request( uri="/consumers", method='GET', @@ -183,6 +231,11 @@ def test_checkcurrentconsumer(httpserver): def test_updateconsumer(httpserver): + """ + Tests :func:'~consumerlocator.ConsumerLocator.updateconsumer' + :param httpserver: simple HTTP server + :return: None + """ httpserver.expect_oneshot_request( uri="/consumers", method='GET', @@ -202,6 +255,11 @@ def test_updateconsumer(httpserver): def test_updateconsumerlist(httpserver): + """ + Tests :func:'~consumerlocator.ConsumerLocator.updateconsumerlist' + :param httpserver: simple HTTP server + :return: None + """ httpserver.expect_oneshot_request( uri="/consumers", method='GET',