Version
tokio@0.2.14 and tokio@0.2.15 exhibit this issue, tokio@0.2.13 does not.
tokio-hang-reproduction v0.1.0 (/Users/bryan/personal/tokio-hang-reproduction)
│ │ │ ├── tokio v0.2.14
│ │ │ │ └── tokio-macros v0.2.5
│ │ │ └── tokio-util v0.3.1
│ │ │ └── tokio v0.2.14 (*)
│ │ ├── tokio v0.2.14 (*)
│ ├── tokio v0.2.14 (*)
└── tokio v0.2.14 (*)
Platform
Currently, I can get this to happen on AWS Lambda.
I can not reproduce on MacOS (Darwin Bryans-MacBook-Pro.local 19.3.0 Darwin Kernel Version 19.3.0: Thu Jan 9 20:58:23 PST 2020; root:xnu-6153.81.5~1/RELEASE_X86_64 x86_64) or in Docker-for-Mac.
Description
For our GraphQL server, we use AWS Lambda + Juniper + Tokio. Juniper is currently a synchronous library, but the Lambda library we use and our model layer are fully tokio@0.2.
In order to get Juniper to call our models, we use futures::executor::block_on, based largely on this comment: #2042 (comment)
Starting with tokio@0.2.14, this approach has started hanging and causing timeouts. Downgrading to tokio@0.2.13 solved the issue.
https://github.com/bryanburgers/tokio-hang-reproduction
#![allow(dead_code)]
use futures::stream::{self, StreamExt};
use tokio::time::delay_for;
use std::time::Duration;
use serde_json::{Value, json};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
let fun = lambda::handler_fn(handler);
lambda::run(fun).await?;
Ok(())
}
async fn handler(_event: Value) -> Result<Value, String> {
let result = invoke_juniper();
// If we don't use juniper and .await the futures normally, it works fine.
// let result = test1(100).await;
println!("result={:?}", result);
Ok(json!({}))
}
// Juniper (https://crates.io/crates/juniper) is a synchronous library.
fn invoke_juniper() -> Vec<usize> {
// And from it, we call into our async code using block_on
futures::executor::block_on(test1(100))
}
// All three of these functions fail after executing ~60 futures.
async fn test1(n: usize) -> Vec<usize> {
stream::iter(0..n).map(pause_and_return).buffer_unordered(10).collect().await
}
async fn test2(n: usize) -> Vec<usize> {
stream::iter(0..n).map(pause_and_return).buffered(10).collect().await
}
async fn test3(n: usize) -> Vec<usize> {
let mut vec = Vec::new();
for i in 0..n {
vec.push(pause_and_return(i).await);
}
vec
}
async fn pause_and_return(n: usize) -> usize {
println!("Starting {}", n);
delay_for(Duration::from_millis(100)).await;
println!("Finished {}", n);
n
}
Version
tokio@0.2.14andtokio@0.2.15exhibit this issue,tokio@0.2.13does not.Platform
Currently, I can get this to happen on AWS Lambda.
I can not reproduce on MacOS (
Darwin Bryans-MacBook-Pro.local 19.3.0 Darwin Kernel Version 19.3.0: Thu Jan 9 20:58:23 PST 2020; root:xnu-6153.81.5~1/RELEASE_X86_64 x86_64) or in Docker-for-Mac.Description
For our GraphQL server, we use AWS Lambda + Juniper + Tokio. Juniper is currently a synchronous library, but the Lambda library we use and our model layer are fully tokio@0.2.
In order to get Juniper to call our models, we use
futures::executor::block_on, based largely on this comment: #2042 (comment)Starting with tokio@0.2.14, this approach has started hanging and causing timeouts. Downgrading to tokio@0.2.13 solved the issue.
https://github.com/bryanburgers/tokio-hang-reproduction