updateClientConnState is invoked by grpc to push a ClientConnState update to the underlying balancer. This is always executed from the serializer, so it is safe to call into the balancer here.
(ccs *balancer.ClientConnState)
| 109 | // the underlying balancer. This is always executed from the serializer, so |
| 110 | // it is safe to call into the balancer here. |
| 111 | func (ccb *ccBalancerWrapper) updateClientConnState(ccs *balancer.ClientConnState) error { |
| 112 | errCh := make(chan error) |
| 113 | uccs := func(ctx context.Context) { |
| 114 | defer close(errCh) |
| 115 | if ctx.Err() != nil || ccb.balancer == nil { |
| 116 | return |
| 117 | } |
| 118 | name := gracefulswitch.ChildName(ccs.BalancerConfig) |
| 119 | if ccb.curBalancerName != name { |
| 120 | ccb.curBalancerName = name |
| 121 | channelz.Infof(logger, ccb.cc.channelz, "Channel switches to new LB policy %q", name) |
| 122 | } |
| 123 | err := ccb.balancer.UpdateClientConnState(*ccs) |
| 124 | if logger.V(2) && err != nil { |
| 125 | logger.Infof("error from balancer.UpdateClientConnState: %v", err) |
| 126 | } |
| 127 | errCh <- err |
| 128 | } |
| 129 | onFailure := func() { close(errCh) } |
| 130 | |
| 131 | // UpdateClientConnState can race with Close, and when the latter wins, the |
| 132 | // serializer is closed, and the attempt to schedule the callback will fail. |
| 133 | // It is acceptable to ignore this failure. But since we want to handle the |
| 134 | // state update in a blocking fashion (when we successfully schedule the |
| 135 | // callback), we have to use the ScheduleOr method and not the MaybeSchedule |
| 136 | // method on the serializer. |
| 137 | ccb.serializer.ScheduleOr(uccs, onFailure) |
| 138 | return <-errCh |
| 139 | } |
| 140 | |
| 141 | // resolverError is invoked by grpc to push a resolver error to the underlying |
| 142 | // balancer. The call to the balancer is executed from the serializer. |
no test coverage detected