-
Notifications
You must be signed in to change notification settings - Fork 198
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
[Breaking] Add support for arbitrary transports. #27
Conversation
Quite a bit of machinery added: * Listener trait * Dialer trait * Stream trait * Transport trait
@@ -569,6 +581,20 @@ mod functional_test { | |||
assert_eq!(3, client2.add(1, 2).get().unwrap()); | |||
} | |||
|
|||
#[test] | |||
fn async_try_clone_unix() { | |||
let handle = Server.spawn_with_config(UnixTransport("/tmp/test"), |
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.
This won't work if you run it twice because the file already exists. We can just delete it at the end I guess?/Choosing something like /tmp/tarpc-async_try_clone_UNIX?
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.
Use this: https://crates.io/crates/tempdir? I think that generates random directories, so you can do Tempdir::new().unwrap().path().join("file");
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.
I don't think tempdir exposes the path? I'll double check.
On Feb 24, 2016 7:40 PM, "shaladdle" notifications@github.com wrote:
In tarpc/src/macros.rs
#27 (comment):@@ -569,6 +581,20 @@ mod functional_test {
assert_eq!(3, client2.add(1, 2).get().unwrap());
}
- #[test]
- fn async_try_clone_unix() {
let handle = Server.spawn_with_config(UnixTransport("/tmp/test"),
Use this: https://crates.io/crates/tempdir? I think that generates random
directories, so you can do Tempdir::new().unwrap().path().join("file");—
Reply to this email directly or view it on GitHub
https://github.com/google/tarpc/pull/27/files#r54045195.
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.
Hm, I must have been looking at a different crate last time. Tempdir should work.
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.
Fixed.
self.accept().map(|(stream, _)| stream) | ||
} | ||
fn dialer(&self) -> io::Result<UnixDialer<PathBuf>> { | ||
self.local_addr().map(|addr| UnixDialer(addr.as_pathname().unwrap().to_owned())) |
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.
I shouldn't be unwrapping here, and we shouldn't merge as-is. I just haven't thought about the proper error handling yet. Thoughts?
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.
Maybe like this:
self.local_addr().map(|addr| {
match addr.as_pathname() {
Some(path) => Ok(UnixDialer(path.to_owned())),
None => Err(io::Error::new(io::ErrorKind::Other, "tried to create unix socket with invalid path")),
}
})
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.
Done.
Basically copied from TcpStream verbatim.
Also, make spawn() take a Dialer, but impl Dialer for str, defaulting to TCP transport.
@@ -47,7 +47,7 @@ impl HelloService for HelloServer { | |||
|
|||
fn main() { | |||
let server_handle = HelloServer.spawn("0.0.0.0:0").unwrap(); | |||
let client = hello_service::Client::new(server_handle.local_addr()).unwrap(); | |||
let client = hello_service::Client::new(server_handle.dialer()).unwrap(); |
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.
Maybe we should have the example in the readme just use a specific IP address? Like localhost:10000 or something? Then people don't have to learn about dialers if they don't care about them.
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.
Alternatively, we could have the server handle have a method that returns a client.
server_handle.new_client().unwrap();
Thoughts?
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.
My thoughts were more that the readme example should be the most common simple case. I think it's more common to have a client/server in different processes, rather than in the same one. So, I was thinking that using an address would be more familiar to some people.
A separate issue is that we don't really have a full suite of examples.. Just the benchmark. That should be addressed separately though.
Returning client seems ok too. The one advantage of having a Dialer is that you can send bogus stuff over a stream, which is useful for verifying that we don't misbehave if someone sends junk to the server.
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.
I'm fine making the example simpler. The handle should have two methods,
one returning Dialer and one creating a new client.
On Mar 2, 2016 8:47 PM, "shaladdle" notifications@github.com wrote:
In README.md
#27 (comment):@@ -47,7 +47,7 @@ impl HelloService for HelloServer {
fn main() {
let server_handle = HelloServer.spawn("0.0.0.0:0").unwrap();
- let client = hello_service::Client::new(server_handle.local_addr()).unwrap();
- let client = hello_service::Client::new(server_handle.dialer()).unwrap();
My thoughts were more that the readme example should be the most common
simple case. I think it's more common to have a client/server in different
processes, rather than in the same one. So, I was thinking that using an
address would be more familiar to some people.A separate issue is that we don't really have a full suite of examples..
Just the benchmark. That should be addressed separately though.Returning client seems ok too. The one advantage of having a Dialer is
that you can send bogus stuff over a stream, which is useful for verifying
that we don't misbehave if someone sends junk to the server.—
Reply to this email directly or view it on GitHub
https://github.com/google/tarpc/pull/27/files#r54835799.
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.
Sounds fine
|
||
/// A transport for TCP. | ||
pub struct TcpTransport<A: ToSocketAddrs>(pub A); | ||
impl<A: ToSocketAddrs> super::Transport for TcpTransport<A> { |
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.
Add a line in between the struct and the impl?
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.
I'll try but it might be from cargo fmt.
On Mar 2, 2016 9:29 PM, "shaladdle" notifications@github.com wrote:
In tarpc/src/transport/tcp.rs
#27 (comment):@@ -0,0 +1,62 @@
+use std::io;
+use std::net::{SocketAddr, TcpListener, TcpStream, ToSocketAddrs};
+use std::time::Duration;
+
+/// A transport for TCP.
+pub struct TcpTransport<A: ToSocketAddrs>(pub A);
+impl<A: ToSocketAddrs> super::Transport for TcpTransport {Add a line in between the struct and the impl?
—
Reply to this email directly or view it on GitHub
https://github.com/google/tarpc/pull/27/files#r54837589.
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.
I don't think so. Line 19 on unix.rs has a line between them.
All comments addressed. Ready for re-review, I think. |
Quite a bit of machinery added:
I made a lot of types default to
Tcp*
for:Before merging this, we shouldimpl
the traits for unix_socket to make sure the trait is compatible.I've now
impl
edTransport
for Unix sockets:Server.spawn(UnixTransport(path))
Client::new(UnixDialer(path))
This is a breaking change but only for code that used
ToSocketAddrs
args other than&str
. Code using&str
to specify address will still work.To update code:
Server.spawn(socket_addr)
=>Server.spawn(TcpTransport(socket_addr))
Bikeshed
As I played around with unix sockets, I grew frustrated with the second-class nature of them WRT tarpc. Specifically, having to use
spawn_with_config
just because the transport changed, even though I was using defaultConfig
settings, was annoying. In light of that, I propose makingspawn
take aTransport
, and just go ahead andimpl<A: ToSocketAddrs> Transport for A { ... }
such that it creates a tcp transport. Even though other transports use sockets, I think it's reasonable to have a sane default here for the sake of ergonomics.If you think that's reasonable, I'll add that to this PR, as well.
Update: the above was implemented as well, but due to coherence, I can only do
impl<'a> Transport for &'a str
. Specialization might allowTransport
impls for allToSocketAddrs
types, but maybe not.Fixes #16