Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion lambdas/delta_backend/src/delta.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,6 @@ def handler(event, _context):
"diagnostics": "Delta Lambda failure: Incorrect invocation of Lambda",
}
logger.exception(operation_outcome["diagnostics"])
send_message(event) # Send failed records to DLQ
log_data = {"function_name": "delta_sync", "operation_outcome": operation_outcome}
send_log_to_firehose(STREAM_NAME, log_data)

Expand Down
21 changes: 20 additions & 1 deletion lambdas/delta_backend/tests/test_delta.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import json
import os
import unittest
from unittest.mock import MagicMock, patch
from unittest.mock import MagicMock, call, patch

from botocore.exceptions import ClientError

Expand Down Expand Up @@ -114,6 +114,25 @@ def test_handler_success_insert(self):
self.assertEqual(put_item_data["SupplierSystem"], supplier)
self.mock_sqs_client.send_message.assert_not_called()

def test_handler_exception(self):
"""Ensure that sqs_client exceptions do not cause the lambda handler itself to raise an exception"""

# Arrange
self.mock_sqs_client.send_message.side_effect = Exception("SQS error")
event = {"invalid_format": True}

# Act
result = handler(event, None)

# Assert
self.assertFalse(result)
self.mock_logger_exception.assert_has_calls(
[
call("Delta Lambda failure: Incorrect invocation of Lambda"),
call("Error sending record to DLQ"),
]
)

def test_handler_overall_failure(self):
# Arrange
event = {"invalid_format": True}
Expand Down
56 changes: 42 additions & 14 deletions lambdas/recordforwarder/tests/test_forwarding_batch_lambda.py
Original file line number Diff line number Diff line change
Expand Up @@ -863,20 +863,48 @@ def test_forward_request_to_dynamo(
expected_values = test_case[0]["expected_values"]
assert expected_values.items() <= call_data.items()

def clear_test_tables(self):
"""Clear DynamoDB table after each test."""
scan = self.table.scan()
items = scan.get("Items", [])
while items:
for item in items:
self.table.delete_item(Key={"PK": item["PK"]})
scan = self.table.scan()
items = scan.get("Items", [])

def teardown(self):
"""Deletes mock dynamodb resource"""
self.table.delete()
self.dynamodb_resource = None
@patch("forwarding_batch_lambda.sqs_client.send_message")
def test_forward_lambda_handler_exception_handler(self, mock_send_message):
"""Test exception handling when sqs_client fails"""
# Arrange
# Ensure there is at least one failure, so that sqs_client is called
test_cases = [
{
"name": "Row 1: Duplication Error: Create failure ",
"input": self.generate_input(row_id=1, operation_requested="CREATE", include_fhir_json=True),
"expected_keys": ForwarderValues.EXPECTED_KEYS_DIAGNOSTICS,
"expected_values": {
"row_id": "row-1",
"diagnostics": create_diagnostics_dictionary(
IdentifierDuplicationError("https://www.ravs.england.nhs.uk/#RSV_002")
),
},
"is_failure": True,
},
]

self.table.put_item(
Item={
"PK": "Immunization#4d2ac1eb-080f-4e54-9598-f2d53334681c",
"PatientPK": "Patient#9732928395",
"PatientSK": "RSV#4d2ac1eb-080f-4e54-9598-f2d53334681c",
"IdentifierPK": "https://www.ravs.england.nhs.uk/#RSV_002",
"Version": 1,
}
)

mock_send_message.side_effect = Exception("Unknown Exception in SQS client")

event = self.generate_event(test_cases)

self.mock_redis.hget.return_value = "RSV"
self.mock_redis_getter.return_value = self.mock_redis

# Act & Assert
with self.assertRaises(Exception) as context:
forward_lambda_handler(event, {})

self.assertEqual("Unknown Exception in SQS client", str(context.exception))


if __name__ == "__main__":
Expand Down