diff --git a/CHANGELOG.md b/CHANGELOG.md index db20a24..09ef706 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ ctx := peer.NewCallContext(context.Background(), pubKey) res, err := c.Gnip(ctx, &pb.GnipRequest{Body: "Gnip"}) ``` +* Add a `WithBlock` DialOption which blocks the caller of Dial until the underlying connection is up. # 0.1.1 diff --git a/README.md b/README.md index becf090..646fd8b 100644 --- a/README.md +++ b/README.md @@ -140,4 +140,4 @@ While the client's are connected, kill the server and see the client's enter a b - [ ] Improve Tests - [ ] Return a response status -- [ ] Add a Blocking DialOption \ No newline at end of file +- [x] Add a Blocking DialOption \ No newline at end of file diff --git a/client.go b/client.go index 5094e7f..f3abe8a 100644 --- a/client.go +++ b/client.go @@ -49,7 +49,10 @@ type ClientConn struct { service *serviceInfo } -// Dial creates a client connection to the given target. +// Dial creates a client connection to the given target. By default, it's +// a non-blocking dial (the function won't wait for connections to be +// established, and connecting happens in the background). To make it a blocking +// dial, use WithBlock() dial option. func Dial(target string, opts ...DialOption) (*ClientConn, error) { cc := &ClientConn{ ctx: context.Background(), @@ -74,6 +77,14 @@ func Dial(target string, opts ...DialOption) (*ClientConn, error) { addrConn.connect() cc.conn = addrConn + if cc.dopts.block { + for { + if addrConn.state == connectivity.Ready { + break + } + } + } + return cc, nil } diff --git a/dialoptions.go b/dialoptions.go index f23e132..2f2e6f5 100644 --- a/dialoptions.go +++ b/dialoptions.go @@ -14,6 +14,7 @@ import ( type dialOptions struct { copts transport.ConnectOptions bs backoff.Strategy + block bool } // DialOption configures how we set up the connection. @@ -54,6 +55,15 @@ func WithTransportCreds(privKey ed25519.PrivateKey, serverPubKey ed25519.PublicK }) } +// WithBlock returns a DialOption which makes caller of Dial blocks until the +// underlying connection is up. Without this, Dial returns immediately and +// connecting the server happens in background. +func WithBlock() DialOption { + return newFuncDialOption(func(o *dialOptions) { + o.block = true + }) +} + func defaultDialOptions() dialOptions { return dialOptions{ copts: transport.ConnectOptions{}, diff --git a/examples/simple/client/main.go b/examples/simple/client/main.go index d2845ba..d99ece6 100644 --- a/examples/simple/client/main.go +++ b/examples/simple/client/main.go @@ -28,7 +28,10 @@ func main() { privKey := keys.FromHex(keys.Clients[cidx].PrivKey) serverPubKey := keys.FromHex(keys.ServerPubKey) - conn, err := wsrpc.Dial("127.0.0.1:1338", wsrpc.WithTransportCreds(privKey, serverPubKey)) + conn, err := wsrpc.Dial("127.0.0.1:1338", + wsrpc.WithTransportCreds(privKey, serverPubKey), + wsrpc.WithBlock(), + ) if err != nil { log.Fatalln(err) } diff --git a/wsrpclog/logger.go b/wsrpclog/logger.go new file mode 100644 index 0000000..6751e56 --- /dev/null +++ b/wsrpclog/logger.go @@ -0,0 +1,59 @@ +package wsrpclog + +import "log" + +// Logger defines a simple logger interface. We may want to consider improving +// logging capabilities. +type Logger interface { + Print(v ...interface{}) + Printf(format string, v ...interface{}) + Println(v ...interface{}) +} + +var ( + Default Logger +) + +func init() { + Default = &logger{} +} + +func SetVerboseLogger() { + Default = &logger{Verbose: true} +} + +type logger struct { + Verbose bool +} + +var _ Logger = (*logger)(nil) + +func (l *logger) Print(v ...interface{}) { + if l.Verbose { + log.Println(v...) + } +} + +func (l *logger) Printf(format string, v ...interface{}) { + if l.Verbose { + log.Printf(format, v...) + } +} + +func (l *logger) Println(v ...interface{}) { + if l.Verbose { + log.Println(v...) + } +} + +func Print(v ...interface{}) { + Default.Print(v...) +} + +func Printf(format string, v ...interface{}) { + Default.Printf(format, v...) +} + +func Println(v ...interface{}) { + Default.Println(v...) +}