-
Notifications
You must be signed in to change notification settings - Fork 17
Implement async support #22
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
Conversation
|
Hi @aDogCalledSpot, thanks for considering taking this on. I'm broadly aligned here and would welcome a PR. I'd actually just been thinking about the future of Butane this month, and with Rust's async story maturing in the time since I created Butane and becoming by far the norm in web servers (although with sqlite support and object-persistence focus, Butane isn't aimed solely at web servers) and in newer ORMs (like SeaORM) plus the second-executor panic, I've come fully around to the view that Butane needs to be primarily async. Let me try to get a post up in the next couple days with my overall thoughts on the future/direction. I'm currently adjusting to life with a newborn so my own code-writing is going to be slow at the moment, but I'll review PRs as quickly as possible. I agree with the async-trait dependency. The one thing I'm a little torn about is whether we want to preserve a sync option for use with the sqlite backend. It would make things a little more complex (or at least larger) but I think there could be value in it for simpler apps that don't need/want async. I won't block this PR on adding that option, but I might do it myself before releasing a new crate version. |
|
Sounds good! We'll get started on it tomorrow 👍 As to the sync option: I think it will be easier to assess the workload for keeping both options once this PR moves ahead. I actually hadn't heard of SeaORM. Using SQLx as a backend looks interesting since then we would have async support for sqlite as well. We'll play around a bit with it. |
|
Switching to tokio-postgres is pretty straightforward. Sqlite however is a bit annoying since the Connection isn't @sssemil has been looking into SQLx a bit more and they offer an |
121e915 to
c132064
Compare
|
Thanks, this is looking good so far! I really appreciate you picking this up.
|
|
Postgres is moving forward nicely, however I'm blocked by Rusqlite is unfortunately causing issues. I decided to use a mutex for guarding the connection so there wouldn't be any issues when doing something like: However, transactions hold a reference to the connection as well and since these are implemented in rusqlite, there is no way to add a mutex there. So two transactions acting upon the same connection concurrently would cause races. I wanted to have a look at how it's done at diesel_async but found out that SQLite isn't supported there. Only MySQL and Postgres are and I guess this is why. How would you like to handle this? |
|
It's a good question. I poked at it a little yesterday but didn't get super far. It occurs to me that one gross would be to run the actual sqlite operations on a dedicated thread pool and interface with the async methods over channels, but aside from high complexity I imagine that would have undesirable perf. It might be worth taking a look at what https://crates.io/crates/sqlx is doing. Or if we preserve the option to run sqlite in sync mode, maybe async-mode sqlite should just go to sqlx rather than rusqlite. |
Why not then use sqlx for everything else? |
Butane has a couple different use cases
Because of (2), as I mentioned above, I'd like to preserve the option to have non-async capabilities at least with the SQLite backend before releasing a new breaking-version (although it doesn't have to be in this PR). Getting back to sqlx. . .I'm a bit reluctant to take an overall non-optional dependency on sqlx because I've hear anecdotes about it having very poor performance, and it's also quite heavyweight in terms of dependencies (not that Butane is lean, but bringing in a whole new pile of transitive dependencies isn't preferable). Related: rusqlite/rusqlite#697 |
|
The problem I see is that maintaining sync and async code side-by-side will result in a lot of duplicate code that can't be extracted because the function signatures differ in their Having a separate subcrate like that could be done in this MR and we would just implement Postgres for now and define features accordingly. We could also have a look at tokio-rusqlite. |
|
My MR mentioned above got merged but the version number for tokio-postgres hasn't been bumped up yet. We can use the git link as dependency for now but will need to check for when it's stabilized. Maybe ask the maintainer to bump up the number if it hasn't been done in the next few weeks. |
|
Could this PR be updated, and using the git dependency until the upstream fix has been released. I would like to be using this PR's branch in the interim. |
|
@aDogCalledSpot I think perhaps what makes the most sense is for me to create a branch called |
fa490b8 to
2b6c1d6
Compare
|
Sounds good! I hope to find some more time this week as I've unfortunately been very busy the last few weeks. I don't think there's much point in you starting on the sqlite part until I've come further with the postgres part since that should sort out most problems with the interfaces. |
2b6c1d6 to
7900468
Compare
|
I was unfortunately sick for a long time and didn't get around to working on it much. I finally made it compile today. So I think the interfaces should largely be correct now. I'll keep you updated on how it goes with testing and revisiting everything to see if some stuff can maybe be simplified. |
|
Completed in #276 |
Async support wouldn't only be good because async is useful for anything using the network but also because using the blocking postgres backend is currently not possible when a butane transaction is made from inside an async fn.
In the postgres library, there are a few instances such as this one where an own executor creates a blocking call to the network interface. If the function butane is called from is already async, then this will lead to a second executor being started and the program panics.
Plans for this PR:
@sssemil and I would like to do the following:
Limitations
Connectiontrait would need to use async fns. However, these were only been introduced to nightly last November and will probably be a while until they are stabilized. We would have to introduce the async-trait crate as a dependency in the meantime.Let us know if there is anything you think we should be aware of or that you would like to discuss.
Related: #13