Skip to content

Commit f13b423

Browse files
committed
check logs to pinpoint pds bad request
1 parent 22fb4ed commit f13b423

5 files changed

Lines changed: 109 additions & 19 deletions

File tree

lambdas/mns_publisher/src/process_records.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ def process_records(records: list[SQSMessage]) -> dict[str, list]:
2727
except Exception:
2828
message_id = record.get("messageId", "unknown")
2929
batch_item_failures.append({"itemIdentifier": message_id})
30-
logger.error(Exception)
30+
logger.exception("Failed to process record", trace_id={"message_id": message_id})
3131

3232
if batch_item_failures:
3333
logger.warning(f"Batch completed with {len(batch_item_failures)} failures")
@@ -62,7 +62,6 @@ def process_record(record: SQSMessage, mns_service: MnsService) -> dict | None:
6262
},
6363
)
6464

65-
# Publish to MNS
6665
mns_service.publish_notification(mns_notification_payload)
6766
logger.info("Successfully created MNS notification", trace_ids={"mns_notification_id": notification_id})
6867

lambdas/mns_publisher/src/sqs_dynamo_utils.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import json
22
from typing import Any
33

4+
from common.clients import logger
45
from constants import DYNAMO_DB_TYPE_DESCRIPTORS, ImmsData
56

67

@@ -18,6 +19,7 @@ def extract_sqs_imms_data(sqs_record: dict) -> ImmsData:
1819
supplier_system = _unwrap_dynamodb_value(new_image.get("SupplierSystem", {}))
1920
vaccine_type = _unwrap_dynamodb_value(new_image.get("VaccineType", {}))
2021
operation = _unwrap_dynamodb_value(new_image.get("Operation", {}))
22+
logger.info("Top Level Fields retrieved successfully")
2123

2224
imms_map = new_image.get("Imms", {}).get("M", {})
2325

lambdas/mns_publisher/tests/test_create_notification.py

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import copy
22
import json
33
import unittest
4-
from pathlib import Path
54
from unittest.mock import MagicMock, patch
65

76
from constants import IMMUNISATION_TYPE, SPEC_VERSION
@@ -10,21 +9,7 @@
109
create_mns_notification,
1110
get_practitioner_details_from_pds,
1211
)
13-
14-
15-
def _load_sample_sqs_event() -> dict:
16-
"""
17-
Loads the sample SQS event and normalises body to a JSON string (as SQS delivers it).
18-
Expects: lambdas/mns_publisher/tests/sqs_event.json
19-
"""
20-
sample_event_path = Path(__file__).parent / "sqs_event.json"
21-
with open(sample_event_path, "r") as f:
22-
raw_event = json.load(f)
23-
24-
if isinstance(raw_event.get("body"), dict):
25-
raw_event["body"] = json.dumps(raw_event["body"])
26-
27-
return raw_event
12+
from test_utils import load_sample_sqs_event
2813

2914

3015
class TestCalculateAgeAtVaccination(unittest.TestCase):
@@ -78,7 +63,7 @@ class TestCreateMnsNotification(unittest.TestCase):
7863

7964
@classmethod
8065
def setUpClass(cls):
81-
cls.sample_sqs_event = _load_sample_sqs_event()
66+
cls.sample_sqs_event = load_sample_sqs_event()
8267

8368
def setUp(self):
8469
self.expected_gp_ods_code = "Y12345"
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import json
2+
import unittest
3+
4+
from sqs_dynamo_utils import _unwrap_dynamodb_value, extract_sqs_imms_data
5+
from test_utils import load_sample_sqs_event
6+
7+
8+
class TestExtractSqsImmsData(unittest.TestCase):
9+
"""
10+
Test SQS Event extraction utility
11+
"""
12+
13+
@classmethod
14+
def setUpClass(cls):
15+
cls.sample_sqs_event = load_sample_sqs_event()
16+
17+
def test_extract_sqs_imms_data(self):
18+
result = extract_sqs_imms_data(self.sample_sqs_event)
19+
20+
self.assertEqual(result["imms_id"], "d058014c-b0fd-4471-8db9-3316175eb825")
21+
self.assertEqual(result["supplier_system"], "TPP")
22+
self.assertEqual(result["vaccine_type"], "hib")
23+
self.assertEqual(result["operation"], "CREATE")
24+
self.assertEqual(result["nhs_number"], "9481152782")
25+
self.assertEqual(result["person_dob"], "20040609")
26+
self.assertEqual(result["date_and_time"], "20260212T17443700")
27+
self.assertEqual(result["site_code"], "B0C4P")
28+
29+
def test_extract_imms_data_field_types(self):
30+
"""Test that extracted fields are the correct types."""
31+
result = extract_sqs_imms_data(self.sample_sqs_event)
32+
33+
self.assertIsInstance(result["imms_id"], str)
34+
self.assertIsInstance(result["supplier_system"], str)
35+
self.assertIsInstance(result["vaccine_type"], str)
36+
self.assertIsInstance(result["operation"], str)
37+
self.assertIsInstance(result["nhs_number"], str)
38+
self.assertIsInstance(result["person_dob"], str)
39+
self.assertIsInstance(result["date_and_time"], str)
40+
self.assertIsInstance(result["site_code"], str)
41+
42+
def test_extract_imms_data_invalid_json_body(self):
43+
"""Test extraction when body is invalid JSON."""
44+
event = {"body": "invalid json {"}
45+
46+
with self.assertRaises(json.JSONDecodeError):
47+
extract_sqs_imms_data(event)
48+
49+
50+
class TestUnwrapDynamodbValue(unittest.TestCase):
51+
"""Tests for _unwrap_dynamodb_value helper function."""
52+
53+
def test_unwrap_string_type(self):
54+
"""Test unwrapping DynamoDB String type."""
55+
value = {"S": "test-value"}
56+
result = _unwrap_dynamodb_value(value)
57+
self.assertEqual(result, "test-value")
58+
59+
def test_unwrap_number_type(self):
60+
"""Test unwrapping DynamoDB Number type."""
61+
value = {"N": "123"}
62+
result = _unwrap_dynamodb_value(value)
63+
self.assertEqual(result, "123")
64+
65+
def test_unwrap_boolean_type(self):
66+
"""Test unwrapping DynamoDB Boolean type."""
67+
value = {"BOOL": True}
68+
result = _unwrap_dynamodb_value(value)
69+
self.assertTrue(result)
70+
71+
def test_unwrap_null_type(self):
72+
"""Test unwrapping DynamoDB NULL type."""
73+
value = {"NULL": True}
74+
result = _unwrap_dynamodb_value(value)
75+
self.assertIsNone(result)
76+
77+
def test_unwrap_map_type(self):
78+
"""Test unwrapping DynamoDB Map type."""
79+
value = {"M": {"key": {"S": "value"}}}
80+
result = _unwrap_dynamodb_value(value)
81+
self.assertEqual(result, {"key": {"S": "value"}})
82+
83+
def test_unwrap_list_type(self):
84+
"""Test unwrapping DynamoDB List type."""
85+
value = {"L": [{"S": "item1"}, {"S": "item2"}]}
86+
result = _unwrap_dynamodb_value(value)
87+
self.assertEqual(result, [{"S": "item1"}, {"S": "item2"}])
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import json
2+
from pathlib import Path
3+
4+
5+
def load_sample_sqs_event() -> dict:
6+
"""
7+
Loads the sample SQS event and normalises body to a JSON string (as SQS delivers it).
8+
Expects: lambdas/mns_publisher/tests/sqs_event.json
9+
"""
10+
sample_event_path = Path(__file__).parent / "sqs_event.json"
11+
with open(sample_event_path, "r") as f:
12+
raw_event = json.load(f)
13+
14+
if isinstance(raw_event.get("body"), dict):
15+
raw_event["body"] = json.dumps(raw_event["body"])
16+
17+
return raw_event

0 commit comments

Comments
 (0)