| // +build ignore,OMIT |
| |
| // The backend command runs a Google server that returns fake results. |
| package main |
| |
| import ( |
| "flag" |
| "fmt" |
| "log" |
| "math/rand" |
| "net" |
| "net/http" |
| _ "net/http/pprof" |
| "time" |
| |
| "golang.org/x/net/context" |
| "golang.org/x/net/trace" |
| pb "golang.org/x/talks/content/2015/gotham-grpc/search" |
| "google.golang.org/grpc" |
| ) |
| |
| var ( |
| index = flag.Int("index", 0, "RPC port is 36061+index; debug port is 36661+index") |
| ) |
| |
| type server struct{} |
| |
| // randomDuration returns a random duration up to max, at intervals of max/10. |
| func randomDuration(max time.Duration) time.Duration { |
| return time.Duration(1+int64(rand.Intn(10))) * (max / 10) |
| } |
| |
| // Search sleeps for a random interval then returns a string |
| // identifying the query and this backend. |
| func (s *server) Search(ctx context.Context, req *pb.Request) (*pb.Result, error) { // HL |
| d := randomDuration(100 * time.Millisecond) |
| logSleep(ctx, d) // HL |
| select { |
| case <-time.After(d): |
| return &pb.Result{ // HL |
| Title: fmt.Sprintf("result for [%s] from backend %d", req.Query, *index), // HL |
| }, nil // HL |
| case <-ctx.Done(): |
| return nil, ctx.Err() |
| } |
| } |
| |
| func logSleep(ctx context.Context, d time.Duration) { |
| if tr, ok := trace.FromContext(ctx); ok { // HL |
| tr.LazyPrintf("sleeping for %s", d) // HL |
| } |
| } |
| |
| // Watch returns a stream of results identifying the query and this |
| // backend, sleeping a random interval between each send. |
| func (s *server) Watch(req *pb.Request, stream pb.Google_WatchServer) error { // HL |
| ctx := stream.Context() |
| for i := 0; ; i++ { |
| d := randomDuration(1 * time.Second) |
| logSleep(ctx, d) // HL |
| select { |
| case <-time.After(d): |
| err := stream.Send(&pb.Result{ // HL |
| Title: fmt.Sprintf("result %d for [%s] from backend %d", i, req.Query, *index), // HL |
| }) // HL |
| if err != nil { |
| return err |
| } |
| case <-ctx.Done(): |
| return ctx.Err() |
| } |
| } |
| } |
| |
| func main() { |
| flag.Parse() |
| rand.Seed(time.Now().UnixNano()) |
| go http.ListenAndServe(fmt.Sprintf(":%d", 36661+*index), nil) // HTTP debugging |
| lis, err := net.Listen("tcp", fmt.Sprintf(":%d", 36061+*index)) // RPC port // HL |
| if err != nil { |
| log.Fatalf("failed to listen: %v", err) |
| } |
| g := grpc.NewServer() // HL |
| pb.RegisterGoogleServer(g, new(server)) // HL |
| g.Serve(lis) // HL |
| } |