Catch unwind of AWS lambda's future

I'm trying to compile an AWS Lambda function that can catch a panic due to connections failing with a postgres RDS server.

Because the AWS runtime is asynchronous, I cannot use a synchronous postgres client (or I gave up trying to figure out how to interoperate async with sync).

So while my synchronous code could easily catch panics, now my async code is failing to compile due to the future produced by the AWS lambda library being unexpected:

25 | AssertUnwindSafe(run(func)).catch_unwind().await
| ^^^^^^^^^^^^ method not found in AssertUnwindSafe<impl std::future::Future<Output = Result<(), Box<(dyn std::error::Error + Send + Sync + 'static)>>>>
|
= help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a use for it:
|
1 | use futures_util::future::future::FutureExt;
|

(I try adding that use but get same result)

My func is quite simple:


#[tokio::main]
async fn main() -> Result<(), Error> {
    let func = service_fn(func);

    let result = AssertUnwindSafe(run(func)).catch_unwind().await;
    println!("panic? {:?}", result);

    Ok(())
}

async fn func(event: LambdaEvent<S3Event>) -> Result<(), Error> {
    let (event, _context) = event.into_parts();

    let (client, connection) = tokio_postgres::connect(
        format!(
            "host={} port={} dbname={} user={} password={} connect_timeout=5",
            "pg.mars-2.rds.amazonaws.com",
            5432,
            "table",
            "postgres",
            "123_Is_My_PW_dont_tell_badguys_plz"
        ).as_str(),
        NoTls
    ).await?;
}

Strangely I can get this to compile if I don't use AWS libraries at all:

So what is special about the AWS libraries that I need to address differently?

Thanks as always for this wonderful community

Could you add the necessary imports for the failing case? I know it can't be tested in the playground due to the missing dependencies, but at least we can get it to compile locally.

of course, I'm very sorry about that I should have just commented them out from the playground... updated my playground link!

for whatever reason this website is giving me a "503" error if I try to edit a response... so adding the updated link here as a new comment!

aws_lambda_events = { version = "0.6.1", default-features = false, features = ["s3"] }
lambda_runtime = "0.5.1"
aws-sdk-s3 = { git = "GitHub - awslabs/aws-sdk-rust: AWS SDK for the Rust Programming Language", branch = "next" }
aws-smithy-http = { git = "GitHub - awslabs/aws-sdk-rust: AWS SDK for the Rust Programming Language", branch = "next" }
aws-config = { git = "GitHub - awslabs/aws-sdk-rust: AWS SDK for the Rust Programming Language", branch = "next" }
aws-types = { git = "GitHub - awslabs/aws-sdk-rust: AWS SDK for the Rust Programming Language", branch = "next" }

Not an answer to the main question, but in general this problem had two answers, depending on whether the synchronous code is Send/Sync friendly.

If it is, you can simply use a spawn_blocking to get futures for the synchronous task that won't starve the executor.

If it isn't, then you generally need to use crossbeam channel or the like to send the requests and responses back and forwards to a processing thread. It can be pretty painful to get it working at all, but it generally works well when you do.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.