/
client.go
214 lines (200 loc) · 5.74 KB
/
client.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
package main
import (
"encoding/json"
"flag"
"fmt"
"io"
"log"
"strconv"
"time"
pb "./books"
"golang.org/x/net/context"
"google.golang.org/grpc"
)
var (
address = flag.String("address", "127.0.0.1:50051", "Address of service")
)
// GetClient attempts to dial the specified address flag and returns a service
// client and its underlying connection. If it is unable to make a connection,
// it dies.
func GetClient() (*grpc.ClientConn, pb.BookServiceClient) {
conn, err := grpc.Dial(*address, grpc.WithTimeout(5*time.Second), grpc.WithInsecure())
if err != nil {
log.Fatalf("did not connect: %v", err)
}
return conn, pb.NewBookServiceClient(conn)
}
func main() {
flag.Parse()
ctx := context.Background()
cmd, ok := commands[flag.Arg(0)]
if !ok {
usage()
} else {
cmd.do(ctx, flag.Args()[1:]...)
}
}
func usage() {
fmt.Println(`client.go is a command-line client for this codelab's gRPC service
Usage:
client.go list List all books
client.go insert <id> <title> <author> Insert a book
client.go get <id> Get a book by its ID
client.go delete <id> Delete a book by its ID
client.go watch Watch for inserted books`)
}
var commands = map[string]struct {
name, desc string
do func(context.Context, ...string)
usage string
}{
"get": {
name: "get",
desc: "Retrieves the indicated book",
do: doGet,
usage: "client.go get <id>",
},
"list": {
name: "list",
desc: "Lists all books",
do: doList,
usage: "client.go list",
},
"insert": {
name: "insert",
desc: "Inserts the provided book",
do: doInsert,
usage: "client.go insert <id> <title> <author> <num>",
},
"delete": {
name: "delete",
desc: "Deletes the indicated book",
do: doDelete,
usage: "client.go delete <id>",
},
"watch": {
name: "watch",
desc: "Watches for inserted books",
do: doWatch,
usage: "client.go watch",
},
}
// printRespAsJson attempts to marshal the provided interface into its JSON
// representation, then prints to stdout.
func printRespAsJson(r interface{}) {
b, err := json.MarshalIndent(r, "", " ")
if err != nil {
log.Fatalf("printResp (%v): %v", r, err)
}
fmt.Println(string(b))
}
// doGet is a basic wrapper around the corresponding book service's RPC.
// It parses the provided arguments, calls the service, and prints the
// response. If any errors are encountered, it dies.
func doGet(ctx context.Context, args ...string) {
if len(args) != 1 {
log.Fatalf("usage: client.go get <id>")
}
id, err := strconv.ParseInt(args[0], 10, 64)
if err != nil {
log.Fatalf("Provided ID %v invalid: %v", args[0], err)
}
conn, client := GetClient()
defer conn.Close()
r, err := client.Get(ctx, &pb.BookIdRequest{int32(id)})
if err != nil {
log.Fatalf("Get book (%v): %v", id, err)
}
fmt.Println("Server response:")
printRespAsJson(r)
}
// doDelete is a basic wrapper around the corresponding book service's RPC.
// It parses the provided arguments, calls the service, and prints the
// response. If any errors are encountered, it dies.
func doDelete(ctx context.Context, args ...string) {
if len(args) != 1 {
log.Fatalf("usage: client.go delete <id>")
}
id, err := strconv.ParseInt(args[0], 10, 64)
if err != nil {
log.Fatalf("Provided ID %v invalid: %v", args[0], err)
}
conn, client := GetClient()
defer conn.Close()
r, err := client.Delete(ctx, &pb.BookIdRequest{int32(id)})
if err != nil {
log.Fatalf("Get book (%v): %v", id, err)
}
fmt.Println("Server response:")
printRespAsJson(r)
}
// doList is a basic wrapper around the corresponding book service's RPC.
// It parses the provided arguments, calls the service, and prints the
// response. If any errors are encountered, it dies.
func doList(ctx context.Context, args ...string) {
startTime := time.Now()
conn, client := GetClient()
defer conn.Close()
rs, err := client.List(ctx, &pb.Empty{})
if err != nil {
log.Fatalf("List books: %v", err)
}
endTime := time.Now()
fmt.Printf("list responces time: %v milli sec \n",int32(endTime.Sub(startTime).Milliseconds()))
fmt.Printf("Server sent %v book(s).\n", len(rs.GetBooks()))
printRespAsJson(rs)
}
// doInsert is a basic wrapper around the corresponding book service's RPC.
// It parses the provided arguments, calls the service, and prints the
// response. If any errors are encountered, it dies.
func doInsert(ctx context.Context, args ...string) {
startTime := time.Now()
// if len(args) != 3 {
// log.Fatalf("usage client.go insert <id> <title> <author>")
// }
id, err := strconv.ParseInt(args[0], 10, 64)
num, err2 := strconv.Atoi(args[3]);
if err != nil && err2 != nil {
log.Fatalf("Provided ID %v invalid: %v", args[0], err)
}
for i := 0; i < num; i++ {
book := &pb.Book{
Id: int32(id),
Title: args[1],
Author: args[2],
}
id += 1
conn, client := GetClient()
defer conn.Close()
r, err := client.Insert(ctx, book)
if err != nil {
log.Fatalf("Insert book (%v): %v", book, err)
}
fmt.Println("Server response:")
printRespAsJson(r)
}
endTime := time.Now()
fmt.Printf("insert responces time: %v milli sec \n",int32(endTime.Sub(startTime).Milliseconds()))
}
// doWatch is a basic wrapper around the corresponding book service's RPC.
// It parses the provided arguments, calls the service, and prints the
// response. If any errors are encountered, it dies.
func doWatch(ctx context.Context, args ...string) {
conn, client := GetClient()
defer conn.Close()
stream, err := client.Watch(ctx, &pb.Empty{})
if err != nil {
log.Fatalf("Watch books: %v", err)
}
for {
book, err := stream.Recv()
if err == io.EOF {
break
}
if err != nil {
log.Fatalf("Watch books stream: %v", err)
}
fmt.Println("Server stream data received:")
printRespAsJson(book)
}
}