Refactor OPC server integrity checks to be asynchronous

Updated the Ingestor and IngestorManager classes to use async methods for checking OPC server integrity and shutting down OPC managers. Adjusted related tests to ensure proper mocking of asynchronous behavior.
This commit is contained in:
vitor-aignosi
2025-10-23 11:46:02 -03:00
parent d62a1e3381
commit 6d2a0e46be
5 changed files with 20 additions and 7 deletions

View File

@@ -414,7 +414,7 @@ class Ingestor:
# Check OPC cycles
self.logger.info('Checking OPC servers integrity...')
self.ingestor_manager.check_opc_servers_integrity()
await self.ingestor_manager.check_opc_servers_integrity()
self.logger.info('Updating managed tags...')
await self.update_ingestor_manager(current_managed_tags)

View File

@@ -228,7 +228,7 @@ class IngestorManager(BaseActivity):
elif server_instance.config != server_config:
self.logger.warning(f'Reinitializing OPC manager for server {server}')
server_instance.disconnect()
await server_instance.shutdown()
del self.opc_managers[server]
server_instance = await self.initialize_opc_from_config(server_config)
else:
@@ -254,12 +254,12 @@ class IngestorManager(BaseActivity):
self.logger.warning(
f'Server {server} not found in managed tags. Desconnecting from server.'
)
await self.opc_managers[server].disconnect()
await self.opc_managers[server].shutdown()
self.opc_managers.pop(server, None)
metrics.OPC_MANAGERS_ACTIVE.labels(pod_id=self.pod_id).set(len(self.opc_managers))
def check_opc_servers_integrity(self):
async def check_opc_servers_integrity(self):
"""
Checks the integrity of the OPC servers and updates the OPC servers if necessary.
@@ -282,6 +282,7 @@ class IngestorManager(BaseActivity):
self.logger.warning(f'OPC server {server} is lost. Server will be disconnected.')
for slot, _config in self.managed_tags.items():
await self.managed_tags[slot][server].shutdown()
self.managed_tags[slot].pop(server, None)
metrics.OPC_MANAGERS_ACTIVE.labels(pod_id=self.pod_id).set(len(self.opc_managers))

View File

@@ -107,6 +107,9 @@ class OpcManager(BaseActivity):
f'nodes={self.nodes}, subscriptions={self.subscriptions}'
)
def __del__(self):
asyncio.run(self.shutdown())
async def shutdown(self):
"""
Comprehensive cleanup method for graceful shutdown.

View File

@@ -184,7 +184,7 @@ async def test_update_opc_servers(metrics, opc_manager, ingestor_manager):
'slot2': {'server3': {'config': 'config3'}, 'server1': {'config': 'config1'}},
}
mock = MagicMock(config={'config': 'old_config2'})
mock = AsyncMock(config={'config': 'old_config2'})
ingestor_manager.opc_managers['server3'] = AsyncMock(config={'config': 'config3'})
ingestor_manager.opc_managers['server2'] = mock
ingestor_manager.opc_managers['server4'] = AsyncMock()
@@ -472,8 +472,9 @@ async def test_subscribe_to_tags(ingestor_manager):
ingestor_manager.managed_tags['slot1'].pop.assert_called_once_with('server3', None)
@mark.asyncio
@patch('ingestor.managers.ingestor_manager.metrics')
def test_check_opc_servers_integrity_all_healthy(metrics, ingestor_manager):
async def test_check_opc_servers_integrity_all_healthy(metrics, ingestor_manager):
# Setup mock OPC managers
opc_manager1 = MagicMock()
opc_manager1.check_cycles.return_value = None
@@ -491,7 +492,7 @@ def test_check_opc_servers_integrity_all_healthy(metrics, ingestor_manager):
ingestor_manager.initialize_opc_from_config = MagicMock()
# Call the method
ingestor_manager.check_opc_servers_integrity()
await ingestor_manager.check_opc_servers_integrity()
# Verify that check_cycles and check_opc_listenning were called for each server
opc_manager1.check_cycles.assert_called_once()

View File

@@ -238,6 +238,7 @@ async def test_loop(ingestor_manager_started):
ingestor_manager_started.manage_no_slots = MagicMock()
ingestor_manager_started.manage_leases = AsyncMock()
ingestor_manager_started.update_ingestor_manager = AsyncMock()
ingestor_manager_started.ingestor_manager.check_opc_servers_integrity = AsyncMock()
ingestor_manager_started.ingestor_manager.managed_tags = {
'slot1': 'server1',
'slot2': 'server2',
@@ -262,12 +263,16 @@ async def test_loop(ingestor_manager_started):
ingestor_manager_started.manage_leases.assert_called_once_with(4, 3, 2)
ingestor_manager_started.ingestor_manager.update_slot_config.assert_called_once()
ingestor_manager_started.ingestor_manager.check_opc_servers_integrity.assert_called_once()
ingestor_manager_started.update_ingestor_manager.assert_called_once()
@mark.asyncio
async def test_loop_no_managed(ingestor_manager_started):
ingestor_manager_started.manage_no_slots = MagicMock()
ingestor_manager_started.manage_leases = AsyncMock()
ingestor_manager_started.update_ingestor_manager = AsyncMock()
ingestor_manager_started.ingestor_manager.check_opc_servers_integrity = AsyncMock()
ingestor_manager_started.ingestor_manager.managed_tags = {}
ingestor_manager_started.ingestor_manager.get_active_ingestors = MagicMock(
return_value=['ingestor1', 'ingestor2']
@@ -288,6 +293,9 @@ async def test_loop_no_managed(ingestor_manager_started):
ingestor_manager_started.ingestor_manager.update_slot_config.assert_called_once()
ingestor_manager_started.logger.info.assert_any_call('No slots acquired in this loop')
ingestor_manager_started.ingestor_manager.check_opc_servers_integrity.assert_called_once()
ingestor_manager_started.update_ingestor_manager.assert_called_once()
@mark.asyncio
async def test_loop_no_ingestor_manager(ingestor_manager_started):