core: remember last pick status in no real stream (#11851) · grpc/grpc-java@7585b16
@@ -129,8 +129,9 @@ public final ClientStream newStream(
129129if (state.shutdownStatus != null) {
130130return new FailingClientStream(state.shutdownStatus, tracers);
131131 }
132+PickResult pickResult = null;
132133if (state.lastPicker != null) {
133-PickResult pickResult = state.lastPicker.pickSubchannel(args);
134+pickResult = state.lastPicker.pickSubchannel(args);
134135callOptions = args.getCallOptions();
135136// User code provided authority takes precedence over the LB provided one.
136137if (callOptions.getAuthority() == null
@@ -156,7 +157,7 @@ public final ClientStream newStream(
156157synchronized (lock) {
157158PickerState newerState = pickerState;
158159if (state == newerState) {
159-return createPendingStream(args, tracers);
160+return createPendingStream(args, tracers, pickResult);
160161 }
161162state = newerState;
162163 }
@@ -171,9 +172,12 @@ public final ClientStream newStream(
171172 * schedule tasks on syncContext.
172173 */
173174@GuardedBy("lock")
174-private PendingStream createPendingStream(
175-PickSubchannelArgs args, ClientStreamTracer[] tracers) {
175+private PendingStream createPendingStream(PickSubchannelArgs args, ClientStreamTracer[] tracers,
176+PickResult pickResult) {
176177PendingStream pendingStream = new PendingStream(args, tracers);
178+if (args.getCallOptions().isWaitForReady() && pickResult != null && pickResult.hasResult()) {
179+pendingStream.lastPickStatus = pickResult.getStatus();
180+ }
177181pendingStreams.add(pendingStream);
178182if (getPendingStreamsCount() == 1) {
179183syncContext.executeLater(reportTransportInUse);
@@ -293,6 +297,9 @@ final void reprocess(@Nullable SubchannelPicker picker) {
293297for (final PendingStream stream : toProcess) {
294298PickResult pickResult = picker.pickSubchannel(stream.args);
295299CallOptions callOptions = stream.args.getCallOptions();
300+if (callOptions.isWaitForReady() && pickResult.hasResult()) {
301+stream.lastPickStatus = pickResult.getStatus();
302+ }
296303final ClientTransport transport = GrpcUtil.getTransportFromPickResult(pickResult,
297304callOptions.isWaitForReady());
298305if (transport != null) {
@@ -349,6 +356,7 @@ private class PendingStream extends DelayedStream {
349356private final PickSubchannelArgs args;
350357private final Context context = Context.current();
351358private final ClientStreamTracer[] tracers;
359+private volatile Status lastPickStatus;
352360353361private PendingStream(PickSubchannelArgs args, ClientStreamTracer[] tracers) {
354362this.args = args;
@@ -405,6 +413,10 @@ protected void onEarlyCancellation(Status reason) {
405413public void appendTimeoutInsight(InsightBuilder insight) {
406414if (args.getCallOptions().isWaitForReady()) {
407415insight.append("wait_for_ready");
416+Status status = lastPickStatus;
417+if (status != null && !status.isOk()) {
418+insight.appendKeyValue("Last Pick Failure", status);
419+ }
408420 }
409421super.appendTimeoutInsight(insight);
410422 }