mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 18:43:34 +00:00
Update to kube v1.17
Signed-off-by: Humble Chirammal <hchiramm@redhat.com>
This commit is contained in:
committed by
mergify[bot]
parent
327fcd1b1b
commit
3af1e26d7c
247
vendor/google.golang.org/grpc/clientconn.go
generated
vendored
247
vendor/google.golang.org/grpc/clientconn.go
generated
vendored
@ -31,7 +31,7 @@ import (
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc/balancer"
|
||||
_ "google.golang.org/grpc/balancer/roundrobin" // To register roundrobin.
|
||||
"google.golang.org/grpc/balancer/base"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/connectivity"
|
||||
"google.golang.org/grpc/credentials"
|
||||
@ -42,10 +42,12 @@ import (
|
||||
"google.golang.org/grpc/internal/transport"
|
||||
"google.golang.org/grpc/keepalive"
|
||||
"google.golang.org/grpc/resolver"
|
||||
_ "google.golang.org/grpc/resolver/dns" // To register dns resolver.
|
||||
_ "google.golang.org/grpc/resolver/passthrough" // To register passthrough resolver.
|
||||
"google.golang.org/grpc/serviceconfig"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
_ "google.golang.org/grpc/balancer/roundrobin" // To register roundrobin.
|
||||
_ "google.golang.org/grpc/internal/resolver/dns" // To register dns resolver.
|
||||
_ "google.golang.org/grpc/internal/resolver/passthrough" // To register passthrough resolver.
|
||||
)
|
||||
|
||||
const (
|
||||
@ -186,11 +188,11 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *
|
||||
}
|
||||
|
||||
if cc.dopts.defaultServiceConfigRawJSON != nil {
|
||||
sc, err := parseServiceConfig(*cc.dopts.defaultServiceConfigRawJSON)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s: %v", invalidDefaultServiceConfigErrPrefix, err)
|
||||
scpr := parseServiceConfig(*cc.dopts.defaultServiceConfigRawJSON)
|
||||
if scpr.Err != nil {
|
||||
return nil, fmt.Errorf("%s: %v", invalidDefaultServiceConfigErrPrefix, scpr.Err)
|
||||
}
|
||||
cc.dopts.defaultServiceConfig = sc
|
||||
cc.dopts.defaultServiceConfig, _ = scpr.Config.(*ServiceConfig)
|
||||
}
|
||||
cc.mkp = cc.dopts.copts.KeepaliveParams
|
||||
|
||||
@ -235,9 +237,7 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *
|
||||
}
|
||||
}
|
||||
if cc.dopts.bs == nil {
|
||||
cc.dopts.bs = backoff.Exponential{
|
||||
MaxDelay: DefaultBackoffConfig.MaxDelay,
|
||||
}
|
||||
cc.dopts.bs = backoff.DefaultExponential
|
||||
}
|
||||
if cc.dopts.resolverBuilder == nil {
|
||||
// Only try to parse target when resolver builder is not already set.
|
||||
@ -443,7 +443,18 @@ func (csm *connectivityStateManager) getNotifyChan() <-chan struct{} {
|
||||
return csm.notifyChan
|
||||
}
|
||||
|
||||
// ClientConn represents a client connection to an RPC server.
|
||||
// ClientConn represents a virtual connection to a conceptual endpoint, to
|
||||
// perform RPCs.
|
||||
//
|
||||
// A ClientConn is free to have zero or more actual connections to the endpoint
|
||||
// based on configuration, load, etc. It is also free to determine which actual
|
||||
// endpoints to use and may change it every RPC, permitting client-side load
|
||||
// balancing.
|
||||
//
|
||||
// A ClientConn encapsulates a range of functionality including name
|
||||
// resolution, TCP connection establishment (with retries and backoff) and TLS
|
||||
// handshakes. It also handles errors on established connections by
|
||||
// re-resolving the name and reconnecting.
|
||||
type ClientConn struct {
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
@ -532,58 +543,104 @@ func (cc *ClientConn) waitForResolvedAddrs(ctx context.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
func (cc *ClientConn) updateResolverState(s resolver.State) error {
|
||||
var emptyServiceConfig *ServiceConfig
|
||||
|
||||
func init() {
|
||||
cfg := parseServiceConfig("{}")
|
||||
if cfg.Err != nil {
|
||||
panic(fmt.Sprintf("impossible error parsing empty service config: %v", cfg.Err))
|
||||
}
|
||||
emptyServiceConfig = cfg.Config.(*ServiceConfig)
|
||||
}
|
||||
|
||||
func (cc *ClientConn) maybeApplyDefaultServiceConfig(addrs []resolver.Address) {
|
||||
if cc.sc != nil {
|
||||
cc.applyServiceConfigAndBalancer(cc.sc, addrs)
|
||||
return
|
||||
}
|
||||
if cc.dopts.defaultServiceConfig != nil {
|
||||
cc.applyServiceConfigAndBalancer(cc.dopts.defaultServiceConfig, addrs)
|
||||
} else {
|
||||
cc.applyServiceConfigAndBalancer(emptyServiceConfig, addrs)
|
||||
}
|
||||
}
|
||||
|
||||
func (cc *ClientConn) updateResolverState(s resolver.State, err error) error {
|
||||
defer cc.firstResolveEvent.Fire()
|
||||
cc.mu.Lock()
|
||||
defer cc.mu.Unlock()
|
||||
// Check if the ClientConn is already closed. Some fields (e.g.
|
||||
// balancerWrapper) are set to nil when closing the ClientConn, and could
|
||||
// cause nil pointer panic if we don't have this check.
|
||||
if cc.conns == nil {
|
||||
cc.mu.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
if cc.dopts.disableServiceConfig || s.ServiceConfig == nil {
|
||||
if cc.dopts.defaultServiceConfig != nil && cc.sc == nil {
|
||||
cc.applyServiceConfig(cc.dopts.defaultServiceConfig)
|
||||
if err != nil {
|
||||
// May need to apply the initial service config in case the resolver
|
||||
// doesn't support service configs, or doesn't provide a service config
|
||||
// with the new addresses.
|
||||
cc.maybeApplyDefaultServiceConfig(nil)
|
||||
|
||||
if cc.balancerWrapper != nil {
|
||||
cc.balancerWrapper.resolverError(err)
|
||||
}
|
||||
|
||||
// No addresses are valid with err set; return early.
|
||||
cc.mu.Unlock()
|
||||
return balancer.ErrBadResolverState
|
||||
}
|
||||
|
||||
var ret error
|
||||
if cc.dopts.disableServiceConfig || s.ServiceConfig == nil {
|
||||
cc.maybeApplyDefaultServiceConfig(s.Addresses)
|
||||
// TODO: do we need to apply a failing LB policy if there is no
|
||||
// default, per the error handling design?
|
||||
} else {
|
||||
if sc, ok := s.ServiceConfig.Config.(*ServiceConfig); s.ServiceConfig.Err == nil && ok {
|
||||
cc.applyServiceConfigAndBalancer(sc, s.Addresses)
|
||||
} else {
|
||||
ret = balancer.ErrBadResolverState
|
||||
if cc.balancerWrapper == nil {
|
||||
var err error
|
||||
if s.ServiceConfig.Err != nil {
|
||||
err = status.Errorf(codes.Unavailable, "error parsing service config: %v", s.ServiceConfig.Err)
|
||||
} else {
|
||||
err = status.Errorf(codes.Unavailable, "illegal service config type: %T", s.ServiceConfig.Config)
|
||||
}
|
||||
cc.blockingpicker.updatePicker(base.NewErrPicker(err))
|
||||
cc.csMgr.updateState(connectivity.TransientFailure)
|
||||
cc.mu.Unlock()
|
||||
return ret
|
||||
}
|
||||
}
|
||||
} else if sc, ok := s.ServiceConfig.(*ServiceConfig); ok {
|
||||
cc.applyServiceConfig(sc)
|
||||
}
|
||||
|
||||
var balCfg serviceconfig.LoadBalancingConfig
|
||||
if cc.dopts.balancerBuilder == nil {
|
||||
// Only look at balancer types and switch balancer if balancer dial
|
||||
// option is not set.
|
||||
var newBalancerName string
|
||||
if cc.sc != nil && cc.sc.lbConfig != nil {
|
||||
newBalancerName = cc.sc.lbConfig.name
|
||||
balCfg = cc.sc.lbConfig.cfg
|
||||
} else {
|
||||
var isGRPCLB bool
|
||||
for _, a := range s.Addresses {
|
||||
if a.Type == resolver.GRPCLB {
|
||||
isGRPCLB = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if isGRPCLB {
|
||||
newBalancerName = grpclbName
|
||||
} else if cc.sc != nil && cc.sc.LB != nil {
|
||||
newBalancerName = *cc.sc.LB
|
||||
} else {
|
||||
newBalancerName = PickFirstBalancerName
|
||||
}
|
||||
}
|
||||
cc.switchBalancer(newBalancerName)
|
||||
} else if cc.balancerWrapper == nil {
|
||||
// Balancer dial option was set, and this is the first time handling
|
||||
// resolved addresses. Build a balancer with dopts.balancerBuilder.
|
||||
cc.curBalancerName = cc.dopts.balancerBuilder.Name()
|
||||
cc.balancerWrapper = newCCBalancerWrapper(cc, cc.dopts.balancerBuilder, cc.balancerBuildOpts)
|
||||
if cc.dopts.balancerBuilder == nil && cc.sc != nil && cc.sc.lbConfig != nil {
|
||||
balCfg = cc.sc.lbConfig.cfg
|
||||
}
|
||||
|
||||
cc.balancerWrapper.updateClientConnState(&balancer.ClientConnState{ResolverState: s, BalancerConfig: balCfg})
|
||||
return nil
|
||||
cbn := cc.curBalancerName
|
||||
bw := cc.balancerWrapper
|
||||
cc.mu.Unlock()
|
||||
if cbn != grpclbName {
|
||||
// Filter any grpclb addresses since we don't have the grpclb balancer.
|
||||
for i := 0; i < len(s.Addresses); {
|
||||
if s.Addresses[i].Type == resolver.GRPCLB {
|
||||
copy(s.Addresses[i:], s.Addresses[i+1:])
|
||||
s.Addresses = s.Addresses[:len(s.Addresses)-1]
|
||||
continue
|
||||
}
|
||||
i++
|
||||
}
|
||||
}
|
||||
uccsErr := bw.updateClientConnState(&balancer.ClientConnState{ResolverState: s, BalancerConfig: balCfg})
|
||||
if ret == nil {
|
||||
ret = uccsErr // prefer ErrBadResolver state since any other error is
|
||||
// currently meaningless to the caller.
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// switchBalancer starts the switching from current balancer to the balancer
|
||||
@ -631,7 +688,7 @@ func (cc *ClientConn) switchBalancer(name string) {
|
||||
cc.balancerWrapper = newCCBalancerWrapper(cc, builder, cc.balancerBuildOpts)
|
||||
}
|
||||
|
||||
func (cc *ClientConn) handleSubConnStateChange(sc balancer.SubConn, s connectivity.State) {
|
||||
func (cc *ClientConn) handleSubConnStateChange(sc balancer.SubConn, s connectivity.State, err error) {
|
||||
cc.mu.Lock()
|
||||
if cc.conns == nil {
|
||||
cc.mu.Unlock()
|
||||
@ -639,7 +696,7 @@ func (cc *ClientConn) handleSubConnStateChange(sc balancer.SubConn, s connectivi
|
||||
}
|
||||
// TODO(bar switching) send updates to all balancer wrappers when balancer
|
||||
// gracefully switching is supported.
|
||||
cc.balancerWrapper.handleSubConnStateChange(sc, s)
|
||||
cc.balancerWrapper.handleSubConnStateChange(sc, s, err)
|
||||
cc.mu.Unlock()
|
||||
}
|
||||
|
||||
@ -736,7 +793,7 @@ func (ac *addrConn) connect() error {
|
||||
}
|
||||
// Update connectivity state within the lock to prevent subsequent or
|
||||
// concurrent calls from resetting the transport more than once.
|
||||
ac.updateConnectivityState(connectivity.Connecting)
|
||||
ac.updateConnectivityState(connectivity.Connecting, nil)
|
||||
ac.mu.Unlock()
|
||||
|
||||
// Start a goroutine connecting to the server asynchronously.
|
||||
@ -822,7 +879,8 @@ func (cc *ClientConn) healthCheckConfig() *healthCheckConfig {
|
||||
}
|
||||
|
||||
func (cc *ClientConn) getTransport(ctx context.Context, failfast bool, method string) (transport.ClientTransport, func(balancer.DoneInfo), error) {
|
||||
t, done, err := cc.blockingpicker.pick(ctx, failfast, balancer.PickOptions{
|
||||
t, done, err := cc.blockingpicker.pick(ctx, failfast, balancer.PickInfo{
|
||||
Ctx: ctx,
|
||||
FullMethodName: method,
|
||||
})
|
||||
if err != nil {
|
||||
@ -831,10 +889,10 @@ func (cc *ClientConn) getTransport(ctx context.Context, failfast bool, method st
|
||||
return t, done, nil
|
||||
}
|
||||
|
||||
func (cc *ClientConn) applyServiceConfig(sc *ServiceConfig) error {
|
||||
func (cc *ClientConn) applyServiceConfigAndBalancer(sc *ServiceConfig, addrs []resolver.Address) {
|
||||
if sc == nil {
|
||||
// should never reach here.
|
||||
return fmt.Errorf("got nil pointer for service config")
|
||||
return
|
||||
}
|
||||
cc.sc = sc
|
||||
|
||||
@ -850,10 +908,38 @@ func (cc *ClientConn) applyServiceConfig(sc *ServiceConfig) error {
|
||||
cc.retryThrottler.Store((*retryThrottler)(nil))
|
||||
}
|
||||
|
||||
return nil
|
||||
if cc.dopts.balancerBuilder == nil {
|
||||
// Only look at balancer types and switch balancer if balancer dial
|
||||
// option is not set.
|
||||
var newBalancerName string
|
||||
if cc.sc != nil && cc.sc.lbConfig != nil {
|
||||
newBalancerName = cc.sc.lbConfig.name
|
||||
} else {
|
||||
var isGRPCLB bool
|
||||
for _, a := range addrs {
|
||||
if a.Type == resolver.GRPCLB {
|
||||
isGRPCLB = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if isGRPCLB {
|
||||
newBalancerName = grpclbName
|
||||
} else if cc.sc != nil && cc.sc.LB != nil {
|
||||
newBalancerName = *cc.sc.LB
|
||||
} else {
|
||||
newBalancerName = PickFirstBalancerName
|
||||
}
|
||||
}
|
||||
cc.switchBalancer(newBalancerName)
|
||||
} else if cc.balancerWrapper == nil {
|
||||
// Balancer dial option was set, and this is the first time handling
|
||||
// resolved addresses. Build a balancer with dopts.balancerBuilder.
|
||||
cc.curBalancerName = cc.dopts.balancerBuilder.Name()
|
||||
cc.balancerWrapper = newCCBalancerWrapper(cc, cc.dopts.balancerBuilder, cc.balancerBuildOpts)
|
||||
}
|
||||
}
|
||||
|
||||
func (cc *ClientConn) resolveNow(o resolver.ResolveNowOption) {
|
||||
func (cc *ClientConn) resolveNow(o resolver.ResolveNowOptions) {
|
||||
cc.mu.RLock()
|
||||
r := cc.resolverWrapper
|
||||
cc.mu.RUnlock()
|
||||
@ -875,8 +961,9 @@ func (cc *ClientConn) resolveNow(o resolver.ResolveNowOption) {
|
||||
// This API is EXPERIMENTAL.
|
||||
func (cc *ClientConn) ResetConnectBackoff() {
|
||||
cc.mu.Lock()
|
||||
defer cc.mu.Unlock()
|
||||
for ac := range cc.conns {
|
||||
conns := cc.conns
|
||||
cc.mu.Unlock()
|
||||
for ac := range conns {
|
||||
ac.resetConnectBackoff()
|
||||
}
|
||||
}
|
||||
@ -962,7 +1049,7 @@ type addrConn struct {
|
||||
}
|
||||
|
||||
// Note: this requires a lock on ac.mu.
|
||||
func (ac *addrConn) updateConnectivityState(s connectivity.State) {
|
||||
func (ac *addrConn) updateConnectivityState(s connectivity.State, lastErr error) {
|
||||
if ac.state == s {
|
||||
return
|
||||
}
|
||||
@ -975,7 +1062,7 @@ func (ac *addrConn) updateConnectivityState(s connectivity.State) {
|
||||
Severity: channelz.CtINFO,
|
||||
})
|
||||
}
|
||||
ac.cc.handleSubConnStateChange(ac.acbw, s)
|
||||
ac.cc.handleSubConnStateChange(ac.acbw, s, lastErr)
|
||||
}
|
||||
|
||||
// adjustParams updates parameters used to create transports upon
|
||||
@ -995,7 +1082,7 @@ func (ac *addrConn) adjustParams(r transport.GoAwayReason) {
|
||||
func (ac *addrConn) resetTransport() {
|
||||
for i := 0; ; i++ {
|
||||
if i > 0 {
|
||||
ac.cc.resolveNow(resolver.ResolveNowOption{})
|
||||
ac.cc.resolveNow(resolver.ResolveNowOptions{})
|
||||
}
|
||||
|
||||
ac.mu.Lock()
|
||||
@ -1024,7 +1111,7 @@ func (ac *addrConn) resetTransport() {
|
||||
// https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md#proposed-backoff-algorithm
|
||||
connectDeadline := time.Now().Add(dialDuration)
|
||||
|
||||
ac.updateConnectivityState(connectivity.Connecting)
|
||||
ac.updateConnectivityState(connectivity.Connecting, nil)
|
||||
ac.transport = nil
|
||||
ac.mu.Unlock()
|
||||
|
||||
@ -1037,7 +1124,7 @@ func (ac *addrConn) resetTransport() {
|
||||
ac.mu.Unlock()
|
||||
return
|
||||
}
|
||||
ac.updateConnectivityState(connectivity.TransientFailure)
|
||||
ac.updateConnectivityState(connectivity.TransientFailure, err)
|
||||
|
||||
// Backoff.
|
||||
b := ac.resetBackoff
|
||||
@ -1093,6 +1180,7 @@ func (ac *addrConn) resetTransport() {
|
||||
// first successful one. It returns the transport, the address and a Event in
|
||||
// the successful case. The Event fires when the returned transport disconnects.
|
||||
func (ac *addrConn) tryAllAddrs(addrs []resolver.Address, connectDeadline time.Time) (transport.ClientTransport, resolver.Address, *grpcsync.Event, error) {
|
||||
var firstConnErr error
|
||||
for _, addr := range addrs {
|
||||
ac.mu.Lock()
|
||||
if ac.state == connectivity.Shutdown {
|
||||
@ -1121,11 +1209,14 @@ func (ac *addrConn) tryAllAddrs(addrs []resolver.Address, connectDeadline time.T
|
||||
if err == nil {
|
||||
return newTr, addr, reconnect, nil
|
||||
}
|
||||
if firstConnErr == nil {
|
||||
firstConnErr = err
|
||||
}
|
||||
ac.cc.blockingpicker.updateConnectionError(err)
|
||||
}
|
||||
|
||||
// Couldn't connect to any address.
|
||||
return nil, resolver.Address{}, nil, fmt.Errorf("couldn't connect to any address")
|
||||
return nil, resolver.Address{}, nil, firstConnErr
|
||||
}
|
||||
|
||||
// createTransport creates a connection to addr. It returns the transport and a
|
||||
@ -1136,10 +1227,16 @@ func (ac *addrConn) createTransport(addr resolver.Address, copts transport.Conne
|
||||
onCloseCalled := make(chan struct{})
|
||||
reconnect := grpcsync.NewEvent()
|
||||
|
||||
authority := ac.cc.authority
|
||||
// addr.ServerName takes precedent over ClientConn authority, if present.
|
||||
if addr.ServerName != "" {
|
||||
authority = addr.ServerName
|
||||
}
|
||||
|
||||
target := transport.TargetInfo{
|
||||
Addr: addr.Addr,
|
||||
Metadata: addr.Metadata,
|
||||
Authority: ac.cc.authority,
|
||||
Authority: authority,
|
||||
}
|
||||
|
||||
once := sync.Once{}
|
||||
@ -1152,7 +1249,7 @@ func (ac *addrConn) createTransport(addr resolver.Address, copts transport.Conne
|
||||
// state to Connecting.
|
||||
//
|
||||
// TODO: this should be Idle when grpc-go properly supports it.
|
||||
ac.updateConnectivityState(connectivity.Connecting)
|
||||
ac.updateConnectivityState(connectivity.Connecting, nil)
|
||||
}
|
||||
})
|
||||
ac.mu.Unlock()
|
||||
@ -1167,7 +1264,7 @@ func (ac *addrConn) createTransport(addr resolver.Address, copts transport.Conne
|
||||
// state to Connecting.
|
||||
//
|
||||
// TODO: this should be Idle when grpc-go properly supports it.
|
||||
ac.updateConnectivityState(connectivity.Connecting)
|
||||
ac.updateConnectivityState(connectivity.Connecting, nil)
|
||||
}
|
||||
})
|
||||
ac.mu.Unlock()
|
||||
@ -1193,7 +1290,7 @@ func (ac *addrConn) createTransport(addr resolver.Address, copts transport.Conne
|
||||
}
|
||||
|
||||
select {
|
||||
case <-time.After(connectDeadline.Sub(time.Now())):
|
||||
case <-time.After(time.Until(connectDeadline)):
|
||||
// We didn't get the preface in time.
|
||||
newTr.Close()
|
||||
grpclog.Warningf("grpc: addrConn.createTransport failed to connect to %v: didn't receive server preface in time. Reconnecting...", addr)
|
||||
@ -1224,7 +1321,7 @@ func (ac *addrConn) startHealthCheck(ctx context.Context) {
|
||||
var healthcheckManagingState bool
|
||||
defer func() {
|
||||
if !healthcheckManagingState {
|
||||
ac.updateConnectivityState(connectivity.Ready)
|
||||
ac.updateConnectivityState(connectivity.Ready, nil)
|
||||
}
|
||||
}()
|
||||
|
||||
@ -1260,13 +1357,13 @@ func (ac *addrConn) startHealthCheck(ctx context.Context) {
|
||||
ac.mu.Unlock()
|
||||
return newNonRetryClientStream(ctx, &StreamDesc{ServerStreams: true}, method, currentTr, ac)
|
||||
}
|
||||
setConnectivityState := func(s connectivity.State) {
|
||||
setConnectivityState := func(s connectivity.State, lastErr error) {
|
||||
ac.mu.Lock()
|
||||
defer ac.mu.Unlock()
|
||||
if ac.transport != currentTr {
|
||||
return
|
||||
}
|
||||
ac.updateConnectivityState(s)
|
||||
ac.updateConnectivityState(s, lastErr)
|
||||
}
|
||||
// Start the health checking stream.
|
||||
go func() {
|
||||
@ -1331,8 +1428,8 @@ func (ac *addrConn) tearDown(err error) {
|
||||
curTr := ac.transport
|
||||
ac.transport = nil
|
||||
// We have to set the state to Shutdown before anything else to prevent races
|
||||
// between setting the state and logic that waits on context cancelation / etc.
|
||||
ac.updateConnectivityState(connectivity.Shutdown)
|
||||
// between setting the state and logic that waits on context cancellation / etc.
|
||||
ac.updateConnectivityState(connectivity.Shutdown, nil)
|
||||
ac.cancel()
|
||||
ac.curAddr = resolver.Address{}
|
||||
if err == errConnDrain && curTr != nil {
|
||||
@ -1355,7 +1452,7 @@ func (ac *addrConn) tearDown(err error) {
|
||||
},
|
||||
})
|
||||
// TraceEvent needs to be called before RemoveEntry, as TraceEvent may add trace reference to
|
||||
// the entity beng deleted, and thus prevent it from being deleted right away.
|
||||
// the entity being deleted, and thus prevent it from being deleted right away.
|
||||
channelz.RemoveEntry(ac.channelzID)
|
||||
}
|
||||
ac.mu.Unlock()
|
||||
|
Reference in New Issue
Block a user