-
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
IX: MultiImp Implementation #2779
Conversation
ccorbo
commented
May 15, 2023
•
edited
Loading
edited
- These changes implements multiimp functionality
- Also bidder param sid is added and passed through
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 have concerns over the feature concept. It looks like the server is picking up on a signal from a request to enable a feature for a set amount of time. It's bad practice for the server to keep state in this manner. Why is this required versus looking for a feature flag on each request?
adapters/ix/ix.go
Outdated
@@ -18,46 +19,69 @@ import ( | |||
"github.com/prebid/openrtb/v19/openrtb2" | |||
) | |||
|
|||
const ( | |||
FtHandleMultiImpOnSingleRequest = "pbs_handle_multi_imp_on_single_req" |
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.
Nitpicks: There is no need to export this constant (or ExpireFtTime
) so please change them to starting with a lowercase letter.
adapters/ix/ix.go
Outdated
FtHandleMultiImpOnSingleRequest = "pbs_handle_multi_imp_on_single_req" | ||
) | ||
|
||
const ExpireFtTime = 3600 //1 hour |
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: Calling this expireFtTimeSeconds
might help provide more context in addition to the comment. However, please see my other comments regarding the server keeping this kind of state.
adapters/ix/ix.go
Outdated
// Multi-size banner imps are split into single-size requests. | ||
// The first size imp requests are added to the first slice. | ||
// Additional size requests are added to the second slice and are merged with the first at the end. | ||
// Preallocate the max possible size to avoid reallocating arrays. | ||
requests := make([]*adapters.RequestData, 0, a.maxRequests) | ||
multiSizeRequests := make([]*adapters.RequestData, 0, a.maxRequests-nImp) | ||
errs := make([]error, 0, 1) |
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.
Let's optimize for the average case where there is no error. If you use var errs []error
there will not be any allocations unless an error is encountered. That will reduce GC pressure a little bit. Same applies to handleMultiImpInSingleRequest
.
} | ||
|
||
if err := moveSid(&imp); err != nil { | ||
errs = append(errs, err) |
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.
To Confirm: It is your intent to continue with the auction if moveSid
fails? Not sure if omitting the continue
statement here is intentional or an oversight.
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.
Confirming it is intentional to still make the bidrequest if that function errors out
adapters/ix/ix.go
Outdated
if len(siteIds) == 1 { | ||
for siteId := range siteIds { | ||
site.Publisher.ID = siteId | ||
} |
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.
This is looping through and setting the publisher id each time, such that the last siteId in the array always wins. You can avoid the loop entirely and access the last item in the slice directly.
adapters/ix/ix.go
Outdated
|
||
// moves sid from imp[].ext.bidder.sid to imp[].ext.sid | ||
func moveSid(imp *openrtb2.Imp) error { | ||
if imp.Ext == nil || len(imp.Ext) == 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.
Nitpick: This can just be if len(imp.Ext) == 0 {
since len
gracefully handles the nil
case.
adapters/ix/ix.go
Outdated
} | ||
|
||
func setFeatureToggles(a *IxAdapter, ext *json.RawMessage) { | ||
if *ext == 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.
Should this be if ext == nil
? You want to verify the ext
has a non-nil pointer before dereferencing. If this is indeed a mistake, consider adding test coverage to catch it.
adapters/ix/ix.go
Outdated
} | ||
|
||
var f interface{} | ||
err := json.Unmarshal(*ext, &f) |
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.
This is a very expensive operation. Is there a reason you can't use a defined structure with unmarshal?
adapters/ix/ix.go
Outdated
if ft, ok := features.(map[string]interface{}); ok { | ||
for k, v := range ft { | ||
if activated, ok := v.(map[string]interface{})["activated"]; ok { | ||
a.clientFeatureStatusMap[k] = FeatureTimestamp{ |
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.
This is not thread safe and will inevitably lead to a panic or unexpected behavior. To fix this, you will need to protect read/write access with a lock of some kind.
I'm confused as to why the server needs to keep track of a feature from an incoming request? Why is each request not evaluated on it's own merit?
Further, Prebid Server is hosted in many large clusters. Such that encountering a single request with a feature enablement will only affect 1 out of many servers.
adapters/ix/ix_test.go
Outdated
@@ -276,3 +294,220 @@ func TestMakeRequestsErrIxDiag(t *testing.T) { | |||
_, errs := bidder.MakeRequests(req, nil) | |||
assert.Len(t, errs, 1) | |||
} | |||
|
|||
func TestSetFeatureToggles(t *testing.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.
It's fine if you want to add unit tests, but we request code coverage via the json framework as that performs additional checks such as for memory corruption issues. We only consider TestJsonSamples
when evaluating code coverage.
Hey Scott - First thanks for the review! That is the reason we need to keep state in the adapter, to control subsequent requests. Let me know what you think of this. Will remove the features controlled from the exchange concept and discuss with my team if we want to avoid the server keeping state. Thank you! |
@ccorbo If I understand this feature, please do not maintain any kind of state in adapter code. If you want to write any business logic then please code that logic in your bidder endpoint. |
Removed feature toggle logic |
@ccorbo Could you please help in explaining what you are trying to accomplish with this PR? |
Hi - This PR changes how we handle multi-imp requests. Previously multi-imp requests would be flattened into multiple requests, with one request for each Imp. Now there will be a single request, with one request for multi-imp. Also this changes sid to be signaled at imp.ext.sid |
I have updated this PR with changes to handle banner multi-size. I have also removed the maximum impression limit and added proper test cases that handle multi-imp, banner multi-size, and multiple site IDs. In summary, this PR as a whole will accomplish the following:
|
Hi @ccorbo, if you don't mind, can you merge with master instead of force pushing going forward? It saves us some time when reviewing. Thanks! |
Yep will do - sorry about that! |
@bsardo Hi Brian - Is it possible to get a review on this before next Wednesdays release? Thanks in advance |
adapters/ix/ix.go
Outdated
|
||
for _, imp := range requestCopy.Imp { | ||
var err error | ||
if err = parseSiteId(&imp, uniqueSiteIDs); err != 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.
In parseSiteId
function, you are unmarshalling the impression json into var of type openrtb_ext.ExtImpIx
and doing the same thing again in moveSid
function. Requesting you to please take out the common umarshal logic from both parseSiteId
and moveSid
function to improve on efficiency.
adapters/ix/ix_test.go
Outdated
@@ -276,3 +274,63 @@ func TestMakeRequestsErrIxDiag(t *testing.T) { | |||
_, errs := bidder.MakeRequests(req, nil) | |||
assert.Len(t, errs, 1) | |||
} | |||
|
|||
func TestMoveSid(t *testing.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.
Requesting you to please move these test case to use json framework as this is the recommended way to test a bid adapter code.
"siteId": "569749", | ||
"sid": "1234" | ||
}, | ||
"sid": "1234" |
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.
Is it necessary to move sid
under ext if that value is already present in ext.bidder.sid
? If your bidder uses ext.sid
then could you please change it to use ext.bidder.sid
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.
@gargcreation1992 Yes it is necessary in the current state to move to ext.sid. We can revisit in the future, but its something we'd like to move for now and get it out
@ccorbo - do you plan to port this to PBS-Java or shall we just put it on the list? |
@bretg - Can you please put it on the list, thanks in advance |
Co-authored-by: Chris Corbo <chris.corbo@indexexchange.com> Co-authored-by: Oronno Mamun <oronno.mamun@indexexchange.com>
Co-authored-by: Chris Corbo <chris.corbo@indexexchange.com> Co-authored-by: Oronno Mamun <oronno.mamun@indexexchange.com>
* Fix: deal tiers no longer ignored due to presence of tid (prebid#2829) * CAPT-787: GPP support for imds bidder. (prebid#2867) Co-authored-by: Timothy M. Ace <tace@imds.tv> * Adsinteractive: change usersync endpoint to https (prebid#2861) Co-authored-by: Balint Vargha <varghabalint@gmail.com> * consumable adapter: add gpp support (prebid#2883) * feat: IX Bid Adapter - gpp support for user sync urls (prebid#2873) Co-authored-by: Chris Corbo <chris.corbo@indexexchange.com> * fix: update links in readme (prebid#2888) authored by @akkapur * New Adapter: AIDEM (prebid#2824) Co-authored-by: AndreaC <67786179+darkstarac@users.noreply.github.com> Co-authored-by: Andrea Tumbarello <Wazabit@users.noreply.github.com> Co-authored-by: darkstar <canazza@wazabit.it> * Improve Digital adapter: Set currency in bid response (prebid#2886) * Sharethrough: Support multiformat bid request impression (prebid#2866) * Triplelift Bid Adapter: Adding GPP Support (prebid#2887) * YahooAdvertising rebranding to Yahoo Ads. (prebid#2872) Co-authored-by: oath-jac <dsp-supply-prebid@verizonmedia.com> * IX: MultiImp Implementation (prebid#2779) Co-authored-by: Chris Corbo <chris.corbo@indexexchange.com> Co-authored-by: Oronno Mamun <oronno.mamun@indexexchange.com> * Exchange unit test fix (prebid#2868) * Semgrep rules for adapters (prebid#2833) * IX: Remove glog statement (prebid#2909) * Activities framework (prebid#2844) * PWBID: Update Default Endpoint (prebid#2903) * script to run semgrep tests against adapter PRs (prebid#2907) authored by @onkarvhanumante * semgrep rule to detect undesirable package imports in adapter code (prebid#2911) * update package-import message (prebid#2913) authored by @onkarvhanumante * Bump google.golang.org/grpc from 1.46.2 to 1.53.0 (prebid#2905) --------- Co-authored-by: Brian Sardo <1168933+bsardo@users.noreply.github.com> Co-authored-by: Timothy Ace <github.com-1@timothyace.com> Co-authored-by: Timothy M. Ace <tace@imds.tv> Co-authored-by: balintvargha <122350182+balintvargha@users.noreply.github.com> Co-authored-by: Balint Vargha <varghabalint@gmail.com> Co-authored-by: Jason Piros <jasonpiros@gmail.com> Co-authored-by: ccorbo <ccorbo2013@gmail.com> Co-authored-by: Chris Corbo <chris.corbo@indexexchange.com> Co-authored-by: Ankush <ankush.kapur@gmail.com> Co-authored-by: Giovanni Sollazzo <gs@aidem.com> Co-authored-by: AndreaC <67786179+darkstarac@users.noreply.github.com> Co-authored-by: Andrea Tumbarello <Wazabit@users.noreply.github.com> Co-authored-by: darkstar <canazza@wazabit.it> Co-authored-by: Jozef Bartek <31618107+jbartek25@users.noreply.github.com> Co-authored-by: Max Dupuis <118775839+maxime-dupuis@users.noreply.github.com> Co-authored-by: Patrick Loughrey <ploughrey@triplelift.com> Co-authored-by: radubarbos <raduiquest79@gmail.com> Co-authored-by: oath-jac <dsp-supply-prebid@verizonmedia.com> Co-authored-by: Oronno Mamun <oronno.mamun@indexexchange.com> Co-authored-by: Veronika Solovei <kalypsonika@gmail.com> Co-authored-by: Onkar Hanumante <onkar.hanumante@xandr.com> Co-authored-by: Stephen Johnston <tiquortoo@gmail.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>