open-match.dev/open-match@v1.8.1/examples/scale/scenarios/firstmatch/firstmatch.go (about) 1 // Copyright 2019 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package firstmatch 16 17 import ( 18 "fmt" 19 "io" 20 "time" 21 22 "open-match.dev/open-match/pkg/pb" 23 ) 24 25 const ( 26 poolName = "all" 27 ) 28 29 func Scenario() *FirstMatchScenario { 30 return &FirstMatchScenario{} 31 } 32 33 type FirstMatchScenario struct { 34 } 35 36 func (*FirstMatchScenario) Profiles() []*pb.MatchProfile { 37 return []*pb.MatchProfile{ 38 { 39 Name: "entirePool", 40 Pools: []*pb.Pool{ 41 { 42 Name: poolName, 43 }, 44 }, 45 }, 46 } 47 } 48 49 func (*FirstMatchScenario) Ticket() *pb.Ticket { 50 return &pb.Ticket{} 51 } 52 53 func (*FirstMatchScenario) Backfill() *pb.Backfill { 54 return nil 55 } 56 57 func (*FirstMatchScenario) MatchFunction(p *pb.MatchProfile, poolBackfills map[string][]*pb.Backfill, poolTickets map[string][]*pb.Ticket) ([]*pb.Match, error) { 58 tickets := poolTickets[poolName] 59 var matches []*pb.Match 60 61 for i := 0; i+1 < len(tickets); i += 2 { 62 matches = append(matches, &pb.Match{ 63 MatchId: fmt.Sprintf("profile-%v-time-%v-%v", p.GetName(), time.Now().Format("2006-01-02T15:04:05.00"), len(matches)), 64 Tickets: []*pb.Ticket{tickets[i], tickets[i+1]}, 65 MatchProfile: p.GetName(), 66 MatchFunction: "rangeExpandingMatchFunction", 67 }) 68 } 69 70 return matches, nil 71 } 72 73 // fifoEvaluate accepts all matches which don't contain the same ticket as in a 74 // previously accepted match. Essentially first to claim the ticket wins. 75 func (*FirstMatchScenario) Evaluate(stream pb.Evaluator_EvaluateServer) error { 76 used := map[string]struct{}{} 77 78 // TODO: once the evaluator client supports sending and receiving at the 79 // same time, don't buffer, just send results immediately. 80 matchIDs := []string{} 81 82 outer: 83 for { 84 req, err := stream.Recv() 85 if err == io.EOF { 86 break 87 } 88 if err != nil { 89 return fmt.Errorf("Error reading evaluator input stream: %w", err) 90 } 91 92 m := req.GetMatch() 93 94 for _, t := range m.Tickets { 95 if _, ok := used[t.Id]; ok { 96 continue outer 97 } 98 } 99 100 for _, t := range m.Tickets { 101 used[t.Id] = struct{}{} 102 } 103 104 matchIDs = append(matchIDs, m.GetMatchId()) 105 } 106 107 for _, mID := range matchIDs { 108 err := stream.Send(&pb.EvaluateResponse{MatchId: mID}) 109 if err != nil { 110 return fmt.Errorf("Error sending evaluator output stream: %w", err) 111 } 112 } 113 114 return nil 115 }