@@ -5,11 +5,12 @@ import (
55 // "encoding/hex"
66 "strings"
77 "sync"
8+ "sync/atomic"
89 "time"
910
10- // "errors"
1111 "bytes"
1212 "encoding/gob"
13+ "errors"
1314 "fmt"
1415 // "math"
1516 mathrand "math/rand"
@@ -2119,7 +2120,8 @@ const MaxClientScore = 50
21192120const ClientScoreSampleCount = 200
21202121
21212122// choose a filter that has at least this number of providers
2122- const MinExportNetReliabilityWeight = float64 (200 )
2123+ // FIXME this scale based on traffic for region
2124+ const MinExportNetReliabilityWeight = float64 (400 )
21232125
21242126// the number of filtered providers to consider a location stable
21252127const MinStableNetReliabilityWeight = float64 (10 )
@@ -2260,15 +2262,17 @@ func UpdateClientScores(ctx context.Context, ttl time.Duration) (returnErr error
22602262 scoreAdjust += missingSpeedScore
22612263 }
22622264
2263- score := 0
22642265 if ! exclude {
2265- score = min (
2266+ score : = min (
22662267 scorePerTier * netTypeScores [rankMode ]+ scoreAdjust ,
22672268 MaxClientScore ,
22682269 )
2270+ clientScore .Scores [rankMode ] = score
2271+ clientScore .Tiers [rankMode ] = score / scorePerTier
2272+ } else {
2273+ clientScore .Scores [rankMode ] = 0
2274+ clientScore .Tiers [rankMode ] = (MaxClientScore + scorePerTier - 1 ) / scorePerTier
22692275 }
2270- clientScore .Scores [rankMode ] = score
2271- clientScore .Tiers [rankMode ] = score / scorePerTier
22722276 }
22732277 }
22742278
@@ -2501,36 +2505,27 @@ func UpdateClientScores(ctx context.Context, ttl time.Duration) (returnErr error
25012505 // to minimize the chance of bad providers in the `FindProviders2` randomized shuffle
25022506 // the last filter represents the worst case the network will expose to users
25032507 filters := []filter {
2504- // filter{
2505- // maxScore: scorePerTier,
2506- // minIndependentReliabilityWeights: map[int]float64{
2507- // 1: float64(0.999),
2508- // 2: float64(0.99),
2509- // 3: float64(0.9),
2510- // },
2511- // // minBytesPerSecond: Mib * 1,
2512- // // maxRelativeLatencyMillis: 200,
2513- // },
25142508 filter {
25152509 maxScore : 2 * scorePerTier ,
25162510 minIndependentReliabilityWeights : map [int ]float64 {
2517- 1 : float64 (0.99 ),
2511+ 1 : float64 (0.9 ),
25182512 2 : float64 (0.9 ),
2513+ 3 : float64 (0.9 ),
2514+ },
2515+ // minBytesPerSecond: Kib * 512,
2516+ },
2517+ // this case allows for some recent outage to otherwise high-SLA providers
2518+ // this case catches system-wide issues
2519+ filter {
2520+ maxScore : 2 * scorePerTier ,
2521+ minIndependentReliabilityWeights : map [int ]float64 {
2522+ 1 : float64 (0.8 ),
2523+ 2 : float64 (0.8 ),
25192524 3 : float64 (0.8 ),
25202525 },
2521- // minBytesPerSecond: Mib * 1 ,
2522- // maxRelativeLatencyMillis: 400 ,
2526+ // minBytesPerSecond: Kib * 512 ,
2527+ // maxRelativeLatencyMillis: 600 ,
25232528 },
2524- // filter{
2525- // maxScore: 2 * scorePerTier,
2526- // minIndependentReliabilityWeights: map[int]float64{
2527- // 1: float64(0.9),
2528- // 2: float64(0.8),
2529- // 3: float64(0.7),
2530- // },
2531- // // minBytesPerSecond: Kib * 512,
2532- // // maxRelativeLatencyMillis: 600,
2533- // },
25342529 }
25352530
25362531 exportClientScores := func (forceMinimum bool , rankMode RankMode , s map [server.Id ]* ClientScore ) (
@@ -2674,42 +2669,85 @@ func UpdateClientScores(ctx context.Context, ttl time.Duration) (returnErr error
26742669 }
26752670 clientLocationIds = append (clientLocationIds , maps .Values (countryCodeLocationIds ())... )
26762671
2677- server .Redis (ctx , func (r server.RedisClient ) {
2678- for _ , forceMinimum := range []bool {false , true } {
2679- for rankMode , _ := range performanceTargets {
2680- for j , clientLocationId := range clientLocationIds {
2681- pipe := r .TxPipeline ()
2682-
2683- glog .Infof ("[nclm]export client location[%d/%d] %s\n " , j + 1 , len (clientLocationIds ), clientLocationId )
2684- for locationId , clientScores := range locationClientScores {
2685- activeClientScores := filterActive (clientScores , clientLocationId )
2686- countsBytes , samplesBytes , filterBytes , counts , _ , _ := exportClientScores (forceMinimum , rankMode , activeClientScores )
2687- pipe .Set (ctx , clientScoreLocationCountsKey (forceMinimum , rankMode , locationId , clientLocationId ), countsBytes , ttl )
2688- pipe .Set (ctx , clientScoreLocationFilterKey (forceMinimum , rankMode , locationId , clientLocationId ), filterBytes , ttl )
2689- for i , sampleBytes := range samplesBytes {
2690- pipe .Set (ctx , clientScoreLocationSampleKey (forceMinimum , rankMode , locationId , clientLocationId , i ), sampleBytes , ttl )
2691- }
2692- glog .V (2 ).Infof ("[nclm]update client scores location samples(%s)[%d] = %v\n " , locationId , len (counts ), counts )
2693- }
2694- for locationGroupId , clientScores := range locationGroupClientScores {
2695- activeClientScores := filterActive (clientScores , clientLocationId )
2696- countsBytes , samplesBytes , filterBytes , counts , _ , _ := exportClientScores (forceMinimum , rankMode , activeClientScores )
2697- pipe .Set (ctx , clientScoreLocationGroupCountsKey (forceMinimum , rankMode , locationGroupId , clientLocationId ), countsBytes , ttl )
2698- pipe .Set (ctx , clientScoreLocationGroupFilterKey (forceMinimum , rankMode , locationGroupId , clientLocationId ), filterBytes , ttl )
2699- for i , sampleBytes := range samplesBytes {
2700- pipe .Set (ctx , clientScoreLocationGroupSampleKey (forceMinimum , rankMode , locationGroupId , clientLocationId , i ), sampleBytes , ttl )
2672+ n := 48
2673+ m := (len (clientLocationIds ) + n - 1 ) / n
2674+ allBlockClientLocationIds := [][]server.Id {}
2675+ for i := 0 ; i < len (clientLocationIds ); i += m {
2676+ allBlockClientLocationIds = append (allBlockClientLocationIds , clientLocationIds [i :min (len (clientLocationIds ), i + m )])
2677+ }
2678+
2679+ var wg sync.WaitGroup
2680+ var exportCount atomic.Uint32
2681+ returnErrs := make (chan error , n )
2682+
2683+ for i := 0 ; i < len (clientLocationIds ); i += m {
2684+ blockClientLocationIds := clientLocationIds [i :min (len (clientLocationIds ), i + m )]
2685+
2686+ wg .Add (1 )
2687+ go connect .HandleError (func () {
2688+ defer wg .Done ()
2689+
2690+ server .Redis (ctx , func (r server.RedisClient ) {
2691+ for _ , forceMinimum := range []bool {false , true } {
2692+ for rankMode , _ := range performanceTargets {
2693+ for _ , clientLocationId := range blockClientLocationIds {
2694+ pipe := r .TxPipeline ()
2695+
2696+ exportIndex := exportCount .Add (1 )
2697+ glog .Infof ("[nclm]export client location[%d/%d] %s\n " , exportIndex + 1 , 2 * len (performanceTargets )* len (clientLocationIds ), clientLocationId )
2698+ for locationId , clientScores := range locationClientScores {
2699+ activeClientScores := filterActive (clientScores , clientLocationId )
2700+ countsBytes , samplesBytes , filterBytes , counts , _ , _ := exportClientScores (forceMinimum , rankMode , activeClientScores )
2701+ pipe .Set (ctx , clientScoreLocationCountsKey (forceMinimum , rankMode , locationId , clientLocationId ), countsBytes , ttl )
2702+ pipe .Set (ctx , clientScoreLocationFilterKey (forceMinimum , rankMode , locationId , clientLocationId ), filterBytes , ttl )
2703+ for i , sampleBytes := range samplesBytes {
2704+ pipe .Set (ctx , clientScoreLocationSampleKey (forceMinimum , rankMode , locationId , clientLocationId , i ), sampleBytes , ttl )
2705+ }
2706+ glog .V (2 ).Infof ("[nclm]update client scores location samples(%s)[%d] = %v\n " , locationId , len (counts ), counts )
2707+ }
2708+ for locationGroupId , clientScores := range locationGroupClientScores {
2709+ activeClientScores := filterActive (clientScores , clientLocationId )
2710+ countsBytes , samplesBytes , filterBytes , counts , _ , _ := exportClientScores (forceMinimum , rankMode , activeClientScores )
2711+ pipe .Set (ctx , clientScoreLocationGroupCountsKey (forceMinimum , rankMode , locationGroupId , clientLocationId ), countsBytes , ttl )
2712+ pipe .Set (ctx , clientScoreLocationGroupFilterKey (forceMinimum , rankMode , locationGroupId , clientLocationId ), filterBytes , ttl )
2713+ for i , sampleBytes := range samplesBytes {
2714+ pipe .Set (ctx , clientScoreLocationGroupSampleKey (forceMinimum , rankMode , locationGroupId , clientLocationId , i ), sampleBytes , ttl )
2715+ }
2716+ glog .V (2 ).Infof ("[nclm]update client scores location group samples(%s)[%d] = %v\n " , locationGroupId , len (counts ), counts )
2717+ }
2718+
2719+ _ , err := pipe .Exec (ctx )
2720+ if err != nil {
2721+ select {
2722+ case <- ctx .Done ():
2723+ return
2724+ case returnErrs <- err :
2725+ return
2726+ }
2727+ }
27012728 }
2702- glog .V (2 ).Infof ("[nclm]update client scores location group samples(%s)[%d] = %v\n " , locationGroupId , len (counts ), counts )
27032729 }
2730+ }
2731+ })
2732+ }, wg .Done )
2733+ }
27042734
2705- _ , returnErr = pipe .Exec (ctx )
2706- if returnErr != nil {
2707- return
2708- }
2735+ wg .Wait ()
2736+ close (returnErrs )
2737+
2738+ func () {
2739+ for {
2740+ select {
2741+ case <- ctx .Done ():
2742+ return
2743+ case err , ok := <- returnErrs :
2744+ if ! ok {
2745+ return
27092746 }
2747+ returnErr = errors .Join (returnErr , err )
27102748 }
27112749 }
2712- })
2750+ }( )
27132751
27142752 if returnErr == nil {
27152753 glog .Infof (
@@ -2841,6 +2879,9 @@ func FindProviders2(
28412879
28422880 excludeFinalDestinations := sync .OnceValue (func () map [server.Id ]bool {
28432881 excludeFinalDestinations := map [server.Id ]bool {}
2882+ for _ , clientId := range findProviders2 .ExcludeClientIds {
2883+ excludeFinalDestinations [clientId ] = true
2884+ }
28442885 for _ , destination := range findProviders2 .ExcludeDestinations {
28452886 excludeFinalDestinations [destination [len (destination )- 1 ]] = true
28462887 }
@@ -2924,7 +2965,7 @@ func FindProviders2(
29242965 glog .Infof ("[nclm]findproviders2 load %.2fms (%d)\n " , loadMillis , len (clientScores ))
29252966 }
29262967
2927- for _ , clientId := range findProviders2 . ExcludeClientIds {
2968+ for clientId , _ := range excludeFinalDestinations () {
29282969 delete (clientScores , clientId )
29292970 }
29302971 // the final hop is excluded
@@ -2936,7 +2977,11 @@ func FindProviders2(
29362977 clientScore .Scores [rankMode ] += intermediaryScore
29372978 }
29382979 }
2939- delete (clientScores , destination [len (destination )- 1 ])
2980+ }
2981+
2982+ adjustedMaxClientScore := MaxClientScore
2983+ for _ , clientScore := range clientScores {
2984+ adjustedMaxClientScore = max (adjustedMaxClientScore , clientScore .Scores [rankMode ])
29402985 }
29412986
29422987 clientIds := maps .Keys (clientScores )
@@ -2946,7 +2991,7 @@ func FindProviders2(
29462991
29472992 connect .WeightedSelectFunc (clientIds , count , func (clientId server.Id ) float32 {
29482993 clientScore := clientScores [clientId ]
2949- qualityWeight := max (0 , MaxClientScore - clientScore .Scores [rankMode ])
2994+ qualityWeight := max (0 , adjustedMaxClientScore - clientScore .Scores [rankMode ])
29502995 return float32 (clientScore .ReliabilityWeight * float64 (qualityWeight ))
29512996 })
29522997 clientIds = clientIds [:min (count , len (clientIds ))]
0 commit comments