-
Notifications
You must be signed in to change notification settings - Fork 748
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add BidderResponseDurationMin
check
#2848
Conversation
- As of now, `bidderRequestStartTime` is part of `ExtraRequestInfo`. The ExtraRequestInfo is further passed as details to Adapter's MakeRequest() implementation. - We don't want to pass bidderRequestStartTime details to `MakeRequest()`. So remove bidderRequestStartTime from ExtraRequestInfo and add it in bidRequestOptions.
addresses: #2848 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm!
The base branch was changed.
This reverts commit ba2c1a3.
The pbsRequestStartTime implies start point of auction handler endpoint. But received value is the start time of bidderRequest loop of GetAllBids[1]. So rename pbsRequestStartTime to bidderRequestStartTime Links: [1] https://github.com/prebid/prebid-server/blob/master/exchange/exchange.go#L698
ec51657
to
1b6ebea
Compare
@Sonali-More-Xandr @gargcreation1992, all dependent PR are merged. However, they added some merge conflicts. So updating PR by pushing following commits to resolve conflicts. PTAL and review in following order: |
@@ -190,11 +193,11 @@ func (bidder *bidderAdapter) requestBid(ctx context.Context, bidderRequest Bidde | |||
dataLen = len(reqData) + len(bidderRequest.BidderStoredResponses) | |||
responseChannel = make(chan *httpCallInfo, dataLen) | |||
if len(reqData) == 1 { | |||
responseChannel <- bidder.doRequest(ctx, reqData[0], reqInfo.BidderRequestStartTime) | |||
responseChannel <- bidder.doRequest(ctx, reqData[0], bidRequestOptions.bidderRequestStartTime, bidRequestOptions.tmaxAdjustments) | |||
} else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we combine two arguments and pass one argument bidRequestOptions
instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
prebid-server/exchange/bidder.go
Lines 65 to 72 in 1b6ebea
type bidRequestOptions struct { | |
accountDebugAllowed bool | |
headerDebugAllowed bool | |
addCallSignHeader bool | |
bidAdjustments map[string]float64 | |
tmaxAdjustments *TmaxAdjustmentsPreprocessed | |
bidderRequestStartTime time.Time | |
} |
bidRequestOptions
holds different values which are not needed by doRequest
. IMO better to pass only values those are needed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
requesting one minor change. Rest lgtm!
@@ -46,6 +47,9 @@ func (b *bidderTmaxCtx) Deadline() (deadline time.Time, ok bool) { | |||
deadline, ok = b.ctx.Deadline() | |||
return | |||
} | |||
func (b *bidderTmaxCtx) Until(t time.Time) time.Duration { | |||
return time.Until(t) | |||
} | |||
|
|||
func getBidderTmax(ctx bidderTmaxContext, requestTmaxMS int64, tmaxAdjustments TmaxAdjustmentsPreprocessed) int64 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we write a short description of the logic behing the calculations this function performs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bd1c910 adds description
@@ -46,6 +47,9 @@ func (b *bidderTmaxCtx) Deadline() (deadline time.Time, ok bool) { | |||
deadline, ok = b.ctx.Deadline() | |||
return | |||
} | |||
func (b *bidderTmaxCtx) Until(t time.Time) time.Duration { | |||
return time.Until(t) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: Are we planning to add more functionality into Until
in the future? If not, given that it doesn't access nor works with bidderTmaxCtx
, maybe we can get rid of it and simply use the time
library function. "time"
is already listed in the imports of exchange/bidder.go
so we wouldn't need the extra import either.
741 func hasShorterDurationThanTmax(ctx bidderTmaxContext, tmaxAdjustments TmaxAdjustmentsPreprocessed) bool {
742 if tmaxAdjustments.IsEnforced {
743 if deadline, ok := ctx.Deadline(); ok {
744 overheadNS := time.Duration(tmaxAdjustments.BidderNetworkLatencyBuffer+tmaxAdjustments.PBSResponsePreparationDuration) * time.Millisecond
745 bidderTmax := deadline.Add(-overheadNS)
746
747 - remainingDuration := ctx.Until(bidderTmax).Milliseconds()
+ remainingDuration := time.Until(bidderTmax).Milliseconds()
748 return remainingDuration < int64(tmaxAdjustments.BidderResponseDurationMin)
749 }
750 }
751 return false
752 }
exchange/bidder.go
This could also be the case of RemainingDurationMS
. Unless this is for testing purposes and I'm missing the big picture.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
time.Until()
internally calls time.Now()
. Its difficult to test code path when value returned from time.Now()
is used. By using ctx.Until()
we can mock this return value.
Refer TestHasShorterDurationThanTmax unit test.
prebid-server/exchange/bidder_test.go
Line 3156 in 1b6ebea
ctx := &mockBidderTmaxCtx{startTime: startTime, deadline: deadline, now: now, ok: true} |
In the test, mockBidderTmaxCtx
is passed as implementer for biddetTmaxCtx
. So during unit test mockBidderTmaxCtx.Until()
is called.
prebid-server/exchange/bidder_test.go
Lines 3081 to 3083 in 1b6ebea
func (m *mockBidderTmaxCtx) Until(t time.Time) time.Duration { | |
return t.Sub(m.now) | |
} |
By using ctx.Until()
with mockBidderTmaxCtx
, we can easily control the return value for testing purposes. This approach enables us to test specific code paths that were previously difficult time.Until()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about avoiding time.Now()
entirely by storing the openrtb2.BidRequest.TMax
field in the tmaxAdjustments
parameter and using it for the calculation. I believe both calculations and test cases could be simplified:
741 - func hasShorterDurationThanTmax(ctx bidderTmaxContext, tmaxAdjustments TmaxAdjustmentsPreprocessed) bool {
+ // hasShorterDurationThanTmax returns true if there's enough tmax to make the roundtrip to the bid server
+ // doing a calculation that involves the original bid request tmax
+ func hasShorterDurationThanTmax(tmaxAdjustments TmaxAdjustmentsPreprocessed) bool {
742 if tmaxAdjustments.IsEnforced {
743 - if deadline, ok := ctx.Deadline(); ok {
744 overheadNS := time.Duration(tmaxAdjustments.BidderNetworkLatencyBuffer+tmaxAdjustments.PBSResponsePreparationDuration) * time.Millisecond
745 - bidderTmax := deadline.Add(-overheadNS)
746
747 - remainingDuration := ctx.Until(bidderTmax).Milliseconds()
+ remainingDuration := tmaxAdjustments.BidRequestTmax - overheadNS
748 return remainingDuration < int64(tmaxAdjustments.BidderResponseDurationMin)
749 - }
750 }
751 return false
752 }
exchange/bidder.go
We would have to copy the openrtb2.BidRequest.TMax
into tmaxAdjustments.BidRequestTmax
and recalculate it's value inside func (e *exchange) makeAuctionContext(ctx context.Context, needsCache bool)
(exchange/exchange.go
line 646) if necessary.
Do you think we can pull this off?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to get the elapsed time since start of auction handler function.
For this we are using, deadline context intialised at the start. Refer following:
prebid-server/endpoints/openrtb2/auction.go
Lines 208 to 213 in 35db00f
timeout := deps.cfg.AuctionTimeouts.LimitAuctionTimeout(time.Duration(req.TMax) * time.Millisecond) | |
if timeout > 0 { | |
var cancel context.CancelFunc | |
ctx, cancel = context.WithDeadline(ctx, start.Add(timeout)) | |
defer cancel() | |
} |
This elapsed time from deadline context is fetched using ctx.Deadline()
and then BidderNetworkLatencyBuffer
, PBSResponsePreparationDuration
is deducted from resultant deadline to get bidderTmax.
I am not sure how using openrtb2.BidRequest.TMax
we can get elapsed time
exchange/tmax_adjustments.go
Outdated
@@ -47,6 +47,8 @@ func (b *bidderTmaxCtx) Deadline() (deadline time.Time, ok bool) { | |||
deadline, ok = b.ctx.Deadline() | |||
return | |||
} | |||
|
|||
// returns the remaining duration until the specified time |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Super nitpick: Can we use the usual Golang convention of prefixing the comment with the name of the function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -46,6 +47,9 @@ func (b *bidderTmaxCtx) Deadline() (deadline time.Time, ok bool) { | |||
deadline, ok = b.ctx.Deadline() | |||
return | |||
} | |||
func (b *bidderTmaxCtx) Until(t time.Time) time.Duration { | |||
return time.Until(t) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about avoiding time.Now()
entirely by storing the openrtb2.BidRequest.TMax
field in the tmaxAdjustments
parameter and using it for the calculation. I believe both calculations and test cases could be simplified:
741 - func hasShorterDurationThanTmax(ctx bidderTmaxContext, tmaxAdjustments TmaxAdjustmentsPreprocessed) bool {
+ // hasShorterDurationThanTmax returns true if there's enough tmax to make the roundtrip to the bid server
+ // doing a calculation that involves the original bid request tmax
+ func hasShorterDurationThanTmax(tmaxAdjustments TmaxAdjustmentsPreprocessed) bool {
742 if tmaxAdjustments.IsEnforced {
743 - if deadline, ok := ctx.Deadline(); ok {
744 overheadNS := time.Duration(tmaxAdjustments.BidderNetworkLatencyBuffer+tmaxAdjustments.PBSResponsePreparationDuration) * time.Millisecond
745 - bidderTmax := deadline.Add(-overheadNS)
746
747 - remainingDuration := ctx.Until(bidderTmax).Milliseconds()
+ remainingDuration := tmaxAdjustments.BidRequestTmax - overheadNS
748 return remainingDuration < int64(tmaxAdjustments.BidderResponseDurationMin)
749 - }
750 }
751 return false
752 }
exchange/bidder.go
We would have to copy the openrtb2.BidRequest.TMax
into tmaxAdjustments.BidRequestTmax
and recalculate it's value inside func (e *exchange) makeAuctionContext(ctx context.Context, needsCache bool)
(exchange/exchange.go
line 646) if necessary.
Do you think we can pull this off?
PR makes changes to add
Tmax.BidderResponseDurationMin
check in auction workflow. As per this change, PBS won't send request to bidder server if remaining duration less thanBidderResponseDurationMin