sorting the wheat from the chaff

First steps in async Rust

§ The target

Learning how to write a simple web service in Rust that performs HTTP requests.

These requests should be asynchronous because we don't know when the external service will answer. Take into account also service timeouts.

§ Tooling

Still not sure what to use, let's try to quickly from the bottom up:

The operating system kernel has threads. When you launch a thread, then you must poll it and when it finishes you get the results.

On top of the OS I need a "runtime", a layer that manages the .poll() method. The poll returns either an "OK" or "NOT YET DONE" kind of response. The runtime puts to sleep this "thing" that polls the thread for some time, than asks again.

Tipically I have a pool of these threads.

An async function in Rust is abstracted as a Future, i.e. something that is launched and will eventually resolve to a result. A Future is polled until is resolves and returns some result (or an error). Future have been recently stabilized in Rust stable.

I'd like to use the soon-to-be (as of July 2019) stabilized async/await syntax. Draft of the syntax is been published here.

§ The runtime

I ought to choose a runtime. There are two possibilities:

  • tokio: tried to use it before we had Future and await/async available and it was impossible to grasp. Looking at the versioning, the project seems to have stalled until recently.

  • Runtime: the name of the project is confusing, the aim seems to add a thin layer to abstract the runtime and let the user choose between two runtimes: tokio and the "native" (Romio+Juliex) one. Reading this comment on the future async dor Rocket, "Runtime" does not looks like a sensible choice. Runtime build on two components:

don't understand the current state of Runtime and if I should use it.

[Q] Why do I, as the developer, should be concerned about choosing a runtime? : only if I'm not using a web framework that abstracts the choice for me.

[Q] Do I really have to manually impl Future for my async methods and manage the states?: Maybe not. I can probably add a placeholder crate (https://github.com/alexcrichton/futures-await) to use today the syntax that will be stabilized tomorrow (hopefully available in Rust stable 1.38/9). But the syntax differs from that of the Runtime crate. And the crate seems to be abandoned.

[Q] How does this crate fits into the picture: https://github.com/rust-lang-nursery/futures-rs

[Q] reqwest/hyper async clients: how do they fit into the picture?: An async client is needed to emit thread-unblocking http requests, that don't block the thread. If I run an async server (ex. Hyper), then I must use also an async client, too.

§ Frameworks

A nice to have, but I think I need something more basic, just something listening and allow some administration of the tasks. Not a user facing component.

Tide: this is Flask-like light framework that uses Runtime. Develope by the async WG.

warp, which relies on hyper and tokio. Developed by Sean McArthur.

tower-web, a (seemingly) very early work-in-progress framework. Relies on futures 0.1 and tokio 0.1. Developed by Carl Leche.

§ Special mentions

actix-web: a full-fledged web framework. Looks to be very fast not easy to grasp (especially the middleware part is confusing).

rocket, I already use it, it's synchronous but I believe works to make it async has started, see this PR (porting to hyper 0.12).

§ References

Comments closed for this article