All Articles

Rust Lamda で Tokio を使うときのイディオム

aws-lambda-rust-runtime の現時点でのリリース版 (0.2) で Tokio を使うときのイディオム。

現状 reqwest や rusoto_dynamodb が tokio 0.2 のランタイムを要求するのに、aws-lambda-rust-runtime が async 対応していないという面倒くささがある(master を使えば対応はしているのであるが)。

結論としてはこんな感じにしておけばいい。

async fn handler(event: Event, context: Context) -> Result<(), HandlerError> {
    // ...
}

fn main() {
    let mut rt = tokio::runtime::Runtime::new().unwrap();
    lambda!(move |event, context| rt.block_on(handler(event, context)));
}

ポイントは runtime は tokio::main ではなく明示的に生成するのと、この runtime をクロージャで使うこと。将来 handler が async で定義できる流れではあると思うので、今からそうしておいた方がいいと思う。

これはダメな例。

fn handler(event: Event, context: Context) -> Result<(), HandlerError> {
    futures::executor::block_on(/* ... */)
}

#[tokio::main]
async fn main() {
    lambda!(handler);
}

おそらく futures と tokio の executor が混ざってしまうからだと思うのだが、この構成だと一応動きはするものの、しばらく Lambda で動かしておくと定期的にタイムアウト(future の解決に失敗している感じ)が起きてしまい、安定して動かなかった。

構成を改めてからは安定して動作している。