-
Notifications
You must be signed in to change notification settings - Fork 741
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
Improving /setuid #86
Conversation
… gometrics-metrics
…server into gometrics-metrics
…nt circular dependencies later.
…ace again because Im neurotic.
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.
Looks ok to me. Not sure about needing an interface for cookie though.
// | ||
// To get an instance of this from a request, use ParseUserSyncMapFromRequest. | ||
// To write an instance onto a response, use SetCookieOnResponse. | ||
type UserSyncMap interface { |
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.
Why do we need use an interface here? The type to me has to be tied to a concrete cookie as I'm not sure what else we could replace it with given the client/server interactions.
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/fair question.
I really just wanted the compiler to guarantee that all the other PBS code was going through the setter methods. I don't want the next guy who refactors an endpoint to have to worry about the fact that facebook IDs shouldn't be 0.
So... I tried to make UIDs
private, and add a the setter method to the PBSCookie
. But it turns out that Golang's JSON marshal & unmarshal don't work on private variables.
This was the next best thing I could come up with. UIDs can stay public, butcookieImpl
will be private. The interface just exists for the public API.
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 guess the tradeoff here is...
If I have an interface, I can make the UIDs property private to the rest of the code. Without an interface, I'd leave a comment saying "// This is only public for JSON serialization. Don't use it directly. Call TrySync
instead."
I generally favor using the build system rather than comments to enforce things when possible... but there is some overhead, and I've been known to take it too far. Let me know if you think it's worth removing.
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 possible instead of having the interface to create a struct that is public just for the purpose of JSON serialization? Something like what is described here (https://stackoverflow.com/questions/28035784/golang-marshal-unmarshal-json-with-both-exported-and-un-exported-fields).
Would that allow the uuids
field to be private still without the need for the interface?
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.
That looks like a viable option. I kinda want to compare the code side-by-side... so I'll stick it in another branch.
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.
Implemented this in #106.
The two look pretty similar in complexity to me... but I think I give a slight edge to the concrete struct. This is how I'm thinking about it:
Concrete struct benefits:
- nil-safety is possible (though it requires some extra branchy code).
nil
is much clearer to mobile apps, since there's no such thing as a UserSync there.
Interface benefits:
- No custom JSON code, so there's less room for bugs
In this case I think the confusion caused by a UserSync map on mobile requests is probably the most important part.... so gonna go with that one.
@@ -162,6 +162,8 @@ func ParsePBSRequest(r *http.Request, cache cache.Cache) (*PBSRequest, error) { | |||
if err != nil { | |||
return nil, fmt.Errorf("Invalid URL '%s': %v", url.Host, err) | |||
} | |||
} else { | |||
pbsReq.SyncMap = NewSyncMap() |
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 an empty SyncMap on mobile app requests for everything to work? Cookie sync doesn’t make sense on mobile app, so having an empty sync map could be confusing.
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.
The short answer is... I'm not sure. I definitely agree that it's confusing.
On the other hand... func (req *PBSRequest) GetUserID(BidderCode string)
surfaced some interesting unit test failures. Apparently in Go any reads on a nil
map are treated as if that map were empty. So pbsReq.UIDs['key']
will just return nil if UIDs
is undefined, but req.SyncMap.GetUID()
will cause panic. Stashing an empty SyncMap
on here makes reads behave nicely.
I don't know offhand whether any of the other PBS code attempts to read cookiesyncs inside the "mobile" code branches... but as a general rule, ab object should be equally usable regardless of how its constructed.
I think this lends some extra weight to your suggestion here. If the methods are defined on a struct, then I can define how they behave on a nil
. Interfaces don't give that flexibility.
… / Ad Pod (prebid#86) * UOE-5440: Changes for capturing Pod algorithm execution time using pbmetrics (prebid#65) * Added function getPrometheusRegistry() * Exported function GetPrometheusRegistry * UOE-5440: Capturing execution time in nanoseconds for algorithms * UOE-5440: Changes for prometheus algorithem metrics for pod using pbsmetrics * UOE-5440: Test cases for prometheus * UOE-5440: Added test cases * UOE-5440: Changing buckets * UOE-5440: changes in pbsmetrics for newly added metrics Co-authored-by: Sachin Survase <sachin.survase@pubmatic.com> Co-authored-by: PubMatic-OpenWrap <UOEDev@pubmatic.com> Co-authored-by: Shriprasad <shriprasad.marathe@pubmatic.com> * UOE-5440: Fixed the Unit test issues (prebid#72) Fixed unit test issues Co-authored-by: Sachin Survase <sachin.survase@pubmatic.com> Co-authored-by: PubMatic-OpenWrap <UOEDev@pubmatic.com> Co-authored-by: Shriprasad <shriprasad.marathe@pubmatic.com> * UOE-5511 Support for skadnetwork in pubmatic (prebid#73) Co-authored-by: Isha Bharti <isha.bharti@pubmatic.com> * Resolved merge issues * BugID:OTT-17 First Commit * OTT-18: moved VideoAuction to selector pattern. This required for mocking PBS response (prebid#76) Co-authored-by: Shriprasad <shriprasad.marathe@pubmatic.com> * OTT-24: Basic support for sorting the deal bids in forming the final ad pod response * OTT-24: Added changes around prebid#1503 (Proposal for Prebid Server) * OTT-27, OTT-32 Supporting Deal Prioritization for CTV * UOE-5616: Support wiid in pubmatic (prebid#77) Co-authored-by: Isha Bharti <isha.bharti@pubmatic.com> * OTT-29 Fixing Skip Dedup Map Issue * OTT-29 Fixing Skip Dedup Map Issue * OTT-29 Adding Video Duration in hb_pb_cat_dur key * OTT-29 Adding Video Duration in hb_pb_cat_dur key OTT-29 Fixing Skip Dedup Map Issue * UOE-5741: adding omitempty for ExtImpPrebid fields * UOE-5741: adding omitempty for ExtImpPrebid fields * OTT-9 Adding Duration in hb_pb_cat_dur field * OTT-9 Adding Duration in hb_pb_cat_dur field * OTT-45: Added logger and Prometheus metrics to capture bid.id collisions (prebid#84) * OTT-45: Added logger and Prometheus metrics to capture bid.id collisions Co-authored-by: Shriprasad <shriprasad.marathe@pubmatic.com> * OTT-9 Removed duplicate import * OTT-45: corrected comment * OTT-9: Reverted with master changes. This changes are not required for OTT-9 Co-authored-by: Sachin Survase <sachin.survase@pubmatic.com> Co-authored-by: PubMatic-OpenWrap <UOEDev@pubmatic.com> Co-authored-by: Shriprasad <shriprasad.marathe@pubmatic.com> Co-authored-by: Isha Bharti <isha.bharti@pubmatic.com> Co-authored-by: Viral Vala <viral.vala@pubmatic.com> Co-authored-by: shalmali-patil <shalmali.patil@pubmatic.com>
This fixes two issues. I grouped them into the same PR because the code overlapped.
/setuid
, separated by bidder.audienceNetwork
if we were told that their UID was 0.The point of (2) is to circumvent around some questionable behavior from the Facebook user sync servers. Currently, they redirect to
/setuid
with a sentinel value of "0" if the user isn't logged into Facebook at the time. This is (at least partially) responsible for some really bad user sync rates, because prebid-server saves those 0s, considers the user to be synced, and then stops trying to sync later.In reality, 0 is an invalid user ID... but eventually, we'd expect the user to log into Facebook, so that the audience network can sync with their real UID.
So... this PR also consolidates all UserSync Sets behind a
TrySync()
function, which it then implements to reject "0" IDs foraudienceNetwork
.