-
-
Notifications
You must be signed in to change notification settings - Fork 34
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
Add support for choosing between async-std and Tokio #29
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow, thanks for the PR! This is great and I'm definitely interested in making this Tokio-compatible, since that seems to be pretty popular, too.
Is making async_std
optional really important? I'd rather not pick up a breaking change if I don't have to.
That said, if we're gonna do a breaking change, I'd rather port cacache to smol
, which would be WAY more lightweight than async-std and it would be more acceptable to have it "always" pulled in, if that makes sense?
@@ -25,15 +22,28 @@ serde = "1.0.130" | |||
serde_derive = "1.0.130" | |||
walkdir = "2.3.2" | |||
either = "1.6.1" | |||
async-std = { version = "1.10.0", features = ["unstable"] } | |||
async-std = { version = "1.10.0", features = ["unstable"], optional = true } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Combined with
[features]
default = ["async-std"]
it doesn't really change anything for your existing users unless they've put default-features = false
on the dependency already, which would be a really odd thing to do on a crate which had no features.
I'm pretty sure that only one runtime can be pulled in at a time, since switching from one to the other means replacing all calls to At least with the way I did it (which was to move all that selecting code to a single module from which all the rest of the code calls them), only one runtime "feature" can be active at once, else you get a bunch of warnings about duplicate definitions:
Incidentally, this approach should make it possible to support other runtimes too, assuming they provide the same facilities required as the others do. I haven't looked into (Oh, also, that Clippy error from the CI comes from existing code that I hadn't touched, but I can add a quick commit to fix it if you'd like to make the CI happy.) |
You can actually pull in multiple runtimes, though generally you only execute one at a time. Futures generated by libraries using one runtime's library functions can be used on the other runtime, and vice-versa, by using https://docs.rs/async-compat for bidirectional conversion. The main catch of using Would this work for you as a solution? Sorry if I seem resistant, but I'm not sure how I feel about the added complexity of forcing users to specify feature flags, or putting out a semver-breaking change when |
Oh, I didn't think to give I understand your hesitation for sure, increased complexity is always something that should be weighed carefully against the potential benefits it brings, and if I mean, there's the issue of documenting these new things (the fact that you can change runtime using feature flags) and potentially complicating doctests (which runtime should be used in them? Only the default one? (But then code in doctests only work for the default one) Both? (But how?) Not to mention the benchmarks; where you can't even have optional dependencies chosen by features. It's a bit of a mess, I see that. 😅 As for semver, like I said in the comment I left on your review comment, I don't think this would be a breaking change for any downstream user unless they have done something very unexpected (set |
So, finally having time to play around with this again, I thought I would, just for fun, try using
Instead, this ran without issue. I'm not quite sure how this works, but... it just does. [dependencies]
tokio = { version = "1.13", features = ["full"] }
cacache = "9" #[tokio::main]
async fn main() {
cacache::write("test", "hello", "world").await.unwrap();
let list = cacache::list_sync("test");
assert_eq!(list.count(), 1);
let mut list = cacache::list_sync("test");
assert_eq!(list.next().unwrap().unwrap().key, "hello");
let value = String::from_utf8(cacache::read("test", "hello").await.unwrap()).unwrap();
assert_eq!(value, "world");
} I... don't know how to feel, lol. |
oh wow. I guess Tokio is trying to be more compatible now or something??? |
Thought I'd leave a note on this that I've been using cacache in a trait with async methods supported via async-trait. I have one implementation of that trait that uses async-std and one that uses tokio, so far I haven't had any issues when using either runtime. |
This PR is based on the work @alexschrod did in PR zkat#29. All I did was carry it over the finish line. This PR adds a feature to the crate named `tokio-runtime`. If you disable default features and enable this new one, cacache uses tokio as its async executor. This makes integrating cacache with tokio-using projects easier, because the file types leak out if you use anything more than the top-level convenience functions. There are a few other small changes in this PR worth noting. - The README shows how to switch runtimes. - Changed around the shims in the async_lib.rs module a little bit. - There's a justfile to run common tasks, including those in makefile.toml. The default shell is `sh`, so this might not work out of the box for Windows users. - The tests can now run under either runtime. The justfile has a recipe that runs them both. - The benchmarks can also run under either runtime. The justfile has two recipe for this, one using bench and the other using criterion's runner. - The dependencies now pull in async-attributes by default along with async-std. This made it easier to swap runtimes in the tests. - All dependency versions have been bumped. Co-authored-by: @alexschrod
This PR is based on the work @alexschrod did in PR zkat#29. All I did was carry it over the finish line. This PR adds a feature to the crate named `tokio-runtime`. If you disable default features and enable this new one, cacache uses tokio as its async executor. This makes integrating cacache with tokio-using projects easier, because the file types leak out if you use anything more than the top-level convenience functions. There are a few other small changes in this PR worth noting. - The README shows how to switch runtimes. - Changed around the shims in the async_lib.rs module a little bit. - There's a justfile to run common tasks, including those in makefile.toml. The default shell is `sh`, so this might not work out of the box for Windows users. - The tests can now run under either runtime. The justfile has a recipe that runs them both. - The benchmarks can also run under either runtime. The justfile has two recipe for this, one using bench and the other using criterion's runner. - The dependencies now pull in async-attributes by default along with async-std. This made it easier to swap runtimes in the tests. - All dependency versions have been bumped. Co-authored-by: @alexschrod
This PR is based on the work @alexschrod did in PR zkat#29. All I did was carry it over the finish line. This PR adds a feature to the crate named `tokio-runtime`. If you disable default features and enable this new one, cacache uses tokio as its async executor. This makes integrating cacache with tokio-using projects easier, because the file types leak out if you use anything more than the top-level convenience functions. The PR implements the feature using shims in a new submodule named `async_lib`. This module conditionally uses either async-std or tokio based on feature selection, and hides some differences with convenience functions. This change should not be a breaking change, because the default is still async-std. There are a few other small changes in this PR worth noting. - The README shows how to switch runtimes. - There's a justfile to run common tasks, including those in makefile.toml. The default shell is `sh`, so this might not work out of the box for Windows users. - The tests can now run under either runtime. The justfile has a recipe that runs them both. - The benchmarks can also run under either runtime. The justfile has two recipe for this, one using bench and the other using criterion's runner. - The dependencies now pull in async-attributes by default along with async-std. This made it easier to swap runtimes in the tests. - All dependency versions have been bumped. Co-authored-by: @alexschrod
Closing in favor of #36, which builds on this work. Thanks again, @alexschrod! |
This PR is based on the work @alexschrod did in PR #29. All I did was carry it over the finish line. This PR adds a feature to the crate named `tokio-runtime`. If you disable default features and enable this new one, cacache uses tokio as its async executor. This makes integrating cacache with tokio-using projects easier, because the file types leak out if you use anything more than the top-level convenience functions. The PR implements the feature using shims in a new submodule named `async_lib`. This module conditionally uses either async-std or tokio based on feature selection, and hides some differences with convenience functions. This change should not be a breaking change, because the default is still async-std. There are a few other small changes in this PR worth noting. - The README shows how to switch runtimes. - There's a justfile to run common tasks, including those in makefile.toml. The default shell is `sh`, so this might not work out of the box for Windows users. - The tests can now run under either runtime. The justfile has a recipe that runs them both. - The benchmarks can also run under either runtime. The justfile has two recipe for this, one using bench and the other using criterion's runner. - The dependencies now pull in async-attributes by default along with async-std. This made it easier to swap runtimes in the tests. - All dependency versions have been bumped. Co-authored-by: @alexschrod
Hello! 👋
I wanted to use this library, but all my async code is using Tokio as the runtime, so the fact that this library was using async-std meant that I couldn't use it. However, after investigating a little, I realized that for the two runtimes are nearly drop-in replaceable, so I added a small "compatibility-layer" module (named
async_lib
) to the project, which exports the currently selected runtime's primitives (and occasional shims, where required) so that the actual business logic code remains mostly the same as it did before.While the code passes regular tests, I have not yet modified the documentation tests/examples, because I'm honestly not sure how to best ensure that the example uses the right runtime without it looking messy in the documentation. So the doctests currently only pass when async-std is selected as the runtime.
As for the benchmarks, dev-dependencies are not allowed to be optional, so I couldn't find a way to make it work for both runtimes, and so I've left the benchmarks only compatible with async-std for now.
I updated the README.md to state that Tokio is now supported, but I didn't specify how to pick the runtime, since I wasn't quite sure where to fit it in. I left async-std as the default runtime, and if a user wants tokio instead, they must do something like
Let me know if you have any thoughts on what I should do with doctests and/or benchmarks if that is currently an issue for accepting this PR, as well as any other feedback you may have.☺️