Skip to content

Commit

Permalink
Merge pull request #94 from NHSDigital/AMB-2290_upgrade_test_suite_re…
Browse files Browse the repository at this point in the history
…cordforwarder

Amb 2290 upgrade test suite recordforwarder
  • Loading branch information
AlexandraBenson authored Nov 13, 2024
2 parents afca140 + 8a7dc86 commit 7629536
Show file tree
Hide file tree
Showing 14 changed files with 801 additions and 1,023 deletions.
4 changes: 2 additions & 2 deletions recordforwarder/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ test:
python -m unittest

coverage run:
coverage run -m unittest discover
coverage run -m unittest discover

coverage report:
coverage report -m

coverage html:
coverage html
coverage html

.PHONY: build package
1 change: 1 addition & 0 deletions recordforwarder/src/clients.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@
s3_client = boto3_client("s3", region_name=REGION_NAME)
kinesis_client = boto3_client("kinesis", region_name=REGION_NAME)
lambda_client = boto3_client("lambda", region_name=REGION_NAME)
firehose_client = boto3_client("firehose", region_name=REGION_NAME)
26 changes: 7 additions & 19 deletions recordforwarder/src/constants.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,12 @@
"""Constants for recordforwarder"""

IMMS_BATCH_APP_NAME = "Imms-Batch-App"

class Constants:
"""Constants for recordforwarder"""

ack_headers = [
"MESSAGE_HEADER_ID",
"HEADER_RESPONSE_CODE",
"ISSUE_SEVERITY",
"ISSUE_CODE",
"ISSUE_DETAILS_CODE",
"RESPONSE_TYPE",
"RESPONSE_CODE",
"RESPONSE_DISPLAY",
"RECEIVED_TIME",
"MAILBOX_FROM",
"LOCAL_ID",
"IMMS_ID",
"OPERATION_OUTCOME",
"MESSAGE_DELIVERY",
]
class Operations:
"""Class containing the CRUD operation lambdas which can be invoked by the batch process"""

IMMS_BATCH_APP_NAME = "Imms-Batch-App"
CREATE = "CREATE"
UPDATE = "UPDATE"
DELETE = "DELETE"
SEARCH = "SEARCH"
2 changes: 1 addition & 1 deletion recordforwarder/src/forwarding_lambda.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def forward_request_to_lambda(message_body):
"""Forwards the request to the Imms API (where possible) and updates the ack file with the outcome"""
# file_key = message_body.get("file_key")
row_id = message_body.get("row_id")
logger.info("BEGINNIING FORWARDING MESSAGE: ID %s", row_id)
logger.info("BEGINNING FORWARDING MESSAGE: ID %s", row_id)
try:
send_request_to_lambda(message_body)
# update_ack_file(file_key, row_id, successful_api_response=True, diagnostics=None, imms_id=imms_id)
Expand Down
11 changes: 5 additions & 6 deletions recordforwarder/src/get_imms_id_and_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,29 @@
import os
import logging
from errors import IdNotFoundError
from clients import lambda_client
from utils_for_record_forwarder import invoke_lambda
from constants import Constants
from constants import IMMS_BATCH_APP_NAME

logger = logging.getLogger()


def get_imms_id_and_version(fhir_json: dict) -> tuple[str, int]:
"""Send a GET request to Imms API requesting the id and version"""
# Create payload
headers = {"SupplierSystem": Constants.IMMS_BATCH_APP_NAME}
headers = {"SupplierSystem": IMMS_BATCH_APP_NAME}
identifier = fhir_json.get("identifier", [{}])[0]
immunization_identifier = f"{identifier.get('system')}|{identifier.get('value')}"
query_string_parameters = {"_element": "id,meta", "immunization.identifier": immunization_identifier}
payload = {"headers": headers, "body": None, "queryStringParameters": query_string_parameters}
request_payload = {"headers": headers, "body": None, "queryStringParameters": query_string_parameters}

# Invoke lambda
status_code, body, _ = invoke_lambda(lambda_client, os.getenv("SEARCH_LAMBDA_NAME"), payload)
status_code, body, _ = invoke_lambda(os.getenv("SEARCH_LAMBDA_NAME"), request_payload)

# Handle non-200 or empty response
if not (body.get("total") == 1 and status_code == 200):
logger.error("imms_id not found:%s and status_code: %s", body, status_code)
raise IdNotFoundError("Imms id not found")

# Return imms_id and version
resource = body.get("entry", [])[0]["resource"]
resource = body.get("entry", [])[0].get("resource", {})
return resource.get("id"), resource.get("meta", {}).get("versionId")
36 changes: 24 additions & 12 deletions recordforwarder/src/send_request_to_lambda.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@
import os
from errors import MessageNotSuccessfulError, IdNotFoundError
from get_imms_id_and_version import get_imms_id_and_version
from clients import lambda_client
from utils_for_record_forwarder import invoke_lambda
from constants import Constants
from constants import IMMS_BATCH_APP_NAME

CREATE_LAMBDA_NAME = os.getenv("CREATE_LAMBDA_NAME")
UPDATE_LAMBDA_NAME = os.getenv("UPDATE_LAMBDA_NAME")
Expand All @@ -15,10 +14,14 @@
def send_create_request(fhir_json: dict, supplier: str, file_key: str, row_id: str):
"""Sends the create request."""
# Send create request
headers = {"SupplierSystem": Constants.IMMS_BATCH_APP_NAME, "BatchSupplierSystem": supplier, "Filename": file_key,
"MessageId": row_id}
headers = {
"SupplierSystem": IMMS_BATCH_APP_NAME,
"BatchSupplierSystem": supplier,
"Filename": file_key,
"MessageId": row_id,
}
payload = {"headers": headers, "body": fhir_json}
invoke_lambda(lambda_client, CREATE_LAMBDA_NAME, payload)
invoke_lambda(CREATE_LAMBDA_NAME, payload)


def send_update_request(fhir_json: dict, supplier: str, file_key: str, row_id: str):
Expand All @@ -29,16 +32,21 @@ def send_update_request(fhir_json: dict, supplier: str, file_key: str, row_id: s
except IdNotFoundError as error:
raise MessageNotSuccessfulError(error) from error
if not imms_id:
raise MessageNotSuccessfulError("Unable to obtain Imms ID")
raise MessageNotSuccessfulError("Unable to obtain Imms id")
if not version:
raise MessageNotSuccessfulError("Unable to obtain Imms version")

# Send update request
fhir_json["id"] = imms_id
headers = {"SupplierSystem": Constants.IMMS_BATCH_APP_NAME, "BatchSupplierSystem": supplier, "E-Tag": version,
"Filename": file_key, "MessageId": row_id}
headers = {
"SupplierSystem": IMMS_BATCH_APP_NAME,
"BatchSupplierSystem": supplier,
"E-Tag": version,
"Filename": file_key,
"MessageId": row_id,
}
payload = {"headers": headers, "body": fhir_json, "pathParameters": {"id": imms_id}}
invoke_lambda(lambda_client, UPDATE_LAMBDA_NAME, payload)
invoke_lambda(UPDATE_LAMBDA_NAME, payload)


def send_delete_request(fhir_json: dict, supplier: str, file_key: str, row_id: str):
Expand All @@ -52,10 +60,14 @@ def send_delete_request(fhir_json: dict, supplier: str, file_key: str, row_id: s
raise MessageNotSuccessfulError("Unable to obtain Imms ID")

# Send delete request
headers = {"SupplierSystem": Constants.IMMS_BATCH_APP_NAME, "BatchSupplierSystem": supplier, "Filename": file_key,
"MessageId": row_id}
headers = {
"SupplierSystem": IMMS_BATCH_APP_NAME,
"BatchSupplierSystem": supplier,
"Filename": file_key,
"MessageId": row_id,
}
payload = {"headers": headers, "body": fhir_json, "pathParameters": {"id": imms_id}}
invoke_lambda(lambda_client, DELETE_LAMBDA_NAME, payload)
invoke_lambda(DELETE_LAMBDA_NAME, payload)


def send_request_to_lambda(message_body: dict):
Expand Down
30 changes: 11 additions & 19 deletions recordforwarder/src/utils_for_record_forwarder.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
import os
import json
from errors import MessageNotSuccessfulError
from typing import Union

from clients import lambda_client


def get_environment() -> str:
Expand All @@ -12,15 +15,9 @@ def get_environment() -> str:
return _env if _env in ["internal-dev", "int", "ref", "sandbox", "prod"] else "internal-dev"


def extract_file_key_elements(file_key: str) -> dict:
"""
Returns a dictionary containing each of the elements which can be extracted from the file key.
All elements are converted to upper case.\n
"""
file_key = file_key.upper()
file_key_parts_without_extension = file_key.split(".")[0].split("_")
file_key_elements = {"vaccine_type": file_key_parts_without_extension[0]}
return file_key_elements
def extract_vaccine_type_from_file_key(file_key: str) -> dict:
"""Returns the vaccine in upper case"""
return file_key.split("_")[0].upper()


def get_operation_outcome_diagnostics(body: dict) -> str:
Expand All @@ -34,25 +31,20 @@ def get_operation_outcome_diagnostics(body: dict) -> str:
return "Unable to obtain diagnostics from API response"


def invoke_lambda(lambda_client, lambda_name: str, payload: dict) -> tuple[int, dict, str]:
def invoke_lambda(lambda_name: str, payload: dict) -> Union[tuple[int, dict, str], None]:
"""
Uses the lambda_client to invoke the specified lambda with the given payload.
Returns the ressponse status code, body (loaded in as a dictionary) and headers.
"""
# Change InvocationType to 'Event' for asynchronous invocation
if ("search_imms" in lambda_name):
if "search_imms" in lambda_name:
response = lambda_client.invoke(
FunctionName=lambda_name, InvocationType="RequestResponse", Payload=json.dumps(payload)
)
response_payload = json.loads(response["Payload"].read())
body = json.loads(response_payload.get("body", "{}"))
return response_payload.get("statusCode"), body, response_payload.get("headers")
else:
response = lambda_client.invoke(
FunctionName=lambda_name, InvocationType="Event", Payload=json.dumps(payload)
)
body = json.loads(response.get("body", "{}"))
if response["statusCode"] != "200":
raise MessageNotSuccessfulError(get_operation_outcome_diagnostics(body))
else:
return "200", None, None
response = lambda_client.invoke(FunctionName=lambda_name, InvocationType="Event", Payload=json.dumps(payload))
if response["StatusCode"] != "202":
raise MessageNotSuccessfulError("Failed to send request to API")
Loading

0 comments on commit 7629536

Please sign in to comment.