# Async-await ecosystem experience report

**URL:** <https://internals.rust-lang.org/t/async-await-ecosystem-experience-report/10707>\
**Category:** libs\
**Created:** [August 14, 2019, 2:35am UTC](https://internals.rust-lang.org/t/async-await-ecosystem-experience-report/10707 "2019-08-14T02:35:07Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![eminence](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/eminence/32/4018_2.png) [@eminence](https://internals.rust-lang.org/u/eminence)\
**Post date:** [August 14, 2019, 2:35am UTC](https://internals.rust-lang.org/t/async-await-ecosystem-experience-report/10707/1 "2019-08-14T02:35:07Z")

</div>

In the same spirit of the [async-await experience reports](https://internals.rust-lang.org/t/async-await-experience-reports/10200) thread, I thought I'd document my experiences trying to implement a very simple async program, but focus on the ecosystem (and not the details of the async/await syntax). The program has the following behavior: Wait for input from the user on stdin, and if nothing is received in 10 seconds, exit the program.

For this exercise, I'm using the latest nightly compiler (`rustc 1.38.0-nightly (60960a260 2019-08-12)`)

## Tokio

I started with tokio, because it's a very familiar name. I'm using the latest published crate ([0.2.0-alpha.1](https://crates.io/crates/tokio/0.2.0-alpha.1)).

Tokio has both a [`Stdin`](https://docs.rs/tokio/0.2.0-alpha.1/tokio/io/struct.Stdin.html) and a [`Timeout`](https://docs.rs/tokio/0.2.0-alpha.1/tokio/timer/struct.Timeout.html) type that look perfect for what I want, and I discovered them quickly. The code was easy to write, and I think easy to read:

```rust
#[tokio::main]
async fn main() {
    let mut stdin = tokio::io::stdin();
    let mut s = String::new();

    let mut read_stdin = tokio::timer::Timeout::new(stdin.read_to_string(&mut s), std::time::Duration::from_secs(10));

    match read_stdin.await {
        Ok(data) => println!("Read data: {:?}", data),
        Err(e) => println!("Timeout: {:?}", e)
    }
}

```

Unfortunately this doesn't execute as expected, as the future always returns an error:

> Read data: Err(Custom { kind: Other, error: "`blocking` annotated I/O must be called from the context of the Tokio runtime." })

This seems to be a [known issue](https://github.com/tokio-rs/tokio/issues/1356).

On the documentation side, the methods like `read_to_string` are part of the `AsyncReadExt` trait, but rustdoc seems to struggle here: Clicking on name of the trait hyperlink seems to lead to some different [unnamed](https://docs.rs/tokio/0.2.0-alpha.1/tokio/prelude/trait._.html) trait that isn't what a want. And expanding the trait docs inline from the Stdin page show that the `read_to_string` method returns some opaque type `ReadToString`. This type is not hyperlinked, and so I have no idea that this thing is actually a future (and is thus no idea that i can use `await` with it, and also no idea what type it yields).

## Runtime

Next, I tried to use the [`runtime`](https://crates.io/crates/runtime) crate ([v0.3.0-alpha.6](https://crates.io/crates/runtime/0.3.0-alpha.6)), and its default native executor, but unfortunately this crate does not yet have support for either stdio streams nor timers (this is mentioned midway down the README for the crate).

## Others

Tokio and Runtime were the only two runtime crates that I knew of without searching. So I did a little [searching](https://crates.io/search?q=async%20runtime) on [crates.io](http://crates.io) for other things to try. I honestly didn't expect this to be very helpful (I've never had the skills to use [crates.io](http://crates.io) as a discovery tool), and indeed I found the results not very helpful. There were a lot of creates with promising, but generic names, such as:

- [futures-async-runtime](https://crates.io/crates/futures-async-runtime)
- [futures-async-runtime-preview](https://crates.io/crates/futures-async-runtime-preview)
- [async-runtime](https://crates.io/crates/async-runtime)
- [runtime-async](https://crates.io/crates/runtime-async)
- [runtime](https://crates.io/crates/runtime)
- [runtime-tokio](https://crates.io/crates/runtime-tokio)

The first looked the most promising (I did not try the others). Its [documentation link](https://docs.rs/futures-async-runtime/0.2.1/futures_async_runtime/) from [crates.io](http://crates.io) was broken, but after some clicking I landed upon [something useful](https://rust-lang-nursery.github.io/futures-api-docs/0.3.0-alpha.18/futures/). I could not find an annotation that could be used to turn `fn main()` into an async function, so I quickly tried to write some old-style futures code. I got something to work that would read from stdin, but could not find any timers:

```rust
async fn read_from_stdin() -> Result<String, Box<dyn Error>> {
    let mut stdin = futures::io::AllowStdIo::new(std::io::stdin());
    let mut s = String::new();
    let len = stdin.read_to_string(&mut s).await?;
    Ok(s[..len].to_owned())
}

fn main() {
    let runner = read_from_stdin().then(|s| {
        println!("data from stdin: {:?}", s);
        futures::future::ok::<(), ()>(())
    });
    ThreadPool::new().unwrap().run(runner);
}

```

This probably took me about 30 minutes to figure out how to write due to some stalls, but this isn't a support forum, so there's no need to get into that now.

Documentation was pretty solid, but it's not easy to hold all the types in your head (Futures, FuturesExt, AsyncRead, ASyncReadExt, AllowIO, etc). There was a lot of flipping between browser tabs. I did notice that this crate has a "async-await" feature, but to be honest it wasn't clear to me what I needed it for (the above code compiles without it).

# Summary

I was pretty excited when writing the tokio version due to how straightforward the code looked. But it was disappointing to not have ended up with any working code. I thought briefly about trying to roll my own runtime, but that felt way over my head (and beyond the scope of what I initially set out to do).

I skimmed the [rust async book](https://rust-lang.github.io/async-book/) to see if it had any suggestions about what other runtimes to try, but it doesn't yet have anything to say here.

I still remain excited about async in rust, but feel like I need to wait a few more months for the ecosystem to continue to build out and up 🚀

---

<div class="post-metadata">

**Author:** ![najamelan](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/najamelan/32/3162_2.png) [@najamelan](https://internals.rust-lang.org/u/najamelan)\
**Post date:** [August 14, 2019, 11:42am UTC](https://internals.rust-lang.org/t/async-await-ecosystem-experience-report/10707/2 "2019-08-14T11:42:04Z")

</div>

Just want to give you some feedback:

- tokio is currently being rewritten for std futures, so it's not at all stable
- stdin is tricky in async because it's a global handle in the entire process and normally a blocking io, but there is examples of how to do it with channels, [like this one](https://gist.github.com/boxdot/0e707be10d86a610296483ab78f6b121) and [more here](https://stackoverflow.com/questions/30012995/how-can-i-read-non-blocking-from-stdin).
- as for timers, there is [futures-timer](https://crates.io/crates/futures-timer)
- as for runtimes, the [runtime](https://crates.io/crates/runtime) crate should work fine, but pulls in network dependencies, otherwise I wrote an [async\_runtime](https://crates.io/crates/naja_async_runtime) which is more barebones, just spawning futures to avoid mixing it with network dependencies and without the need to box the futures.

---

<div class="post-metadata">

**Author:** ![eminence](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/eminence/32/4018_2.png) [@eminence](https://internals.rust-lang.org/u/eminence)\
**Post date:** [August 14, 2019, 1:48pm UTC](https://internals.rust-lang.org/t/async-await-ecosystem-experience-report/10707/3 "2019-08-14T13:48:12Z")

</div>

Thanks for the hints. I'll try to wire up `runtime` + `futures-timer` tonight to see how that goes.

I just realized that I omitted your own crate in my list of crate search results. That was definitely unintentional, and I'm sorry about that. I'll also give your crate a try, too!

---

<div class="post-metadata">

**Author:** ![najamelan](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/najamelan/32/3162_2.png) [@najamelan](https://internals.rust-lang.org/u/najamelan)\
**Post date:** [August 14, 2019, 1:49pm UTC](https://internals.rust-lang.org/t/async-await-ecosystem-experience-report/10707/4 "2019-08-14T13:49:53Z")

</div>

@eminince np, the main difference for you here will be that your crate doesn't need to pull network dependencies as you don't seem to do networking.

oh, and that if you want you can spawn futures on a LocalPool (not threadpool) if you don't need threads.

---

<div class="post-metadata">

**Author:** ![najamelan](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/najamelan/32/3162_2.png) [@najamelan](https://internals.rust-lang.org/u/najamelan)\
**Post date:** [August 14, 2019, 7:14pm UTC](https://internals.rust-lang.org/t/async-await-ecosystem-experience-report/10707/5 "2019-08-14T19:14:43Z")

</div>

Just discovered yet another timers crate:

> **[tinaun/futures-native-timers](https://github.com/tinaun/futures-native-timers)**
>
> native timers for futures 0.3. Contribute to tinaun/futures-native-timers development by creating an account on GitHub.

And some discussion about it:

> <https://github.com/withoutboats/romio/issues/62>

Haven't got any experience with either crate.

---

<div class="post-metadata">

**Author:** ![atagunov](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/atagunov/32/5877_2.png) [@atagunov](https://internals.rust-lang.org/u/atagunov)\
**Post date:** [August 14, 2019, 7:58pm UTC](https://internals.rust-lang.org/t/async-await-ecosystem-experience-report/10707/6 "2019-08-14T19:58:46Z")

</div>

Would be pretty cool to add this (another?) list of crates to the async book  
Even better with some examples

Internet is _full_ of .1 tutorials  
Uber confusing

---

<div class="post-metadata">

**Author:** ![najamelan](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/najamelan/32/3162_2.png) [@najamelan](https://internals.rust-lang.org/u/najamelan)\
**Post date:** [August 15, 2019, 1:14pm UTC](https://internals.rust-lang.org/t/async-await-ecosystem-experience-report/10707/7 "2019-08-15T13:14:06Z")

</div>

I was thinking this too. At some point before stabilization it would be good if there was a blog post giving a good overview of all the crates that are up to date with async-await going from basic (runtimes) to more specific (some specific functionality, but which has an async API).

Maybe that's a good thing for areweasyncyet.rs?

---

<div class="post-metadata">

**Author:** ![eminence](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/eminence/32/4018_2.png) [@eminence](https://internals.rust-lang.org/u/eminence)\
**Post date:** [August 15, 2019, 1:23pm UTC](https://internals.rust-lang.org/t/async-await-ecosystem-experience-report/10707/8 "2019-08-15T13:23:56Z")

</div>

Would it be appropriate for the rust async book to make specific recommendations about what crates to use? Or would that be too opinionated for an official rust book?

---

<div class="post-metadata">

**Author:** ![najamelan](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/najamelan/32/3162_2.png) [@najamelan](https://internals.rust-lang.org/u/najamelan)\
**Post date:** [August 15, 2019, 1:25pm UTC](https://internals.rust-lang.org/t/async-await-ecosystem-experience-report/10707/9 "2019-08-15T13:25:14Z")

</div>

In my opinion this is more something for a blog post than for the async book. The async book has enough on it's plate covering all ecosystem independent aspects of the language.

Also because the ecosystem is by definition a moving target, and so after 6 months whatever we write now is bound to be outdated.

---

<div class="post-metadata">

**Author:** ![atagunov](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/atagunov/32/5877_2.png) [@atagunov](https://internals.rust-lang.org/u/atagunov)\
**Post date:** [August 16, 2019, 9:27pm UTC](https://internals.rust-lang.org/t/async-await-ecosystem-experience-report/10707/10 "2019-08-16T21:27:18Z")

</div>

> [@najamelan](#):
>
> this is more something for a blog post than for the async book

batteries not included/futures not usable w/o a runtime  
=\> a semi-official list of recommended runtime crates is needed

> [@najamelan](#):
>
> after 6 months whatever we write now is bound to be outdate

being on github book can be updated too?  
could it have chapters like "Runtimes Overview Sep 2019"?

---

<div class="post-metadata">

**Author:** ![DoumanAsh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/doumanash/32/5790_2.png) [@DoumanAsh](https://internals.rust-lang.org/u/DoumanAsh)\
**Post date:** [August 17, 2019, 7:34am UTC](https://internals.rust-lang.org/t/async-await-ecosystem-experience-report/10707/11 "2019-08-17T07:34:25Z")

</div>

I have OS based timers crate of my own [https://github.com/DoumanAsh/async-timer](https://github.com/DoumanAsh/async-timer)

It is more militaristic

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [November 15, 2019, 7:41am UTC](https://internals.rust-lang.org/t/async-await-ecosystem-experience-report/10707/12 "2019-11-15T07:41:44Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
