Skip to content

Commit 6561eff

Browse files
committed
Sonarcloud fixes
1 parent 4cb8398 commit 6561eff

24 files changed

Lines changed: 111 additions & 62 deletions

File tree

application/common/dos.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ def db_rows_to_spec_open_times(db_rows: Iterable[dict]) -> list[SpecifiedOpening
254254
for date, rows in groupby(date_sorted_rows, lambda row: row["date"]):
255255
is_open = True
256256
open_periods = []
257-
for row in list(rows):
257+
for row in rows:
258258
if row["isclosed"] is True:
259259
is_open = False
260260
else:

application/common/errors.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,7 @@ class ValidationError(Exception):
44

55
class DynamoDBError(Exception):
66
"""Exception raised for all DynamoDB errors."""
7+
8+
9+
class SecretsManagerError(Exception):
10+
"""Exception raised for AWS Secrets Manager errors."""

application/common/nhs.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ def _get_specified_opening_times(self: Self) -> list[SpecifiedOpeningTime]:
165165
date = datetime.strptime(date_str, "%b %d %Y").date()
166166
is_open = True
167167

168-
for item in list(op_dict_list):
168+
for item in op_dict_list:
169169
if item["IsOpen"]:
170170
open_periods.append(OpenPeriod.from_string_times(item["OpeningTime"], item["ClosingTime"]))
171171
else:

application/common/secretsmanager.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
from boto3 import client
55
from botocore.exceptions import ClientError
66

7+
from .errors import SecretsManagerError
8+
79
logger = Logger()
810

911
secrets_manager = client(service_name="secretsmanager")
@@ -16,7 +18,7 @@ def get_secret(secret_name: str) -> dict[str, str]:
1618
secret_name (str): Secret name to get
1719
1820
Raises:
19-
e: ClientError caused by secrets manager
21+
SecretsManagerError: When unable to retrieve secret from AWS Secrets Manager
2022
2123
Returns:
2224
Dict[str, str]: Secrets as a dictionary
@@ -25,6 +27,6 @@ def get_secret(secret_name: str) -> dict[str, str]:
2527
secret_value_response = secrets_manager.get_secret_value(SecretId=secret_name)
2628
except ClientError as err:
2729
msg = f"Failed getting secret '{secret_name}' from secrets manager"
28-
raise Exception(msg) from err # noqa: TRY002
30+
raise SecretsManagerError(msg) from err
2931
secrets_json_str = secret_value_response["SecretString"]
3032
return loads(secrets_json_str)

application/event_replay/event_replay.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,19 @@
88
from aws_lambda_powertools.utilities.typing import LambdaContext
99
from boto3 import client
1010
from boto3.dynamodb.types import TypeDeserializer
11+
from botocore.config import Config
1112
from simplejson import dumps
1213

1314
from common.middlewares import unhandled_exception_logging
1415

16+
# Configure boto3 client with explicit timeout to prevent hanging in Lambda
17+
# Timeouts tuned for typical DynamoDB/SQS operations while preventing indefinite hangs
18+
boto_config = Config(connect_timeout=10, read_timeout=15)
19+
20+
# Create clients at module level for connection reuse across Lambda invocations
21+
dynamodb_client = client("dynamodb", config=boto_config)
22+
sqs_client = client("sqs", config=boto_config)
23+
1524
tracer = Tracer()
1625
logger = Logger()
1726

@@ -75,7 +84,7 @@ def get_change_event(odscode: str, sequence_number: Decimal) -> dict[str, Any]:
7584
Returns:
7685
dict[str, Any]: The change event
7786
"""
78-
response = client("dynamodb").query(
87+
response = dynamodb_client.query(
7988
TableName=getenv("CHANGE_EVENTS_TABLE_NAME"),
8089
IndexName="gsi_ods_sequence",
8190
ProjectionExpression="Event",
@@ -112,11 +121,10 @@ def send_change_event(change_event: dict[str, Any], odscode: str, sequence_numbe
112121
sequence_number (int): The sequence number of the change event
113122
correlation_id (str): The correlation id of the event replay
114123
"""
115-
sqs = client("sqs")
116124
queue_url = getenv("CHANGE_EVENT_SQS_URL")
117125
logger.info("Sending change event to SQS", queue_url=queue_url)
118126
change_event_str = dumps(change_event)
119-
response = sqs.send_message(
127+
response = sqs_client.send_message(
120128
QueueUrl=queue_url,
121129
MessageBody=change_event_str,
122130
MessageGroupId=odscode,

application/ingest_change_event/ingest_change_event.py

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,22 @@
77
from aws_lambda_powertools.utilities.data_classes import SQSEvent, event_source
88
from aws_lambda_powertools.utilities.typing.lambda_context import LambdaContext
99
from boto3 import client
10+
from botocore.config import Config
11+
from botocore.exceptions import ClientError
1012

1113
from .change_event_validation import validate_change_event
1214
from common.dynamodb import add_change_event_to_dynamodb, get_latest_sequence_id_for_a_given_odscode_from_dynamodb
1315
from common.middlewares import redact_staff_key_from_event, unhandled_exception_logging
1416
from common.types import HoldingQueueChangeEventItem
1517
from common.utilities import extract_body, get_sequence_number
1618

19+
# Configure boto3 client with explicit timeout to prevent hanging in Lambda
20+
boto_config = Config(connect_timeout=10, read_timeout=15)
21+
1722
logger = Logger()
1823
tracer = Tracer()
19-
sqs = client("sqs")
24+
# Create SQS client at module level for connection reuse across Lambda invocations
25+
sqs_client = client("sqs", config=boto_config)
2026

2127

2228
@redact_staff_key_from_event()
@@ -82,8 +88,17 @@ def lambda_handler(event: SQSEvent, context: LambdaContext) -> None: # noqa: AR
8288
correlation_id=logger.get_correlation_id(),
8389
)
8490
logger.debug("Change event validated", holding_queue_change_event_item=holding_queue_change_event_item)
85-
sqs.send_message(
86-
QueueUrl=getenv("HOLDING_QUEUE_URL"),
87-
MessageBody=dumps(holding_queue_change_event_item),
88-
MessageGroupId=ods_code,
89-
)
91+
try:
92+
sqs_client.send_message(
93+
QueueUrl=getenv("HOLDING_QUEUE_URL"),
94+
MessageBody=dumps(holding_queue_change_event_item),
95+
MessageGroupId=ods_code,
96+
)
97+
except ClientError as err:
98+
logger.error(
99+
"Failed to send message to holding queue",
100+
error=str(err),
101+
error_code=err.response["Error"]["Code"],
102+
queue_url=getenv("HOLDING_QUEUE_URL"),
103+
)
104+
raise
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
aws-lambda-powertools[tracer] ~= 3.20.0
22
psycopg[binary]
3-
pytz

application/service_matcher/service_matcher.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from aws_lambda_powertools.utilities.data_classes import SQSEvent, event_source
99
from aws_lambda_powertools.utilities.typing.lambda_context import LambdaContext
1010
from boto3 import client
11+
from botocore.config import Config
1112

1213
from .matching import get_matching_services
1314
from .review_matches import review_matches
@@ -16,9 +17,13 @@
1617
from common.types import HoldingQueueChangeEventItem, UpdateRequest
1718
from common.utilities import extract_body
1819

20+
# Configure boto3 client with explicit timeout to prevent hanging in Lambda
21+
boto_config = Config(connect_timeout=10, read_timeout=15)
22+
1923
logger = Logger()
2024
tracer = Tracer()
21-
sqs = client("sqs")
25+
# Create SQS client at module level for connection reuse across Lambda invocations
26+
sqs_client = client("sqs", config=boto_config)
2227

2328

2429
@unhandled_exception_logging()

application/service_sync/data_processing/service_histories.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from aws_lambda_powertools.logging import Logger
88
from psycopg import Connection
99
from psycopg.rows import dict_row
10-
from pytz import timezone
10+
from zoneinfo import ZoneInfo
1111

1212
from .service_histories_change import ServiceHistoriesChange
1313
from common.constants import (
@@ -209,7 +209,7 @@ def save_service_histories(self: Self, connection: Connection) -> None:
209209
# Generate the epoch time in seconds rounded down to the nearest second at the time of saving
210210
current_epoch_time = str(int(time()))
211211
# Get local datetime and format it to DoS date/time format
212-
current_date_time = datetime.now(timezone("Europe/London")).strftime("%Y-%m-%d %H:%M:%S")
212+
current_date_time = datetime.now(ZoneInfo("Europe/London")).strftime("%Y-%m-%d %H:%M:%S")
213213
# Rename the new_change key to the current epoch time
214214
self.service_history[current_epoch_time] = self.service_history.pop("new_change")
215215
# Add the current time to the service_histories json

application/service_sync/data_processing/service_histories_change.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,19 @@
1919
class ServiceHistoriesChange:
2020
"""A change to be added to the servicehistories table."""
2121

22-
data: str
22+
data: str | dict
2323
previous_value: str
2424
change_key: str
2525
change_action: str
2626
area: str
2727

2828
def __init__(
29-
self: Self, data: str, previous_value: str, change_key: str, area: str = DOS_DEMOGRAPHICS_AREA_TYPE
29+
self: Self, data: str | dict, previous_value: str, change_key: str, area: str = DOS_DEMOGRAPHICS_AREA_TYPE
3030
) -> None:
3131
"""Initialises the ServiceHistoriesChange object.
3232
3333
Args:
34-
data (str): The data to be added to the servicehistories table.
34+
data (str | dict): The data to be added to the servicehistories table.
3535
previous_value (str): The previous value of the data to be added to the servicehistories table.
3636
change_key (str): The change key for the data to be added to the servicehistories table.
3737
area (str): The area of the data to be added to the servicehistories table.
@@ -76,8 +76,7 @@ def get_sgsd_change_action(self: Self) -> str:
7676
Returns:
7777
str: Change action - add, delete
7878
"""
79-
new_value: dict[list[str]] = self.data
80-
value = next(iter(new_value.keys()))
79+
value = next(iter(self.data.keys()))
8180
return "add" if value == "add" else "delete"
8281

8382
def get_opening_times_change_action(self: Self) -> str:

0 commit comments

Comments
 (0)