delegateToChildPoliciesLocked is a helper function which iterates through the list of child policy wrappers in a cache entry and attempts to find a child policy to which this RPC can be routed to. If all child policies are in TRANSIENT_FAILURE, we delegate to the last child policy arbitrarily. Retur
(dcEntry *cacheEntry, info balancer.PickInfo)
| 185 | // TRANSIENT_FAILURE, we delegate to the last child policy arbitrarily. Returns |
| 186 | // a function to be invoked to record metrics. |
| 187 | func (p *rlsPicker) delegateToChildPoliciesLocked(dcEntry *cacheEntry, info balancer.PickInfo) (balancer.PickResult, func(), error) { |
| 188 | const rlsDataHeaderName = "x-google-rls-data" |
| 189 | for i, cpw := range dcEntry.childPolicyWrappers { |
| 190 | state := (*balancer.State)(atomic.LoadPointer(&cpw.state)) |
| 191 | // Delegate to the child policy if it is not in TRANSIENT_FAILURE, or if |
| 192 | // it is the last one (which handles the case of delegating to the last |
| 193 | // child picker if all child policies are in TRANSIENT_FAILURE). |
| 194 | if state.ConnectivityState != connectivity.TransientFailure || i == len(dcEntry.childPolicyWrappers)-1 { |
| 195 | // Any header data received from the RLS server is stored in the |
| 196 | // cache entry and needs to be sent to the actual backend in the |
| 197 | // X-Google-RLS-Data header. |
| 198 | res, err := state.Picker.Pick(info) |
| 199 | if err != nil { |
| 200 | pr := errToPickResult(err) |
| 201 | customLabel := estats.CustomLabelFromContext(info.Ctx) |
| 202 | return res, func() { |
| 203 | if pr == "queue" { |
| 204 | // Don't record metrics for queued Picks. |
| 205 | return |
| 206 | } |
| 207 | targetPicksMetric.Record(p.metricsRecorder, 1, p.grpcTarget, p.rlsServerTarget, cpw.target, pr, customLabel) |
| 208 | }, err |
| 209 | } |
| 210 | |
| 211 | if res.Metadata == nil { |
| 212 | res.Metadata = metadata.Pairs(rlsDataHeaderName, dcEntry.headerData) |
| 213 | } else { |
| 214 | res.Metadata.Append(rlsDataHeaderName, dcEntry.headerData) |
| 215 | } |
| 216 | return res, func() { |
| 217 | customLabel := estats.CustomLabelFromContext(info.Ctx) |
| 218 | targetPicksMetric.Record(p.metricsRecorder, 1, p.grpcTarget, p.rlsServerTarget, cpw.target, "complete", customLabel) |
| 219 | }, nil |
| 220 | } |
| 221 | } |
| 222 | |
| 223 | // In the unlikely event that we have a cache entry with no targets, we end up |
| 224 | // queueing the RPC. |
| 225 | return balancer.PickResult{}, func() {}, balancer.ErrNoSubConnAvailable |
| 226 | } |
| 227 | |
| 228 | // useDefaultPickIfPossible is a helper method which delegates to the default |
| 229 | // target if one is configured, or fails the pick with the given error. Returns |