Skip to content

Conversation

@lmammino
Copy link
Contributor

@lmammino lmammino commented Nov 24, 2025

📬 Issue #, if available:

✍️ Description of changes

This PR improves the ergonomics of working with SqsBatchResponse and
KinesisEventResponse.

Since v1.0, these structs have been marked as #[non_exhaustive], which means you
can no longer construct them and provide their content in a single expression.

Note

This is also the case for the related structs SqsBatchItemFailure and
KinesisBatchItemFailure.


❌ Previous (pre-1.0, now broken) API

The following code used to be valid before 1.0, but no longer compiles:

use aws_lambda_events::event::sqs::{SqsEvent, SqsBatchResponse,
SqsBatchItemFailure};

async fn function_handler(
    event: LambdaEvent<SqsEvent>
) -> Result<SqsBatchResponse, Error> {
    let mut batch_item_failures = Vec::new();

    for record in event.payload.records {
        let message_id = record.message_id.clone().unwrap_or_default();

        // Try to process the message
        if let Err(e) = process_record(&record).await {
            println!("Failed to process message {}: {}", message_id, e);
            // Add to failures list so it will be retried
            batch_item_failures.push(SqsBatchItemFailure {
                item_identifier: message_id,
            });
        }
    }

    // Return the list of failed messages
    Ok(SqsBatchResponse {
        batch_item_failures,
    })
}

// ...

⚠️ Current (working but verbose) pattern

With #[non_exhaustive], you now need something slightly more verbose, similar to
the official example in the repo
([advanced-sqs-partial-batch-failures](https://github.com/aws/aws-lambda-rust-runti
me/blob/main/examples/advanced-sqs-partial-batch-failures/src/main.rs)):

use aws_lambda_events::event::sqs::{SqsEvent, SqsBatchResponse,
SqsBatchItemFailure};

async fn function_handler(
    event: LambdaEvent<SqsEvent>
) -> Result<SqsBatchResponse, Error> {
    let mut batch_item_failures = Vec::new();

    for record in event.payload.records {
        let message_id = record.message_id.clone().unwrap_or_default();

        // Try to process the message
        if let Err(e) = process_record(&record).await {
            println!("Failed to process message {}: {}", message_id, e);

            // Build failure using Default because SqsBatchItemFailure is
#[non_exhaustive]
            let mut failure = SqsBatchItemFailure::default();
            failure.item_identifier = message_id;

            // Add to failures list so it will be retried
            batch_item_failures.push(failure);
        }
    }

    // Return the list of failed messages
    let mut response = SqsBatchResponse::default();
    response.batch_item_failures = batch_item_failures;

    Ok(response)
}

// ...

This works, but it is more verbose and a bit less ergonomic for a very common usage
pattern.


✅ Proposed (this PR): ergonomic helper API

This PR adds two helper methods to both SqsBatchResponse and
KinesisEventResponse:

  1. add_failure(item_identifier) - Add a single failure to the response
  2. set_failures(item_identifiers) - Set multiple failures at once (replaces
    any existing failures)

Both methods accept flexible input types via impl Into<String>, so you can pass
&str, String, or any other compatible type.

SQS Example using add_failure:

use aws_lambda_events::event::sqs::{SqsEvent, SqsBatchResponse};

async fn function_handler(
    event: LambdaEvent<SqsEvent>,
) -> Result<SqsBatchResponse, Error> {
    let mut response = SqsBatchResponse::default();

    for record in event.payload.records {
        let message_id = record.message_id.clone().unwrap_or_default();

        if let Err(e) = process_record(&record).await {
            println!("Failed to process message {}: {}", message_id, e);
            response.add_failure(message_id);
        }
    }

    Ok(response)
}

// ...

SQS Example using set_failures:

use aws_lambda_events::event::sqs::{SqsEvent, SqsBatchResponse};

async fn function_handler(
    event: LambdaEvent<SqsEvent>,
) -> Result<SqsBatchResponse, Error> {
    let mut failed_ids = Vec::new();

    for record in event.payload.records {
        let message_id = record.message_id.clone().unwrap_or_default();

        if let Err(e) = process_record(&record).await {
            println!("Failed to process message {}: {}", message_id, e);
            failed_ids.push(message_id);
        }
    }

    let mut response = SqsBatchResponse::default();
    response.set_failures(failed_ids);

    Ok(response)
}

// ...

Kinesis Example using add_failure:

use aws_lambda_events::event::kinesis::KinesisEvent;
use aws_lambda_events::event::streams::KinesisEventResponse;

async fn function_handler(
    event: LambdaEvent<KinesisEvent>,
) -> Result<KinesisEventResponse, Error> {
    let mut response = KinesisEventResponse::default();

    for record in event.payload.records {
        let sequence_number = record.kinesis.sequence_number.clone();

        if let Err(e) = process_record(&record).await {
            println!("Failed to process record {}: {}", sequence_number, e);
            response.add_failure(sequence_number);
        }
    }

    Ok(response)
}

// ...

This keeps the types #[non_exhaustive] while restoring a convenient and
discoverable way to build partial batch responses.


🔏 By submitting this pull request

  • I confirm that I've run cargo +nightly fmt.
  • I confirm that I've run cargo clippy --fix.
  • I confirm that I've made a best-effort attempt to update all relevant
    documentation.
  • I confirm that my contribution is made under the terms of the Apache 2.0
    license.

@lmammino lmammino changed the title feat: Improve ergonomics of SqsBatchResponse feat(‎lambda-events): Improve ergonomics of SqsBatchResponse Nov 24, 2025
@lmammino lmammino changed the title feat(‎lambda-events): Improve ergonomics of SqsBatchResponse feat(‎lambda-events): Improve ergonomics of SqsBatchResponse Nov 24, 2025
@lmammino lmammino changed the title feat(‎lambda-events): Improve ergonomics of SqsBatchResponse feat(‎lambda-events): Improve ergonomics of SqsBatchResponse and KinesisEventResponse Nov 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant