Пример #1
0
func (rep *LossyRep) vote(guid string, instance instance.Instance, c chan types.VoteResult) {
	result := types.VoteResult{
		Rep: guid,
	}
	defer func() {
		c <- result
	}()

	if rep.beSlowAndFlakey(guid) {
		result.Error = "timeout"
		return
	}

	score, err := rep.reps[guid].Vote(instance)
	if err != nil {
		result.Error = err.Error()
		return
	}

	result.Score = score
	return
}
Пример #2
0
func (rep *RepHTTPClient) vote(guid string, instance instance.Instance, c chan types.VoteResult) {
	rep.enter()
	defer rep.exit()
	result := types.VoteResult{
		Rep: guid,
	}
	defer func() {
		c <- result
	}()

	body := new(bytes.Buffer)
	err := json.NewEncoder(body).Encode(instance)
	if err != nil {
		result.Error = err.Error()
		return
	}

	resp, err := rep.client.Post(rep.endpoints[guid]+"/vote", "application/json", body)
	if err != nil {
		println(err.Error())
		result.Error = err.Error()
		return
	}

	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		result.Error = "failed"
		return
	}

	var score float64
	err = json.NewDecoder(resp.Body).Decode(&score)
	if err != nil {
		result.Error = err.Error()
		return
	}
	result.Score = score

	return
}
Пример #3
0
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),
	}
}
Пример #4
0
func Start(natsAddrs []string, rep *representative.Representative) {
	client := yagnats.NewClient()

	clusterInfo := &yagnats.ConnectionCluster{}

	for _, addr := range natsAddrs {
		clusterInfo.Members = append(clusterInfo.Members, &yagnats.ConnectionInfo{
			Addr: addr,
		})
	}

	err := client.Connect(clusterInfo)
	if err != nil {
		log.Fatalln("no nats:", err)
	}

	guid := rep.Guid()

	client.Subscribe(guid+".guid", func(msg *yagnats.Message) {
		jguid, _ := json.Marshal(rep.Guid())
		client.Publish(msg.ReplyTo, jguid)
	})

	client.Subscribe(guid+".total_resources", func(msg *yagnats.Message) {
		jresources, _ := json.Marshal(rep.TotalResources())
		client.Publish(msg.ReplyTo, jresources)
	})

	client.Subscribe(guid+".reset", func(msg *yagnats.Message) {
		rep.Reset()
		client.Publish(msg.ReplyTo, successResponse)
	})

	client.Subscribe(guid+".set_instances", func(msg *yagnats.Message) {
		var instances []instance.Instance

		err := json.Unmarshal(msg.Payload, &instances)
		if err != nil {
			client.Publish(msg.ReplyTo, errorResponse)
		}

		rep.SetInstances(instances)
		client.Publish(msg.ReplyTo, successResponse)
	})

	client.Subscribe(guid+".instances", func(msg *yagnats.Message) {
		jinstances, _ := json.Marshal(rep.Instances())
		client.Publish(msg.ReplyTo, jinstances)
	})

	client.Subscribe(guid+".vote", func(msg *yagnats.Message) {
		var inst instance.Instance

		err := json.Unmarshal(msg.Payload, &inst)
		if err != nil {
			panic(err)
		}

		response := types.VoteResult{
			Rep: guid,
		}

		defer func() {
			payload, _ := json.Marshal(response)
			client.Publish(msg.ReplyTo, payload)
		}()

		score, err := rep.Vote(inst)
		if err != nil {
			// log.Println(guid, "failed to vote:", err)
			response.Error = err.Error()
			return
		}

		response.Score = score
	})

	client.Subscribe(guid+".reserve_and_recast_vote", func(msg *yagnats.Message) {
		var inst instance.Instance

		responsePayload := errorResponse
		defer func() {
			client.Publish(msg.ReplyTo, responsePayload)
		}()

		err := json.Unmarshal(msg.Payload, &inst)
		if err != nil {
			// log.Println(guid, "invalid reserve_and_recast_vote request:", err)
			return
		}

		score, err := rep.ReserveAndRecastVote(inst)
		if err != nil {
			// log.Println(guid, "failed to reserve_and_recast_vote:", err)
			return
		}

		responsePayload, _ = json.Marshal(score)
	})

	client.Subscribe(guid+".release", func(msg *yagnats.Message) {
		var inst instance.Instance

		responsePayload := errorResponse
		defer func() {
			client.Publish(msg.ReplyTo, responsePayload)
		}()

		err := json.Unmarshal(msg.Payload, &inst)
		if err != nil {
			log.Println(guid, "invalid reserve_and_recast_vote request:", err)
			return
		}

		rep.Release(inst)

		responsePayload = successResponse
	})

	client.Subscribe(guid+".claim", func(msg *yagnats.Message) {
		var inst instance.Instance

		responsePayload := errorResponse
		defer func() {
			client.Publish(msg.ReplyTo, responsePayload)
		}()

		err := json.Unmarshal(msg.Payload, &inst)
		if err != nil {
			log.Println(guid, "invalid reserve_and_recast_vote request:", err)
			return
		}

		rep.Claim(inst)

		responsePayload = successResponse
	})

	fmt.Printf("[%s] listening for nats\n", guid)

	select {}
}