core: remember last pick status in no real stream (#11851)

This commit is contained in:
MV Shiva 2025-02-14 11:38:06 +05:30 committed by GitHub
parent 122b683717
commit 7585b1607d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 33 additions and 4 deletions

View File

@ -129,8 +129,9 @@ final class DelayedClientTransport implements ManagedClientTransport {
if (state.shutdownStatus != null) {
return new FailingClientStream(state.shutdownStatus, tracers);
}
PickResult pickResult = null;
if (state.lastPicker != null) {
PickResult pickResult = state.lastPicker.pickSubchannel(args);
pickResult = state.lastPicker.pickSubchannel(args);
callOptions = args.getCallOptions();
// User code provided authority takes precedence over the LB provided one.
if (callOptions.getAuthority() == null
@ -156,7 +157,7 @@ final class DelayedClientTransport implements ManagedClientTransport {
synchronized (lock) {
PickerState newerState = pickerState;
if (state == newerState) {
return createPendingStream(args, tracers);
return createPendingStream(args, tracers, pickResult);
}
state = newerState;
}
@ -171,9 +172,12 @@ final class DelayedClientTransport implements ManagedClientTransport {
* schedule tasks on syncContext.
*/
@GuardedBy("lock")
private PendingStream createPendingStream(
PickSubchannelArgs args, ClientStreamTracer[] tracers) {
private PendingStream createPendingStream(PickSubchannelArgs args, ClientStreamTracer[] tracers,
PickResult pickResult) {
PendingStream pendingStream = new PendingStream(args, tracers);
if (args.getCallOptions().isWaitForReady() && pickResult != null && pickResult.hasResult()) {
pendingStream.lastPickStatus = pickResult.getStatus();
}
pendingStreams.add(pendingStream);
if (getPendingStreamsCount() == 1) {
syncContext.executeLater(reportTransportInUse);
@ -293,6 +297,9 @@ final class DelayedClientTransport implements ManagedClientTransport {
for (final PendingStream stream : toProcess) {
PickResult pickResult = picker.pickSubchannel(stream.args);
CallOptions callOptions = stream.args.getCallOptions();
if (callOptions.isWaitForReady() && pickResult.hasResult()) {
stream.lastPickStatus = pickResult.getStatus();
}
final ClientTransport transport = GrpcUtil.getTransportFromPickResult(pickResult,
callOptions.isWaitForReady());
if (transport != null) {
@ -349,6 +356,7 @@ final class DelayedClientTransport implements ManagedClientTransport {
private final PickSubchannelArgs args;
private final Context context = Context.current();
private final ClientStreamTracer[] tracers;
private volatile Status lastPickStatus;
private PendingStream(PickSubchannelArgs args, ClientStreamTracer[] tracers) {
this.args = args;
@ -405,6 +413,10 @@ final class DelayedClientTransport implements ManagedClientTransport {
public void appendTimeoutInsight(InsightBuilder insight) {
if (args.getCallOptions().isWaitForReady()) {
insight.append("wait_for_ready");
Status status = lastPickStatus;
if (status != null && !status.isOk()) {
insight.appendKeyValue("Last Pick Failure", status);
}
}
super.appendTimeoutInsight(insight);
}

View File

@ -745,6 +745,23 @@ public class DelayedClientTransportTest {
.matches("\\[wait_for_ready, buffered_nanos=[0-9]+\\, waiting_for_connection]");
}
@Test
public void pendingStream_appendTimeoutInsight_waitForReady_withLastPickFailure() {
ClientStream stream = delayedTransport.newStream(
method, headers, callOptions.withWaitForReady(), tracers);
stream.start(streamListener);
SubchannelPicker picker = mock(SubchannelPicker.class);
when(picker.pickSubchannel(any(PickSubchannelArgs.class)))
.thenReturn(PickResult.withError(Status.PERMISSION_DENIED));
delayedTransport.reprocess(picker);
InsightBuilder insight = new InsightBuilder();
stream.appendTimeoutInsight(insight);
assertThat(insight.toString())
.matches("\\[wait_for_ready, "
+ "Last Pick Failure=Status\\{code=PERMISSION_DENIED, description=null, cause=null\\},"
+ " buffered_nanos=[0-9]+, waiting_for_connection]");
}
private static TransportProvider newTransportProvider(final ClientTransport transport) {
return new TransportProvider() {
@Override