如何同时使用 actix-web 3 和 rusoto 0.46?

问题描述

当我尝试同时使用 actix-web 3 和 rusoto 0.46 时,出现以下运行时错误

#include <stdio.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>

#define KEY_ENTER   0x000a
#define KEY_ESCAPE  0x001b

static struct termios term,oterm;

static int getch(void);
static int kbhit(void);
static int kbesc(void);
static int kbget(void);

static int getch(void)
{
    int c = 0;

    tcgetattr(0,&oterm);
    memcpy(&term,&oterm,sizeof(term));
    term.c_lflag &= ~(ICANON | ECHO);
    term.c_cc[VMIN] = 1;
    term.c_cc[VTIME] = 0;
    tcsetattr(0,TCSANow,&term);
    c = getchar();
    tcsetattr(0,&oterm);
    return c;
}

static int kbhit(void)
{
    int c = 0;

    tcgetattr(0,sizeof(term));
    term.c_lflag &= ~(ICANON | ECHO);
    term.c_cc[VMIN] = 0;
    term.c_cc[VTIME] = 1;
    tcsetattr(0,&oterm);
    if (c != -1) ungetc(c,stdin);
    return ((c != -1) ? 1 : 0);
}

static int kbesc(void)
{
    int c;
    
    while (kbhit())
    {
        c = getch();
    }
    return c;
}

static int kbget(void)
{
    int c;

    c = getch();
    return (c == KEY_ESCAPE) ? kbesc() : c;
}

int main(void)
{
    int c;

    while (1)
    {
        c = kbget();
        if (c == KEY_ENTER)
        {
            break;
        }
        putchar('b');
    }
    printf("\n");
    return 0;
}

小可重复性:

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

随附货物文件

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
}

这是带有完整代码link to a very small GitHub repo 以及如何重现错误

[package]
name = "hello_actix_rusoto"
version = "0.1.0"
authors = ["Matt Roberts <mattroberts297@users.noreply.github.com>"]
edition = "2018"

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

解决方法

rusoto v0.46 依赖于 tokio v1.0。然而,actix-web v3 仍在使用 tokio v0.2。这两个版本不向后兼容,因此出现错误消息。要解决此问题,您可以升级到更新版本的 actix-web:

actix-web = "4.0.0-beta.8"

或者您可以使用 tokio-compat2 兼容层。这需要在任何不兼容的 .await 调用前加上 .compat()

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

或者您可以将 rusoto 降级到使用 tokio v0.2 的旧版本:

rusoto_core = "0.43"