From 6acc5faaa8cd7a163f418855a5efc18b6ee50810 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Tue, 27 Aug 2024 11:39:01 +0100 Subject: [PATCH] feat(idempotency): simplify access to expiration time in `DataRecord` class (#5082) Accessing expiration time --- .../idempotency/persistence/datarecord.py | 21 +++++++++++++++++++ .../src/working_with_response_hook.py | 8 +++---- .../idempotency/test_idempotency.py | 2 ++ 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/aws_lambda_powertools/utilities/idempotency/persistence/datarecord.py b/aws_lambda_powertools/utilities/idempotency/persistence/datarecord.py index 3cbdd1da468..12e025b5e98 100644 --- a/aws_lambda_powertools/utilities/idempotency/persistence/datarecord.py +++ b/aws_lambda_powertools/utilities/idempotency/persistence/datarecord.py @@ -92,3 +92,24 @@ def response_json_as_dict(self) -> dict | None: previous response data deserialized """ return json.loads(self.response_data) if self.response_data else None + + def get_expiration_datetime(self) -> datetime.datetime | None: + """ + Converts the expiry timestamp to a datetime object. + + This method checks if an expiry timestamp exists and converts it to a + datetime object. If no timestamp is present, it returns None. + + Returns: + ------- + datetime.datetime | None + A datetime object representing the expiration time, or None if no expiry timestamp is set. + + Note: + ---- + The returned datetime object is timezone-naive and assumes the timestamp + is in the system's local timezone. Lambda default timezone is UTC. + """ + if self.expiry_timestamp: + return datetime.datetime.fromtimestamp(int(self.expiry_timestamp)) + return None diff --git a/examples/idempotency/src/working_with_response_hook.py b/examples/idempotency/src/working_with_response_hook.py index 2c2208d25a5..810574934c3 100644 --- a/examples/idempotency/src/working_with_response_hook.py +++ b/examples/idempotency/src/working_with_response_hook.py @@ -1,4 +1,3 @@ -import datetime import uuid from typing import Dict @@ -20,11 +19,10 @@ def my_response_hook(response: Dict, idempotent_data: DataRecord) -> Dict: # Return inserted Header data into the Idempotent Response response["x-idempotent-key"] = idempotent_data.idempotency_key - # expiry_timestamp could be None so include if set - expiry_timestamp = idempotent_data.expiry_timestamp + # expiry_timestamp can be None so include if set + expiry_timestamp = idempotent_data.get_expiration_datetime() if expiry_timestamp: - expiry_time = datetime.datetime.fromtimestamp(int(expiry_timestamp)) - response["x-idempotent-expiration"] = expiry_time.isoformat() + response["x-idempotent-expiration"] = expiry_timestamp.isoformat() # Must return the response here return response diff --git a/tests/functional/idempotency/test_idempotency.py b/tests/functional/idempotency/test_idempotency.py index c499d3af7a8..98980efb86c 100644 --- a/tests/functional/idempotency/test_idempotency.py +++ b/tests/functional/idempotency/test_idempotency.py @@ -2045,6 +2045,7 @@ def test_idempotent_lambda_already_completed_response_hook_is_called( def idempotent_response_hook(response: Any, idempotent_data: DataRecord) -> Any: """Modify the response provided by adding a new key""" response["idempotent_response"] = True + response["idempotent_expiration"] = idempotent_data.get_expiration_datetime() return response @@ -2070,6 +2071,7 @@ def lambda_handler(event, context): # Then idempotent_response value will be added to the response assert lambda_resp["idempotent_response"] + assert lambda_resp["idempotent_expiration"] == datetime.datetime.fromtimestamp(int(timestamp_future)) stubber.assert_no_pending_responses() stubber.deactivate()