SIENTIAPDE-1110
Refactor notification handling in Gates and OPC activities to use send_notification method with metadata integration, enhancing error reporting and traceability.
This commit is contained in:
@@ -14,7 +14,7 @@ def mock_logger():
|
||||
@fixture
|
||||
def opc_repository(mock_logger):
|
||||
return OpcRepository(
|
||||
name="test_repo",
|
||||
id="test_repo",
|
||||
url="opc.tcp://localhost:4840",
|
||||
logger=mock_logger,
|
||||
notification_handler=Mock(),
|
||||
@@ -34,8 +34,18 @@ def mock_client():
|
||||
yield client_instance
|
||||
|
||||
|
||||
metadata = {
|
||||
"metadata": {
|
||||
"model_id": "test_model",
|
||||
"model_name": "test_model",
|
||||
"workflow_name": "test_workflow",
|
||||
"schema_name": "test_schedule",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def test_init(opc_repository):
|
||||
assert opc_repository.name == "test_repo"
|
||||
assert opc_repository.id == "test_repo"
|
||||
assert opc_repository.url == "opc.tcp://localhost:4840"
|
||||
assert opc_repository.server_uri == "urn:test:server"
|
||||
assert opc_repository.cert_path == "/path/to/cert.pem"
|
||||
@@ -110,7 +120,7 @@ def test_try_connect_fail(opc_repository):
|
||||
opc_repository.client.connect.assert_called_once()
|
||||
assert opc_repository.last_reconnection_time is not None
|
||||
opc_repository.notification_handler.build_and_send_notification.assert_called_once_with(
|
||||
notification_id=f"OPC_CONNECTION_ERROR_{opc_repository.name}",
|
||||
notification_id=f"OPC_CONNECTION_ERROR_{opc_repository.id}",
|
||||
message="Failed to connect to OPC server: Test error",
|
||||
block="opc_repository",
|
||||
level=NotificationLevel.ERROR,
|
||||
@@ -126,6 +136,17 @@ def test_disconnect(opc_repository, mock_client):
|
||||
assert opc_repository.client is None
|
||||
|
||||
|
||||
def test_disconnect_error(opc_repository, mock_client):
|
||||
opc_repository.client = mock_client
|
||||
mock_client.disconnect.side_effect = Exception("Test error")
|
||||
opc_repository.disconnect()
|
||||
|
||||
opc_repository.logger.error.assert_called_once_with(
|
||||
"Failed to disconnect from OPC server: Test error"
|
||||
)
|
||||
assert opc_repository.client is None
|
||||
|
||||
|
||||
def test_validate_connection_none_client(opc_repository):
|
||||
opc_repository.client = None
|
||||
opc_repository.connect = MagicMock()
|
||||
@@ -174,11 +195,11 @@ def test_validate_connection_lost_time_to_reconect(_mock_datetime, opc_repositor
|
||||
opc_repository.client = MagicMock()
|
||||
opc_repository.client.aio_obj.uaclient.protocol = None
|
||||
opc_repository.last_reconnection_time = datetime(2025, 1, 1, 0, 0, 0)
|
||||
opc_repository.try_connect = MagicMock()
|
||||
opc_repository.connect = MagicMock()
|
||||
|
||||
response = opc_repository.validate_connection()
|
||||
opc_repository.try_connect.assert_called_once()
|
||||
assert response == opc_repository.try_connect.return_value
|
||||
opc_repository.connect.assert_called_once()
|
||||
assert response == opc_repository.connect.return_value
|
||||
|
||||
|
||||
def test_validate_connection_failed(opc_repository):
|
||||
@@ -192,7 +213,8 @@ def test_validate_connection_failed(opc_repository):
|
||||
def test_write_data_validate_connection_do_nothing(opc_repository):
|
||||
opc_repository.validate_connection = MagicMock(return_value=True)
|
||||
opc_repository.client = MagicMock()
|
||||
opc_repository.write_data("ns=2;s=TestNode", 42.0, "float")
|
||||
opc_repository.write_data("ns=2;s=TestNode", 42.0,
|
||||
"float", opc_repository.logger, metadata)
|
||||
opc_repository.validate_connection.assert_called_once()
|
||||
opc_repository.client.get_node.assert_called_once_with("ns=2;s=TestNode")
|
||||
|
||||
@@ -201,7 +223,8 @@ def test_write_data_validate_connection_failed(opc_repository):
|
||||
opc_repository.validate_connection = MagicMock(return_value=False)
|
||||
opc_repository.client = MagicMock()
|
||||
opc_repository.error_count = 0
|
||||
opc_repository.write_data("ns=2;s=TestNode", 42.0, "float")
|
||||
opc_repository.write_data("ns=2;s=TestNode", 42.0,
|
||||
"float", opc_repository.logger, metadata)
|
||||
opc_repository.validate_connection.assert_called_once()
|
||||
opc_repository.client.get_node.assert_not_called()
|
||||
|
||||
@@ -211,12 +234,13 @@ def test_write_data_get_node_failed(opc_repository):
|
||||
opc_repository.client = MagicMock()
|
||||
opc_repository.error_count = 0
|
||||
opc_repository.client.get_node.side_effect = Exception("Test error")
|
||||
opc_repository.write_data("ns=2;s=TestNode", 42.0, "float")
|
||||
opc_repository.write_data("ns=2;s=TestNode", 42.0,
|
||||
"float", opc_repository.logger, metadata)
|
||||
opc_repository.validate_connection.assert_called_once()
|
||||
opc_repository.client.get_node.assert_called_once_with("ns=2;s=TestNode")
|
||||
opc_repository.notification_handler.build_and_send_notification.assert_called_once_with(
|
||||
notification_id=f"OPC_WRITE_GET_NODE_ERROR_{opc_repository.name}",
|
||||
message="Failed to get node from OPC server: Test error",
|
||||
notification_id=f"OPC_WRITE_GET_NODE_ERROR_{opc_repository.id}",
|
||||
message="Failed to get node from OPC server: Test error | metadata: {'metadata': {'model_id': 'test_model', 'model_name': 'test_model', 'workflow_name': 'test_workflow', 'schema_name': 'test_schedule'}}",
|
||||
block="opc_repository",
|
||||
level=NotificationLevel.ERROR,
|
||||
attachment_content=ANY
|
||||
@@ -230,13 +254,14 @@ def test_write_data_invalid_data_type(opc_repository, mock_client):
|
||||
mock_node = MagicMock()
|
||||
mock_client.get_node.return_value = mock_node
|
||||
|
||||
opc_repository.write_data("ns=2;s=TestNode", 42.0, "invalid_type")
|
||||
opc_repository.write_data("ns=2;s=TestNode", 42.0,
|
||||
"invalid_type", opc_repository.logger, metadata)
|
||||
opc_repository.validate_connection.assert_called_once()
|
||||
mock_client.get_node.assert_called_once_with("ns=2;s=TestNode")
|
||||
|
||||
opc_repository.notification_handler.build_and_send_notification.assert_called_once_with(
|
||||
notification_id=f"OPC_WRITE_DATA_TYPE_ERROR_{opc_repository.name}",
|
||||
message="Unsupported data type: invalid_type",
|
||||
notification_id=f"OPC_WRITE_DATA_TYPE_ERROR_{opc_repository.id}",
|
||||
message="Unsupported data type: invalid_type | metadata: {'metadata': {'model_id': 'test_model', 'model_name': 'test_model', 'workflow_name': 'test_workflow', 'schema_name': 'test_schedule'}}",
|
||||
block="opc_repository",
|
||||
level=NotificationLevel.ERROR
|
||||
)
|
||||
@@ -248,12 +273,11 @@ def test_write_data(opc_repository, mock_client):
|
||||
mock_node = MagicMock()
|
||||
mock_client.get_node.return_value = mock_node
|
||||
|
||||
opc_repository.write_data("ns=2;s=TestNode", 42.0, "float")
|
||||
opc_repository.write_data("ns=2;s=TestNode", 42.0,
|
||||
"float", opc_repository.logger, metadata)
|
||||
|
||||
mock_client.get_node.assert_called_once_with("ns=2;s=TestNode")
|
||||
mock_node.write_value.assert_called_once()
|
||||
opc_repository.logger.info.assert_called_once_with(
|
||||
"Writing 42.0 - <class 'float'> to " + str(mock_node))
|
||||
|
||||
|
||||
def test_write_data_write_value_failed(opc_repository, mock_client):
|
||||
@@ -263,13 +287,14 @@ def test_write_data_write_value_failed(opc_repository, mock_client):
|
||||
opc_repository.error_count = 0
|
||||
mock_client.get_node.return_value = mock_node
|
||||
mock_node.write_value.side_effect = Exception("Test error")
|
||||
opc_repository.write_data("ns=2;s=TestNode", 42.0, "float")
|
||||
opc_repository.write_data("ns=2;s=TestNode", 42.0,
|
||||
"float", opc_repository.logger, metadata)
|
||||
opc_repository.validate_connection.assert_called_once()
|
||||
mock_client.get_node.assert_called_once_with("ns=2;s=TestNode")
|
||||
mock_node.write_value.assert_called_once()
|
||||
opc_repository.notification_handler.build_and_send_notification.assert_called_once_with(
|
||||
notification_id=f"OPC_WRITE_DATA_ERROR_{opc_repository.name}",
|
||||
message="Failed to write data to OPC server: Test error",
|
||||
notification_id=f"OPC_WRITE_DATA_ERROR_{opc_repository.id}",
|
||||
message="Failed to write data to OPC server: Test error | metadata: {'metadata': {'model_id': 'test_model', 'model_name': 'test_model', 'workflow_name': 'test_workflow', 'schema_name': 'test_schedule'}}",
|
||||
block="opc_repository",
|
||||
level=NotificationLevel.ERROR,
|
||||
attachment_content=ANY
|
||||
|
||||
@@ -54,7 +54,7 @@ def test_build_opc_config_with_env_vars():
|
||||
def test_build_opc_config_with_individual_env_vars():
|
||||
# Arrange
|
||||
environ.pop('OPC_CONFIG', None)
|
||||
environ['OPC_NAME'] = 'test-name'
|
||||
environ['OPC_ID'] = '1'
|
||||
environ['OPC_URL'] = 'opc.tcp://test:4840'
|
||||
environ['OPC_SERVER_URI'] = 'opc.tcp://test:4840'
|
||||
environ['OPC_RECONNECTION_INTERVAL'] = '300'
|
||||
@@ -63,16 +63,16 @@ def test_build_opc_config_with_individual_env_vars():
|
||||
config = build_opc_config()
|
||||
|
||||
# Assert
|
||||
assert config['opc']['name'] == 'test-name'
|
||||
assert config['opc']['url'] == 'opc.tcp://test:4840'
|
||||
assert config['opc']['server_uri'] == 'opc.tcp://test:4840'
|
||||
assert config['opc']['reconnection_interval'] == 300
|
||||
assert config['1']['id'] == '1'
|
||||
assert config['1']['url'] == 'opc.tcp://test:4840'
|
||||
assert config['1']['server_uri'] == 'opc.tcp://test:4840'
|
||||
assert config['1']['reconnection_interval'] == 300
|
||||
|
||||
|
||||
def test_build_opc_config_with_defaults():
|
||||
# Arrange
|
||||
environ.pop('OPC_CONFIG', None)
|
||||
environ.pop('OPC_NAME', None)
|
||||
environ.pop('OPC_ID', None)
|
||||
environ.pop('OPC_URL', None)
|
||||
environ.pop('OPC_SERVER_URI', None)
|
||||
environ.pop('OPC_RECONNECTION_INTERVAL', None)
|
||||
@@ -81,10 +81,10 @@ def test_build_opc_config_with_defaults():
|
||||
config = build_opc_config()
|
||||
|
||||
# Assert
|
||||
assert config['opc']['name'] == 'opc'
|
||||
assert config['opc']['url'] == 'opc.tcp://localhost:4840'
|
||||
assert config['opc']['server_uri'] == 'opc.tcp://localhost:4840'
|
||||
assert config['opc']['reconnection_interval'] == 120
|
||||
assert config['1']['id'] == '1'
|
||||
assert config['1']['url'] == 'opc.tcp://localhost:4840'
|
||||
assert config['1']['server_uri'] == 'opc.tcp://localhost:4840'
|
||||
assert config['1']['reconnection_interval'] == 120
|
||||
|
||||
|
||||
def test_build_postgres_config_with_env_vars():
|
||||
|
||||
Reference in New Issue
Block a user