@Test public void resetConnectBackoff() throws Exception { SocketAddress addr = mock(SocketAddress.class); createInternalSubchannel(addr); internalSubchannel.obtainActiveTransport(); assertExactCallbackInvokes("onStateChange:CONNECTING"); verify(mockTransportFactory).newClientTransport(addr, createClientTransportOptions()); transports.poll().listener.transportShutdown(Status.UNAVAILABLE); assertExactCallbackInvokes("onStateChange:" + UNAVAILABLE_STATE); FakeClock.ScheduledTask reconnectTask = null; for (FakeClock.ScheduledTask task : fakeClock.getPendingTasks()) { if (task.command.toString().contains("EndOfCurrentBackoff")) { assertNull("There shouldn't be more than one reconnectTask", reconnectTask); assertFalse(task.isDone()); reconnectTask = task; } } assertNotNull("There should be at least one reconnectTask", reconnectTask); internalSubchannel.resetConnectBackoff(); verify(mockTransportFactory, times(2)) .newClientTransport(addr, createClientTransportOptions()); assertExactCallbackInvokes("onStateChange:CONNECTING"); assertTrue(reconnectTask.isCancelled()); reconnectTask.command.run(); assertNoCallbackInvoke(); verify(mockTransportFactory, times(2)) .newClientTransport(addr, createClientTransportOptions()); verify(mockBackoffPolicyProvider, times(1)).get(); transports.poll().listener.transportShutdown(Status.UNAVAILABLE); assertExactCallbackInvokes("onStateChange:" + UNAVAILABLE_STATE); verify(mockBackoffPolicyProvider, times(2)).get(); fakeClock.forwardNanos(10); assertExactCallbackInvokes("onStateChange:CONNECTING"); assertEquals(CONNECTING, internalSubchannel.getState()); }
void resetConnectBackoff() { try { synchronized (lock) { if (state.getState() != TRANSIENT_FAILURE) { return; } cancelReconnectTask(); channelLogger.log(ChannelLogLevel.INFO, "CONNECTING; backoff interrupted"); gotoNonErrorState(CONNECTING); startNewTransport(); } } finally { syncContext.drain(); } }
InternalSubchannel implements InternalInstrumented<ChannelStats> { void resetConnectBackoff() { try { synchronized (lock) { if (state.getState() != TRANSIENT_FAILURE) { return; } cancelReconnectTask(); channelLogger.log(ChannelLogLevel.INFO, "CONNECTING; backoff interrupted"); gotoNonErrorState(CONNECTING); startNewTransport(); } } finally { syncContext.drain(); } } }
InternalSubchannel implements InternalInstrumented<ChannelStats> { void resetConnectBackoff() { try { synchronized (lock) { if (state.getState() != TRANSIENT_FAILURE) { return; } cancelReconnectTask(); channelLogger.log(ChannelLogLevel.INFO, "CONNECTING; backoff interrupted"); gotoNonErrorState(CONNECTING); startNewTransport(); } } finally { syncContext.drain(); } } InternalSubchannel(List<EquivalentAddressGroup> addressGroups, String authority, String userAgent,
      BackoffPolicy.Provider backoffPolicyProvider,
      ClientTransportFactory transportFactory, ScheduledExecutorService scheduledExecutor,
      Supplier<Stopwatch> stopwatchSupplier, SynchronizationContext syncContext, Callback callback,
      InternalChannelz channelz, CallTracer callsTracer, ChannelTracer channelTracer,
      InternalLogId logId, TimeProvider timeProvider); }
InternalSubchannel implements InternalInstrumented<ChannelStats> { void resetConnectBackoff() { try { synchronized (lock) { if (state.getState() != TRANSIENT_FAILURE) { return; } cancelReconnectTask(); channelLogger.log(ChannelLogLevel.INFO, "CONNECTING; backoff interrupted"); gotoNonErrorState(CONNECTING); startNewTransport(); } } finally { syncContext.drain(); } } InternalSubchannel(List<EquivalentAddressGroup> addressGroups, String authority, String userAgent,
      BackoffPolicy.Provider backoffPolicyProvider,
      ClientTransportFactory transportFactory, ScheduledExecutorService scheduledExecutor,
      Supplier<Stopwatch> stopwatchSupplier, SynchronizationContext syncContext, Callback callback,
      InternalChannelz channelz, CallTracer callsTracer, ChannelTracer channelTracer,
      InternalLogId logId, TimeProvider timeProvider); void updateAddresses(List<EquivalentAddressGroup> newAddressGroups); void shutdown(Status reason); @Override String toString(); @Override InternalLogId getLogId(); @Override ListenableFuture<ChannelStats> getStats(); }
InternalSubchannel implements InternalInstrumented<ChannelStats> { void resetConnectBackoff() { try { synchronized (lock) { if (state.getState() != TRANSIENT_FAILURE) { return; } cancelReconnectTask(); channelLogger.log(ChannelLogLevel.INFO, "CONNECTING; backoff interrupted"); gotoNonErrorState(CONNECTING); startNewTransport(); } } finally { syncContext.drain(); } } InternalSubchannel(List<EquivalentAddressGroup> addressGroups, String authority, String userAgent,
      BackoffPolicy.Provider backoffPolicyProvider,
      ClientTransportFactory transportFactory, ScheduledExecutorService scheduledExecutor,
      Supplier<Stopwatch> stopwatchSupplier, SynchronizationContext syncContext, Callback callback,
      InternalChannelz channelz, CallTracer callsTracer, ChannelTracer channelTracer,
      InternalLogId logId, TimeProvider timeProvider); void updateAddresses(List<EquivalentAddressGroup> newAddressGroups); void shutdown(Status reason); @Override String toString(); @Override InternalLogId getLogId(); @Override ListenableFuture<ChannelStats> getStats();  }