How do I use actix-web 3 and rusoto 0.46 together?
Asked Answered
F

1

7

When I try to use actix-web 3 and rusoto 0.46 together I get the following runtime error:

thread 'actix-rt:worker:0' panicked at 'there is no reactor running, must be called from the context of a Tokio 1.x runtime', /Users/matt/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.2.0/src/runtime/blocking/pool.rs:85:33

Small reproducible:

use actix_web::{get, App, HttpResponse, HttpServer, Responder}; // 3
use rusoto_core::Region; // 0.46 
use rusoto_dynamodb::{DynamoDb, DynamoDbClient, ListTablesInput};
use std::default::Default;

#[get("/tables")]
async fn tables(_req_body: String) -> impl Responder {
    let client = DynamoDbClient::new(Region::default());
    let list_tables_input: ListTablesInput = Default::default();
    match client.list_tables(list_tables_input).await {
        Ok(_output) => HttpResponse::Ok().finish(),
        Err(_error) => HttpResponse::InternalServerError().finish(),
    }
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| App::new().service(tables))
        .bind("0.0.0.0:8080")?
        .run()
        .await
}

Accompanying Cargo file:

[package]
name = "hello_actix_rusoto"
version = "0.1.0"
authors = ["Matt Roberts <[email protected]>"]
edition = "2018"

[dependencies]
rusoto_core = "0.46"
rusoto_dynamodb = "0.46"
actix-web = "3"

Here is a link to a very small GitHub repo with the full code and here is how to reproduce the error:

git clone [email protected]:mattroberts297/hello_actix_rusoto.git
cd hello_actix_rusoto
docker-compose up -d
AWS_REGION=local cargo run &
curl -v 'http://127.0.0.1:8080/tables'
Fenrir answered 9/2, 2021 at 13:22 Comment(0)
C
12

rusoto v0.46 depends on tokio v1.0. actix-web v3 however, is still using tokio v0.2. The two versions are not backward compatible, hence the error message. To solve this, you can upgrade to a newer version of actix-web:

actix-web = "4.0.0-beta.8"

Or you can use the tokio-compat2 compatibility layer. This requires prefixing any incompatible .await call with .compat()

async fn index() -> impl Responder {
    let client = DynamoDbClient::new("[region]");
    let tables = client.list_tables(list_tables_input).compat().await;
    // ...
}

Or you could downgrade rusoto to an older version that uses tokio v0.2:

rusoto_core = "0.43"
Command answered 9/2, 2021 at 14:21 Comment(4)
Thank you very much for the fast and detailed reply. I hoped tokio-compat2 might be the answer. Unfortunately, after adding tokio-compat2 I still get the same run time error. Upgrading actix results in multiple compile time errors (related to dependencies). I appreciate your help and patience!Fenrir
@MattRoberts The latest actix-rt release broke 4.0.0-beta.1, and there are workarounds here. I am not sure why tokio-compat2 wouldn't be working.... your best bet is probably to downgrade rusoto until actix v4.0 is released.Command
Thank you @ibraheem-ahmed. Downgrading rusoto_core and rusoto_dynamo to 0.43 worked. I have made it work with sync() and tokio Core. I just need to refactor the Core into the actix app state and then will edit your answer to include solution (provided you're happy with that). Appreciate the workaround for the upgrade path also. Thank you again.Fenrir
Just looping back round to this. In the end I went the upgrade path. Downgrading to rusoto did work, but I could only get sync() working at runtime. I think that would mean blocking current thread (which seems like it wouldn't scale). Link to branch that works at compile-time and runtime. Thanks again.Fenrir

© 2022 - 2024 — McMap. All rights reserved.