Skip to content
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

Merged
merged 27 commits into from
Apr 25, 2016

Conversation

tikue
Copy link
Collaborator

@tikue tikue commented Feb 23, 2016

Quite a bit of machinery added:

  • Listener trait
  • Dialer trait
  • Stream trait
  • Transport trait

I made a lot of types default to Tcp* for:

  1. Convenience
  2. Backwards compatibility (though it's still a breaking change in some respects)

Before merging this, we should impl the traits for unix_socket to make sure the trait is compatible.
I've now impled Transport 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 default Config settings, was annoying. In light of that, I propose making spawn take a Transport, and just go ahead and impl<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 allow Transport impls for all ToSocketAddrs types, but maybe not.

Fixes #16

Quite a bit of machinery added:
 * Listener trait
 * Dialer trait
 * Stream trait
 * Transport trait
@tikue tikue changed the title Add support for arbitrary transports. [Breaking] Add support for arbitrary transports. Feb 23, 2016
@@ -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"),
Copy link
Collaborator Author

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?

Copy link
Collaborator

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");

Copy link
Collaborator Author

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.

Copy link
Collaborator Author

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.

Copy link
Collaborator Author

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()))
Copy link
Collaborator Author

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?

Copy link
Collaborator

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")),
  }
})

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@@ -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();
Copy link
Collaborator

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.

Copy link
Collaborator Author

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?

Copy link
Collaborator

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.

Copy link
Collaborator Author

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.

Copy link
Collaborator

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> {
Copy link
Collaborator

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?

Copy link
Collaborator Author

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.

Copy link
Collaborator

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.

@tikue
Copy link
Collaborator Author

tikue commented Mar 17, 2016

All comments addressed. Ready for re-review, I think.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.8%) to 84.044% when pulling 4d636d2 on tikue:listener into 3693c95 on google:master.

@shaladdle shaladdle merged commit 6ce3a3d into google:master Apr 25, 2016
@tikue tikue deleted the listener branch September 16, 2016 23:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants