-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tracking Issue for Async I/O migration #1065
Comments
Wasn't
I don't see why not. Though it would be relatively trivial to create it I'll take a look at @jebrosen Roughly how much of the documentation can be switched over to |
Right! I'll fix that.
The issue is the return type of routes. Currently the codegen assumes that a non-async function returns some type
The only place where there is a choice is routes; currently everything else is an async-only API and documentation should reflect that. I was going to wait a bit before pushing hard for docs, as there are likely a few design issues to be resolved with which APIs return which futures with what lifetime bounds. My admittedly hand-wavy assumption was that we would explain traits like Another really important point here is that manual |
That certainly makes sense. Adding support for
Probably best to hold off on docs for the time being, then. |
Quick advertisement for https://github.com/rustasync/async-compression, this should allow just drop-in wrappers to transparently compress/decompress |
@jebrosen this is awesome! Just as a side note, both tokio and hyper master are working with |
|
Hi - what would you be looking for in a pull request to explore this? I've been developing some projects using Rocket and have been using both tokio-postgres and the synchronous rust-postgres, as well as their connection pools, and I would like to help if I think I know how. |
I have not tried too hard to test what "ensure they will be usable" entails. There are a few problems I can see ahead of time:
At a minimum, I think we should be able to:
|
I am mostly waiting on #1071 (after a new tokio alpha and hyperium/hyper#1897) so that we don't need to significantly rewrite too much code that directly deals with the low-level bits -- which are pretty different between tokio 0.1 and 0.2. For example, I suspect #1070 will take almost as much work again as it would to implement it now. At present all public APIs use async/await and futures 0.3, but everything runs on a tokio 0.1 runtime. This means that I/O types from tokio 0.2 cannot be used directly in routes yet, for example. For anyone interested in kicking the tires pretty early on, I have written a short and possibly incomplete guide to trying projects against the async branch. At this stage the most helpful feedback would be examples of "things I can't do anymore" or that now require expensive allocations, especially in implementations of
|
@jebrosen have you taken a look at |
I did try async-trait today and ran into some issues that might be able to be worked around. I would prefer to use async-trait on either all affected traits or none of them, and I'm hopeful that it will be usable. |
Unfortunately that would be a breaking change to any public traits, as far as I know there's no way to be forward compatible with GATs in traits. You can be forward compatible with using |
Yeah, it would definitely be a breaking change, as APIs would be different. I was referring to the changes in the code itself, which would amount to deleting a few lines. |
Update on the attempt to use |
|
I fixed this bug on nightly. Please make sure however that your uses of |
After attempting to convert r-spacex/Titan to the current HEAD of the async branch (dcea956), I ran into a glaring issue that needs to be addressed before even a prerelease. Currently, diesel (at least its PostgreSQL type) doesn't implement While not directly related to Rocket, this is something we'll likely want to work with @sgrif et al. to ensure full compatibility. |
I tried the async hello world it was working fine.
|
Yes, TLS is not implemented yet. I'll make that clearer in the main comment. |
Not sure if this is the right place for such a question, but here we go: I'm currently writing a backend for a web app with Rocket, using tokio-postgres directly at the moment (but this should apply to pools as well). Would it be possible to implement such an async variant? I have no idea how much work would have to go into that, as far as I can tell, it probably wouldn't be as elegant as the current local_cache implementation, but it should be doable (taking a future instead of a closure and awaiting it once). If it's not too hard, maybe I could even contribute it. EDIT, 10 minutes later: pub async fn local_cache_async<T, F>(&self, fut: F) -> &T
where F: std::future::Future<Output = T>,
T: Send + Sync + 'static
{
if let Some(s) = self.state.cache.try_get() {
s
} else {
self.state.cache.set(fut.await);
self.state.cache.get()
}
} I just want to say that I love async. |
Why use |
You're right, it's not a good example; I'm currently waiting for Rocket to implement async pooling support, that's why I use the connection directly. However, as I said, this also applies to async pools, and if I want to implement something like |
You can still implement (side note: let's move this conversation to #1117) |
Hi, I'm getting a bunch of |
@Razican Do you know what code that is ultimately coming from? As far as I can tell it's not from rocket or hyper. |
@jebrosen solved. It turns out it was coming from the PostgreSQL database backend. It seems that doing all the tests in parallel, it was creating too many connections at the same time :) |
@jebrosen whats the status on getting the async branch merged? Are there any issues we can help with to push it over the finish line? |
Since my last update comment above, these were also done:
I am currently working on the following, in #1242 (and forgot to link it back here):
My next PR after that will likely be a wrapper making it safe(r) to use the currently supported blocking databases. I will look into any async-specific issues that could use assistance. One that comes to mind now is typed headers - e.g. hyperium/headers#48 (comment), or an investigation into which typed header crate(s) would be suitable for built-in support in Rocket would be helpful. |
I have posted a shortup writeup on what kind of investigation needs to be done on typed headers, if anyone is interested in helping with that particular effort - #1067 (comment) |
Has there been any work regarding logging? I think tracing would fit the bill quite nicely as outlined in #21 |
Hi all, I've switched over fully to the latest Rocket with full async for a couple of my latest projects, but was running into the fact that compression support doesn't exist yet. This was inflating responses to my users and bringing up the cost of my bill for network egress, so I hacked up a placeholder solution that adds back gzip support: Ameobea@eab53cf The API is exactly the same as before; you just add I figured this may be useful to other people who wanted to gain the benefits of compression and the latest async Rocket without having to re-write any of their code. Once someone gets around to doing the job properly, it should just be a change to EDIT 2021-07-17: I've created a library that performs response compression using the |
Note that I'm getting some issues when using a managed state async fn dependencies(state: State<App>, repo: String) -> String { }
|
@mimoo from what I've seen, when using async routes, you have to specify the anonymous lifetime like so async fn dependencies(state: State<App, '_>, repo: String) -> String { String::new() } |
Note that this is not a Rocket restriction, but rather, a Rust restriction. Also, it's |
I'm guessing that Responder is still a sync trait in the latest async code. I was hoping to make a request with reqwest in |
This was a conscious decision, not something that's left to do. In fact, Specific to your comment, sending HTTP requests in the responder sounds rather odd. A responder generates a response, while this sounds like more processing, which should occur in the handler. |
@SergioBenitez You're correct, that it's not the place for it. I was using okapi for OpenAPI, and part of the API is for an upstream server, I have stub handlers with dummy data for now, but the idea is that I want to send all headers and all of the body to the upstream server, then respond with exactly what it said. What the upstream server said will likely be what the return type of the handler was, but I didn't want to deserialize just to reserialize, so I made a "wrapper" responder that implemented the traits for Rocket and okapi, but it generated the response completely. However, when I added in reqwest, I got a panic, and I also found that I didn't have access to the body, so I switched to using a FromData struct that I'll pass in to that responder, so all of the |
Is there a better way to do forwarding? |
It sounds like you should be implementing a custom |
@SergioBenitez Thanks! Great framework, by the way! |
@Type1J I had this exact issue recently, with some messing around you can get a compatible async stream from the reqwest response body to store in a struct implementing |
I've implemented async response compression using the https://github.com/Ameobea/rocket_async_compression It currently only works with the git version of Rocket. The internal implementation is extremely simple and I think it's pretty much good to go for including in Rocket itself. Let me know if anyone is interested in making that work. |
@Ameobea might be worth making the compression level customizable via the |
With the new |
Status
Rocket's
master
branch is currently fully asynchronous and supports async/await!Pending
A "blocking-in-async" lint in
clippy
orrustc
would be much nicer, if feasible, but would occur upstream...someday.TODO.async
) throughout code.Done
AsyncRead
vsStream<Item=Result<Chunk, Error>>
Design
The
async
APIs are based on rust's async/await feature andstd::future::Future
, running on thetokio
(0.2) runtime.#[get|post|route(...)] async fn(params...) -> R
whereR
is anyResponder
type. Routes that do notawait
anything can remain unchanged.#[catch]
ers can also be defined as anasync fn
.Data
now returnFuture
s that must be.await
ed. As a consequence, any route that usesData
directly must beasync
. Routes that use data guards such asJson
are not affected by this change.async
, as it will allow other requests to continue while waiting for the operation.FromTransformedData
andFromData
,Fairing
,Responder
)async-trait
, re-exported as#[rocket::async_trait]
.DataStream
implementstokio::io::AsyncRead
instead ofRead
. Thus,FromTransformedData::transform
andFrom(Transformed)Data::from_data
areasync fn
or returnFuture
s.set_body
and related methods expecttokio::io::AsyncRead
instead ofRead
.Fairing::on_response
andResponder::respond_to
are nowasync fn
. This allows Responders and Fairings to access and/or replace the body data.rocket::local::asynchronous
androcket::local::blocking
. Theblocking
test API is simpler to use, and recommended when possible.#[rocket::main]
,#[rocket::launch]
, and#[rocket::async_test]
have been added to makeasync fn
easily accessible formain()
andtest()
.The text was updated successfully, but these errors were encountered: