Skip to content

Commit 58f98fa

Browse files
VeronikaSolovei9hhhjort
authored andcommitted
Cache validation fix (prebid#911)
* Cache validation fix if no bids returned - don't throw cache error, just return empty result * Cache validation fix - optimization: do not run auction logic if no bids returned * Cache validation fix: minor refactoring * Cache validation fix: minor refactoring * Cache validation fix: added unit test for no bids returned * Cache validation fix: minor refactoring
1 parent 295e483 commit 58f98fa

File tree

3 files changed

+39
-20
lines changed

3 files changed

+39
-20
lines changed

endpoints/openrtb2/video_auction.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -359,8 +359,10 @@ func minMax(array []int) (int, int) {
359359
func buildVideoResponse(bidresponse *openrtb.BidResponse, podErrors []PodError) (*openrtb_ext.BidResponseVideo, error) {
360360

361361
adPods := make([]*openrtb_ext.AdPod, 0)
362+
anyBidsReturned := false
362363
for _, seatBid := range bidresponse.SeatBid {
363364
for _, bid := range seatBid.Bid {
365+
anyBidsReturned = true
364366

365367
var tempRespBidExt openrtb_ext.ExtBid
366368
if err := json.Unmarshal(bid.Ext, &tempRespBidExt); err != nil {
@@ -393,14 +395,14 @@ func buildVideoResponse(bidresponse *openrtb.BidResponse, podErrors []PodError)
393395
}
394396
}
395397

396-
if len(adPods) == 0 {
398+
//check if there are any bids in response.
399+
//if there are no bids - empty response should be returned, no cache errors
400+
if len(adPods) == 0 && anyBidsReturned {
397401
//means there is a global cache error, we need to reject all bids
398402
err := errors.New("caching failed for all bids")
399403
return nil, err
400404
}
401405

402-
videoResponse := openrtb_ext.BidResponseVideo{}
403-
404406
// If there were incorrect pods, we put them back to response with error message
405407
if len(podErrors) > 0 {
406408
for _, podEr := range podErrors {
@@ -412,9 +414,7 @@ func buildVideoResponse(bidresponse *openrtb.BidResponse, podErrors []PodError)
412414
}
413415
}
414416

415-
videoResponse.AdPods = adPods
416-
417-
return &videoResponse, nil
417+
return &openrtb_ext.BidResponseVideo{AdPods: adPods}, nil
418418
}
419419

420420
func findAdPod(podInd int64, pods []*openrtb_ext.AdPod) *openrtb_ext.AdPod {

endpoints/openrtb2/video_auction_test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,15 @@ func TestVideoBuildVideoResponsePodErrors(t *testing.T) {
478478
assert.Equal(t, int64(333), bidRespVideo.AdPods[2].PodId, "AdPods should contain error element at index 2")
479479
}
480480

481+
func TestVideoBuildVideoResponseNoBids(t *testing.T) {
482+
openRtbBidResp := openrtb.BidResponse{}
483+
podErrors := make([]PodError, 0, 0)
484+
openRtbBidResp.SeatBid = make([]openrtb.SeatBid, 0)
485+
bidRespVideo, err := buildVideoResponse(&openRtbBidResp, podErrors)
486+
assert.NoError(t, err, "Error should be nil")
487+
assert.Len(t, bidRespVideo.AdPods, 0, "AdPods length should be 0")
488+
}
489+
481490
func mockDeps(t *testing.T, ex *mockExchangeVideo) *endpointDeps {
482491
theMetrics := pbsmetrics.NewMetrics(metrics.NewRegistry(), openrtb_ext.BidderList())
483492
edep := &endpointDeps{

exchange/exchange.go

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -138,21 +138,26 @@ func (e *exchange) HoldAuction(ctx context.Context, bidRequest *openrtb.BidReque
138138
// Get currency rates conversions for the auction
139139
conversions := e.currencyConverter.Rates()
140140

141-
adapterBids, adapterExtra := e.getAllBids(auctionCtx, cleanRequests, aliases, bidAdjustmentFactors, blabels, conversions)
142-
bidCategory, adapterBids, err := applyCategoryMapping(ctx, requestExt, adapterBids, *categoriesFetcher, targData)
143-
auc := newAuction(adapterBids, len(bidRequest.Imp))
144-
if err != nil {
145-
return nil, fmt.Errorf("Error in category mapping : %s", err.Error())
146-
}
141+
adapterBids, adapterExtra, anyBidsReturned := e.getAllBids(auctionCtx, cleanRequests, aliases, bidAdjustmentFactors, blabels, conversions)
142+
143+
if anyBidsReturned {
144+
bidCategory, adapterBids, err := applyCategoryMapping(ctx, requestExt, adapterBids, *categoriesFetcher, targData)
145+
if err != nil {
146+
return nil, fmt.Errorf("Error in category mapping : %s", err.Error())
147+
}
147148

148-
if targData != nil && adapterBids != nil {
149-
auc.setRoundedPrices(targData.priceGranularity)
150-
cacheErrs := auc.doCache(ctx, e.cache, targData, bidRequest, 60, &e.defaultTTLs, bidCategory)
151-
if len(cacheErrs) > 0 {
152-
errs = append(errs, cacheErrs...)
149+
auc := newAuction(adapterBids, len(bidRequest.Imp))
150+
151+
if targData != nil {
152+
auc.setRoundedPrices(targData.priceGranularity)
153+
cacheErrs := auc.doCache(ctx, e.cache, targData, bidRequest, 60, &e.defaultTTLs, bidCategory)
154+
if len(cacheErrs) > 0 {
155+
errs = append(errs, cacheErrs...)
156+
}
157+
targData.setTargeting(auc, bidRequest.App != nil, bidCategory)
153158
}
154-
targData.setTargeting(auc, bidRequest.App != nil, bidCategory)
155159
}
160+
156161
// Build the response
157162
return e.buildBidResponse(ctx, liveAdapters, adapterBids, bidRequest, resolvedRequest, adapterExtra, errs)
158163
}
@@ -169,11 +174,12 @@ func (e *exchange) makeAuctionContext(ctx context.Context, needsCache bool) (auc
169174
}
170175

171176
// This piece sends all the requests to the bidder adapters and gathers the results.
172-
func (e *exchange) getAllBids(ctx context.Context, cleanRequests map[openrtb_ext.BidderName]*openrtb.BidRequest, aliases map[string]string, bidAdjustments map[string]float64, blabels map[openrtb_ext.BidderName]*pbsmetrics.AdapterLabels, conversions currencies.Conversions) (map[openrtb_ext.BidderName]*pbsOrtbSeatBid, map[openrtb_ext.BidderName]*seatResponseExtra) {
177+
func (e *exchange) getAllBids(ctx context.Context, cleanRequests map[openrtb_ext.BidderName]*openrtb.BidRequest, aliases map[string]string, bidAdjustments map[string]float64, blabels map[openrtb_ext.BidderName]*pbsmetrics.AdapterLabels, conversions currencies.Conversions) (map[openrtb_ext.BidderName]*pbsOrtbSeatBid, map[openrtb_ext.BidderName]*seatResponseExtra, bool) {
173178
// Set up pointers to the bid results
174179
adapterBids := make(map[openrtb_ext.BidderName]*pbsOrtbSeatBid, len(cleanRequests))
175180
adapterExtra := make(map[openrtb_ext.BidderName]*seatResponseExtra, len(cleanRequests))
176181
chBids := make(chan *bidResponseWrapper, len(cleanRequests))
182+
bidsFound := false
177183

178184
for bidderName, req := range cleanRequests {
179185
// Here we actually call the adapters and collect the bids.
@@ -228,9 +234,13 @@ func (e *exchange) getAllBids(ctx context.Context, cleanRequests map[openrtb_ext
228234
brw := <-chBids
229235
adapterBids[brw.bidder] = brw.adapterBids
230236
adapterExtra[brw.bidder] = brw.adapterExtra
237+
238+
if !bidsFound && adapterBids[brw.bidder] != nil && len(adapterBids[brw.bidder].bids) > 0 {
239+
bidsFound = true
240+
}
231241
}
232242

233-
return adapterBids, adapterExtra
243+
return adapterBids, adapterExtra, bidsFound
234244
}
235245

236246
func (e *exchange) recoverSafely(inner func(openrtb_ext.BidderName, openrtb_ext.BidderName, *openrtb.BidRequest, *pbsmetrics.AdapterLabels, currencies.Conversions), chBids chan *bidResponseWrapper) func(openrtb_ext.BidderName, openrtb_ext.BidderName, *openrtb.BidRequest, *pbsmetrics.AdapterLabels, currencies.Conversions) {

0 commit comments

Comments
 (0)