| /* | |
| * | |
| * Copyright 2019 gRPC authors. | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| * | |
| */ | |
| // Binary server demonstrates to enforce retries on client side. | |
| package main | |
| import ( | |
| "context" | |
| "flag" | |
| "fmt" | |
| "log" | |
| "net" | |
| "sync" | |
| "google.golang.org/grpc" | |
| "google.golang.org/grpc/codes" | |
| "google.golang.org/grpc/status" | |
| pb "google.golang.org/grpc/examples/features/proto/echo" | |
| ) | |
| var port = flag.Int("port", 50052, "port number") | |
| type failingServer struct { | |
| pb.UnimplementedEchoServer | |
| mu sync.Mutex | |
| reqCounter uint | |
| reqModulo uint | |
| } | |
| // this method will fail reqModulo - 1 times RPCs and return status code Unavailable, | |
| // and succeeded RPC on reqModulo times. | |
| func (s *failingServer) maybeFailRequest() error { | |
| s.mu.Lock() | |
| defer s.mu.Unlock() | |
| s.reqCounter++ | |
| if (s.reqModulo > 0) && (s.reqCounter%s.reqModulo == 0) { | |
| return nil | |
| } | |
| return status.Errorf(codes.Unavailable, "maybeFailRequest: failing it") | |
| } | |
| func (s *failingServer) UnaryEcho(_ context.Context, req *pb.EchoRequest) (*pb.EchoResponse, error) { | |
| if err := s.maybeFailRequest(); err != nil { | |
| log.Println("request failed count:", s.reqCounter) | |
| return nil, err | |
| } | |
| log.Println("request succeeded count:", s.reqCounter) | |
| return &pb.EchoResponse{Message: req.Message}, nil | |
| } | |
| func main() { | |
| flag.Parse() | |
| address := fmt.Sprintf(":%v", *port) | |
| lis, err := net.Listen("tcp", address) | |
| if err != nil { | |
| log.Fatalf("failed to listen: %v", err) | |
| } | |
| fmt.Println("listen on address", address) | |
| s := grpc.NewServer() | |
| // Configure server to pass every fourth RPC; | |
| // client is configured to make four attempts. | |
| failingservice := &failingServer{ | |
| reqCounter: 0, | |
| reqModulo: 4, | |
| } | |
| pb.RegisterEchoServer(s, failingservice) | |
| if err := s.Serve(lis); err != nil { | |
| log.Fatalf("failed to serve: %v", err) | |
| } | |
| } |