Add an async interface using futures-rs#141
Conversation
d7fe429 to
c9fba9e
Compare
|
This should be "done" now. Only the basic |
|
Awesome. So happy to see this moving forward |
|
Thanks! I will be playing with this. |
|
Really nice. This makes me very happy :) I would merge it as such and then fix up some smaller things such as missing documentation on master. I would not waste too much time on that yet in case it turns out we need to tweak the API more. Would just need a release of combine before I can merge this. |
mitsuhiko
left a comment
There was a problem hiding this comment.
Only thing that needs changing before merging from my part is that combine points to a release.
|
👍 so good to see work here happening. I’ll look over the code today as well. |
src/connection.rs
Outdated
| pub trait ConnectionLike: Sized { | ||
| /// Sends an already encoded (packed) command into the TCP socket and | ||
| /// reads the single response from it. | ||
| fn req_packed_command(self, cmd: Vec<u8>) -> RedisFuture<(Self, Value)>; |
There was a problem hiding this comment.
I may have stuck a bit to close to the synchronous versions by using this pattern actually. I will be making a separate PR (building on this one) hopefully today where the Connection allows multiple commands to be in flight concurrently without needing an explicit pipeline. The trade off is that it won't be able to handle explicitly built pipelines (at least not initially) and there is some additional overhead due to needing Arc/Rc.
| match pieces.next() { | ||
| Some(detail) => fail!((kind, desc, detail.to_string())), | ||
| None => fail!((kind, desc)), | ||
| match parser.poll()? { |
There was a problem hiding this comment.
I should mention that instead of calling the asynchronous parsing here, we could parse directly from the Read instance. The only drawback is that the parser needs to be instantiated twice (once for I == PartialStream<easy::Stream<&[u8]>> and once for I == ReadStream<R>.
| keys: vec![], | ||
| } | ||
| .invoke(con) | ||
| script: self, |
There was a problem hiding this comment.
Sorry for the churn caused by accidentally having rustfmt on. I could revert some of the changes If you want but I fear the files I modified may have to stick. (Would be nice to run through rustfmt on the whole repo though in my opinion).
There was a problem hiding this comment.
@Marwes i'm fine enforcing rustfmt. I tried to do it in the past but it completely broke with some of the macros at the point. Need to reinvestigate this.
I should release 3.0.0-beta.1 (beta == only minor breaking changes planned) later today unless I get caught up in something and don't have time. |
src/connection.rs
Outdated
| } | ||
| } | ||
|
|
||
| pub mod async { |
There was a problem hiding this comment.
The file is already quite long and here we have another module.
IMO this should be extracted into its own file here.
There was a problem hiding this comment.
Just wanted to say. Also makes reading the diff hard because the types have the same name :)
There was a problem hiding this comment.
I could change to AsyncConnection etc but I feel it is more idiomatic to write async::Connection to avoid ambiguities in that case.
src/lib.rs
Outdated
| pub use types::{/* utility functions */ from_redis_value, /* error kinds */ ErrorKind, | ||
| /* conversion traits */ FromRedisValue, /* utility types */ InfoDict, | ||
| NumericBehavior, /* error and result types */ RedisError, RedisResult, | ||
| ToRedisArgs, /* low level values */ Value, RedisFuture}; |
There was a problem hiding this comment.
This auto-formatted change makes it both harder to read and to change.
IMO we should keep the old formatting and mark it so rustfmt does not touch it.
| @@ -0,0 +1,236 @@ | |||
| use std::fmt::Arguments; | |||
There was a problem hiding this comment.
Would it be better to have connection::sync and connection::async modules?
There was a problem hiding this comment.
As long as we still export connection::sync::Connection (and other types from that module) on the root module, we could split it up and not break existing usage.
There was a problem hiding this comment.
@badboy we never exposed modules anyways. Only the toplevel thing.
There was a problem hiding this comment.
@mitsuhiko Exactly, that's why I just wanted to mention that we re-export it to keep it working
There was a problem hiding this comment.
I left it under src/async.rs since I would need to re-export it as async under the root anyway.
|
I guess I can close my nom attempt which is a good thing! |
|
@gsquire Thanks for your effort anyway! |
|
Released a new version of combine and updated this PR to point to it https://crates.io/crates/combine |
|
Is there anything blocking this from being merged? |
|
IMO 2 things:
|
No, that only affects the async interface (they are largely separate implementations in that respect) |
👍 Thanks for clearing that up. I recall some discussion around having the implementations be unified, and it's good to hear there won't be any breaking changes due to this feature on the sync side. At least, until they unify :). |
|
Bump (@mitsuhiko @badboy ) |
|
Ping @mitsuhiko and @badboy . Anything I can do to help get this and #143 merged? |
|
I'm just back from a work week. I'll put this on my schedule for the week. |
badboy
left a comment
There was a problem hiding this comment.
Good job!
The rustfmt made it a bit harder to review, but I'm fine with it being done now and not having to deal with it later.
@mitsuhiko's "Request changes" should be resolved.
Some small things remaining and one last question:
Is it likely that we can switch away from a boxed future in the future (pun intended) by using -> impl X? (No need to do it here now)
Furthermore, we should at least run cargo bench --no-run on CI with nightly to ensure the code actually compiles. That can be done in another bug.
Cargo.toml
Outdated
| [features] | ||
| with-rustc-json = ["rustc-serialize"] | ||
| with-unix-sockets = ["unix_socket"] | ||
| # with-async-unix-sockets = ["tokio-uds"] |
There was a problem hiding this comment.
Please remove this comment.
Cargo.toml
Outdated
| tokio-reactor = "0.1" | ||
| tokio-tcp = "0.1" | ||
| tokio-io = "0.1" | ||
| # tokio-uds = { git = "https://github.com/Marwes/tokio-uds", branch = "only_tokio_upgrade", optional = true } |
benches/bench_basic.rs
Outdated
| extern crate tokio_core; | ||
|
|
||
| use futures::Future; | ||
| use tokio_core::reactor::Core; |
There was a problem hiding this comment.
tokio_core is not in the dependencies anymore. This whole benchmark needs a rewrite.
benches/bench_basic.rs
Outdated
| fn bench_simple_getsetdel_async(b: &mut Bencher) { | ||
| let client = get_client(); | ||
| let mut core = Core::new().unwrap(); | ||
| let con = client.get_async_connection(&core.handle()); |
There was a problem hiding this comment.
get_async_connection doesn't take a handle anymore, so I guess this all needs to change.
There was a problem hiding this comment.
Fixed (and I enabled cargo check for travis)
benches/bench_basic.rs
Outdated
| bench_encode_pipeline, | ||
| bench_encode_pipeline_nested | ||
| bench_encode_pipeline_nested, | ||
| bench_long_pipeline |
src/async.rs
Outdated
| .map(|con| ActualConnection::Tcp(BufReader::new(con))), | ||
| ) | ||
| } | ||
| #[cfg(feature = "with-async-unix-sockets")] |
There was a problem hiding this comment.
It's weird seeing this feature, when it's not available in Cargo.toml.
What do you think about extracting the async-unix-socket code from this PR, but immediately opening one adding it, pending the updated tokio-uds crate?
There was a problem hiding this comment.
tokio-uds actually got a release so I removed the feature and enable tokio-uds support with the normal uds feature https://crates.io/crates/tokio-uds
src/parser.rs
Outdated
| Some(detail) => fail!((kind, desc, detail.to_string())), | ||
| None => fail!((kind, desc)), | ||
| match parser.poll()? { | ||
| Async::NotReady => panic!("Blocking read received WouldBlock error"), |
There was a problem hiding this comment.
Seeing a panic makes me kinda worry:
Is it likely that code is ever hit? Is it an actual error that can't be handled at all?
There was a problem hiding this comment.
Changed it to return WouldBlock again which is the only reason why it could happen.
| extern crate futures; | ||
| extern crate partial_io; | ||
| #[macro_use] | ||
| extern crate quickcheck; |
There was a problem hiding this comment.
Yey for seeing quickcheck used here.
…ync Read instance
Version 0.2 were released a few weeks ago so we might as well enable it immediately
Sorry about that. I think I had it split up before but I ended up with a nasty rebase and had to remove it to make it easier. Tried to break it up into two commits again but looked pretty nasty still.
Not in the trait methods which return a future, but in all the other functions then certainly.
Did it as |
I think I resolved everything (can't find anything I missed at least)? |
Now uses combine v3.0.0 (stable release)
|
Hmmm, the tests fail on Windows: |
|
Kicking of a println test on appveyor to see if it is an easy fix, otherwise I will try and get this work locally on windows tonight. |
|
@Marwes Just ping me again if this is resolved. I'm happy to merge it then :) |
These are rarely necessary and should hopefully fix the issue on windows since a rather weird use of net2 could be removed
|
@badboy I made some mistake when using the If someone ends up needing a function that takes an explicit handle we can revisit this and try to implement it then instead. Everything is green now! |
|
Great! Merging it now! |
|
Great work! Looking forward to trying this out! |
Add cluster scan functionality
Adding timeouts to CI jobs.
* Add `ECHO` command. (redis-rs#141) Signed-off-by: Andrew Carbonetto <andrew.carbonetto@improving.com> * Update echo command to provide cluster impl Signed-off-by: Andrew Carbonetto <andrew.carbonetto@improving.com> --------- Signed-off-by: Yury-Fridlyand <yury.fridlyand@improving.com> Signed-off-by: Andrew Carbonetto <andrew.carbonetto@improving.com> Co-authored-by: Yury-Fridlyand <yury.fridlyand@improving.com> Co-authored-by: SanHalacogluImproving <san.halacoglu@improving.com>
This adds support for communicating with redis instances asynchronously using futures and tokio. Putting this up now to show the changes and additions I have done so far.
Since the current response parser is tied to reading synchronously from a
Readinstance I rewrote it using https://github.com/Marwes/combine. I choose combine since I know it (obviously) and I wanted to try the state machine support I have been working on in tandem with this PR (this PR is what made me come up with the idea). Though I am a bit biased I do think it should be a good fit after I have worked out the bugs so I hope the change is acceptable. (I did see the Nom parser in #129 but didn't use it as I'd still need to code the state machine manually whereas combine creates it automatically).query(_async)is currently the only added API and there is also a bunch of cleanup to be done.Closes #103