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
Async Diesel middleware and example #309
Comments
This is definitely a better approach IMO, but my only concern is that I'm not sure we should really push Diesel that much if it truly won't support async... if we push synchronous database calls into a Gotham environment, the whole thing is going to run much slower. I mean, people are opting into that by using Diesel, but I just want to make sure we make it clear (even in the API) that that's what they're doing. |
I think that using a relational DB from a web app is so common, and Diesel is the defacto standard in rust to do that, Gotham would be lacking not to provide good support and examples for it. Also, correct me if I misunderstand what
It doesn't seem that Diesel natively supporting async is anywhere in sight. Are there drawbacks to the proposed approach that I'm missing? |
Sure, I don't disagree with that! Just that I'm not entirely sure how we go about this. I don't know |
Thanks @colinbankier for working on Diesel support. I've spent the weekend exploring Gotham a bit, and like it a lot. I did get blocked eventually, though, when I tried to work with a database. An official middleware, or a new example would be much appreciated. Is there anything I can do to help? |
Gotham has had unofficial support for Diesel for a while. A half finished middleware exists in its Git repository, and a work-in-progress pull request for an example using this middleware was closed recently. Official support seems to be a bit further down the road, as different ways to enable proper async support are currently being discussed (see gotham-rs/gotham#309). To get unblocked until official support arrives, the existing middleware implementation has been copied into the project. The goal is to remove it asap, but this is blocked by the above issue in Gotham.
Great to hear this would be useful @jdno. |
Awesome, I'll check out the branch somewhere this week. Maybe I can contribute something to the documentation. |
I found some time today to look at your code and the examples, and refactor my app to use the new middleware. The proof of concept endpoint I've built is a simple health check that prints the current environment (e.g. pub fn check(state: State) -> Box<HandlerFuture> {
let app_state = AppState::borrow_from(&state).clone();
let repo = Repository::borrow_from(&state).clone();
let future = repo
.run(move |connection| sql_query("SELECT 1").execute(&connection))
.map_err(|e| e.into_handler_error())
.then(move |result| {
let postgres_status = match result {
Ok(_) => Status::Pass,
Err(_) => Status::Fail,
};
let health = Health {
environment: app_state.config.env.clone(),
postgres: postgres_status,
};
let response = create_response(
&state,
StatusCode::OK,
mime::APPLICATION_JSON,
serde_json::to_string(&health).expect("Failed to serialize health"),
);
future::ok((state, response))
});
Box::new(future)
} It should be said that I am quite new to Rust, so this is probably not the best implementation. And most of my struggles could just be related to my lack of experience with futures and tokio. Having said that, these are my observations:
On the positive side, it was pretty easy to set this up. And knowing that Diesel won't block the main thread is quite nice. 🙂 |
Thanks for the great feedback @jdno. |
This is a really good point. I saw that the examples use Arcs, but didn’t understand why until now.
No worries. I’m a week on vacation myself. When I’m back I’ll play a bit more with the code to see what improvements I can make to the code, and my understanding of it. 😅 |
I have opened #313 to get some more feedback and suggestions on this approach. Thanks @jdno - based on your feedback I simplified the return type from I have a slightly larger app (also WIP) here: https://github.com/colinbankier/realworld-gotham |
Mostly this should be same as combining or chaining other sorts of futures. |
The current "under development" Diesel middleware provides a "blocking" api to use Diesel.
Some previous work was done (and abandoned) to provide a worker
CpuPool
middleware to allow not blocking request handling when using diesel.I have been experimenting with continuing this, but with a different approach. Although Diesel doesn't directly support async, we can still build an async application around it using
tokio_threadpool::blocking
. This removes the need to explicitly manage a separateCpuPool
, and looks like it will be a simpler implementation and api.I'm opening this issue to solicit discussion around this approach and coordinate efforts in pushing Diesel support forward.
The new experimental api so far provides a
repo
abstraction that handles the DB connection pool and wrapstokio_threadpool::blocking
. Usage looks something like:Previous work this would supersede includes:
#227
#77
#126
The text was updated successfully, but these errors were encountered: