client: in UpdateBalancerState, update picker before connectivity state (#2431)

In very rare cases, we could start an RPC before the picker had been updated to
one that would return a valid SubConn.  This is not a problem as the new picker
will be called again as soon as it is updated, but it can lead to test flakes
that depend upon the picker not being called before being ready.
This commit is contained in:
Doug Fawley 2018-11-02 10:27:41 -07:00 коммит произвёл GitHub
Родитель 761a6b364c
Коммит 8f2842d4f0
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
2 изменённых файлов: 7 добавлений и 2 удалений

Просмотреть файл

@ -229,8 +229,13 @@ func (ccb *ccBalancerWrapper) UpdateBalancerState(s connectivity.State, p balanc
if ccb.subConns == nil {
return
}
ccb.cc.csMgr.updateState(s)
// Update picker before updating state. Even though the ordering here does
// not matter, it can lead to multiple calls of Pick in the common start-up
// case where we wait for ready and then perform an RPC. If the picker is
// updated later, we could call the "connecting" picker when the state is
// updated, and then call the "ready" picker after the picker gets updated.
ccb.cc.blockingpicker.updatePicker(p)
ccb.cc.csMgr.updateState(s)
}
func (ccb *ccBalancerWrapper) ResolveNow(o resolver.ResolveNowOption) {

Просмотреть файл

@ -68,7 +68,7 @@ func (b *testBalancer) HandleResolvedAddrs(addrs []resolver.Address, err error)
grpclog.Errorf("testBalancer: failed to NewSubConn: %v", err)
return
}
b.cc.UpdateBalancerState(connectivity.Idle, &picker{sc: b.sc, bal: b})
b.cc.UpdateBalancerState(connectivity.Connecting, &picker{sc: b.sc, bal: b})
b.sc.Connect()
}
}