@@ -2,78 +2,17 @@ package exchange
22
33import (
44 "encoding/json"
5- "math"
65 "time"
76
8- "github.com/buger/jsonparser"
9- "github.com/golang/glog"
107 "github.com/prebid/openrtb/v19/openrtb2"
118 "github.com/prebid/prebid-server/exchange/entities"
129 "github.com/prebid/prebid-server/openrtb_ext"
13- jsonpatch "gopkg.in/evanphx/json-patch.v4"
1410)
1511
1612const (
1713 MSP_SEAT_IN_HOUSE = "msp-in-house"
1814)
1915
20- type MSBExt struct {
21- MSB MSBConfig `json:"msb"`
22- }
23-
24- type MSBConfig struct {
25- LastPeek MSBLastPeekConfig `json:"last_peek"`
26- }
27-
28- type MSBLastPeekConfig struct {
29- // start peek available bids after this
30- PeekStartTimeMilliSeconds int64 `json:"peek_start_time_miliseconds"`
31- // bidder -> FloorMult
32- // set floor for last peek bidder = current_available_max_bid_price * FloorMult to:
33- // 1. break tie
34- // 2. gain more revenue
35- PeekBidderFloorMultMap map [string ]float64 `json:"peek_bidder_floor_mult_map"`
36- }
37-
38- /*
39- MSB feature controller(req.ext) example:
40- {
41- "ext": {
42- "msb": {
43- "last_peek": {
44- "peek_start_time_miliseconds": 900,
45- "peek_bidder_floor_mult_map": {
46- "msp_google": 1.01,
47- "msp_nova": 1.01
48- }
49- }
50- }
51- }
52- }
53- MSP server is response for adding above MSB info to requests for certain traffic/placement/exps. peek_bidder_floor_mult_map controls which bidders
54- are there for different peek tiers
55-
56- In the bove example
57- there are two peek tiers for bidders:
58- 1. last peek tier
59- 2. the rest(normal tier)
60-
61- after all reponses are ready for normal tier or timeout=peek_start_time_miliseconds(900ms), for bidders in last peek tier(msp_google and msp_nova) peek available responses from normal tier,
62- get max_available_bid_prices_for_normal_tier and set floor = max_available_bid_prices_for_normal_tier * peek_bidder_floor_mult_map[bidder]
63- */
64-
65- type MSPFloor struct {
66- Floor float64 `json:"floor"`
67- }
68-
69- var mspBidders = map [openrtb_ext.BidderName ]int {
70- openrtb_ext .BidderMspGoogle : 1 ,
71- openrtb_ext .BidderMspFbAlpha : 1 ,
72- openrtb_ext .BidderMspFbBeta : 1 ,
73- openrtb_ext .BidderMspFbGamma : 1 ,
74- openrtb_ext .BidderMspNova : 1 ,
75- }
76-
7716func mspUpdateStoredAuctionResponse (r * AuctionRequest ) bool {
7817 if len (r .StoredAuctionResponses ) > 0 {
7918 if rawSeatBid , ok := r .StoredAuctionResponses [r .BidRequestWrapper .Imp [0 ].ID ]; ok {
@@ -121,107 +60,3 @@ func mspPostProcessAuction(
12160
12261 return adapterBids , fledge , liveAdapters , nil , anyBidsReturned
12362}
124-
125- // peek max available(ready) bid price from channel without comsuming
126- func peekChannelAvailableMaxBidPriceWithinTimeout (peekTier string , chBids chan * bidResponseWrapper , lastPeekConfig MSBLastPeekConfig , totalNormalBidders int ) float64 {
127- timeout := time .After (time .Duration (lastPeekConfig .PeekStartTimeMilliSeconds ) * time .Millisecond )
128- maxPrice := 0.0
129- hasData := true
130- peekedRespList := []* bidResponseWrapper {}
131- availableBidders := []string {}
132- // keep consuming message from channel until all normal bidder requests are collected or timeout reaches
133- for hasData {
134- select {
135- case resp , ok := <- chBids :
136- if ! ok {
137- hasData = false
138- } else {
139- for _ , bids := range resp .adapterSeatBids {
140- for _ , bid := range bids .Bids {
141- if bid .Bid != nil {
142- maxPrice = math .Max (maxPrice , bid .Bid .Price )
143- }
144- }
145- }
146- peekedRespList = append (peekedRespList , resp )
147- availableBidders = append (availableBidders , resp .bidder .String ())
148- if len (peekedRespList ) == totalNormalBidders {
149- hasData = false
150- }
151- }
152-
153- case <- timeout :
154- hasData = false
155- }
156-
157- }
158- // push message back
159- for _ , resp := range peekedRespList {
160- chBids <- resp
161- }
162- glog .Infof ("MSB tier %s, peeked from available bidders %v, current max bid price: %f" , peekTier , availableBidders , maxPrice )
163- return maxPrice
164- }
165-
166- func mspUpdateLastPeekBiddersRequest (
167- chBids chan * bidResponseWrapper ,
168- lastPeekBidderRequests []BidderRequest ,
169- lastPeekConfig MSBLastPeekConfig ,
170- totalNormalBidders int ,
171- ) []BidderRequest {
172- maxPrice := peekChannelAvailableMaxBidPriceWithinTimeout ("lastPeek" , chBids , lastPeekConfig , totalNormalBidders )
173- for reqIdx := range lastPeekBidderRequests {
174- mult := lastPeekConfig .PeekBidderFloorMultMap [lastPeekBidderRequests [reqIdx ].BidderName .String ()]
175- updatedFloor := mult * maxPrice
176- for idx := range lastPeekBidderRequests [reqIdx ].BidRequest .Imp {
177- bidder := & lastPeekBidderRequests [reqIdx ]
178- // update req.imp.bidfloor
179- bidder .BidRequest .Imp [idx ].BidFloor = math .Max (bidder .BidRequest .Imp [idx ].BidFloor , updatedFloor )
180-
181- // for msp bidders, update req.imp.ext.bidder.floor which is the source of truth for msp bidder's floor and
182- // will be updated/overwritten later by msp module stage: https://github.com/ParticleMedia/msp/blob/master/pkg/modules/dam_buckets/module/hook_bidder_request.go#L69
183- if _ , found := mspBidders [bidder .BidderName ]; found {
184- extBytes , err := jsonObject (bidder .BidRequest .Imp [idx ].Ext , "bidder" )
185- if err == nil {
186- var impExt MSPFloor
187- err = json .Unmarshal (extBytes , & impExt )
188- if err == nil {
189- impExt .Floor = math .Max (impExt .Floor , updatedFloor )
190- updatedBytes , _ := json .Marshal (impExt )
191- updatedBidderBytes , _ := jsonpatch .MergePatch (extBytes , updatedBytes )
192- updatedExtBytes , _ := jsonparser .Set (bidder .BidRequest .Imp [idx ].Ext , updatedBidderBytes , "bidder" )
193- bidder .BidRequest .Imp [idx ].Ext = updatedExtBytes
194- }
195- }
196- }
197- }
198- }
199- return lastPeekBidderRequests
200- }
201-
202- func jsonObject (data []byte , keys ... string ) ([]byte , error ) {
203- if result , dataType , _ , err := jsonparser .Get (data , keys ... ); err == nil && dataType == jsonparser .Object {
204- return result , nil
205- } else {
206- return nil , err
207- }
208- }
209-
210- func extractMSBInfoBidders (reqList []BidderRequest ) MSBConfig {
211- if len (reqList ) > 0 {
212- return ExtractMSBInfoReq (reqList [0 ].BidRequest )
213- }
214-
215- return MSBConfig {}
216- }
217-
218- func ExtractMSBInfoReq (req * openrtb2.BidRequest ) MSBConfig {
219- var config MSBExt
220- if req != nil {
221- err := json .Unmarshal (req .Ext , & config )
222- if err != nil {
223- glog .Error ("MSB extract bidder config:" , err )
224- }
225- }
226- return config .MSB
227- }
0 commit comments