SIENTIAPDE-1049

Update ingestor and data manager for improved shutdown handling and logging

- Incremented project version in quality gate configuration.
- Commented out ingestor service in docker-compose for clarity.
- Enhanced main loop in app.py to handle exit signals and exceptions.
- Added shutdown methods in Ingestor and DataManager classes for graceful resource cleanup.
- Updated unit tests to validate shutdown behavior and exception handling.
- Introduced coverage configuration to omit specific files.
This commit is contained in:
2025-05-20 17:19:41 -03:00
parent 92ed3c9cb2
commit c7dbe3585b
13 changed files with 235 additions and 163 deletions

View File

@@ -1,5 +1,7 @@
from logging import Formatter, StreamHandler, getLogger
from os import getenv
from copy import deepcopy
from typing import Dict, Any
from sientia_do.notifications.handlers import NotificationHandler
@@ -11,7 +13,8 @@ class Ingestor:
"""
Initializes the ingestor with configuration values retrieved from environment variables.
Environment Variables:
KAFKA_SERVERS (str): Comma-separated list of Kafka server addresses. Defaults to "localhost:9092".
KAFKA_SERVERS (str): Comma-separated list of Kafka server addresses.
Defaults to "localhost:9092".
REDIS_HOST (str): Hostname of the Redis server. Defaults to "localhost".
REDIS_PORT (int): Port number of the Redis server. Defaults to 6379.
LEASE_TTL (int): Time-to-live for leases in seconds. Defaults to 10.
@@ -53,6 +56,13 @@ class Ingestor:
self.ingestor_manager = None
def shutdown(self):
if self.ingestor_manager:
self.ingestor_manager.shutdown()
def __del__(self):
self.shutdown()
def init_logger(self):
"""
Initializes a logger instance for the class.
@@ -147,9 +157,7 @@ class Ingestor:
# This ingestor is active and has no slots, so we need to try to
# Get slot lease
acquired = self.ingestor_manager.get_slot_leases(1)
self.handle_acquired_tags(acquired)
self.ingestor_manager.get_slot_leases(1)
def manage_leases(self, available_slots: int, lacking_ingestors: int, slot_diff: int):
"""
@@ -174,9 +182,7 @@ class Ingestor:
self.logger.info("Slots available: %s", available_slots)
# Get slot lease
acquired = self.ingestor_manager.get_slot_leases(available_slots)
self.handle_acquired_tags(acquired)
self.ingestor_manager.get_slot_leases(available_slots)
elif lacking_ingestors == 0 and slot_diff > 0:
@@ -188,6 +194,36 @@ class Ingestor:
self.ingestor_manager.drop_slot_leases(overleases)
def update_ingestor_manager(self, old_managed_tags: Dict[str, Any]):
"""
Updates the ingestor manager with the new managed tags.
Args:
old_managed_tags (Dict[str, Any]): The old managed tags.
"""
self.logger.debug("Current managed tags: %s",
self.ingestor_manager.managed_tags)
self.ingestor_manager.update_opc_servers()
new_managed_tags = deepcopy(self.ingestor_manager.managed_tags)
self.logger.debug("Comparing new managed tags %s"
"with old managed tags %s",
new_managed_tags, old_managed_tags)
for slot, config in new_managed_tags.items():
if slot not in old_managed_tags:
self.ingestor_manager.subscribe_to_tags({slot: config})
continue
if config != old_managed_tags[slot]:
self.ingestor_manager.unsubscribe_slot(slot)
self.ingestor_manager.subscribe_to_tags({slot: config})
for slot in old_managed_tags.keys():
if slot not in new_managed_tags:
self.ingestor_manager.unsubscribe_slot(slot)
def loop(self):
"""
Executes the main loop for managing ingestors and slots.
@@ -212,6 +248,8 @@ class Ingestor:
self.logger.info("Polling for slot updates...")
# Get active ingestors
current_managed_tags = deepcopy(self.ingestor_manager.managed_tags)
ingestors = self.ingestor_manager.get_active_ingestors()
number_of_ingestors = len(ingestors)
number_of_leases = self.ingestor_manager.get_number_of_leases()
@@ -251,3 +289,8 @@ class Ingestor:
# Check OPC cycles
self.logger.debug("Checking OPC servers integrity...")
self.ingestor_manager.check_opc_servers_integrity()
self.logger.debug("Updating managed tags...")
self.update_ingestor_manager(
current_managed_tags
)