func Auction(client types.RepPoolClient, auctionRequest types.AuctionRequest) types.AuctionResult { var auctionWinner string var representatives []string if !auctionRequest.Rules.RepickEveryRound { representatives = randomSubset(auctionRequest.RepGuids, auctionRequest.Rules.MaxBiddingPool) } numRounds, numVotes := 0, 0 t := time.Now() for round := 1; round <= auctionRequest.Rules.MaxRounds; round++ { if auctionRequest.Rules.RepickEveryRound { representatives = randomSubset(auctionRequest.RepGuids, auctionRequest.Rules.MaxBiddingPool) } numRounds++ winner, _, err := vote(client, auctionRequest.Instance, representatives) numVotes += len(representatives) if err != nil { continue } c := make(chan types.VoteResult) go func() { winnerScore, err := client.ReserveAndRecastVote(winner, auctionRequest.Instance) result := types.VoteResult{ Rep: winner, } if err != nil { result.Error = err.Error() c <- result return } result.Score = winnerScore c <- result }() secondRoundVoters := []string{} for _, rep := range representatives { if rep != winner { secondRoundVoters = append(secondRoundVoters, rep) } } _, secondPlaceScore, err := vote(client, auctionRequest.Instance, secondRoundVoters) winnerRecast := <-c numVotes += len(representatives) if winnerRecast.Error != "" { //winner ran out of space on the recast, retry continue } if err == nil && secondPlaceScore < winnerRecast.Score && round < auctionRequest.Rules.MaxRounds { client.Release(winner, auctionRequest.Instance) continue } client.Claim(winner, auctionRequest.Instance) auctionWinner = winner break } return types.AuctionResult{ Winner: auctionWinner, Instance: auctionRequest.Instance, NumRounds: numRounds, NumVotes: numVotes, Duration: time.Since(t), } }