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

Priority Bidder Ejection #2952

Merged
merged 23 commits into from
Sep 19, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
f1ce470
Priority Bidder Code
AlexBVolcy Jul 17, 2023
de5e618
Tweak Priority Ejector to update pri groups
AlexBVolcy Jul 19, 2023
73a9daf
Fallback Ejector
AlexBVolcy Jul 19, 2023
b0feb46
Opt out non prioity key support for oldest ejector
AlexBVolcy Jul 24, 2023
f29fafa
Simplified removeElementFromPriorityGroup
AlexBVolcy Jul 25, 2023
bb16689
Add ejector specific tests
AlexBVolcy Jul 25, 2023
6c9b7d1
Ejector refactor, remove fallback, add tests
AlexBVolcy Aug 2, 2023
8f963f4
Merge branch 'master' into final_priority_bidder_ejection
AlexBVolcy Aug 3, 2023
0112ea7
Fix validate merge fail
AlexBVolcy Aug 3, 2023
53c05f5
Address comments
AlexBVolcy Aug 3, 2023
489d34a
Update IsSyncerPriority, update Pri Ejector
AlexBVolcy Aug 3, 2023
b22b404
Update ejector logic
AlexBVolcy Aug 11, 2023
8060ba4
Implement TieEjector logic
AlexBVolcy Aug 15, 2023
4891b4e
Minor tweaks
AlexBVolcy Aug 15, 2023
bc8c72a
Update IsSyncerPriority logic
AlexBVolcy Aug 17, 2023
7d801a8
One line update to pri ejector
AlexBVolcy Aug 17, 2023
54dfaae
Clean up, add tests
AlexBVolcy Aug 18, 2023
8440f54
Sole element > MaxCookieSize edge case
AlexBVolcy Aug 24, 2023
2e84e37
Pass syncerByBidder, add new test
AlexBVolcy Aug 29, 2023
958fcdc
Merge branch 'master' into final_priority_bidder_ejection
AlexBVolcy Sep 12, 2023
10aebbc
Return unaltered cookie and 200
AlexBVolcy Sep 13, 2023
48876a1
Just return 200 and warning, cookie unchanged
AlexBVolcy Sep 14, 2023
50589d9
Merge branch 'master' into final_priority_bidder_ejection
AlexBVolcy Sep 19, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -951,6 +951,8 @@ func SetupViper(v *viper.Viper, filename string, bidderInfos BidderInfos) {

v.SetDefault("event.timeout_ms", 1000)

v.SetDefault("user_sync.priority_groups", [][]string{})

v.SetDefault("accounts.filesystem.enabled", false)
v.SetDefault("accounts.filesystem.directorypath", "./stored_requests/data/by_id")
v.SetDefault("accounts.in_memory_cache.type", "none")
Expand Down
10 changes: 5 additions & 5 deletions config/usersync.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ package config

// UserSync specifies the static global user sync configuration.
type UserSync struct {
Cooperative UserSyncCooperative `mapstructure:"coop_sync"`
ExternalURL string `mapstructure:"external_url"`
RedirectURL string `mapstructure:"redirect_url"`
Cooperative UserSyncCooperative `mapstructure:"coop_sync"`
ExternalURL string `mapstructure:"external_url"`
RedirectURL string `mapstructure:"redirect_url"`
PriorityGroups [][]string `mapstructure:"priority_groups"`
AlexBVolcy marked this conversation as resolved.
Show resolved Hide resolved
}

// UserSyncCooperative specifies the static global default cooperative cookie sync
type UserSyncCooperative struct {
EnabledByDefault bool `mapstructure:"default"`
PriorityGroups [][]string `mapstructure:"priority_groups"`
EnabledByDefault bool `mapstructure:"default"`
}
2 changes: 1 addition & 1 deletion endpoints/cookie_sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ func (c *cookieSyncEndpoint) parseRequest(r *http.Request) (usersync.Request, pr
Bidders: request.Bidders,
Cooperative: usersync.Cooperative{
Enabled: (request.CooperativeSync != nil && *request.CooperativeSync) || (request.CooperativeSync == nil && c.config.UserSync.Cooperative.EnabledByDefault),
PriorityGroups: c.config.UserSync.Cooperative.PriorityGroups,
PriorityGroups: c.config.UserSync.PriorityGroups,
},
Limit: request.Limit,
Privacy: usersyncPrivacy{
Expand Down
25 changes: 12 additions & 13 deletions endpoints/cookie_sync_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -515,9 +515,9 @@ func TestCookieSyncParseRequest(t *testing.T) {
givenGDPRConfig: config.GDPR{Enabled: true, DefaultValue: "0"},
givenCCPAEnabled: true,
givenConfig: config.UserSync{
PriorityGroups: [][]string{{"a", "b", "c"}},
Cooperative: config.UserSyncCooperative{
EnabledByDefault: false,
PriorityGroups: [][]string{{"a", "b", "c"}},
},
},
expectedPrivacy: privacy.Policies{
Expand Down Expand Up @@ -562,9 +562,9 @@ func TestCookieSyncParseRequest(t *testing.T) {
givenGDPRConfig: config.GDPR{Enabled: true, DefaultValue: "0"},
givenCCPAEnabled: true,
givenConfig: config.UserSync{
PriorityGroups: [][]string{{"a", "b", "c"}},
Cooperative: config.UserSyncCooperative{
EnabledByDefault: false,
PriorityGroups: [][]string{{"a", "b", "c"}},
},
},
expectedPrivacy: privacy.Policies{
Expand Down Expand Up @@ -615,9 +615,9 @@ func TestCookieSyncParseRequest(t *testing.T) {
givenGDPRConfig: config.GDPR{Enabled: true, DefaultValue: "0"},
givenCCPAEnabled: true,
givenConfig: config.UserSync{
PriorityGroups: [][]string{{"a", "b", "c"}},
Cooperative: config.UserSyncCooperative{
EnabledByDefault: true,
PriorityGroups: [][]string{{"a", "b", "c"}},
},
},
expectedPrivacy: privacy.Policies{},
Expand All @@ -641,9 +641,9 @@ func TestCookieSyncParseRequest(t *testing.T) {
givenGDPRConfig: config.GDPR{Enabled: true, DefaultValue: "0"},
givenCCPAEnabled: true,
givenConfig: config.UserSync{
PriorityGroups: [][]string{{"a", "b", "c"}},
Cooperative: config.UserSyncCooperative{
EnabledByDefault: false,
PriorityGroups: [][]string{{"a", "b", "c"}},
},
},
expectedPrivacy: privacy.Policies{},
Expand All @@ -667,9 +667,9 @@ func TestCookieSyncParseRequest(t *testing.T) {
givenGDPRConfig: config.GDPR{Enabled: true, DefaultValue: "0"},
givenCCPAEnabled: true,
givenConfig: config.UserSync{
PriorityGroups: [][]string{{"a", "b", "c"}},
Cooperative: config.UserSyncCooperative{
EnabledByDefault: true,
PriorityGroups: [][]string{{"a", "b", "c"}},
},
},
expectedPrivacy: privacy.Policies{},
Expand All @@ -693,9 +693,9 @@ func TestCookieSyncParseRequest(t *testing.T) {
givenGDPRConfig: config.GDPR{Enabled: true, DefaultValue: "0"},
givenCCPAEnabled: true,
givenConfig: config.UserSync{
PriorityGroups: [][]string{{"a", "b", "c"}},
Cooperative: config.UserSyncCooperative{
EnabledByDefault: false,
PriorityGroups: [][]string{{"a", "b", "c"}},
},
},
expectedPrivacy: privacy.Policies{},
Expand All @@ -719,9 +719,9 @@ func TestCookieSyncParseRequest(t *testing.T) {
givenGDPRConfig: config.GDPR{Enabled: true, DefaultValue: "0"},
givenCCPAEnabled: true,
givenConfig: config.UserSync{
PriorityGroups: [][]string{{"a", "b", "c"}},
Cooperative: config.UserSyncCooperative{
EnabledByDefault: true,
PriorityGroups: [][]string{{"a", "b", "c"}},
},
},
expectedPrivacy: privacy.Policies{},
Expand All @@ -745,9 +745,9 @@ func TestCookieSyncParseRequest(t *testing.T) {
givenGDPRConfig: config.GDPR{Enabled: true, DefaultValue: "0"},
givenCCPAEnabled: true,
givenConfig: config.UserSync{
PriorityGroups: [][]string{{"a", "b", "c"}},
Cooperative: config.UserSyncCooperative{
EnabledByDefault: false,
PriorityGroups: [][]string{{"a", "b", "c"}},
},
},
expectedPrivacy: privacy.Policies{},
Expand Down Expand Up @@ -888,9 +888,8 @@ func TestCookieSyncParseRequest(t *testing.T) {
givenGDPRConfig: config.GDPR{Enabled: true, DefaultValue: "0"},
givenCCPAEnabled: true,
givenConfig: config.UserSync{
Cooperative: config.UserSyncCooperative{
PriorityGroups: [][]string{{"a", "b", "c"}},
},
PriorityGroups: [][]string{{"a", "b", "c"}},
Cooperative: config.UserSyncCooperative{},
},
expectedPrivacy: privacy.Policies{},
expectedRequest: usersync.Request{
Expand Down Expand Up @@ -918,9 +917,9 @@ func TestCookieSyncParseRequest(t *testing.T) {
givenGDPRConfig: config.GDPR{Enabled: true, DefaultValue: "0"},
givenCCPAEnabled: true,
givenConfig: config.UserSync{
PriorityGroups: [][]string{{"a", "b", "c"}},
Cooperative: config.UserSyncCooperative{
EnabledByDefault: false,
PriorityGroups: [][]string{{"a", "b", "c"}},
},
},
expectedPrivacy: privacy.Policies{},
Expand Down Expand Up @@ -949,9 +948,9 @@ func TestCookieSyncParseRequest(t *testing.T) {
givenGDPRConfig: config.GDPR{Enabled: true, DefaultValue: "0"},
givenCCPAEnabled: true,
givenConfig: config.UserSync{
PriorityGroups: [][]string{{"a", "b", "c"}},
Cooperative: config.UserSyncCooperative{
EnabledByDefault: false,
PriorityGroups: [][]string{{"a", "b", "c"}},
},
},
expectedPrivacy: privacy.Policies{},
Expand Down
2 changes: 1 addition & 1 deletion endpoints/setuid.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ func NewSetUIDEndpoint(cfg *config.Configuration, syncersByBidder map[string]use
setSiteCookie := siteCookieCheck(r.UserAgent())

// Write Cookie
encodedCookie, err := cookie.PrepareCookieForWrite(&cfg.HostCookie, encoder)
encodedCookie, err := cookie.PrepareCookieForWrite(&cfg.HostCookie, encoder, &usersync.PriorityBidderEjector{PriorityGroups: cfg.UserSync.PriorityGroups, SyncerKey: syncer.Key(), OldestEjector: usersync.OldestEjector{}})
if err != nil {
w.WriteHeader(http.StatusBadRequest)
metricsEngine.RecordSetUid(metrics.SetUidBadRequest)
Expand Down
2 changes: 1 addition & 1 deletion pbs/usersync.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ func (deps *UserSyncDeps) OptOut(w http.ResponseWriter, r *http.Request, _ httpr
pc.SetOptOut(optout != "")

// Write Cookie
encodedCookie, err := pc.PrepareCookieForWrite(deps.HostCookieConfig, encoder)
encodedCookie, err := pc.PrepareCookieForWrite(deps.HostCookieConfig, encoder, &usersync.OldestEjector{}) // TODO: Getting Non Priority Keys Here
AlexBVolcy marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
Expand Down
30 changes: 5 additions & 25 deletions usersync/cookie.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"encoding/json"
"errors"
"net/http"
"sort"
"time"

"github.com/prebid/prebid-server/config"
Expand Down Expand Up @@ -58,10 +57,7 @@ func ReadCookie(r *http.Request, decoder Decoder, host *config.HostCookie) *Cook
}

// PrepareCookieForWrite ejects UIDs as long as the cookie is too full
func (cookie *Cookie) PrepareCookieForWrite(cfg *config.HostCookie, encoder Encoder) (string, error) {
uuidKeys := sortUIDs(cookie.uids)

i := 0
func (cookie *Cookie) PrepareCookieForWrite(cfg *config.HostCookie, encoder Encoder, ejector Ejector) (string, error) {
for len(cookie.uids) > 0 {
encodedCookie, err := encoder.Encode(cookie)
if err != nil {
AlexBVolcy marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -82,10 +78,11 @@ func (cookie *Cookie) PrepareCookieForWrite(cfg *config.HostCookie, encoder Enco
return encodedCookie, nil
}

uidToDelete := uuidKeys[i]
uidToDelete, err := ejector.Choose(cookie.uids)
if err != nil {
return encodedCookie, err
}
delete(cookie.uids, uidToDelete)

i++
}
return "", nil
}
Expand Down Expand Up @@ -132,23 +129,6 @@ func (cookie *Cookie) Sync(key string, uid string) error {
return nil
}

// sortUIDs is used to get a list of uids sorted from oldest to newest
// This list is used to eject oldest uids from the cookie
// This will be incorporated with a more complex ejection framework in a future PR
func sortUIDs(uids map[string]UIDEntry) []string {
if len(uids) > 0 {
uuidKeys := make([]string, 0, len(uids))
for key := range uids {
uuidKeys = append(uuidKeys, key)
}
sort.SliceStable(uuidKeys, func(i, j int) bool {
return uids[uuidKeys[i]].Expires.Before(uids[uuidKeys[j]].Expires)
})
return uuidKeys
}
return nil
}

// SyncHostCookie syncs the request cookie with the host cookie
func SyncHostCookie(r *http.Request, requestCookie *Cookie, host *config.HostCookie) {
if uid, _, _ := requestCookie.GetUID(host.Family); uid == "" && host.CookieName != "" {
Expand Down
15 changes: 14 additions & 1 deletion usersync/cookie_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,19 @@ func TestPrepareCookieForWrite(t *testing.T) {
optOut: false,
}

ejector := &PriorityBidderEjector{
PriorityGroups: [][]string{
{"1"},
{"2", "3"},
{"4", "5", "6"},
{"7"},
},
SyncerKey: "1",
OldestEjector: OldestEjector{
nonPriorityKeys: []string{},
},
}

testCases := []struct {
name string
givenMaxCookieSize int
Expand Down Expand Up @@ -447,7 +460,7 @@ func TestPrepareCookieForWrite(t *testing.T) {

for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
encodedCookie, err := cookieToSend.PrepareCookieForWrite(&config.HostCookie{MaxCookieSizeBytes: test.givenMaxCookieSize}, encoder)
encodedCookie, err := cookieToSend.PrepareCookieForWrite(&config.HostCookie{MaxCookieSizeBytes: test.givenMaxCookieSize}, encoder, ejector)
assert.NoError(t, err)
decodedCookie := decoder.Decode(encodedCookie)

Expand Down
Loading
Loading