MCPcopy
hub / github.com/grpc/grpc-go / pick

Method pick

picker_wrapper.go:105–203  ·  view source on GitHub ↗

pick returns the transport that will be used for the RPC. It may block in the following cases: - there's no picker - the current picker returns ErrNoSubConnAvailable - the current picker returns other errors and failfast is false. - the subConn returned by the current picker is not READY When one of

(ctx context.Context, failfast bool, info balancer.PickInfo)

Source from the content-addressed store, hash-verified

103// - the subConn returned by the current picker is not READY
104// When one of these situations happens, pick blocks until the picker gets updated.
105func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.PickInfo) (pick, error) {
106 var ch chan struct{}
107
108 var lastPickErr error
109 pickBlocked := false
110
111 for {
112 pg := pw.pickerGen.Load()
113 if pg == nil {
114 return pick{}, ErrClientConnClosing
115 }
116 if pg.picker == nil {
117 ch = pg.blockingCh
118 }
119 if ch == pg.blockingCh {
120 // This could happen when either:
121 // - pw.picker is nil (the previous if condition), or
122 // - we have already called pick on the current picker.
123 select {
124 case <-ctx.Done():
125 var errStr string
126 if lastPickErr != nil {
127 errStr = "latest balancer error: " + lastPickErr.Error()
128 } else {
129 errStr = fmt.Sprintf("%v while waiting for connections to become ready", ctx.Err())
130 }
131 switch ctx.Err() {
132 case context.DeadlineExceeded:
133 return pick{}, status.Error(codes.DeadlineExceeded, errStr)
134 case context.Canceled:
135 return pick{}, status.Error(codes.Canceled, errStr)
136 }
137 case <-ch:
138 }
139 continue
140 }
141
142 // If the channel is set, it means that the pick call had to wait for a
143 // new picker at some point. Either it's the first iteration and this
144 // function received the first picker, or a picker errored with
145 // ErrNoSubConnAvailable or errored with failfast set to false, which
146 // will trigger a continue to the next iteration. In the first case this
147 // conditional will hit if this call had to block (the channel is set).
148 // In the second case, the only way it will get to this conditional is
149 // if there is a new picker.
150 if ch != nil {
151 pickBlocked = true
152 }
153
154 ch = pg.blockingCh
155 p := pg.picker
156
157 pickResult, err := p.Pick(info)
158 if err != nil {
159 if err == balancer.ErrNoSubConnAvailable {
160 continue
161 }
162 if st, ok := status.FromError(err); ok {

Callers

nothing calls this directly

Calls 14

ErrorFunction · 0.92
FromErrorFunction · 0.92
ErrorfFunction · 0.92
IsOnFunction · 0.92
doneChannelzWrapperFunction · 0.85
ErrMethod · 0.80
getReadyTransportMethod · 0.80
ErrorMethod · 0.65
PickMethod · 0.65
ErrorfMethod · 0.65
VMethod · 0.65
InfofMethod · 0.65

Tested by

no test coverage detected