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

Floors: Dynamic fetch #2732

Merged
merged 27 commits into from
Nov 16, 2023
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
b11cd46
Floors dynamic fetch
pm-nikhil-vaidya Apr 26, 2023
ded71ef
Merge branch 'master' into floors-dynamic-fetch
pm-nikhil-vaidya May 24, 2023
b361710
Incorporated review comments
pm-nikhil-vaidya May 25, 2023
44c2a7f
minor modification in test cases
pm-nikhil-vaidya May 26, 2023
2641495
Merge branch 'master' into floors-dynamic-fetch
pm-nikhil-vaidya May 26, 2023
a1af4f9
Merge branch 'master' into floors-dynamic-fetch
pm-nikhil-vaidya Jun 7, 2023
4fc2981
Merge branch 'master' into floors-dynamic-fetch
pm-nikhil-vaidya Jun 8, 2023
2d55ecd
Added unit test cases
pm-nikhil-vaidya Jun 9, 2023
46b2e80
Merge branch 'master' into floors-dynamic-fetch
pm-nikhil-vaidya Jul 10, 2023
7f78433
Entire enforcement object will be copied from request in merging process
pm-nikhil-vaidya Jul 10, 2023
9fd6544
Review comments addressed
pm-nikhil-vaidya Jul 20, 2023
645b8b8
addressed review comments
pm-nikhil-vaidya Aug 1, 2023
62dc5b8
Addressed review comments
pm-nikhil-vaidya Aug 1, 2023
4bb510b
Addressed review comments
pm-nikhil-vaidya Aug 1, 2023
91017be
Merge branch 'master' into floors-dynamic-fetch
pm-nikhil-vaidya Aug 1, 2023
143099a
Addressed review comments
pm-nikhil-vaidya Aug 7, 2023
52ddac1
Addressed review comments
pm-nikhil-vaidya Aug 19, 2023
14185e8
Merge branch 'master' into floors-dynamic-fetch
pm-nikhil-vaidya Aug 22, 2023
8730af8
Addressed Review Comments
pm-nikhil-vaidya Aug 22, 2023
70437b1
minor code modifications
pm-nikhil-vaidya Aug 23, 2023
1d3e7ee
Handled null deference case when floor fetcher is nil
pm-nikhil-vaidya Sep 9, 2023
a3ae44a
Merge branch 'master' into floors-dynamic-fetch
pm-nikhil-vaidya Sep 9, 2023
3b174ce
Removed repeated cache check with period
pm-nikhil-vaidya Sep 15, 2023
7bbc973
Merge branch 'master' into floors-dynamic-fetch
pm-nikhil-vaidya Oct 4, 2023
16b9d9c
Added retry mechanism if a fetch URL is long dead
pm-nikhil-vaidya Oct 4, 2023
4f8ba10
Added unit test cases for max retries config
pm-nikhil-vaidya Oct 4, 2023
c2839e0
Merge branch 'master' into floors-dynamic-fetch
pm-nikhil-vaidya Oct 30, 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
57 changes: 49 additions & 8 deletions config/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,17 +58,30 @@ type AccountCCPA struct {
}

type AccountPriceFloors struct {
Enabled bool `mapstructure:"enabled" json:"enabled"`
EnforceFloorsRate int `mapstructure:"enforce_floors_rate" json:"enforce_floors_rate"`
AdjustForBidAdjustment bool `mapstructure:"adjust_for_bid_adjustment" json:"adjust_for_bid_adjustment"`
EnforceDealFloors bool `mapstructure:"enforce_deal_floors" json:"enforce_deal_floors"`
UseDynamicData bool `mapstructure:"use_dynamic_data" json:"use_dynamic_data"`
MaxRule int `mapstructure:"max_rules" json:"max_rules"`
MaxSchemaDims int `mapstructure:"max_schema_dims" json:"max_schema_dims"`
Enabled bool `mapstructure:"enabled" json:"enabled"`
EnforceFloorsRate int `mapstructure:"enforce_floors_rate" json:"enforce_floors_rate"`
AdjustForBidAdjustment bool `mapstructure:"adjust_for_bid_adjustment" json:"adjust_for_bid_adjustment"`
EnforceDealFloors bool `mapstructure:"enforce_deal_floors" json:"enforce_deal_floors"`
UseDynamicData bool `mapstructure:"use_dynamic_data" json:"use_dynamic_data"`
MaxRule int `mapstructure:"max_rules" json:"max_rules"`
MaxSchemaDims int `mapstructure:"max_schema_dims" json:"max_schema_dims"`
Fetcher AccountFloorFetch `mapstructure:"fetch" json:"fetch"`
pm-nikhil-vaidya marked this conversation as resolved.
Show resolved Hide resolved
}

func (pf *AccountPriceFloors) validate(errs []error) []error {
// AccountFloorFetch defines the configuration for dynamic floors fetching.
type AccountFloorFetch struct {
Enabled bool `mapstructure:"enabled" json:"enabled"`
URL string `mapstructure:"url" json:"url"`
Timeout int `mapstructure:"timeout_ms" json:"timeout_ms"`
MaxFileSizeKB int `mapstructure:"max_file_size_kb" json:"max_file_size_kb"`
MaxRules int `mapstructure:"max_rules" json:"max_rules"`
MaxAge int `mapstructure:"max_age_sec" json:"max_age_sec"`
Period int `mapstructure:"period_sec" json:"period_sec"`
MaxSchemaDims int `mapstructure:"max_schema_dims" json:"max_schema_dims"`
AccountID string `mapstructure:"accountID" json:"accountID"`
}

func (pf *AccountPriceFloors) validate(errs []error) []error {
if pf.EnforceFloorsRate < 0 || pf.EnforceFloorsRate > 100 {
errs = append(errs, fmt.Errorf(`account_defaults.price_floors.enforce_floors_rate should be between 0 and 100`))
}
Expand All @@ -81,6 +94,34 @@ func (pf *AccountPriceFloors) validate(errs []error) []error {
errs = append(errs, fmt.Errorf(`account_defaults.price_floors.max_schema_dims should be between 0 and 20`))
}

if pf.Fetcher.Period > pf.Fetcher.MaxAge {
errs = append(errs, fmt.Errorf(`account_defaults.price_floors.fetch.period_sec should be less than account_defaults.price_floors.fetch.max_age_sec`))
}

if pf.Fetcher.Period < 300 {
pm-nikhil-vaidya marked this conversation as resolved.
Show resolved Hide resolved
errs = append(errs, fmt.Errorf(`account_defaults.price_floors.fetch.period_sec should not be less than 300 seconds`))
}

if pf.Fetcher.MaxAge < 600 {
errs = append(errs, fmt.Errorf(`account_defaults.price_floors.fetch.max_age_sec should not be less than 600 seconds and greater than maximum integer value`))
}
pm-nikhil-vaidya marked this conversation as resolved.
Show resolved Hide resolved

if !(pf.Fetcher.Timeout > 10 && pf.Fetcher.Timeout < 10000) {
errs = append(errs, fmt.Errorf(`account_defaults.price_floors.fetch.timeout_ms should be between 10 to 10,000 miliseconds`))
}

if pf.Fetcher.MaxRules < 0 {
errs = append(errs, fmt.Errorf(`account_defaults.price_floors.fetch.max_rules should be greater than or equal to 0`))
}

if pf.Fetcher.MaxFileSizeKB < 0 {
errs = append(errs, fmt.Errorf(`account_defaults.price_floors.fetch.max_file_size_kb should be greater than or equal to 0`))
}

if !(pf.Fetcher.MaxSchemaDims >= 0 && pf.Fetcher.MaxSchemaDims < 20) {
errs = append(errs, fmt.Errorf(`account_defaults.price_floors.fetch.max_schema_dims should not be less than 0 and greater than 20`))
}

return errs
}

Expand Down
128 changes: 127 additions & 1 deletion config/account_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -795,7 +795,6 @@ func TestModulesGetConfig(t *testing.T) {
}

func TestAccountPriceFloorsValidate(t *testing.T) {

tests := []struct {
description string
pf *AccountPriceFloors
Expand All @@ -807,36 +806,163 @@ func TestAccountPriceFloorsValidate(t *testing.T) {
EnforceFloorsRate: 100,
MaxRule: 200,
MaxSchemaDims: 10,
Fetcher: AccountFloorFetch{
Period: 300,
MaxAge: 600,
Timeout: 12,
},
},
},
{
description: "Invalid configuration: EnforceFloorRate:110",
pf: &AccountPriceFloors{
EnforceFloorsRate: 110,
Fetcher: AccountFloorFetch{
Period: 300,
MaxAge: 600,
Timeout: 12,
},
},
want: []error{errors.New("account_defaults.price_floors.enforce_floors_rate should be between 0 and 100")},
},
{
description: "Invalid configuration: EnforceFloorRate:-10",
pf: &AccountPriceFloors{
EnforceFloorsRate: -10,
Fetcher: AccountFloorFetch{
Period: 300,
MaxAge: 600,
Timeout: 12,
},
},
want: []error{errors.New("account_defaults.price_floors.enforce_floors_rate should be between 0 and 100")},
},
{
description: "Invalid configuration: MaxRule:-20",
pf: &AccountPriceFloors{
MaxRule: -20,
Fetcher: AccountFloorFetch{
Period: 300,
MaxAge: 600,
Timeout: 12,
},
},
want: []error{errors.New("account_defaults.price_floors.max_rules should be between 0 and 2147483647")},
},
{
description: "Invalid configuration: MaxSchemaDims:100",
pf: &AccountPriceFloors{
MaxSchemaDims: 100,
Fetcher: AccountFloorFetch{
Period: 300,
MaxAge: 600,
Timeout: 12,
},
},
want: []error{errors.New("account_defaults.price_floors.max_schema_dims should be between 0 and 20")},
},
{
description: "Invalid period for fetch",
pf: &AccountPriceFloors{
EnforceFloorsRate: 100,
MaxRule: 200,
MaxSchemaDims: 10,
Fetcher: AccountFloorFetch{
Period: 100,
MaxAge: 600,
Timeout: 12,
},
},
want: []error{errors.New("account_defaults.price_floors.fetch.period_sec should not be less than 300 seconds")},
},
{
description: "Invalid max age for fetch",
pf: &AccountPriceFloors{
EnforceFloorsRate: 100,
MaxRule: 200,
MaxSchemaDims: 10,
Fetcher: AccountFloorFetch{
Period: 300,
MaxAge: 500,
Timeout: 12,
},
},
want: []error{errors.New("account_defaults.price_floors.fetch.max_age_sec should not be less than 600 seconds and greater than maximum integer value")},
},
{
description: "Period is greater than max age",
pf: &AccountPriceFloors{
EnforceFloorsRate: 100,
MaxRule: 200,
MaxSchemaDims: 10,
Fetcher: AccountFloorFetch{
Period: 700,
MaxAge: 600,
Timeout: 12,
},
},
want: []error{errors.New("account_defaults.price_floors.fetch.period_sec should be less than account_defaults.price_floors.fetch.max_age_sec")},
},
{
description: "Invalid timeout",
pf: &AccountPriceFloors{
EnforceFloorsRate: 100,
MaxRule: 200,
MaxSchemaDims: 10,
Fetcher: AccountFloorFetch{
Period: 300,
MaxAge: 600,
Timeout: 4,
},
},
want: []error{errors.New("account_defaults.price_floors.fetch.timeout_ms should be between 10 to 10,000 miliseconds")},
},
{
description: "Invalid Max Rules",
pf: &AccountPriceFloors{
EnforceFloorsRate: 100,
MaxRule: 200,
MaxSchemaDims: 10,
Fetcher: AccountFloorFetch{
Period: 300,
MaxAge: 600,
Timeout: 12,
MaxRules: -2,
},
},
want: []error{errors.New("account_defaults.price_floors.fetch.max_rules should be greater than or equal to 0")},
},
{
description: "Invalid Max File size",
pf: &AccountPriceFloors{
EnforceFloorsRate: 100,
MaxRule: 200,
MaxSchemaDims: 10,
Fetcher: AccountFloorFetch{
Period: 300,
MaxAge: 600,
Timeout: 12,
MaxFileSizeKB: -1,
},
},
want: []error{errors.New("account_defaults.price_floors.fetch.max_file_size_kb should be greater than or equal to 0")},
},
{
description: "Invalid max_schema_dims",
pf: &AccountPriceFloors{
EnforceFloorsRate: 100,
MaxRule: 200,
MaxSchemaDims: 10,
Fetcher: AccountFloorFetch{
Period: 300,
MaxAge: 600,
Timeout: 12,
MaxFileSizeKB: 10,
MaxSchemaDims: 40,
},
},
want: []error{errors.New("account_defaults.price_floors.fetch.max_schema_dims should not be less than 0 and greater than 20")},
},
}
for _, tt := range tests {
t.Run(tt.description, func(t *testing.T) {
Expand Down
36 changes: 31 additions & 5 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,16 @@ type Configuration struct {
}

type PriceFloors struct {
Enabled bool `mapstructure:"enabled"`
Enabled bool `mapstructure:"enabled"`
Fetcher PriceFloorFetcher `mapstructure:"fetcher"`
}

type PriceFloorFetcher struct {
HttpClient HTTPClient `mapstructure:"http_client"`
CacheSize int `mapstructure:"cache_size_mb"`
Worker int `mapstructure:"worker"`
Capacity int `mapstructure:"capacity"`
MaxRetries int `mapstructure:"max_retries"`
}

const MIN_COOKIE_SIZE_BYTES = 500
Expand Down Expand Up @@ -139,10 +148,6 @@ func (cfg *Configuration) validate(v *viper.Viper) []error {
glog.Warning(`account_defaults.events has no effect as the feature is under development.`)
}

if cfg.PriceFloors.Enabled {
glog.Warning(`cfg.PriceFloors.Enabled will currently not do anything as price floors feature is still under development.`)
}

errs = cfg.Experiment.validate(errs)
errs = cfg.BidderInfos.validate(errs)
errs = cfg.AccountDefaults.Privacy.IPv6Config.Validate(errs)
Expand Down Expand Up @@ -1059,9 +1064,30 @@ func SetupViper(v *viper.Viper, filename string, bidderInfos BidderInfos) {
v.SetDefault("account_defaults.price_floors.use_dynamic_data", false)
v.SetDefault("account_defaults.price_floors.max_rules", 100)
v.SetDefault("account_defaults.price_floors.max_schema_dims", 3)
v.SetDefault("account_defaults.price_floors.fetch.enabled", false)
v.SetDefault("account_defaults.price_floors.fetch.url", "")
v.SetDefault("account_defaults.price_floors.fetch.timeout_ms", 3000)
v.SetDefault("account_defaults.price_floors.fetch.max_file_size_kb", 100)
v.SetDefault("account_defaults.price_floors.fetch.max_rules", 1000)
v.SetDefault("account_defaults.price_floors.fetch.max_age_sec", 86400)
v.SetDefault("account_defaults.price_floors.fetch.period_sec", 3600)
v.SetDefault("account_defaults.price_floors.fetch.max_schema_dims", 0)

v.SetDefault("account_defaults.events_enabled", false)
v.SetDefault("account_defaults.privacy.ipv6.anon_keep_bits", 56)
v.SetDefault("account_defaults.privacy.ipv4.anon_keep_bits", 24)

//Defaults for Price floor fetcher
v.SetDefault("price_floors.fetcher.worker", 20)
v.SetDefault("price_floors.fetcher.capacity", 20000)
v.SetDefault("price_floors.fetcher.cache_size_mb", 64)
v.SetDefault("price_floors.fetcher.http_client.max_connections_per_host", 0) // unlimited
v.SetDefault("price_floors.fetcher.http_client.max_idle_connections", 40)
v.SetDefault("price_floors.fetcher.http_client.max_idle_connections_per_host", 2)
v.SetDefault("price_floors.fetcher.http_client.idle_connection_timeout_seconds", 60)
v.SetDefault("price_floors.fetcher.max_retries", 10)

v.SetDefault("account_defaults.events_enabled", false)
v.SetDefault("compression.response.enable_gzip", false)
v.SetDefault("compression.request.enable_gzip", false)

Expand Down
Loading
Loading