Description
Expected Behaviour
@heitorlessa this is a continuation of 23777
When using the BatchProcessor
with process_partial_response
from here I have noticed that the event does not have to respect the model and it can return an empty list for the batchItemFailures
which will tell AWS to delete the messages from the queue in case of SQS triggers.
I'd expect the behavior to be fail-first fail-fast. If I got a bunch of messages to my Lambda that do not have the format of an EventType.SQS
that should fail right away, in my opinion. Passing a random dict
to the process_partial_response
should not be considered a valid event.
Current Behaviour
The current implementation of process_partial_response
accepts any dict
passed in. Since it used the dict
method .get
to get the Records
which is a key in SQS type events. But returns a default empty list in case the key doesn't exist. Which in turn will tell the context manager to run the processor on an empty list of records, which will always return success.
Code snippet
from aws_lambda_powertools.utilities.batch import (
BatchProcessor, EventType, process_partial_response
)
from aws_lambda_powertools.utilities.typing import LambdaContext
import pydantic
class Event(pydantic.BaseModel):
foo: str
bar: str
def record_handler(record: Event):
print(record)
if record.foo == "barr":
raise ValueError
def handler(event: dict, context: LambdaContext):
return process_partial_response(
event=event,
record_handler=record_handler,
processor=BatchProcessor(
event_type=EventType.SQS,
model=Event,
),
context=context
)
# This is an invalid event since it's not of the type SQS
# But the error about missing SQS model field is only thrown after the record_handler is called
# It should be at the very beginning, before any business logic occurs
print(handler({'Records': [{"foo": "bar", "bar": "baz"}, {"foo": "barr", "bar": "bazz"}]}, object))
# This is not valid, but does not throw an error
# And the batchItemFailures returns an empty list which is not accurate.
print(handler({"foo": "bar", "bar": "baz"}, object))
# This throws ValueError: Invalid event format. Please ensure batch event is a valid SQS event.
print(handler(["foo", "bar", "bar", "baz"], object))
Possible Solution
I'm sure there are a variety of reasons for why this is the way it is that I'm not considering. One obvious answer is that SQS event types will always have the 'Records` key hence anything that doesn't have it should answer the question: "How did you get here and should you even be considered?"
But I believe that we can be a bit more strict on enforcing that the dict
passed is indeed of the type SQS, DynamoDB stream or Kinesis before doing any processing.
For example, in the snippet above, I pass in a dict
with the Records
key, but the rest of the event does not have the remaining SQS keys. When the record_handler
fails, the batch processor looks for the messageId
field, which doesn't exist. I believe if this was done upfront and fail immediately it would be a better developer experience.
What's everyone's thoughts?
Steps to Reproduce
Snippet above should be enough to demonstrate all scenarios brought up.
Powertools for AWS Lambda (Python) version
latest
AWS Lambda function runtime
3.10
Packaging format used
Lambda Layers
Debugging logs
No response
Metadata
Metadata
Assignees
Type
Projects
Status