Some musings on the async ecosystem and compatibility between async-std and tokio... 1/15
When the async-std runtime was first introduced, some were worried that the async ecosystem would get split into two: one based on tokio and one based on async-std.
Now I'm working on the third major runtime. Very soon we'll have a lot of different runtimes to choose from. 2/15
Now I'm working on the third major runtime. Very soon we'll have a lot of different runtimes to choose from. 2/15
But remember, the Future trait and the futures crate have always been intentionally designed to be completely agnostic to the underlying runtimes. So there shouldn't be any fragmentation, no matter how many runtimes there are. 3/15
To avoid the ecosystem split, async libraries should not depend on async-std or tokio. Only binaries should use a runtime as a dependency. 4/15
The main question is then: what should async libraries do if they need to spawn futures or use types like TcpStream? The answer is that they shouldn't. And in most cases they really don't need to... 5/15
Instead of spawning a future, your async library should return the future to the user so that the user can spawn it however they want. 6/15
Instead of creating a TcpStream inside your async library, let the user create one for you and then accept any stream implementing AsyncRead and AsyncWrite as an argument. 7/15
To illustrate what that means in practice, let's compare hyper and async-h1. 8/15
https://docs.rs/hyper
https://docs.rs/async-h1
https://docs.rs/hyper
https://docs.rs/async-h1
Here's a hyper server running on async-std. 9/15
https://github.com/async-rs/async-std-hyper/blob/6025fafe549a2b4715c8bf9e80fa8240be81ff8a/src/main.rs
https://github.com/async-rs/async-std-hyper/blob/6025fafe549a2b4715c8bf9e80fa8240be81ff8a/src/main.rs
Here's an async-h1 server running on async-std. 10/15
https://github.com/http-rs/async-h1/blob/f930e7bbbb48c21c69535ab86a4cdc5a36ecde49/examples/server.rs
https://github.com/http-rs/async-h1/blob/f930e7bbbb48c21c69535ab86a4cdc5a36ecde49/examples/server.rs
Hyper requires a lot of glue code because it starts an HTTP server on its own and then needs to invoke your runtime's functions. 11/15
In contrast to that, async-h1 lets you create a TCP listener and accept TCP streams on your own. Then, all async-h1 does is it reads HTTP requests from an AsyncRead and writes HTTP responses into an AsyncWrite. 12/15
The key difference is: hyper acts like a framework because it invokes your code, while async-h1 acts like a library because it's invoked by your code. 13/15
Async-h1 doesn't even care about the actual HTTP server - it's basically an async HTTP serialization/deserialization library! 14/15
In conclusion, prefer async libraries over async frameworks.
If async libraries only use the standard Future/Stream/AsyncRead/AsyncWrite traits to interface with the outside world, we won't end up with an ecosystem split. 15/15
If async libraries only use the standard Future/Stream/AsyncRead/AsyncWrite traits to interface with the outside world, we won't end up with an ecosystem split. 15/15