Skip to content

Commit

Permalink
weightedroundrobin: Move functions to manage Endpoint weights into a …
Browse files Browse the repository at this point in the history
…new internal package (#8087)
  • Loading branch information
arjan-bal authored Feb 19, 2025
1 parent 607565d commit 42fc25a
Show file tree
Hide file tree
Showing 10 changed files with 171 additions and 181 deletions.
9 changes: 9 additions & 0 deletions balancer/weightedroundrobin/balancer.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,15 @@
*
*/

// Package weightedroundrobin provides an implementation of the weighted round
// robin LB policy, as defined in [gRFC A58].
//
// # Experimental
//
// Notice: This package is EXPERIMENTAL and may be changed or removed in a
// later release.
//
// [gRFC A58]: https://github.com/grpc/proposal/blob/master/A58-client-side-weighted-round-robin-lb-policy.md
package weightedroundrobin

import (
Expand Down
85 changes: 0 additions & 85 deletions balancer/weightedroundrobin/weightedroundrobin.go

This file was deleted.

82 changes: 0 additions & 82 deletions balancer/weightedroundrobin/weightedroundrobin_test.go

This file was deleted.

66 changes: 66 additions & 0 deletions internal/balancer/weight/weight.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
*
* Copyright 2025 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

// Package weight contains utilities to manage endpoint weights. Weights are
// used by LB policies such as ringhash to distribute load across multiple
// endpoints.
package weight

import (
"fmt"

"google.golang.org/grpc/resolver"
)

// attributeKey is the type used as the key to store EndpointInfo in the
// Attributes field of resolver.Endpoint.
type attributeKey struct{}

// EndpointInfo will be stored in the Attributes field of Endpoints in order to
// use the ringhash balancer.
type EndpointInfo struct {
Weight uint32
}

// Equal allows the values to be compared by Attributes.Equal.
func (a EndpointInfo) Equal(o any) bool {
oa, ok := o.(EndpointInfo)
return ok && oa.Weight == a.Weight
}

// Set returns a copy of endpoint in which the Attributes field is updated with
// EndpointInfo.
func Set(endpoint resolver.Endpoint, epInfo EndpointInfo) resolver.Endpoint {
endpoint.Attributes = endpoint.Attributes.WithValue(attributeKey{}, epInfo)
return endpoint
}

// String returns a human-readable representation of EndpointInfo.
// This method is intended for logging, testing, and debugging purposes only.
// Do not rely on the output format, as it is not guaranteed to remain stable.
func (a EndpointInfo) String() string {
return fmt.Sprintf("Weight: %d", a.Weight)
}

// FromEndpoint returns the EndpointInfo stored in the Attributes field of an
// endpoint. It returns an empty EndpointInfo if attribute is not found.
func FromEndpoint(endpoint resolver.Endpoint) EndpointInfo {
v := endpoint.Attributes.Value(attributeKey{})
ei, _ := v.(EndpointInfo)
return ei
}
83 changes: 83 additions & 0 deletions internal/balancer/weight/weight_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
*
* Copyright 2025 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package weight_test

import (
"testing"

"github.com/google/go-cmp/cmp"
"google.golang.org/grpc/attributes"
"google.golang.org/grpc/internal/balancer/weight"
"google.golang.org/grpc/internal/grpctest"
"google.golang.org/grpc/resolver"
)

type s struct {
grpctest.Tester
}

func Test(t *testing.T) {
grpctest.RunSubTests(t, s{})
}

func (s) TestEndpointInfoToAndFromAttributes(t *testing.T) {
tests := []struct {
desc string
inputEndpointInfo weight.EndpointInfo
inputAttributes *attributes.Attributes
wantEndpointInfo weight.EndpointInfo
}{
{
desc: "empty_attributes",
inputEndpointInfo: weight.EndpointInfo{Weight: 100},
inputAttributes: nil,
wantEndpointInfo: weight.EndpointInfo{Weight: 100},
},
{
desc: "non-empty_attributes",
inputEndpointInfo: weight.EndpointInfo{Weight: 100},
inputAttributes: attributes.New("foo", "bar"),
wantEndpointInfo: weight.EndpointInfo{Weight: 100},
},
{
desc: "endpointInfo_not_present_in_empty_attributes",
inputEndpointInfo: weight.EndpointInfo{},
inputAttributes: nil,
wantEndpointInfo: weight.EndpointInfo{},
},
{
desc: "endpointInfo_not_present_in_non-empty_attributes",
inputEndpointInfo: weight.EndpointInfo{},
inputAttributes: attributes.New("foo", "bar"),
wantEndpointInfo: weight.EndpointInfo{},
},
}

for _, test := range tests {
t.Run(test.desc, func(t *testing.T) {
endpoint := resolver.Endpoint{Attributes: test.inputAttributes}
endpoint = weight.Set(endpoint, test.inputEndpointInfo)
gotEndpointInfo := weight.FromEndpoint(endpoint)
if !cmp.Equal(gotEndpointInfo, test.wantEndpointInfo) {
t.Errorf("gotEndpointInfo: %v, wantEndpointInfo: %v", gotEndpointInfo, test.wantEndpointInfo)
}

})
}
}
4 changes: 2 additions & 2 deletions xds/internal/balancer/clusterresolver/configbuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import (
"fmt"
"sort"

"google.golang.org/grpc/balancer/weightedroundrobin"
"google.golang.org/grpc/internal/balancer/weight"
"google.golang.org/grpc/internal/hierarchy"
internalserviceconfig "google.golang.org/grpc/internal/serviceconfig"
"google.golang.org/grpc/resolver"
Expand Down Expand Up @@ -281,7 +281,7 @@ func priorityLocalitiesToClusterImpl(localities []xdsresource.Locality, priority
if endpoint.Weight != 0 {
ew = endpoint.Weight
}
resolverEndpoint = weightedroundrobin.SetAddrInfoInEndpoint(resolverEndpoint, weightedroundrobin.AddrInfo{Weight: lw * ew})
resolverEndpoint = weight.Set(resolverEndpoint, weight.EndpointInfo{Weight: lw * ew})
retEndpoints = append(retEndpoints, resolverEndpoint)
}
}
Expand Down
4 changes: 2 additions & 2 deletions xds/internal/balancer/clusterresolver/configbuilder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import (
"google.golang.org/grpc/attributes"
"google.golang.org/grpc/balancer"
"google.golang.org/grpc/balancer/roundrobin"
"google.golang.org/grpc/balancer/weightedroundrobin"
"google.golang.org/grpc/internal/balancer/weight"
"google.golang.org/grpc/internal/hierarchy"
iserviceconfig "google.golang.org/grpc/internal/serviceconfig"
"google.golang.org/grpc/internal/xds/bootstrap"
Expand Down Expand Up @@ -653,7 +653,7 @@ func testEndpointWithAttrs(addrStrs []string, localityWeight, endpointWeight uin
}
endpoint = hierarchy.SetInEndpoint(endpoint, path)
endpoint = wrrlocality.SetAddrInfoInEndpoint(endpoint, wrrlocality.AddrInfo{LocalityWeight: localityWeight})
endpoint = weightedroundrobin.SetAddrInfoInEndpoint(endpoint, weightedroundrobin.AddrInfo{Weight: localityWeight * endpointWeight})
endpoint = weight.Set(endpoint, weight.EndpointInfo{Weight: localityWeight * endpointWeight})
return endpoint
}

Expand Down
9 changes: 5 additions & 4 deletions xds/internal/balancer/ringhash/ring_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@ import (
"math"
"testing"

xxhash "github.com/cespare/xxhash/v2"
"google.golang.org/grpc/balancer/weightedroundrobin"
"google.golang.org/grpc/internal/balancer/weight"
"google.golang.org/grpc/resolver"

xxhash "github.com/cespare/xxhash/v2"
)

var testEndpoints []resolver.Endpoint
Expand All @@ -43,9 +44,9 @@ func init() {
testEndpointStateMap.Set(testEndpoints[2], &endpointState{firstAddr: "c", weight: 4})
}

func testEndpoint(addr string, weight uint32) resolver.Endpoint {
func testEndpoint(addr string, endpointWeight uint32) resolver.Endpoint {
ep := resolver.Endpoint{Addresses: []resolver.Address{{Addr: addr}}}
return weightedroundrobin.SetAddrInfoInEndpoint(ep, weightedroundrobin.AddrInfo{Weight: weight})
return weight.Set(ep, weight.EndpointInfo{Weight: endpointWeight})
}

func (s) TestRingNew(t *testing.T) {
Expand Down
Loading

0 comments on commit 42fc25a

Please sign in to comment.