Skip to content

Bug: event mutations influence idempotency hash used #1093

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
ojongerius opened this issue Apr 5, 2022 · 2 comments
Closed

Bug: event mutations influence idempotency hash used #1093

ojongerius opened this issue Apr 5, 2022 · 2 comments
Labels
bug Something isn't working

Comments

@ojongerius
Copy link
Contributor

Expected Behaviour

A function that (inadvertently) updates the event it has received should execute successfully, and have one idempotency document written.

Current Behaviour

A function that (inadvertently) updates the event it has received executes successfully, but has two documents corresponding to it's execution:

  • An initial document with a hashed idempotency key based on the original payload that will be stuck in INPROGRESS and has no return data
  • A second document with a hashed idempotency key based on the mutated payload with status COMPLETED and the correct return value

Code snippet

@pytest.mark.parametrize("idempotency_config", [{"use_local_cache": False}, {"use_local_cache": True}], indirect=True)
def test_idempotent_lambda_first_execution_event_mutation(
    idempotency_config: IdempotencyConfig,
    persistence_store: DynamoDBPersistenceLayer,
    lambda_apigw_event,
    expected_params_update_item,
    expected_params_put_item,
    lambda_response,
    serialized_lambda_response,
    deserialized_lambda_response,
    hashed_idempotency_key,
    lambda_context,
):
    """
    Test idempotent decorator where lambda_handler mutates the event
    """

    stubber = stub.Stubber(persistence_store.table.meta.client)
    ddb_response = {}

    stubber.add_response("put_item", ddb_response, expected_params_put_item)
    stubber.add_response("update_item", ddb_response, expected_params_update_item)
    stubber.activate()

    @idempotent(config=idempotency_config, persistence_store=persistence_store)
    def lambda_handler(event, context):
        event.popitem() # <- 💣
        return lambda_response

    lambda_handler(lambda_apigw_event, lambda_context)

    stubber.assert_no_pending_responses()
    stubber.deactivate()

Possible Solution

A few options:

  • Create the idempotency key on entry and save it (in say self.idempotency_key)
  • Use copy.deepcopy() when saving self.data which forces a pass by value and gets the result of hash function stable

The former solution would be more performant, the latter less code.

Steps to Reproduce

Add the idempotency decorator to any lambda function, update the event data, ie: event.popitem() and observe that 2 DDB documents were written of which one is stuck in INPROGRESS until it's TTLed

AWS Lambda Powertools for Python version

latest

AWS Lambda function runtime

{"label"=>"3.8"}

Packaging format used

{"label"=>"PyPi"}

Debugging logs

No response

@ojongerius ojongerius added bug Something isn't working triage Pending triage from maintainers labels Apr 5, 2022
@boring-cyborg
Copy link

boring-cyborg bot commented Apr 5, 2022

Thanks for opening your first issue here! We'll come back to you as soon as we can.

@heitorlessa heitorlessa added area/idempotency pending-release Fix or implementation already in dev waiting to be released and removed triage Pending triage from maintainers labels Apr 6, 2022
@github-actions
Copy link
Contributor

github-actions bot commented Apr 8, 2022

This is now released under 1.25.7 version!

@github-actions github-actions bot closed this as completed Apr 8, 2022
@github-actions github-actions bot removed the pending-release Fix or implementation already in dev waiting to be released label Apr 8, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants