rebase: bump google.golang.org/grpc from 1.71.1 to 1.72.0

Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.71.1 to 1.72.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.71.1...v1.72.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-version: 1.72.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
dependabot[bot]
2025-04-21 20:59:21 +00:00
committed by mergify[bot]
parent 7ee9fa24dd
commit c82b38deda
18 changed files with 191 additions and 118 deletions

4
go.mod
View File

@ -32,7 +32,7 @@ require (
golang.org/x/crypto v0.37.0 golang.org/x/crypto v0.37.0
golang.org/x/net v0.39.0 golang.org/x/net v0.39.0
golang.org/x/sys v0.32.0 golang.org/x/sys v0.32.0
google.golang.org/grpc v1.71.1 google.golang.org/grpc v1.72.0
google.golang.org/protobuf v1.36.6 google.golang.org/protobuf v1.36.6
k8s.io/api v0.32.3 k8s.io/api v0.32.3
k8s.io/apimachinery v0.32.3 k8s.io/apimachinery v0.32.3
@ -153,7 +153,7 @@ require (
golang.org/x/text v0.24.0 // indirect golang.org/x/text v0.24.0 // indirect
golang.org/x/time v0.8.0 // indirect golang.org/x/time v0.8.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a // indirect
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect

8
go.sum
View File

@ -1255,8 +1255,8 @@ google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX
google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
google.golang.org/genproto v0.0.0-20220602131408-e326c6e8e9c8/go.mod h1:yKyY4AMRwFiC8yMMNaMi+RkCnjZJt9LoWuvhXjMs+To= google.golang.org/genproto v0.0.0-20220602131408-e326c6e8e9c8/go.mod h1:yKyY4AMRwFiC8yMMNaMi+RkCnjZJt9LoWuvhXjMs+To=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a h1:51aaUVRocpvUOSQKM6Q7VuoaktNIaMCLuhZB6DKksq4=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a/go.mod h1:uRxBH1mhmO8PGhU89cMcHaXKZqO+OfakD8QQO0oYwlQ=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
@ -1288,8 +1288,8 @@ google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11
google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc v1.71.1 h1:ffsFWr7ygTUscGPI0KKK6TLrGz0476KUvvsbqWK0rPI= google.golang.org/grpc v1.72.0 h1:S7UkcVa60b5AAQTaO6ZKamFp1zMZSU0fGDK2WZLbBnM=
google.golang.org/grpc v1.71.1/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= google.golang.org/grpc v1.72.0/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=

View File

@ -41,7 +41,7 @@ func (bb *baseBuilder) Build(cc balancer.ClientConn, _ balancer.BuildOptions) ba
cc: cc, cc: cc,
pickerBuilder: bb.pickerBuilder, pickerBuilder: bb.pickerBuilder,
subConns: resolver.NewAddressMap(), subConns: resolver.NewAddressMapV2[balancer.SubConn](),
scStates: make(map[balancer.SubConn]connectivity.State), scStates: make(map[balancer.SubConn]connectivity.State),
csEvltr: &balancer.ConnectivityStateEvaluator{}, csEvltr: &balancer.ConnectivityStateEvaluator{},
config: bb.config, config: bb.config,
@ -65,7 +65,7 @@ type baseBalancer struct {
csEvltr *balancer.ConnectivityStateEvaluator csEvltr *balancer.ConnectivityStateEvaluator
state connectivity.State state connectivity.State
subConns *resolver.AddressMap subConns *resolver.AddressMapV2[balancer.SubConn]
scStates map[balancer.SubConn]connectivity.State scStates map[balancer.SubConn]connectivity.State
picker balancer.Picker picker balancer.Picker
config Config config Config
@ -100,7 +100,7 @@ func (b *baseBalancer) UpdateClientConnState(s balancer.ClientConnState) error {
// Successful resolution; clear resolver error and ensure we return nil. // Successful resolution; clear resolver error and ensure we return nil.
b.resolverErr = nil b.resolverErr = nil
// addrsSet is the set converted from addrs, it's used for quick lookup of an address. // addrsSet is the set converted from addrs, it's used for quick lookup of an address.
addrsSet := resolver.NewAddressMap() addrsSet := resolver.NewAddressMapV2[any]()
for _, a := range s.ResolverState.Addresses { for _, a := range s.ResolverState.Addresses {
addrsSet.Set(a, nil) addrsSet.Set(a, nil)
if _, ok := b.subConns.Get(a); !ok { if _, ok := b.subConns.Get(a); !ok {
@ -122,8 +122,7 @@ func (b *baseBalancer) UpdateClientConnState(s balancer.ClientConnState) error {
} }
} }
for _, a := range b.subConns.Keys() { for _, a := range b.subConns.Keys() {
sci, _ := b.subConns.Get(a) sc, _ := b.subConns.Get(a)
sc := sci.(balancer.SubConn)
// a was removed by resolver. // a was removed by resolver.
if _, ok := addrsSet.Get(a); !ok { if _, ok := addrsSet.Get(a); !ok {
sc.Shutdown() sc.Shutdown()
@ -173,8 +172,7 @@ func (b *baseBalancer) regeneratePicker() {
// Filter out all ready SCs from full subConn map. // Filter out all ready SCs from full subConn map.
for _, addr := range b.subConns.Keys() { for _, addr := range b.subConns.Keys() {
sci, _ := b.subConns.Get(addr) sc, _ := b.subConns.Get(addr)
sc := sci.(balancer.SubConn)
if st, ok := b.scStates[sc]; ok && st == connectivity.Ready { if st, ok := b.scStates[sc]; ok && st == connectivity.Ready {
readySCs[sc] = SubConnInfo{Address: addr} readySCs[sc] = SubConnInfo{Address: addr}
} }

View File

@ -73,7 +73,7 @@ func NewBalancer(cc balancer.ClientConn, opts balancer.BuildOptions, childBuilde
esOpts: esOpts, esOpts: esOpts,
childBuilder: childBuilder, childBuilder: childBuilder,
} }
es.children.Store(resolver.NewEndpointMap()) es.children.Store(resolver.NewEndpointMap[*balancerWrapper]())
return es return es
} }
@ -90,7 +90,7 @@ type endpointSharding struct {
// calls into a child. To avoid deadlocks, do not acquire childMu while // calls into a child. To avoid deadlocks, do not acquire childMu while
// holding mu. // holding mu.
childMu sync.Mutex childMu sync.Mutex
children atomic.Pointer[resolver.EndpointMap] // endpoint -> *balancerWrapper children atomic.Pointer[resolver.EndpointMap[*balancerWrapper]]
// inhibitChildUpdates is set during UpdateClientConnState/ResolverError // inhibitChildUpdates is set during UpdateClientConnState/ResolverError
// calls (calls to children will each produce an update, only want one // calls (calls to children will each produce an update, only want one
@ -122,7 +122,7 @@ func (es *endpointSharding) UpdateClientConnState(state balancer.ClientConnState
var ret error var ret error
children := es.children.Load() children := es.children.Load()
newChildren := resolver.NewEndpointMap() newChildren := resolver.NewEndpointMap[*balancerWrapper]()
// Update/Create new children. // Update/Create new children.
for _, endpoint := range state.ResolverState.Endpoints { for _, endpoint := range state.ResolverState.Endpoints {
@ -131,9 +131,8 @@ func (es *endpointSharding) UpdateClientConnState(state balancer.ClientConnState
// update. // update.
continue continue
} }
var childBalancer *balancerWrapper childBalancer, ok := children.Get(endpoint)
if val, ok := children.Get(endpoint); ok { if ok {
childBalancer = val.(*balancerWrapper)
// Endpoint attributes may have changed, update the stored endpoint. // Endpoint attributes may have changed, update the stored endpoint.
es.mu.Lock() es.mu.Lock()
childBalancer.childState.Endpoint = endpoint childBalancer.childState.Endpoint = endpoint
@ -166,7 +165,7 @@ func (es *endpointSharding) UpdateClientConnState(state balancer.ClientConnState
for _, e := range children.Keys() { for _, e := range children.Keys() {
child, _ := children.Get(e) child, _ := children.Get(e)
if _, ok := newChildren.Get(e); !ok { if _, ok := newChildren.Get(e); !ok {
child.(*balancerWrapper).closeLocked() child.closeLocked()
} }
} }
es.children.Store(newChildren) es.children.Store(newChildren)
@ -189,7 +188,7 @@ func (es *endpointSharding) ResolverError(err error) {
}() }()
children := es.children.Load() children := es.children.Load()
for _, child := range children.Values() { for _, child := range children.Values() {
child.(*balancerWrapper).resolverErrorLocked(err) child.resolverErrorLocked(err)
} }
} }
@ -202,7 +201,7 @@ func (es *endpointSharding) Close() {
defer es.childMu.Unlock() defer es.childMu.Unlock()
children := es.children.Load() children := es.children.Load()
for _, child := range children.Values() { for _, child := range children.Values() {
child.(*balancerWrapper).closeLocked() child.closeLocked()
} }
} }
@ -222,8 +221,7 @@ func (es *endpointSharding) updateState() {
childStates := make([]ChildState, 0, children.Len()) childStates := make([]ChildState, 0, children.Len())
for _, child := range children.Values() { for _, child := range children.Values() {
bw := child.(*balancerWrapper) childState := child.childState
childState := bw.childState
childStates = append(childStates, childState) childStates = append(childStates, childState)
childPicker := childState.State.Picker childPicker := childState.State.Picker
switch childState.State.ConnectivityState { switch childState.State.ConnectivityState {

View File

@ -122,7 +122,7 @@ func (pickfirstBuilder) Build(cc balancer.ClientConn, bo balancer.BuildOptions)
target: bo.Target.String(), target: bo.Target.String(),
metricsRecorder: cc.MetricsRecorder(), metricsRecorder: cc.MetricsRecorder(),
subConns: resolver.NewAddressMap(), subConns: resolver.NewAddressMapV2[*scData](),
state: connectivity.Connecting, state: connectivity.Connecting,
cancelConnectionTimer: func() {}, cancelConnectionTimer: func() {},
} }
@ -220,7 +220,7 @@ type pickfirstBalancer struct {
// updates. // updates.
state connectivity.State state connectivity.State
// scData for active subonns mapped by address. // scData for active subonns mapped by address.
subConns *resolver.AddressMap subConns *resolver.AddressMapV2[*scData]
addressList addressList addressList addressList
firstPass bool firstPass bool
numTF int numTF int
@ -319,7 +319,7 @@ func (b *pickfirstBalancer) UpdateClientConnState(state balancer.ClientConnState
prevAddr := b.addressList.currentAddress() prevAddr := b.addressList.currentAddress()
prevSCData, found := b.subConns.Get(prevAddr) prevSCData, found := b.subConns.Get(prevAddr)
prevAddrsCount := b.addressList.size() prevAddrsCount := b.addressList.size()
isPrevRawConnectivityStateReady := found && prevSCData.(*scData).rawConnectivityState == connectivity.Ready isPrevRawConnectivityStateReady := found && prevSCData.rawConnectivityState == connectivity.Ready
b.addressList.updateAddrs(newAddrs) b.addressList.updateAddrs(newAddrs)
// If the previous ready SubConn exists in new address list, // If the previous ready SubConn exists in new address list,
@ -381,21 +381,21 @@ func (b *pickfirstBalancer) startFirstPassLocked() {
b.numTF = 0 b.numTF = 0
// Reset the connection attempt record for existing SubConns. // Reset the connection attempt record for existing SubConns.
for _, sd := range b.subConns.Values() { for _, sd := range b.subConns.Values() {
sd.(*scData).connectionFailedInFirstPass = false sd.connectionFailedInFirstPass = false
} }
b.requestConnectionLocked() b.requestConnectionLocked()
} }
func (b *pickfirstBalancer) closeSubConnsLocked() { func (b *pickfirstBalancer) closeSubConnsLocked() {
for _, sd := range b.subConns.Values() { for _, sd := range b.subConns.Values() {
sd.(*scData).subConn.Shutdown() sd.subConn.Shutdown()
} }
b.subConns = resolver.NewAddressMap() b.subConns = resolver.NewAddressMapV2[*scData]()
} }
// deDupAddresses ensures that each address appears only once in the slice. // deDupAddresses ensures that each address appears only once in the slice.
func deDupAddresses(addrs []resolver.Address) []resolver.Address { func deDupAddresses(addrs []resolver.Address) []resolver.Address {
seenAddrs := resolver.NewAddressMap() seenAddrs := resolver.NewAddressMapV2[*scData]()
retAddrs := []resolver.Address{} retAddrs := []resolver.Address{}
for _, addr := range addrs { for _, addr := range addrs {
@ -481,7 +481,7 @@ func addressFamily(address string) ipAddrFamily {
// This ensures that the subchannel map accurately reflects the current set of // This ensures that the subchannel map accurately reflects the current set of
// addresses received from the name resolver. // addresses received from the name resolver.
func (b *pickfirstBalancer) reconcileSubConnsLocked(newAddrs []resolver.Address) { func (b *pickfirstBalancer) reconcileSubConnsLocked(newAddrs []resolver.Address) {
newAddrsMap := resolver.NewAddressMap() newAddrsMap := resolver.NewAddressMapV2[bool]()
for _, addr := range newAddrs { for _, addr := range newAddrs {
newAddrsMap.Set(addr, true) newAddrsMap.Set(addr, true)
} }
@ -491,7 +491,7 @@ func (b *pickfirstBalancer) reconcileSubConnsLocked(newAddrs []resolver.Address)
continue continue
} }
val, _ := b.subConns.Get(oldAddr) val, _ := b.subConns.Get(oldAddr)
val.(*scData).subConn.Shutdown() val.subConn.Shutdown()
b.subConns.Delete(oldAddr) b.subConns.Delete(oldAddr)
} }
} }
@ -500,13 +500,12 @@ func (b *pickfirstBalancer) reconcileSubConnsLocked(newAddrs []resolver.Address)
// becomes ready, which means that all other subConn must be shutdown. // becomes ready, which means that all other subConn must be shutdown.
func (b *pickfirstBalancer) shutdownRemainingLocked(selected *scData) { func (b *pickfirstBalancer) shutdownRemainingLocked(selected *scData) {
b.cancelConnectionTimer() b.cancelConnectionTimer()
for _, v := range b.subConns.Values() { for _, sd := range b.subConns.Values() {
sd := v.(*scData)
if sd.subConn != selected.subConn { if sd.subConn != selected.subConn {
sd.subConn.Shutdown() sd.subConn.Shutdown()
} }
} }
b.subConns = resolver.NewAddressMap() b.subConns = resolver.NewAddressMapV2[*scData]()
b.subConns.Set(selected.addr, selected) b.subConns.Set(selected.addr, selected)
} }
@ -539,18 +538,17 @@ func (b *pickfirstBalancer) requestConnectionLocked() {
b.subConns.Set(curAddr, sd) b.subConns.Set(curAddr, sd)
} }
scd := sd.(*scData) switch sd.rawConnectivityState {
switch scd.rawConnectivityState {
case connectivity.Idle: case connectivity.Idle:
scd.subConn.Connect() sd.subConn.Connect()
b.scheduleNextConnectionLocked() b.scheduleNextConnectionLocked()
return return
case connectivity.TransientFailure: case connectivity.TransientFailure:
// The SubConn is being re-used and failed during a previous pass // The SubConn is being re-used and failed during a previous pass
// over the addressList. It has not completed backoff yet. // over the addressList. It has not completed backoff yet.
// Mark it as having failed and try the next address. // Mark it as having failed and try the next address.
scd.connectionFailedInFirstPass = true sd.connectionFailedInFirstPass = true
lastErr = scd.lastErr lastErr = sd.lastErr
continue continue
case connectivity.Connecting: case connectivity.Connecting:
// Wait for the connection attempt to complete or the timer to fire // Wait for the connection attempt to complete or the timer to fire
@ -558,7 +556,7 @@ func (b *pickfirstBalancer) requestConnectionLocked() {
b.scheduleNextConnectionLocked() b.scheduleNextConnectionLocked()
return return
default: default:
b.logger.Errorf("SubConn with unexpected state %v present in SubConns map.", scd.rawConnectivityState) b.logger.Errorf("SubConn with unexpected state %v present in SubConns map.", sd.rawConnectivityState)
return return
} }
@ -753,8 +751,7 @@ func (b *pickfirstBalancer) endFirstPassIfPossibleLocked(lastErr error) {
} }
// Connect() has been called on all the SubConns. The first pass can be // Connect() has been called on all the SubConns. The first pass can be
// ended if all the SubConns have reported a failure. // ended if all the SubConns have reported a failure.
for _, v := range b.subConns.Values() { for _, sd := range b.subConns.Values() {
sd := v.(*scData)
if !sd.connectionFailedInFirstPass { if !sd.connectionFailedInFirstPass {
return return
} }
@ -765,8 +762,7 @@ func (b *pickfirstBalancer) endFirstPassIfPossibleLocked(lastErr error) {
Picker: &picker{err: lastErr}, Picker: &picker{err: lastErr},
}) })
// Start re-connecting all the SubConns that are already in IDLE. // Start re-connecting all the SubConns that are already in IDLE.
for _, v := range b.subConns.Values() { for _, sd := range b.subConns.Values() {
sd := v.(*scData)
if sd.rawConnectivityState == connectivity.Idle { if sd.rawConnectivityState == connectivity.Idle {
sd.subConn.Connect() sd.subConn.Connect()
} }
@ -927,6 +923,5 @@ func (al *addressList) hasNext() bool {
// fields that are meaningful to the SubConn. // fields that are meaningful to the SubConn.
func equalAddressIgnoringBalAttributes(a, b *resolver.Address) bool { func equalAddressIgnoringBalAttributes(a, b *resolver.Address) bool {
return a.Addr == b.Addr && a.ServerName == b.ServerName && return a.Addr == b.Addr && a.ServerName == b.ServerName &&
a.Attributes.Equal(b.Attributes) && a.Attributes.Equal(b.Attributes)
a.Metadata == b.Metadata
} }

View File

@ -18,7 +18,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.4 // protoc-gen-go v1.36.5
// protoc v5.27.1 // protoc v5.27.1
// source: grpc/binlog/v1/binarylog.proto // source: grpc/binlog/v1/binarylog.proto

View File

@ -1231,8 +1231,7 @@ func (ac *addrConn) updateConnectivityState(s connectivity.State, lastErr error)
// adjustParams updates parameters used to create transports upon // adjustParams updates parameters used to create transports upon
// receiving a GoAway. // receiving a GoAway.
func (ac *addrConn) adjustParams(r transport.GoAwayReason) { func (ac *addrConn) adjustParams(r transport.GoAwayReason) {
switch r { if r == transport.GoAwayTooManyPings {
case transport.GoAwayTooManyPings:
v := 2 * ac.dopts.copts.KeepaliveParams.Time v := 2 * ac.dopts.copts.KeepaliveParams.Time
ac.cc.mu.Lock() ac.cc.mu.Lock()
if v > ac.cc.keepaliveParams.Time { if v > ac.cc.keepaliveParams.Time {

View File

@ -51,10 +51,24 @@ var (
// xDS server in the list of server configs will be used. // xDS server in the list of server configs will be used.
XDSFallbackSupport = boolFromEnv("GRPC_EXPERIMENTAL_XDS_FALLBACK", true) XDSFallbackSupport = boolFromEnv("GRPC_EXPERIMENTAL_XDS_FALLBACK", true)
// NewPickFirstEnabled is set if the new pickfirst leaf policy is to be used // NewPickFirstEnabled is set if the new pickfirst leaf policy is to be used
// instead of the exiting pickfirst implementation. This can be enabled by // instead of the exiting pickfirst implementation. This can be disabled by
// setting the environment variable "GRPC_EXPERIMENTAL_ENABLE_NEW_PICK_FIRST" // setting the environment variable "GRPC_EXPERIMENTAL_ENABLE_NEW_PICK_FIRST"
// to "true". // to "false".
NewPickFirstEnabled = boolFromEnv("GRPC_EXPERIMENTAL_ENABLE_NEW_PICK_FIRST", false) NewPickFirstEnabled = boolFromEnv("GRPC_EXPERIMENTAL_ENABLE_NEW_PICK_FIRST", true)
// XDSEndpointHashKeyBackwardCompat controls the parsing of the endpoint hash
// key from EDS LbEndpoint metadata. Endpoint hash keys can be disabled by
// setting "GRPC_XDS_ENDPOINT_HASH_KEY_BACKWARD_COMPAT" to "true". When the
// implementation of A76 is stable, we will flip the default value to false
// in a subsequent release. A final release will remove this environment
// variable, enabling the new behavior unconditionally.
XDSEndpointHashKeyBackwardCompat = boolFromEnv("GRPC_XDS_ENDPOINT_HASH_KEY_BACKWARD_COMPAT", true)
// RingHashSetRequestHashKey is set if the ring hash balancer can get the
// request hash header by setting the "requestHashHeader" field, according
// to gRFC A76. It can be enabled by setting the environment variable
// "GRPC_EXPERIMENTAL_RING_HASH_SET_REQUEST_HASH_KEY" to "true".
RingHashSetRequestHashKey = boolFromEnv("GRPC_EXPERIMENTAL_RING_HASH_SET_REQUEST_HASH_KEY", false)
) )
func boolFromEnv(envVar string, def bool) bool { func boolFromEnv(envVar string, def bool) bool {

View File

@ -259,6 +259,13 @@ var (
// SetBufferPoolingThresholdForTesting updates the buffer pooling threshold, for // SetBufferPoolingThresholdForTesting updates the buffer pooling threshold, for
// testing purposes. // testing purposes.
SetBufferPoolingThresholdForTesting any // func(int) SetBufferPoolingThresholdForTesting any // func(int)
// TimeAfterFunc is used to create timers. During tests the function is
// replaced to track allocated timers and fail the test if a timer isn't
// cancelled.
TimeAfterFunc = func(d time.Duration, f func()) Timer {
return time.AfterFunc(d, f)
}
) )
// HealthChecker defines the signature of the client-side LB channel health // HealthChecker defines the signature of the client-side LB channel health
@ -300,3 +307,9 @@ type EnforceSubConnEmbedding interface {
type EnforceClientConnEmbedding interface { type EnforceClientConnEmbedding interface {
enforceClientConnEmbedding() enforceClientConnEmbedding()
} }
// Timer is an interface to allow injecting different time.Timer implementations
// during tests.
type Timer interface {
Stop() bool
}

View File

@ -97,13 +97,11 @@ func hasNotPrintable(msg string) bool {
return false return false
} }
// ValidatePair validate a key-value pair with the following rules (the pseudo-header will be skipped) : // ValidateKey validates a key with the following rules (pseudo-headers are
// // skipped):
// - key must contain one or more characters. // - the key must contain one or more characters.
// - the characters in the key must be contained in [0-9 a-z _ - .]. // - the characters in the key must be in [0-9 a-z _ - .].
// - if the key ends with a "-bin" suffix, no validation of the corresponding value is performed. func ValidateKey(key string) error {
// - the characters in the every value must be printable (in [%x20-%x7E]).
func ValidatePair(key string, vals ...string) error {
// key should not be empty // key should not be empty
if key == "" { if key == "" {
return fmt.Errorf("there is an empty key in the header") return fmt.Errorf("there is an empty key in the header")
@ -119,6 +117,20 @@ func ValidatePair(key string, vals ...string) error {
return fmt.Errorf("header key %q contains illegal characters not in [0-9a-z-_.]", key) return fmt.Errorf("header key %q contains illegal characters not in [0-9a-z-_.]", key)
} }
} }
return nil
}
// ValidatePair validates a key-value pair with the following rules
// (pseudo-header are skipped):
// - the key must contain one or more characters.
// - the characters in the key must be in [0-9 a-z _ - .].
// - if the key ends with a "-bin" suffix, no validation of the corresponding
// value is performed.
// - the characters in every value must be printable (in [%x20-%x7E]).
func ValidatePair(key string, vals ...string) error {
if err := ValidateKey(key); err != nil {
return err
}
if strings.HasSuffix(key, "-bin") { if strings.HasSuffix(key, "-bin") {
return nil return nil
} }

View File

@ -59,7 +59,7 @@ func (s *ClientStream) Read(n int) (mem.BufferSlice, error) {
return b, err return b, err
} }
// Close closes the stream and popagates err to any readers. // Close closes the stream and propagates err to any readers.
func (s *ClientStream) Close(err error) { func (s *ClientStream) Close(err error) {
var ( var (
rst bool rst bool

View File

@ -1390,8 +1390,7 @@ func (t *http2Client) handleGoAway(f *http2.GoAwayFrame) error {
// the caller. // the caller.
func (t *http2Client) setGoAwayReason(f *http2.GoAwayFrame) { func (t *http2Client) setGoAwayReason(f *http2.GoAwayFrame) {
t.goAwayReason = GoAwayNoReason t.goAwayReason = GoAwayNoReason
switch f.ErrCode { if f.ErrCode == http2.ErrCodeEnhanceYourCalm {
case http2.ErrCodeEnhanceYourCalm:
if string(f.DebugData()) == "too_many_pings" { if string(f.DebugData()) == "too_many_pings" {
t.goAwayReason = GoAwayTooManyPings t.goAwayReason = GoAwayTooManyPings
} }

View File

@ -35,6 +35,7 @@ import (
"golang.org/x/net/http2" "golang.org/x/net/http2"
"golang.org/x/net/http2/hpack" "golang.org/x/net/http2/hpack"
"google.golang.org/grpc/internal"
"google.golang.org/grpc/internal/grpclog" "google.golang.org/grpc/internal/grpclog"
"google.golang.org/grpc/internal/grpcutil" "google.golang.org/grpc/internal/grpcutil"
"google.golang.org/grpc/internal/pretty" "google.golang.org/grpc/internal/pretty"
@ -598,6 +599,22 @@ func (t *http2Server) operateHeaders(ctx context.Context, frame *http2.MetaHeade
if len(t.activeStreams) == 1 { if len(t.activeStreams) == 1 {
t.idle = time.Time{} t.idle = time.Time{}
} }
// Start a timer to close the stream on reaching the deadline.
if timeoutSet {
// We need to wait for s.cancel to be updated before calling
// t.closeStream to avoid data races.
cancelUpdated := make(chan struct{})
timer := internal.TimeAfterFunc(timeout, func() {
<-cancelUpdated
t.closeStream(s, true, http2.ErrCodeCancel, false)
})
oldCancel := s.cancel
s.cancel = func() {
oldCancel()
timer.Stop()
}
close(cancelUpdated)
}
t.mu.Unlock() t.mu.Unlock()
if channelz.IsOn() { if channelz.IsOn() {
t.channelz.SocketMetrics.StreamsStarted.Add(1) t.channelz.SocketMetrics.StreamsStarted.Add(1)
@ -1274,7 +1291,6 @@ func (t *http2Server) Close(err error) {
// deleteStream deletes the stream s from transport's active streams. // deleteStream deletes the stream s from transport's active streams.
func (t *http2Server) deleteStream(s *ServerStream, eosReceived bool) { func (t *http2Server) deleteStream(s *ServerStream, eosReceived bool) {
t.mu.Lock() t.mu.Lock()
if _, ok := t.activeStreams[s.id]; ok { if _, ok := t.activeStreams[s.id]; ok {
delete(t.activeStreams, s.id) delete(t.activeStreams, s.id)
@ -1324,7 +1340,10 @@ func (t *http2Server) closeStream(s *ServerStream, rst bool, rstCode http2.ErrCo
// called to interrupt the potential blocking on other goroutines. // called to interrupt the potential blocking on other goroutines.
s.cancel() s.cancel()
s.swapState(streamDone) oldState := s.swapState(streamDone)
if oldState == streamDone {
return
}
t.deleteStream(s, eosReceived) t.deleteStream(s, eosReceived)
t.controlBuf.put(&cleanupStream{ t.controlBuf.put(&cleanupStream{

View File

@ -35,8 +35,10 @@ type ServerStream struct {
*Stream // Embed for common stream functionality. *Stream // Embed for common stream functionality.
st internalServerTransport st internalServerTransport
ctxDone <-chan struct{} // closed at the end of stream. Cache of ctx.Done() (for performance) ctxDone <-chan struct{} // closed at the end of stream. Cache of ctx.Done() (for performance)
cancel context.CancelFunc // invoked at the end of stream to cancel ctx. // cancel is invoked at the end of stream to cancel ctx. It also stops the
// timer for monitoring the rpc deadline if configured.
cancel func()
// Holds compressor names passed in grpc-accept-encoding metadata from the // Holds compressor names passed in grpc-accept-encoding metadata from the
// client. // client.

View File

@ -24,16 +24,22 @@ import (
"strings" "strings"
) )
type addressMapEntry struct { type addressMapEntry[T any] struct {
addr Address addr Address
value any value T
} }
// AddressMap is a map of addresses to arbitrary values taking into account // AddressMap is an AddressMapV2[any]. It will be deleted in an upcoming
// release of grpc-go.
//
// Deprecated: use the generic AddressMapV2 type instead.
type AddressMap = AddressMapV2[any]
// AddressMapV2 is a map of addresses to arbitrary values taking into account
// Attributes. BalancerAttributes are ignored, as are Metadata and Type. // Attributes. BalancerAttributes are ignored, as are Metadata and Type.
// Multiple accesses may not be performed concurrently. Must be created via // Multiple accesses may not be performed concurrently. Must be created via
// NewAddressMap; do not construct directly. // NewAddressMap; do not construct directly.
type AddressMap struct { type AddressMapV2[T any] struct {
// The underlying map is keyed by an Address with fields that we don't care // The underlying map is keyed by an Address with fields that we don't care
// about being set to their zero values. The only fields that we care about // about being set to their zero values. The only fields that we care about
// are `Addr`, `ServerName` and `Attributes`. Since we need to be able to // are `Addr`, `ServerName` and `Attributes`. Since we need to be able to
@ -47,23 +53,30 @@ type AddressMap struct {
// The value type of the map contains a slice of addresses which match the key // The value type of the map contains a slice of addresses which match the key
// in their `Addr` and `ServerName` fields and contain the corresponding value // in their `Addr` and `ServerName` fields and contain the corresponding value
// associated with them. // associated with them.
m map[Address]addressMapEntryList m map[Address]addressMapEntryList[T]
} }
func toMapKey(addr *Address) Address { func toMapKey(addr *Address) Address {
return Address{Addr: addr.Addr, ServerName: addr.ServerName} return Address{Addr: addr.Addr, ServerName: addr.ServerName}
} }
type addressMapEntryList []*addressMapEntry type addressMapEntryList[T any] []*addressMapEntry[T]
// NewAddressMap creates a new AddressMap. // NewAddressMap creates a new AddressMapV2[any].
//
// Deprecated: use the generic NewAddressMapV2 constructor instead.
func NewAddressMap() *AddressMap { func NewAddressMap() *AddressMap {
return &AddressMap{m: make(map[Address]addressMapEntryList)} return NewAddressMapV2[any]()
}
// NewAddressMapV2 creates a new AddressMapV2.
func NewAddressMapV2[T any]() *AddressMapV2[T] {
return &AddressMapV2[T]{m: make(map[Address]addressMapEntryList[T])}
} }
// find returns the index of addr in the addressMapEntry slice, or -1 if not // find returns the index of addr in the addressMapEntry slice, or -1 if not
// present. // present.
func (l addressMapEntryList) find(addr Address) int { func (l addressMapEntryList[T]) find(addr Address) int {
for i, entry := range l { for i, entry := range l {
// Attributes are the only thing to match on here, since `Addr` and // Attributes are the only thing to match on here, since `Addr` and
// `ServerName` are already equal. // `ServerName` are already equal.
@ -75,28 +88,28 @@ func (l addressMapEntryList) find(addr Address) int {
} }
// Get returns the value for the address in the map, if present. // Get returns the value for the address in the map, if present.
func (a *AddressMap) Get(addr Address) (value any, ok bool) { func (a *AddressMapV2[T]) Get(addr Address) (value T, ok bool) {
addrKey := toMapKey(&addr) addrKey := toMapKey(&addr)
entryList := a.m[addrKey] entryList := a.m[addrKey]
if entry := entryList.find(addr); entry != -1 { if entry := entryList.find(addr); entry != -1 {
return entryList[entry].value, true return entryList[entry].value, true
} }
return nil, false return value, false
} }
// Set updates or adds the value to the address in the map. // Set updates or adds the value to the address in the map.
func (a *AddressMap) Set(addr Address, value any) { func (a *AddressMapV2[T]) Set(addr Address, value T) {
addrKey := toMapKey(&addr) addrKey := toMapKey(&addr)
entryList := a.m[addrKey] entryList := a.m[addrKey]
if entry := entryList.find(addr); entry != -1 { if entry := entryList.find(addr); entry != -1 {
entryList[entry].value = value entryList[entry].value = value
return return
} }
a.m[addrKey] = append(entryList, &addressMapEntry{addr: addr, value: value}) a.m[addrKey] = append(entryList, &addressMapEntry[T]{addr: addr, value: value})
} }
// Delete removes addr from the map. // Delete removes addr from the map.
func (a *AddressMap) Delete(addr Address) { func (a *AddressMapV2[T]) Delete(addr Address) {
addrKey := toMapKey(&addr) addrKey := toMapKey(&addr)
entryList := a.m[addrKey] entryList := a.m[addrKey]
entry := entryList.find(addr) entry := entryList.find(addr)
@ -113,7 +126,7 @@ func (a *AddressMap) Delete(addr Address) {
} }
// Len returns the number of entries in the map. // Len returns the number of entries in the map.
func (a *AddressMap) Len() int { func (a *AddressMapV2[T]) Len() int {
ret := 0 ret := 0
for _, entryList := range a.m { for _, entryList := range a.m {
ret += len(entryList) ret += len(entryList)
@ -122,7 +135,7 @@ func (a *AddressMap) Len() int {
} }
// Keys returns a slice of all current map keys. // Keys returns a slice of all current map keys.
func (a *AddressMap) Keys() []Address { func (a *AddressMapV2[T]) Keys() []Address {
ret := make([]Address, 0, a.Len()) ret := make([]Address, 0, a.Len())
for _, entryList := range a.m { for _, entryList := range a.m {
for _, entry := range entryList { for _, entry := range entryList {
@ -133,8 +146,8 @@ func (a *AddressMap) Keys() []Address {
} }
// Values returns a slice of all current map values. // Values returns a slice of all current map values.
func (a *AddressMap) Values() []any { func (a *AddressMapV2[T]) Values() []T {
ret := make([]any, 0, a.Len()) ret := make([]T, 0, a.Len())
for _, entryList := range a.m { for _, entryList := range a.m {
for _, entry := range entryList { for _, entry := range entryList {
ret = append(ret, entry.value) ret = append(ret, entry.value)
@ -149,21 +162,21 @@ type endpointMapKey string
// unordered set of address strings within an endpoint. This map is not thread // unordered set of address strings within an endpoint. This map is not thread
// safe, thus it is unsafe to access concurrently. Must be created via // safe, thus it is unsafe to access concurrently. Must be created via
// NewEndpointMap; do not construct directly. // NewEndpointMap; do not construct directly.
type EndpointMap struct { type EndpointMap[T any] struct {
endpoints map[endpointMapKey]endpointData endpoints map[endpointMapKey]endpointData[T]
} }
type endpointData struct { type endpointData[T any] struct {
// decodedKey stores the original key to avoid decoding when iterating on // decodedKey stores the original key to avoid decoding when iterating on
// EndpointMap keys. // EndpointMap keys.
decodedKey Endpoint decodedKey Endpoint
value any value T
} }
// NewEndpointMap creates a new EndpointMap. // NewEndpointMap creates a new EndpointMap.
func NewEndpointMap() *EndpointMap { func NewEndpointMap[T any]() *EndpointMap[T] {
return &EndpointMap{ return &EndpointMap[T]{
endpoints: make(map[endpointMapKey]endpointData), endpoints: make(map[endpointMapKey]endpointData[T]),
} }
} }
@ -183,25 +196,25 @@ func encodeEndpoint(e Endpoint) endpointMapKey {
} }
// Get returns the value for the address in the map, if present. // Get returns the value for the address in the map, if present.
func (em *EndpointMap) Get(e Endpoint) (value any, ok bool) { func (em *EndpointMap[T]) Get(e Endpoint) (value T, ok bool) {
val, found := em.endpoints[encodeEndpoint(e)] val, found := em.endpoints[encodeEndpoint(e)]
if found { if found {
return val.value, true return val.value, true
} }
return nil, false return value, false
} }
// Set updates or adds the value to the address in the map. // Set updates or adds the value to the address in the map.
func (em *EndpointMap) Set(e Endpoint, value any) { func (em *EndpointMap[T]) Set(e Endpoint, value T) {
en := encodeEndpoint(e) en := encodeEndpoint(e)
em.endpoints[en] = endpointData{ em.endpoints[en] = endpointData[T]{
decodedKey: Endpoint{Addresses: e.Addresses}, decodedKey: Endpoint{Addresses: e.Addresses},
value: value, value: value,
} }
} }
// Len returns the number of entries in the map. // Len returns the number of entries in the map.
func (em *EndpointMap) Len() int { func (em *EndpointMap[T]) Len() int {
return len(em.endpoints) return len(em.endpoints)
} }
@ -210,7 +223,7 @@ func (em *EndpointMap) Len() int {
// the unordered set of addresses. Thus, endpoint information returned is not // the unordered set of addresses. Thus, endpoint information returned is not
// the full endpoint data (drops duplicated addresses and attributes) but can be // the full endpoint data (drops duplicated addresses and attributes) but can be
// used for EndpointMap accesses. // used for EndpointMap accesses.
func (em *EndpointMap) Keys() []Endpoint { func (em *EndpointMap[T]) Keys() []Endpoint {
ret := make([]Endpoint, 0, len(em.endpoints)) ret := make([]Endpoint, 0, len(em.endpoints))
for _, en := range em.endpoints { for _, en := range em.endpoints {
ret = append(ret, en.decodedKey) ret = append(ret, en.decodedKey)
@ -219,8 +232,8 @@ func (em *EndpointMap) Keys() []Endpoint {
} }
// Values returns a slice of all current map values. // Values returns a slice of all current map values.
func (em *EndpointMap) Values() []any { func (em *EndpointMap[T]) Values() []T {
ret := make([]any, 0, len(em.endpoints)) ret := make([]T, 0, len(em.endpoints))
for _, val := range em.endpoints { for _, val := range em.endpoints {
ret = append(ret, val.value) ret = append(ret, val.value)
} }
@ -228,7 +241,7 @@ func (em *EndpointMap) Values() []any {
} }
// Delete removes the specified endpoint from the map. // Delete removes the specified endpoint from the map.
func (em *EndpointMap) Delete(e Endpoint) { func (em *EndpointMap[T]) Delete(e Endpoint) {
en := encodeEndpoint(e) en := encodeEndpoint(e)
delete(em.endpoints, en) delete(em.endpoints, en)
} }

View File

@ -36,7 +36,12 @@ type RPCStats interface {
IsClient() bool IsClient() bool
} }
// Begin contains stats when an RPC attempt begins. // Begin contains stats for the start of an RPC attempt.
//
// - Server-side: Triggered after `InHeader`, as headers are processed
// before the RPC lifecycle begins.
// - Client-side: The first stats event recorded.
//
// FailFast is only valid if this Begin is from client side. // FailFast is only valid if this Begin is from client side.
type Begin struct { type Begin struct {
// Client is true if this Begin is from client side. // Client is true if this Begin is from client side.
@ -69,7 +74,7 @@ func (*PickerUpdated) IsClient() bool { return true }
func (*PickerUpdated) isRPCStats() {} func (*PickerUpdated) isRPCStats() {}
// InPayload contains the information for an incoming payload. // InPayload contains stats about an incoming payload.
type InPayload struct { type InPayload struct {
// Client is true if this InPayload is from client side. // Client is true if this InPayload is from client side.
Client bool Client bool
@ -98,7 +103,9 @@ func (s *InPayload) IsClient() bool { return s.Client }
func (s *InPayload) isRPCStats() {} func (s *InPayload) isRPCStats() {}
// InHeader contains stats when a header is received. // InHeader contains stats about header reception.
//
// - Server-side: The first stats event after the RPC request is received.
type InHeader struct { type InHeader struct {
// Client is true if this InHeader is from client side. // Client is true if this InHeader is from client side.
Client bool Client bool
@ -123,7 +130,7 @@ func (s *InHeader) IsClient() bool { return s.Client }
func (s *InHeader) isRPCStats() {} func (s *InHeader) isRPCStats() {}
// InTrailer contains stats when a trailer is received. // InTrailer contains stats about trailer reception.
type InTrailer struct { type InTrailer struct {
// Client is true if this InTrailer is from client side. // Client is true if this InTrailer is from client side.
Client bool Client bool
@ -139,7 +146,7 @@ func (s *InTrailer) IsClient() bool { return s.Client }
func (s *InTrailer) isRPCStats() {} func (s *InTrailer) isRPCStats() {}
// OutPayload contains the information for an outgoing payload. // OutPayload contains stats about an outgoing payload.
type OutPayload struct { type OutPayload struct {
// Client is true if this OutPayload is from client side. // Client is true if this OutPayload is from client side.
Client bool Client bool
@ -166,7 +173,10 @@ func (s *OutPayload) IsClient() bool { return s.Client }
func (s *OutPayload) isRPCStats() {} func (s *OutPayload) isRPCStats() {}
// OutHeader contains stats when a header is sent. // OutHeader contains stats about header transmission.
//
// - Client-side: Only occurs after 'Begin', as headers are always the first
// thing sent on a stream.
type OutHeader struct { type OutHeader struct {
// Client is true if this OutHeader is from client side. // Client is true if this OutHeader is from client side.
Client bool Client bool
@ -189,14 +199,15 @@ func (s *OutHeader) IsClient() bool { return s.Client }
func (s *OutHeader) isRPCStats() {} func (s *OutHeader) isRPCStats() {}
// OutTrailer contains stats when a trailer is sent. // OutTrailer contains stats about trailer transmission.
type OutTrailer struct { type OutTrailer struct {
// Client is true if this OutTrailer is from client side. // Client is true if this OutTrailer is from client side.
Client bool Client bool
// WireLength is the wire length of trailer. // WireLength is the wire length of trailer.
// //
// Deprecated: This field is never set. The length is not known when this message is // Deprecated: This field is never set. The length is not known when this
// emitted because the trailer fields are compressed with hpack after that. // message is emitted because the trailer fields are compressed with hpack
// after that.
WireLength int WireLength int
// Trailer contains the trailer metadata sent to the client. This // Trailer contains the trailer metadata sent to the client. This
// field is only valid if this OutTrailer is from the server side. // field is only valid if this OutTrailer is from the server side.
@ -208,7 +219,7 @@ func (s *OutTrailer) IsClient() bool { return s.Client }
func (s *OutTrailer) isRPCStats() {} func (s *OutTrailer) isRPCStats() {}
// End contains stats when an RPC ends. // End contains stats about RPC completion.
type End struct { type End struct {
// Client is true if this End is from client side. // Client is true if this End is from client side.
Client bool Client bool
@ -238,7 +249,7 @@ type ConnStats interface {
IsClient() bool IsClient() bool
} }
// ConnBegin contains the stats of a connection when it is established. // ConnBegin contains stats about connection establishment.
type ConnBegin struct { type ConnBegin struct {
// Client is true if this ConnBegin is from client side. // Client is true if this ConnBegin is from client side.
Client bool Client bool
@ -249,7 +260,7 @@ func (s *ConnBegin) IsClient() bool { return s.Client }
func (s *ConnBegin) isConnStats() {} func (s *ConnBegin) isConnStats() {}
// ConnEnd contains the stats of a connection when it ends. // ConnEnd contains stats about connection termination.
type ConnEnd struct { type ConnEnd struct {
// Client is true if this ConnEnd is from client side. // Client is true if this ConnEnd is from client side.
Client bool Client bool

View File

@ -19,4 +19,4 @@
package grpc package grpc
// Version is the current grpc version. // Version is the current grpc version.
const Version = "1.71.1" const Version = "1.72.0"

6
vendor/modules.txt vendored
View File

@ -598,11 +598,11 @@ golang.org/x/time/rate
# gomodules.xyz/jsonpatch/v2 v2.4.0 # gomodules.xyz/jsonpatch/v2 v2.4.0
## explicit; go 1.20 ## explicit; go 1.20
gomodules.xyz/jsonpatch/v2 gomodules.xyz/jsonpatch/v2
# google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f # google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a
## explicit; go 1.22 ## explicit; go 1.22
google.golang.org/genproto/googleapis/rpc/status google.golang.org/genproto/googleapis/rpc/status
# google.golang.org/grpc v1.71.1 # google.golang.org/grpc v1.72.0
## explicit; go 1.22.0 ## explicit; go 1.23
google.golang.org/grpc google.golang.org/grpc
google.golang.org/grpc/attributes google.golang.org/grpc/attributes
google.golang.org/grpc/backoff google.golang.org/grpc/backoff