Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,14 @@ public void close() {
channel.shutdown();

try {
channel.awaitTermination(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
log.error("Failed to shutdown channel within 5 seconds", e);
} finally {
if (!channel.isTerminated()) {
if (!channel.awaitTermination(5, TimeUnit.SECONDS)) {
log.warn("Channel did not terminate within 5 seconds, forcing shutdown");
channel.shutdownNow();
}
} catch (InterruptedException e) {
log.warn("Channel shutdown interrupted, forcing immediate termination", e);
channel.shutdownNow();
Thread.currentThread().interrupt();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ void shouldNotEnableRetriesWhenDisabled() {
void callsManagedChannelCleanup() {
val mockChannel = mock(ManagedChannel.class);
val mockChannelBuilder = getMockChannelBuilderWithChannel(mockChannel);
when(mockChannel.isTerminated()).thenReturn(false, true);
when(mockChannel.awaitTermination(anyLong(), any(TimeUnit.class))).thenReturn(true);

val stubProvider = JdbcDriverStubProvider.of(mockChannelBuilder);
stubProvider.close();
Expand All @@ -185,10 +185,10 @@ void callsManagedChannelCleanup() {

@SneakyThrows
@Test
void callsManagedChannelShutdownNow() {
void callsManagedChannelShutdownNowOnTimeout() {
val mockChannel = mock(ManagedChannel.class);
val mockChannelBuilder = getMockChannelBuilderWithChannel(mockChannel);
when(mockChannel.isTerminated()).thenReturn(false);
when(mockChannel.awaitTermination(anyLong(), any(TimeUnit.class))).thenReturn(false);

val stubProvider = JdbcDriverStubProvider.of(mockChannelBuilder);
stubProvider.close();
Expand All @@ -197,4 +197,25 @@ void callsManagedChannelShutdownNow() {
verify(mockChannel).awaitTermination(5, TimeUnit.SECONDS);
verify(mockChannel).shutdownNow();
}

@SneakyThrows
@Test
void handlesInterruptDuringShutdown() {
val mockChannel = mock(ManagedChannel.class);
val mockChannelBuilder = getMockChannelBuilderWithChannel(mockChannel);
when(mockChannel.awaitTermination(anyLong(), any(TimeUnit.class)))
.thenThrow(new InterruptedException("Test interruption"));

val stubProvider = JdbcDriverStubProvider.of(mockChannelBuilder);
stubProvider.close();

verify(mockChannel).shutdown();
verify(mockChannel).awaitTermination(5, TimeUnit.SECONDS);
verify(mockChannel).shutdownNow();

// Verify interrupt status is restored per Java best practices
assert Thread.currentThread().isInterrupted() : "Thread interrupt status should be restored";
// Clear interrupt status for other tests
Thread.interrupted();
}
}