go/grpshuffle_server/lib/server.go (48 lines of code) (raw):

package grpshuffle_server import ( "context" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "math/rand" "time" "github.com/korosuke613/grpshuffle/go/grpshuffle" ) // Server is implemented ComputeServer type Server struct { // 将来 proto ファイルに RPC が追加されてインタフェースが拡張された際、 // ビルドエラーになるのを防止する仕組み。 grpshuffle.UnimplementedComputeServer } // インタフェースが実装できていることをコンパイル時に確認するおまじない var _ grpshuffle.ComputeServer = &Server{} // Shuffle is gRPC server func (s *Server) Shuffle(ctx context.Context, req *grpshuffle.ShuffleRequest) (*grpshuffle.ShuffleResponse, error) { shuffledTargets := make([]string, len(req.Targets)) copy(shuffledTargets, req.Targets) if !req.Sequential { // randomly swap targets. rand.Seed(time.Now().UnixNano()) rand.Shuffle(len(req.Targets), func(i, j int) { shuffledTargets[i], shuffledTargets[j] = shuffledTargets[j], shuffledTargets[i] }) } if req.Divide >= uint64(len(req.Targets)) { return nil, status.Errorf(codes.InvalidArgument, "Must have `divide` >= `targets` num.") } // split targets by the number of divide. slicedTargets := make([]*grpshuffle.Combination, 0) average := int(uint64(len(req.Targets)) / req.Divide) remainder := int(uint64(len(req.Targets)) % req.Divide) var sliceSize int loopCount := 0 for i := 0; i < len(req.Targets); i += sliceSize { if loopCount < remainder { sliceSize = average + 1 } else { sliceSize = average } endCursor := i + sliceSize if endCursor > len(req.Targets) { endCursor = len(req.Targets) } tmp := shuffledTargets[i:endCursor] slicedTargets = append(slicedTargets, &grpshuffle.Combination{Targets: tmp}) loopCount += 1 } return &grpshuffle.ShuffleResponse{ Combinations: slicedTargets, }, nil }