Merge pull request #218 from basvanbeek/grpc-fix
Fixed grpc.Client to be go-routine safe.
Peter Bourgon
8 years ago
1 | 1 | |
2 | 2 | import ( |
3 | 3 | "fmt" |
4 | "reflect" | |
4 | 5 | |
5 | 6 | "golang.org/x/net/context" |
6 | 7 | "google.golang.org/grpc" |
17 | 18 | method string |
18 | 19 | enc EncodeRequestFunc |
19 | 20 | dec DecodeResponseFunc |
20 | grpcReply interface{} | |
21 | grpcReply reflect.Type | |
21 | 22 | before []RequestFunc |
22 | 23 | } |
23 | 24 | |
32 | 33 | options ...ClientOption, |
33 | 34 | ) *Client { |
34 | 35 | c := &Client{ |
35 | client: cc, | |
36 | method: fmt.Sprintf("/pb.%s/%s", serviceName, method), | |
37 | enc: enc, | |
38 | dec: dec, | |
39 | grpcReply: grpcReply, | |
40 | before: []RequestFunc{}, | |
36 | client: cc, | |
37 | method: fmt.Sprintf("/pb.%s/%s", serviceName, method), | |
38 | enc: enc, | |
39 | dec: dec, | |
40 | // We are using reflect.Indirect here to allow both reply structs and | |
41 | // pointers to these reply structs. New consumers of the client should | |
42 | // use structs directly, while existing consumers will not break if they | |
43 | // remain to use pointers to structs. | |
44 | grpcReply: reflect.TypeOf( | |
45 | reflect.Indirect( | |
46 | reflect.ValueOf(grpcReply), | |
47 | ).Interface(), | |
48 | ), | |
49 | before: []RequestFunc{}, | |
41 | 50 | } |
42 | 51 | for _, option := range options { |
43 | 52 | option(c) |
72 | 81 | } |
73 | 82 | ctx = metadata.NewContext(ctx, *md) |
74 | 83 | |
75 | if err = grpc.Invoke(ctx, c.method, req, c.grpcReply, c.client); err != nil { | |
84 | grpcReply := reflect.New(c.grpcReply).Interface() | |
85 | if err = grpc.Invoke(ctx, c.method, req, grpcReply, c.client); err != nil { | |
76 | 86 | return nil, fmt.Errorf("Invoke: %v", err) |
77 | 87 | } |
78 | 88 | |
79 | response, err := c.dec(ctx, c.grpcReply) | |
89 | response, err := c.dec(ctx, grpcReply) | |
80 | 90 | if err != nil { |
81 | 91 | return nil, fmt.Errorf("Decode: %v", err) |
82 | 92 | } |