exitIdleMode moves the channel out of idle mode by recreating the name resolver and load balancer. This should never be called directly; use cc.idlenessMgr.ExitIdleMode instead.
()
| 392 | // resolver and load balancer. This should never be called directly; use |
| 393 | // cc.idlenessMgr.ExitIdleMode instead. |
| 394 | func (cc *ClientConn) exitIdleMode() error { |
| 395 | cc.mu.Lock() |
| 396 | if cc.conns == nil { |
| 397 | cc.mu.Unlock() |
| 398 | return errConnClosing |
| 399 | } |
| 400 | cc.mu.Unlock() |
| 401 | |
| 402 | // Set state to CONNECTING before building the name resolver |
| 403 | // so the channel does not remain in IDLE. |
| 404 | cc.csMgr.updateState(connectivity.Connecting) |
| 405 | |
| 406 | // This needs to be called without cc.mu because this builds a new resolver |
| 407 | // which might update state or report error inline, which would then need to |
| 408 | // acquire cc.mu. |
| 409 | if err := cc.resolverWrapper.start(); err != nil { |
| 410 | // If resolver creation fails, treat it like an error reported by the |
| 411 | // resolver before any valid updates. Set channel's state to |
| 412 | // TransientFailure, and set an erroring picker with the resolver build |
| 413 | // error, which will returned as part of any subsequent RPCs. |
| 414 | logger.Warningf("Failed to start resolver: %v", err) |
| 415 | cc.csMgr.updateState(connectivity.TransientFailure) |
| 416 | cc.mu.Lock() |
| 417 | cc.updateResolverStateAndUnlock(resolver.State{}, err) |
| 418 | return fmt.Errorf("failed to start resolver: %w", err) |
| 419 | } |
| 420 | |
| 421 | cc.addTraceEvent("exiting idle mode") |
| 422 | return nil |
| 423 | } |
| 424 | |
| 425 | // initIdleStateLocked initializes common state to how it should be while idle. |
| 426 | func (cc *ClientConn) initIdleStateLocked() { |
no test coverage detected