Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 8 additions & 0 deletions e2e/price_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,10 @@ var expectedPricingConfig = `
"price_per_hour_usd": 0.00005,
"price_per_gib_usd": 0.016
},
"runtime": {
"price_per_hour_usd": 0.00005,
"price_per_gib_usd": 0.016
},
"dvpn": {
"price_per_hour_usd": 0.00005,
"price_per_gib_usd": 0.05
Expand All @@ -186,6 +190,10 @@ var expectedPricingConfig = `
"price_per_hour_usd": 0.00005,
"price_per_gib_usd": 0.012
},
"runtime": {
"price_per_hour_usd": 0.00005,
"price_per_gib_usd": 0.012
},
"dvpn": {
"price_per_hour_usd": 0.00005,
"price_per_gib_usd": 0.03
Expand Down
19 changes: 19 additions & 0 deletions price/pricingbyservice/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"encoding/json"
"errors"
"fmt"
"strings"
"sync"
"time"

Expand Down Expand Up @@ -164,6 +165,7 @@ const (
ServiceTypeDataTransfer ServiceType = "data_transfer"
ServiceTypeDVPN ServiceType = "dvpn"
ServiceTypeMonitoring ServiceType = "monitoring"
ServiceTypeRuntime ServiceType = "runtime"
)

var validServiceTypes = map[ServiceType]struct{}{
Expand All @@ -173,6 +175,7 @@ var validServiceTypes = map[ServiceType]struct{}{
ServiceTypeDataTransfer: {},
ServiceTypeDVPN: {},
ServiceTypeMonitoring: {},
ServiceTypeRuntime: {},
}

var allServiceTypes = []ServiceType{
Expand All @@ -182,9 +185,13 @@ var allServiceTypes = []ServiceType{
ServiceTypeDataTransfer,
ServiceTypeDVPN,
ServiceTypeMonitoring,
ServiceTypeRuntime,
}

func (s ServiceType) Validate() error {
if strings.HasPrefix(string(s), string(ServiceTypeRuntime)+"-") {
return nil
}
if _, ok := validServiceTypes[s]; !ok {
return fmt.Errorf("%v is an invalid service type", s)
}
Expand Down Expand Up @@ -216,6 +223,7 @@ type PriceByServiceTypeUSD struct {
DataTransfer PriceUSD `json:"data_transfer"`
DVPN PriceUSD `json:"dvpn"`
Monitoring PriceUSD `json:"monitoring"`
Runtime PriceUSD `json:"runtime"`
}

func (p PriceByServiceTypeUSD) Validate() error {
Expand All @@ -234,6 +242,9 @@ func (p PriceByServiceTypeUSD) Validate() error {
if err := p.Monitoring.Validate(); err != nil {
return err
}
if err := p.Runtime.Validate(); err != nil {
return err
}
return p.DataTransfer.Validate()
}

Expand Down Expand Up @@ -281,6 +292,10 @@ var defaultPriceConfig = `{
"price_per_hour_usd": 0.00005,
"price_per_gib_usd": 0.016
},
"runtime": {
"price_per_hour_usd": 0.00005,
"price_per_gib_usd": 0.016
},
"dvpn": {
"price_per_hour_usd": 0.00005,
"price_per_gib_usd": 0.05
Expand All @@ -307,6 +322,10 @@ var defaultPriceConfig = `{
"price_per_hour_usd": 0.00005,
"price_per_gib_usd": 0.012
},
"runtime": {
"price_per_hour_usd": 0.00005,
"price_per_gib_usd": 0.012
},
"dvpn": {
"price_per_hour_usd": 0.00005,
"price_per_gib_usd": 0.03
Expand Down
35 changes: 35 additions & 0 deletions price/pricingbyservice/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ func TestConfig_Validate(t *testing.T) {
DataTransfer: mprice,
DVPN: mprice,
Monitoring: mprice,
Runtime: mprice,
},
Other: &PriceByServiceTypeUSD{
Wireguard: mprice,
Expand All @@ -38,6 +39,7 @@ func TestConfig_Validate(t *testing.T) {
DataTransfer: mprice,
DVPN: mprice,
Monitoring: mprice,
Runtime: mprice,
},
},
CountryModifiers: map[ISO3166CountryCode]Modifier{
Expand All @@ -60,6 +62,7 @@ func TestConfig_Validate(t *testing.T) {
DataTransfer: mprice,
DVPN: mprice,
Monitoring: mprice,
Runtime: mprice,
},
Other: &PriceByServiceTypeUSD{
Wireguard: mprice,
Expand All @@ -68,6 +71,7 @@ func TestConfig_Validate(t *testing.T) {
DataTransfer: mprice,
DVPN: mprice,
Monitoring: mprice,
Runtime: mprice,
},
},
CountryModifiers: map[ISO3166CountryCode]Modifier{
Expand All @@ -90,6 +94,7 @@ func TestConfig_Validate(t *testing.T) {
DataTransfer: mprice,
DVPN: mprice,
Monitoring: mprice,
Runtime: mprice,
},
Other: &PriceByServiceTypeUSD{
Wireguard: mprice,
Expand All @@ -98,6 +103,7 @@ func TestConfig_Validate(t *testing.T) {
DataTransfer: mprice,
DVPN: mprice,
Monitoring: mprice,
Runtime: mprice,
},
},
CountryModifiers: map[ISO3166CountryCode]Modifier{
Expand All @@ -119,6 +125,7 @@ func TestConfig_Validate(t *testing.T) {
DataTransfer: mprice,
DVPN: mprice,
Monitoring: mprice,
Runtime: mprice,
},
Other: &PriceByServiceTypeUSD{
Wireguard: mprice,
Expand All @@ -130,6 +137,7 @@ func TestConfig_Validate(t *testing.T) {
},
DVPN: mprice,
Monitoring: mprice,
Runtime: mprice,
},
},
CountryModifiers: map[ISO3166CountryCode]Modifier{
Expand All @@ -152,13 +160,15 @@ func TestConfig_Validate(t *testing.T) {
DataTransfer: mprice,
DVPN: mprice,
Monitoring: mprice,
Runtime: mprice,
},
Other: &PriceByServiceTypeUSD{
Scraping: mprice,
QUICScraping: mprice,
DataTransfer: mprice,
DVPN: mprice,
Monitoring: mprice,
Runtime: mprice,
},
},
CountryModifiers: map[ISO3166CountryCode]Modifier{
Expand All @@ -184,6 +194,31 @@ func TestConfig_Validate(t *testing.T) {
}
}

func TestServiceTypeValidate(t *testing.T) {
for _, serviceType := range []ServiceType{ServiceTypeRuntime, "runtime-cdp"} {
if err := serviceType.Validate(); err != nil {
t.Errorf("Validate() error = %v for service type %q", err, serviceType)
}
}
}

func TestRuntimePricesUseRuntimeConfiguration(t *testing.T) {
priceUpdater := &PriceUpdater{}
runtimePrice := PriceUSD{PricePerHour: 0.01, PricePerGiB: 0.02}
config := Config{BasePrices: PriceByTypeUSD{
Residential: &PriceByServiceTypeUSD{DataTransfer: PriceUSD{PricePerHour: 1, PricePerGiB: 1}, Runtime: runtimePrice},
Other: &PriceByServiceTypeUSD{DataTransfer: PriceUSD{PricePerHour: 1, PricePerGiB: 1}, Runtime: runtimePrice},
}}

prices := priceUpdater.generateNewDefaults(1, config)
if prices.Current.Residential.Runtime.PricePerHourHumanReadable != runtimePrice.PricePerHour {
t.Fatalf("runtime price per hour = %v, want %v", prices.Current.Residential.Runtime.PricePerHourHumanReadable, runtimePrice.PricePerHour)
}
if prices.Current.Other.Runtime.PricePerGiBHumanReadable != runtimePrice.PricePerGiB {
t.Fatalf("runtime price per GiB = %v, want %v", prices.Current.Other.Runtime.PricePerGiBHumanReadable, runtimePrice.PricePerGiB)
}
}

func TestDemandBoostConfig_Validate(t *testing.T) {
tests := []struct {
name string
Expand Down
41 changes: 40 additions & 1 deletion price/pricingbyservice/price_updater.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"math/big"
"strings"
"sync"
"time"

Expand Down Expand Up @@ -164,13 +165,20 @@ func DemandBoostServiceMultipliers(cfg Config, demandIndexes map[ISO3166CountryC

multipliers[country] = make(map[ServiceType]float64, len(serviceTypes))
for _, serviceType := range serviceTypes {
multipliers[country][serviceType] = multiplier
multipliers[country][canonicalServiceType(serviceType)] = multiplier
}
}

return multipliers
}

func canonicalServiceType(serviceType ServiceType) ServiceType {
if strings.HasPrefix(string(serviceType), string(ServiceTypeRuntime)+"-") {
return ServiceTypeRuntime
}
return serviceType
}

func demandBoostMultiplier(boostCfg DemandBoostCountryCfg, currentDemandIndex float64) float64 {
gapRatio := (boostCfg.TargetDemandIndex - currentDemandIndex) / boostCfg.TargetDemandIndex
if gapRatio < 0 {
Expand Down Expand Up @@ -237,6 +245,11 @@ func (p *PriceUpdater) submitPriceMetric(country string, price *PriceByType) {
metrics.CurrentPriceByCountry.WithLabelValues(country, "residential", "data_transfer", "per_gib").Set(price.Residential.DataTransfer.PricePerGiBHumanReadable)
metrics.CurrentPriceByCountry.WithLabelValues(country, "residential", "data_transfer", "per_hour").Set(price.Residential.DataTransfer.PricePerHourHumanReadable)

metrics.CurrentPriceByCountry.WithLabelValues(country, "other", "runtime", "per_gib").Set(price.Other.Runtime.PricePerGiBHumanReadable)
metrics.CurrentPriceByCountry.WithLabelValues(country, "other", "runtime", "per_hour").Set(price.Other.Runtime.PricePerHourHumanReadable)
metrics.CurrentPriceByCountry.WithLabelValues(country, "residential", "runtime", "per_gib").Set(price.Residential.Runtime.PricePerGiBHumanReadable)
metrics.CurrentPriceByCountry.WithLabelValues(country, "residential", "runtime", "per_hour").Set(price.Residential.Runtime.PricePerHourHumanReadable)

metrics.CurrentPriceByCountry.WithLabelValues(country, "other", "dvpn", "per_gib").Set(price.Other.DVPN.PricePerGiBHumanReadable)
metrics.CurrentPriceByCountry.WithLabelValues(country, "other", "dvpn", "per_hour").Set(price.Other.DVPN.PricePerHourHumanReadable)
metrics.CurrentPriceByCountry.WithLabelValues(country, "residential", "dvpn", "per_gib").Set(price.Residential.DVPN.PricePerGiBHumanReadable)
Expand Down Expand Up @@ -300,6 +313,12 @@ func (p *PriceUpdater) generateNewDefaults(mystUSD float64, cfg Config) *PriceHi
PricePerGiB: calculatePriceMYST(mystUSD, cfg.BasePrices.Residential.DataTransfer.PricePerGiB, 1),
PricePerGiBHumanReadable: calculatePriceMystFloat(mystUSD, cfg.BasePrices.Residential.DataTransfer.PricePerGiB, 1),
},
Runtime: Price{
PricePerHour: calculatePriceMYST(mystUSD, cfg.BasePrices.Residential.Runtime.PricePerHour, 1),
PricePerHourHumanReadable: calculatePriceMystFloat(mystUSD, cfg.BasePrices.Residential.Runtime.PricePerHour, 1),
PricePerGiB: calculatePriceMYST(mystUSD, cfg.BasePrices.Residential.Runtime.PricePerGiB, 1),
PricePerGiBHumanReadable: calculatePriceMystFloat(mystUSD, cfg.BasePrices.Residential.Runtime.PricePerGiB, 1),
},
DVPN: Price{
PricePerHour: calculatePriceMYST(mystUSD, cfg.BasePrices.Residential.DVPN.PricePerHour, 1),
PricePerHourHumanReadable: calculatePriceMystFloat(mystUSD, cfg.BasePrices.Residential.DVPN.PricePerHour, 1),
Expand Down Expand Up @@ -338,6 +357,12 @@ func (p *PriceUpdater) generateNewDefaults(mystUSD float64, cfg Config) *PriceHi
PricePerGiB: calculatePriceMYST(mystUSD, cfg.BasePrices.Other.DataTransfer.PricePerGiB, 1),
PricePerGiBHumanReadable: calculatePriceMystFloat(mystUSD, cfg.BasePrices.Other.DataTransfer.PricePerGiB, 1),
},
Runtime: Price{
PricePerHour: calculatePriceMYST(mystUSD, cfg.BasePrices.Other.Runtime.PricePerHour, 1),
PricePerHourHumanReadable: calculatePriceMystFloat(mystUSD, cfg.BasePrices.Other.Runtime.PricePerHour, 1),
PricePerGiB: calculatePriceMYST(mystUSD, cfg.BasePrices.Other.Runtime.PricePerGiB, 1),
PricePerGiBHumanReadable: calculatePriceMystFloat(mystUSD, cfg.BasePrices.Other.Runtime.PricePerGiB, 1),
},
DVPN: Price{
PricePerHour: calculatePriceMYST(mystUSD, cfg.BasePrices.Other.DVPN.PricePerHour, 1),
PricePerHourHumanReadable: calculatePriceMystFloat(mystUSD, cfg.BasePrices.Other.DVPN.PricePerHour, 1),
Expand Down Expand Up @@ -407,6 +432,7 @@ func (p *PriceUpdater) generateNewPerCountryWithModifier(mystUSD float64, cfg Co
scrapingMod := modifierFor(countryCode, ServiceTypeScraping)
quicScrapingMod := modifierFor(countryCode, ServiceTypeQUICScraping)
dataTransferMod := modifierFor(countryCode, ServiceTypeDataTransfer)
runtimeMod := modifierFor(countryCode, ServiceTypeRuntime)
dvpnMod := modifierFor(countryCode, ServiceTypeDVPN)
monitoringMod := modifierFor(countryCode, ServiceTypeMonitoring)

Expand Down Expand Up @@ -437,6 +463,12 @@ func (p *PriceUpdater) generateNewPerCountryWithModifier(mystUSD float64, cfg Co
PricePerGiB: calculatePriceMYST(mystUSD, cfg.BasePrices.Residential.DataTransfer.PricePerGiB, dataTransferMod.Residential),
PricePerGiBHumanReadable: calculatePriceMystFloat(mystUSD, cfg.BasePrices.Residential.DataTransfer.PricePerGiB, dataTransferMod.Residential),
},
Runtime: Price{
PricePerHour: calculatePriceMYST(mystUSD, cfg.BasePrices.Residential.Runtime.PricePerHour, runtimeMod.Residential),
PricePerHourHumanReadable: calculatePriceMystFloat(mystUSD, cfg.BasePrices.Residential.Runtime.PricePerHour, runtimeMod.Residential),
PricePerGiB: calculatePriceMYST(mystUSD, cfg.BasePrices.Residential.Runtime.PricePerGiB, runtimeMod.Residential),
PricePerGiBHumanReadable: calculatePriceMystFloat(mystUSD, cfg.BasePrices.Residential.Runtime.PricePerGiB, runtimeMod.Residential),
},
DVPN: Price{
PricePerHour: calculatePriceMYST(mystUSD, cfg.BasePrices.Residential.DVPN.PricePerHour, dvpnMod.Residential),
PricePerHourHumanReadable: calculatePriceMystFloat(mystUSD, cfg.BasePrices.Residential.DVPN.PricePerHour, dvpnMod.Residential),
Expand Down Expand Up @@ -475,6 +507,12 @@ func (p *PriceUpdater) generateNewPerCountryWithModifier(mystUSD float64, cfg Co
PricePerGiB: calculatePriceMYST(mystUSD, cfg.BasePrices.Other.DataTransfer.PricePerGiB, dataTransferMod.Other),
PricePerGiBHumanReadable: calculatePriceMystFloat(mystUSD, cfg.BasePrices.Other.DataTransfer.PricePerGiB, dataTransferMod.Other),
},
Runtime: Price{
PricePerHour: calculatePriceMYST(mystUSD, cfg.BasePrices.Other.Runtime.PricePerHour, runtimeMod.Other),
PricePerHourHumanReadable: calculatePriceMystFloat(mystUSD, cfg.BasePrices.Other.Runtime.PricePerHour, runtimeMod.Other),
PricePerGiB: calculatePriceMYST(mystUSD, cfg.BasePrices.Other.Runtime.PricePerGiB, runtimeMod.Other),
PricePerGiBHumanReadable: calculatePriceMystFloat(mystUSD, cfg.BasePrices.Other.Runtime.PricePerGiB, runtimeMod.Other),
},
DVPN: Price{
PricePerHour: calculatePriceMYST(mystUSD, cfg.BasePrices.Other.DVPN.PricePerHour, dvpnMod.Other),
PricePerHourHumanReadable: calculatePriceMystFloat(mystUSD, cfg.BasePrices.Other.DVPN.PricePerHour, dvpnMod.Other),
Expand Down Expand Up @@ -574,6 +612,7 @@ type PriceByServiceType struct {
Scraping Price `json:"scraping"`
QUICScraping Price `json:"quic_scraping"`
DataTransfer Price `json:"data_transfer"`
Runtime Price `json:"runtime"`
DVPN Price `json:"dvpn"`
Monitoring Price `json:"monitoring"`
}
Expand Down
17 changes: 15 additions & 2 deletions price/pricingbyservice/price_updater_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ func TestDemandBoostServiceMultipliers(t *testing.T) {
"PL": {
TargetDemandIndex: 0.1,
MaxBonus: 0.5,
ServiceTypes: []ServiceType{ServiceTypeDVPN, ServiceTypeWireguard},
ServiceTypes: []ServiceType{ServiceTypeDVPN, ServiceTypeWireguard, "runtime-cdp"},
},
"GB": {TargetDemandIndex: 0.1, MaxBonus: 0.5},
},
Expand All @@ -102,6 +102,9 @@ func TestDemandBoostServiceMultipliers(t *testing.T) {
if got["PL"][ServiceTypeDVPN] != 1.5 || got["PL"][ServiceTypeWireguard] != 1.5 {
t.Fatalf("expected PL selected service multipliers to be boosted, got %#v", got["PL"])
}
if got["PL"][ServiceTypeRuntime] != 1.5 {
t.Fatalf("expected PL runtime multiplier to be boosted, got %#v", got["PL"])
}
if _, ok := got["PL"][ServiceTypeScraping]; ok {
t.Fatalf("expected PL scraping to be omitted, got %#v", got["PL"])
}
Expand Down Expand Up @@ -818,7 +821,9 @@ func TestPricer_generateNewDefaults(t *testing.T) {
p := &PriceUpdater{
lp: tt.fields.lp,
}
if got := p.generateNewDefaults(tt.args.mystInUSD, tt.fields.cfg); !reflect.DeepEqual(got, tt.want) {
got := p.generateNewDefaults(tt.args.mystInUSD, tt.fields.cfg)
clearRuntimePrices(got)
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("Pricer.generateNewDefaults() = %v, want %v", got, tt.want)
}
})
Expand Down Expand Up @@ -1628,10 +1633,18 @@ func TestPricer_generateNewPerCountry(t *testing.T) {
generated := p.generateNewPerCountry(tt.args.mystInUSD, tt.fields.cfg)
got := generated["US"]
want := tt.want["US"]
clearRuntimePrices(got)

if !reflect.DeepEqual(got, want) {
t.Errorf("Pricer.generateNewPerCountry() = %v, want %v", got, want)
}
})
}
}

func clearRuntimePrices(priceHistory *PriceHistory) {
for _, prices := range []*PriceByType{priceHistory.Current, priceHistory.Previous} {
prices.Residential.Runtime = Price{}
prices.Other.Runtime = Price{}
}
}
Loading