Code

Add an initial version of sample code for my Go talk.
[go-talk.git] / grpc / server / main.go
1 // Copyright (C) 2016 Sebastian 'tokkee' Harl <sh@tokkee.org>
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions
6 // are met:
7 // 1. Redistributions of source code must retain the above copyright
8 //    notice, this list of conditions and the following disclaimer.
9 // 2. Redistributions in binary form must reproduce the above copyright
10 //    notice, this list of conditions and the following disclaimer in the
11 //    documentation and/or other materials provided with the distribution.
12 //
13 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
14 // ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
15 // TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
17 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
20 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
21 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
22 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
23 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 // server is the backend server implementation.
26 package main
28 import (
29         "flag"
30         "log"
31         "net"
32         "strconv"
33         "strings"
35         "golang.org/x/net/context"
37         "google.golang.org/grpc"
38         "google.golang.org/grpc/codes"
39         "google.golang.org/grpc/peer"
41         pb "tokkee.org/go-talk/grpc/proto/backend"
42 )
44 var (
45         listen = flag.String("listen", ":50051", "listening address")
46 )
48 // A server implements the Backend service.
49 type server struct{}
51 // Query runs the user-provided query and returns the result.
52 func (*server) Query(ctx context.Context, in *pb.QueryRequest) (*pb.QueryReply, error) {
53         if peer, ok := peer.FromContext(ctx); ok {
54                 log.Printf("Query() called from %v", peer)
55         } else {
56                 log.Print("No peer information available")
57         }
59         t, n, err := runQuery(in.Query)
60         if err != nil {
61                 return nil, err
62         }
64         return &pb.QueryReply{
65                 Type: t,
66                 N:    n,
67         }, nil
68 }
70 // runQuery executes a query. It implements a highly sophisticated query
71 // engine.
72 func runQuery(q string) (string, int64, error) {
73         fields := strings.SplitN(q, " ", 2)
74         if len(fields) != 2 {
75                 return "", 0, grpc.Errorf(codes.InvalidArgument, "invalid query %q: want <cmd> <arg>", q)
76         }
78         var n int64
79         cmd, arg := strings.ToUpper(fields[0]), fields[1]
80         switch cmd {
81         case "COUNT":
82                 n = int64(len(arg))
83         case "RANDOM":
84                 i, err := strconv.Atoi(arg)
85                 if err != nil {
86                         return "", 0, grpc.Errorf(codes.InvalidArgument, "RANDOM: %v", err)
87                 }
89                 // Chosen by fair dice roll.
90                 n = 4
91                 if i <= 4 {
92                         n = 0
93                 }
94         default:
95                 return "", 0, grpc.Errorf(codes.InvalidArgument, "unknown query command %q", cmd)
96         }
98         return cmd, n, nil
99 }
101 func main() {
102         flag.Parse()
104         l, err := net.Listen("tcp", *listen)
105         if err != nil {
106                 log.Fatalf("Failed to listen on %s: %v", *listen, err)
107         }
109         log.Printf("Listening on %s ...", *listen)
110         s := grpc.NewServer()
111         pb.RegisterBackendServer(s, &server{})
112         s.Serve(l)