Skip to content
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 ORTB 2.4 schain support #2108

Merged
merged 10 commits into from
Jan 13, 2022
Merged

Add ORTB 2.4 schain support #2108

merged 10 commits into from
Jan 13, 2022

Conversation

bsardo
Copy link
Collaborator

@bsardo bsardo commented Dec 9, 2021

This PR adds ORTB 2.4 schain support as described in issue #2080.

  • If an schain is defined in one of the ORTB 2.5 locations (.source.ext.schain or .ext.prebid.schains) and in the ORTB 2.4 location (.ext.schain), the 2.5 schains take precedence so the ORTB 2.4 schain is ignored.
  • If an schain is defined in the ORTB 2.4 location (.ext.schain) but not in one of the ORTB 2.5 schain locations, the ORTB 2.4 schain is copied to the ORTB 2.5 location (.source.ext.schain) for each bid request.

The PR refactors the schain logic as part of introducing ORTB 2.4 schain support. An SChainWriter interface is introduced with concrete ORTB 2.4 and 2.5 implementations. Each concrete type's Write method modifies the request .source.ext.schain accordingly ensuring that any fields defined in .source are copied (this was a recently fixed bug).

It should also be noted that the function BidderToPrebidSChains in schain/schain.go and its corresponding tests were copied verbatim from exchange/utils.go.

@@ -2734,47 +2623,6 @@ func TestBuildXPrebidHeader(t *testing.T) {
}
}

func TestSourceExtSChainCopied(t *testing.T) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test was deleted because the corresponding logic was moved into the schain writer implementation Write methods which have tests that cover this logic.

return json.Marshal(extCopy)
}

func prepareSource(req *openrtb2.BidRequest, bidder string, sChainsByBidder map[string]*openrtb_ext.ExtRequestPrebidSChainSChain) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic has been moved to the schain writer implementation Write methods.

@bsardo bsardo marked this pull request as ready for review December 13, 2021 21:09
@@ -31,23 +32,6 @@ var integrationTypeMap = map[metrics.RequestType]config.IntegrationType{

const unknownBidder string = ""

func BidderToPrebidSChains(sChains []*openrtb_ext.ExtRequestPrebidSChain) (map[string]*openrtb_ext.ExtRequestPrebidSChainSChain, error) {
Copy link
Collaborator Author

@bsardo bsardo Dec 13, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function was copied to schain/schain.go.

Comment on lines +121 to +129
func extPrebidSChainExists(reqExt *openrtb_ext.ExtRequest) bool {
if reqExt == nil {
return false
}
if reqExt.Prebid.SChains == nil {
return false
}
return true
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function was written this way instead of a simple one liner of return reqExt != nil && reqExt.Prebid.SChains != nil because I think it helps us ensure code coverage of each condition when running the tests with code coverage enabled. The same applies to the two helper functions right after it.
If anyone prefers I use a one liner LMK. I thought the benefits here outweighed the slight increase in LOC.

Copy link
Contributor

@VeronikaSolovei9 VeronikaSolovei9 Dec 20, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was going to write a comment about this :)
I only think it's better to check reqExt.Prebid.SChains != nil. In this case returning false by default sounds more reasonable to me.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we also need to check if reqExt is nil otherwise we will get an error when attempting to access the Prebid field on a nil reqExt.

@VeronikaSolovei9
Copy link
Contributor

VeronikaSolovei9 commented Dec 20, 2021

While reviewing this PR and reading description at the 100th time, I started to think there is no need of ORTBTwoFourSChainWriter. If an schain is defined in the ORTB 2.4 location (.ext.schain) but not in one of the ORTB 2.5 schain locations, the ORTB 2.4 schain is copied to the ORTB 2.5 location (.source.ext.schain) for each bid request. -> sounds there will always be ORTB 2.5.
Also code in func (w ORTBTwoFourSChainWriter) Write(req *openrtb2.BidRequest, bidder string) duplicates code in func (w ORTBTwoFiveSChainWriter) Write(req *openrtb2.BidRequest, bidder string).
Also you execute sChainWriter.Write(&reqCopy, bidder) inside of the loop, so ORTBTwoFourSChainWriter still writes data to each bidder request (even if it's the same) and bidder param doesn't have any usages.
Would it be reasonable to have just one SChainWriter?
Please let me know if I miss something

@bsardo
Copy link
Collaborator Author

bsardo commented Dec 20, 2021

An schain can be defined in the ORTB 2.4 or the ORTB 2.5 location of the original request. Each of the writers is used to set the schain in the ORTB 2.5 location of each bid request. If no ORTB 2.5 schain is defined but an ORTB 2.4 schain is defined, the ORTB 2.4 schain writer is what is instantiated and then used to write the 2.4 schain to the 2.5 location. So yes, there will always be an schain in the 2.5 location of each bid request assuming an schain was defined somewhere in the original request.
I created two separate writers, each of which writes to the 2.5 location, because IMO it is better design (smaller functions, easier to test, more extensible) to separate the 2.4 and 2.5 logic than to mix that logic together. I agree there is a little code duplication in the Write function. That could be extracted into a common function.
Also, yes, the bidder isn't used in the 2.4 writer Write function; it is there to satisfy the interface contract at this time. If we have some concerns about the fact that the 2.4 writer is called in a loop and just does the same thing for each bidder, the marshalling could happen on instantiation to address any performance concerns.
Thoughts @VeronikaSolovei9 @mansinahar?

@stale
Copy link

stale bot commented Jan 8, 2022

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Jan 8, 2022
@stale stale bot removed the stale label Jan 10, 2022
@@ -456,6 +511,19 @@ func (re *RequestExt) SetPrebid(prebid *ExtRequestPrebid) {
re.prebidDirty = true
}

func (re *RequestExt) GetSChain() *ExtRequestPrebidSChainSChain {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we please add a comment here saying that these Schain functions on the request ext are only for backwards compatibility for openrtb 2.4 and shouldn't really be used for anything else. Only source.ext.schain or reques.ext.prebid.schain should be used?

if tt.wantReqExtSChain == nil {
assert.Nil(t, reqExtSChain, tt.description)
} else {
assert.Equal(t, tt.wantReqExtSChain, reqExtSChain, tt.description)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't this assert.Equal call take care of the nil case as well? Do we need the if-else conditional here? Similar for the source ext below

Copy link
Contributor

@VeronikaSolovei9 VeronikaSolovei9 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for changing the code, LGTM

@mansinahar mansinahar merged commit 9f908f6 into prebid:master Jan 13, 2022
wwwyyy pushed a commit to wwwyyy/prebid-server that referenced this pull request Jan 18, 2022
* 'master' of https://github.com/wwwyyy/prebid-server:
  GDPR: pass geo based on special feature 1 opt-in (prebid#2122)
  Adyoulike: Fix adapter errors if no content (prebid#2134)
  Update adyoulike.yaml (prebid#2131)
  Add ORTB 2.4 schain support (prebid#2108)
  Stored response fetcher (with new func for stored resp) (prebid#2099)
  Adot: Add OpenRTB macros resolution (prebid#2118)
  Rubicon adapter: accept accountId, siteId, zoneId as strings (prebid#2110)
  Operaads: support multiformat request (prebid#2121)
  Update go-gdpr to v1.11.0 (prebid#2125)
  Adgeneration: Update request to include device and app related info in headers and query params (prebid#2109)
  Adnuntius: Read device information from ortb Request (prebid#2112)
  New Adapter: apacdex and Remove Adapter: valueimpression (prebid#2097)
  New Adapter: Compass (prebid#2102)
  Orbidder: bidfloor currency handling (prebid#2093)
ramyferjaniadot pushed a commit to adotmob/prebid-server that referenced this pull request Feb 2, 2022
jorgeluisrocha pushed a commit to jwplayer/prebid-server that referenced this pull request Sep 28, 2022
shunj-nb pushed a commit to ParticleMedia/prebid-server that referenced this pull request Nov 8, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants