-
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
ORTB 2.6: Push wrapper into Eidpermissions and ApplyFPD #3998
Conversation
// eid scrubbing | ||
if err := removeUnpermissionedEids(reqWrapperCopy, bidder); err != nil { | ||
errs = append(errs, fmt.Errorf("unable to enforce request.ext.prebid.data.eidpermissions because %v", err)) | ||
continue | ||
} | ||
|
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.
removeUnpermissionedEids
function should be executed before buildRequestExtForBidder
because it needs access to req.ext.prebid.data.eidpermissions
.
buildRequestExtForBidder
function rebuilds req.ext
and doesn't add req.ext.prebid.data.eidpermissions
.
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.
I think you're right. It looks like we just need to read from req.ext.prebid.data
and copy any applicable EIDs to req.user
and then we can discard req.ext.prebid.data
. If that's the case then we should move removeUnpermissionedEids
just before buildRequestExtForBidder
since buildRequestExtForBidder
will delete req.ext.prebid.data
.
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
exchange/utils.go
Outdated
|
||
// exit early if there are no eids (empty array) | ||
if len(eids) == 0 { | ||
if reqExt.GetPrebid() == nil || reqExt.GetPrebid().Data == nil || len(reqExt.GetPrebid().Data.EidPermissions) == 0 { |
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.
You might want to consider setting GetPrebid()
to a variable to avoid the unnecessary struct copy operation that will take place each time it is called:
reqExtPrebid := reqExt.GetPrebid()
if reqExtPrebid == nil || reqExtPrebid.Data == nil || len(reqExtPrebid.Data.EidPermissions) == 0 {
return nil
}
You can also use this variable in the range
loop on line 783.
exchange/utils.go
Outdated
if fpdToApply.User != nil { | ||
//BuyerUID is a value obtained between fpd extraction and fpd application. | ||
//BuyerUID needs to be set back to fpd before applying this fpd to final bidder request | ||
if bidRequest.User != nil && len(bidRequest.User.BuyerUID) > 0 { | ||
fpdToApply.User.BuyerUID = bidRequest.User.BuyerUID | ||
if reqWrapper.User != nil && len(reqWrapper.User.BuyerUID) > 0 { | ||
fpdToApply.User.BuyerUID = reqWrapper.User.BuyerUID | ||
} | ||
bidRequest.User = fpdToApply.User | ||
reqWrapper.User = fpdToApply.User | ||
} |
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.
I think we might have always had a bug here. Notice how we first update fpdToApply.User.BuyerUID
to reqWrapper.User.BuyerUID
before assigning fpdToApply.User
to reqWrapper.User
in case the buyer UID was updated after fpdToApply.User
was populated upstream. Similarly, I think we should copy reqWrapper.User.EIDs
to fpdToApply.User.EIDs
because EIDs might have been removed by removeUnpermissionedEids
.
} | ||
bidRequest.User = fpdToApply.User | ||
reqWrapper.User = fpdToApply.User |
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.
Just checking, this statement will change the user object pointer on reqWrapper
to point to the user object on fpdToApply
. I believe the fpdToApply
user object may contain changes to the user ext. Will the request wrapper behave correctly when RebuildRequest
is called or will the ext changes be lost? I think the changes may be lost if a change is made to the UserExt
object on the request wrapper that result in it being marked as dirty so that a user ext rebuild is triggered when RebuildRequest
is called.
If you all agree that this is a problem, I think it could be fixed in a future PR after we have released ORTB 2.6 support since I think this issue has always existed.
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.
Yes, if fpdToApply.User.ext
has been modified, then the wrapper will overwrite those changes when the request is rebuilt.
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.
Good point, we will need to fix it.
exchange/utils.go
Outdated
//BuyerUID needs to be set back to fpd before applying this fpd to final bidder request | ||
fpdToApply.User.BuyerUID = reqWrapper.User.BuyerUID | ||
} | ||
if len(reqWrapper.User.EIDs) > 0 { |
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.
I don't think we want the conditional. Maybe this is simply just the statement fpdToApply.User.EIDs = reqWrapper.User.EIDs
so it always executes. It's possible that there were EIDs but they were all removed bringing the count to 0. Thoughts?
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.
Done
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.
Discussed offline. More changes are in progress
if len(userExt) == 0 { | ||
setUserExtWithCopy(request, nil) | ||
return nil | ||
reqWrapper.User.EIDs = eidsAllowed | ||
} |
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.
Do we need both cases anymore? If eidsAllowed
is null when there are no eids allowed, then we can get rid of the if statement and just set reqWrapper.User.EIDs = eidsAllowed
.
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.
I think we can remove the conditional here if we change
eidsAllowed := make([]openrtb2.EID, 0, len(eids))
to var eidsAllowed []openrtb2.EID
If we do that eidsAllowed
will start off as nil
, however there will be the performance penalty when building up that slice via append
.
@SyntaxNode thoughts?
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.
Discussed offline. We'll keep it the way it is using make
to initialize eidsAllowed
and the conditional check here.
…removeUnpermissionedEids
exchange/utils.go
Outdated
@@ -157,6 +157,8 @@ func (rs *requestSplitter) cleanOpenRTBRequests(ctx context.Context, | |||
bidderRequests = make([]BidderRequest, 0, len(impsByBidder)) | |||
|
|||
for bidder, imps := range impsByBidder { | |||
userEIDsOverride := fpdUserEIDExists(req, auctionReq.FirstPartyData, bidder) | |||
fpdUserEIDExists(req, auctionReq.FirstPartyData, bidder) |
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.
I think you can delete the second occurrence of fpdUserEIDExists
here.
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.
Yes, good catch, I used it for the debugging and forgot to remove.
exchange/utils.go
Outdated
@@ -157,6 +157,8 @@ func (rs *requestSplitter) cleanOpenRTBRequests(ctx context.Context, | |||
bidderRequests = make([]BidderRequest, 0, len(impsByBidder)) | |||
|
|||
for bidder, imps := range impsByBidder { | |||
userEIDsOverride := fpdUserEIDExists(req, auctionReq.FirstPartyData, bidder) |
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 changing this variable name to fpdUserEIDsExist
or fpdUserEIDsPresent
? I think this will be much easier to understand downstream if you make this same change to the parameter passed to applyFPD
as your conditional there will then read:
if !fpdUserEIDsExist {
fpdToApply.User.EIDs = reqWrapper.User.EIDs
}
The override language confuses me a bit.
if len(fpdUserEIDs) == 0 { | ||
return false | ||
} |
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 remove this statement? Technically it is possible that EID
is specified as first party data as an empty array.
We can just lean on your length check and for loop below to make the determination.
exchange/utils.go
Outdated
pReqUserEID := &reqUserEIDs[i] | ||
pFpdUserEID := &fpdUserEIDs[i] | ||
if pReqUserEID != pFpdUserEID { | ||
return false |
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.
Isn't this supposed to be return true
?
exchange/utils.go
Outdated
} | ||
|
||
} | ||
return true |
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.
Isn't this supposed to be return false
?
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.
Refactored
exchange/utils.go
Outdated
fpdToApply.User.EIDs = reqWrapper.User.EIDs | ||
|
||
// if FPD config didn't have user.eids - use reqWrapper.User.EIDs after removeUnpermissionedEids | ||
if userEIDsOverride { |
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.
As mentioned in an earlier comment, I suggest changing this variable name to fpdUserEIDsExist
so the meaning is clearer.
Also, isn't this conditional supposed to be negated: if !fpdUserEIDsExist
?
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.
Addressed
exchange/utils.go
Outdated
@@ -819,37 +844,15 @@ func removeUnpermissionedEids(request *openrtb2.BidRequest, bidder string, reque | |||
return nil | |||
} | |||
|
|||
// marshal eidsAllowed back to userExt | |||
// set eidsAllowed back to userExt |
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 you either change the userExt
part of this comment or delete the comment?
if len(userExt) == 0 { | ||
setUserExtWithCopy(request, nil) | ||
return nil | ||
reqWrapper.User.EIDs = eidsAllowed | ||
} |
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.
I think we can remove the conditional here if we change
eidsAllowed := make([]openrtb2.EID, 0, len(eids))
to var eidsAllowed []openrtb2.EID
If we do that eidsAllowed
will start off as nil
, however there will be the performance penalty when building up that slice via append
.
@SyntaxNode thoughts?
…r removeUnpermissionedEids
return false | ||
} | ||
fpdUserEIDs := fpdToApply.User.EIDs | ||
reqUserEIDs := req.User.EIDs |
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 User
be nil?
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.
if len(fpdUserEIDs) == 0 {
return false
}
if req.User == nil {
return true
}
exchange/utils_test.go
Outdated
description: "req.User is defined and had bidder fpd user eids (userEIDsOverride); bidderFPD.User defined and has EIDs. Expect to see user.EIDs in result request taken from fpd", | ||
inputFpd: map[openrtb_ext.BidderName]*firstpartydata.ResolvedFirstPartyData{ | ||
"bidderNormalized": {Site: &openrtb2.Site{ID: "SiteId"}, App: &openrtb2.App{ID: "AppId"}, User: &openrtb2.User{ID: "UserId", EIDs: []openrtb2.EID{{Source: "source1"}, {Source: "source2"}}}}, | ||
}, | ||
inputBidderName: "bidderFromRequest", | ||
inputBidderCoreName: "bidderNormalized", | ||
inputBidderIsRequestAlias: false, | ||
inputRequest: openrtb2.BidRequest{User: &openrtb2.User{ID: "UserId", EIDs: []openrtb2.EID{{Source: "source3"}, {Source: "source4"}}}}, | ||
expectedRequest: openrtb2.BidRequest{Site: &openrtb2.Site{ID: "SiteId"}, App: &openrtb2.App{ID: "AppId"}, User: &openrtb2.User{ID: "UserId", EIDs: []openrtb2.EID{{Source: "source1"}, {Source: "source2"}}}}, | ||
fpdUserEIDsExisted: true, | ||
}, | ||
{ | ||
description: "req.User is defined and doesn't have fpr user eids (userEIDsOverride); bidderFPD.User defined and has EIDs. Expect to see user.EIDs in result request taken from original req", | ||
inputFpd: map[openrtb_ext.BidderName]*firstpartydata.ResolvedFirstPartyData{ | ||
"bidderNormalized": {Site: &openrtb2.Site{ID: "SiteId"}, App: &openrtb2.App{ID: "AppId"}, User: &openrtb2.User{ID: "UserId", EIDs: []openrtb2.EID{{Source: "source1"}, {Source: "source2"}}}}, | ||
}, | ||
inputBidderName: "bidderFromRequest", | ||
inputBidderCoreName: "bidderNormalized", | ||
inputBidderIsRequestAlias: false, | ||
inputRequest: openrtb2.BidRequest{User: &openrtb2.User{ID: "UserId", EIDs: []openrtb2.EID{{Source: "source3"}, {Source: "source4"}}}}, | ||
expectedRequest: openrtb2.BidRequest{Site: &openrtb2.Site{ID: "SiteId"}, App: &openrtb2.App{ID: "AppId"}, User: &openrtb2.User{ID: "UserId", EIDs: []openrtb2.EID{{Source: "source3"}, {Source: "source4"}}}}, | ||
fpdUserEIDsExisted: false, | ||
}, |
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: remove references to variable userEIDsOverride
in the descriptions.
exchange/utils_test.go
Outdated
reqWrapper, | ||
testCase.fpdUserEIDsExisted, | ||
) | ||
assert.Equal(t, &testCase.expectedRequest, reqWrapper.BidRequest, fmt.Sprintf("incorrect request after applying fpd, testcase %s", testCase.description)) |
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: you can delete the last parameter now that you're using t.Run
.
exchange/utils_test.go
Outdated
assert.NoError(t, resultErr, test.description) | ||
assert.Equal(t, expectedRequest, reqWrapper.BidRequest, test.description) |
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: you can delete the last parameter now that you're using t.Run
.
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
No description provided.