예제 #1
0
파일: redispacer.go 프로젝트: mdominoni/rtb
func (p *RedisPacer) CanBid(campaign rtb.Campaign) bool {
	id := campaign.Id()
	key := p.paceAccountKey(campaign.Id())

	// Update remaining budget every time to compensate for unspent bids last cycle
	cpi := rtb.MicroCentsPerImpression(campaign.BidCpmInMicroCents())
	budget := p.banker.RemainingDailyBudgetInMicroCents(id)

	// Account not yet configured, or they actually have no budget. The pacer is not needed.
	if budget == 0 || cpi == 0 {
		return true // Allow it to pass and configure it
	}

	now := time.Now().UTC()
	midnight := time.Date(now.Year(), now.Month(), now.Day()+1, 0, 0, 0, 0, time.UTC)

	// TODO: This definitely only needs to be calculated at the end of each segment. Not every time we request a bid.
	durationToMidnight := midnight.Sub(now)
	segmentsToMidnight := int64(durationToMidnight / p.segment)
	remaining := (budget / cpi) / segmentsToMidnight

	remainingBudget, err := p.da.DebitIfNotZero(key, 1, remaining, time.Now().UTC().Add(p.segment))

	//	fmt.Printf("Campign: %v, Bids Per Segment: %v, Segment: %v, Remaining Budget: %v\n", id, remaining, p.segment, remainingBudget)

	if err == nil {
		return remainingBudget > 0
	} else {
		return false
	}
}
예제 #2
0
// highestBidder Returns the highest bidder with available funds.
// campaigns must be in order from highest CPM to lowest
// Caller is committed to using the campaign returned by this
func (b *BidRequestBidder) highestBidder(campaigns []rtb.Campaign) (campaign rtb.Campaign, remainingDailyBudgetInMicroCents int64) {
	for _, campaign := range campaigns {
		id := campaign.Id()

		if b.Pacer == nil || b.Pacer.CanBid(campaign) {
			bid := campaign.BidCpmInMicroCents()

			if remainingDailyBudgetInMicroCents, err := b.CampaignProvider.DebitCampaign(id, rtb.MicroCentsPerImpression(bid), b.dailyBudgetExpirationTime); err == nil {
				return campaign, remainingDailyBudgetInMicroCents
			}
		}
	}

	return nil, 0
}