Skip to content

Commit ee419a7

Browse files
committed
Add channel shutdown grace period property
1 parent 165b8f8 commit ee419a7

File tree

2 files changed

+69
-7
lines changed

2 files changed

+69
-7
lines changed

grpc-client-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/client/channelfactory/AbstractChannelFactory.java

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,16 @@
1717

1818
package net.devh.boot.grpc.client.channelfactory;
1919

20+
import static java.util.Comparator.comparingLong;
2021
import static java.util.Objects.requireNonNull;
22+
import static java.util.concurrent.TimeUnit.MILLISECONDS;
2123

2224
import java.time.Duration;
25+
import java.util.ArrayList;
2326
import java.util.Collections;
2427
import java.util.List;
2528
import java.util.Map;
29+
import java.util.Map.Entry;
2630
import java.util.concurrent.ConcurrentHashMap;
2731
import java.util.concurrent.CountDownLatch;
2832
import java.util.concurrent.TimeUnit;
@@ -302,16 +306,30 @@ public synchronized void close() {
302306
return;
303307
}
304308
this.shutdown = true;
305-
for (final ManagedChannel channel : this.channels.values()) {
309+
final List<ShutdownRecord> shutdownEntries = new ArrayList<>();
310+
for (final Entry<String, ManagedChannel> entry : this.channels.entrySet()) {
311+
final ManagedChannel channel = entry.getValue();
306312
channel.shutdown();
313+
final long gracePeriod = this.properties.getChannel(entry.getKey()).getShutdownGracePeriod().toMillis();
314+
shutdownEntries.add(new ShutdownRecord(entry.getKey(), channel, gracePeriod));
307315
}
308316
try {
309-
final long waitLimit = System.currentTimeMillis() + 60_000; // wait 60 seconds at max
310-
for (final ManagedChannel channel : this.channels.values()) {
311-
int i = 0;
312-
do {
313-
log.debug("Awaiting channel shutdown: {} ({}s)", channel, i++);
314-
} while (System.currentTimeMillis() < waitLimit && !channel.awaitTermination(1, TimeUnit.SECONDS));
317+
final long start = System.currentTimeMillis();
318+
shutdownEntries.sort(comparingLong(ShutdownRecord::getGracePeriod));
319+
320+
for (final ShutdownRecord entry : shutdownEntries) {
321+
if (!entry.channel.isTerminated()) {
322+
log.debug("Awaiting channel termination: {}", entry.name);
323+
324+
final long waitedTime = System.currentTimeMillis() - start;
325+
final long waitTime = entry.gracePeriod - waitedTime;
326+
327+
if (waitTime > 0) {
328+
entry.channel.awaitTermination(waitTime, MILLISECONDS);
329+
}
330+
entry.channel.shutdownNow();
331+
}
332+
log.debug("Completed channel termination: {}", entry.name);
315333
}
316334
} catch (final InterruptedException e) {
317335
Thread.currentThread().interrupt();
@@ -330,4 +348,22 @@ public synchronized void close() {
330348
log.debug("GrpcCannelFactory closed (including {} channels)", channelCount);
331349
}
332350

351+
private static class ShutdownRecord {
352+
353+
private final String name;
354+
private final ManagedChannel channel;
355+
private final long gracePeriod;
356+
357+
public ShutdownRecord(final String name, final ManagedChannel channel, final long gracePeriod) {
358+
this.name = name;
359+
this.channel = channel;
360+
this.gracePeriod = gracePeriod;
361+
}
362+
363+
long getGracePeriod() {
364+
return this.gracePeriod;
365+
}
366+
367+
}
368+
333369
}

grpc-client-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/client/config/GrpcChannelProperties.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,32 @@ public void setKeepAliveWithoutCalls(final Boolean keepAliveWithoutCalls) {
263263
this.keepAliveWithoutCalls = keepAliveWithoutCalls;
264264
}
265265

266+
// --------------------------------------------------
267+
268+
@DurationUnit(ChronoUnit.SECONDS)
269+
private Duration shutdownGracePeriod;
270+
private static final Duration DEFAULT_SHUTDOWN_GRACE_PERIOD = Duration.ofSeconds(30);
271+
272+
/**
273+
* Gets the time to wait for the channel to gracefully shutdown. If set to {@code -1} the server waits forever. If
274+
* set to {@code 0} the server will force shutdown immediately. Defaults to {@code 30s}.
275+
*
276+
* @return The time to wait for a graceful shutdown.
277+
*/
278+
public Duration getShutdownGracePeriod() {
279+
return this.shutdownGracePeriod == null ? DEFAULT_SHUTDOWN_GRACE_PERIOD : this.shutdownGracePeriod;
280+
}
281+
282+
/**
283+
* Sets the time to wait for the channel to gracefully shutdown (completing all requests). If set to {@code -1} the
284+
* channel waits forever. If set to {@code 0} the channel will force shutdown immediately. Defaults to {@code 30s}.
285+
*
286+
* @param shutdownGracePeriod The time to wait for a graceful shutdown.
287+
*/
288+
public void setShutdownGracePeriod(final Duration shutdownGracePeriod) {
289+
this.shutdownGracePeriod = shutdownGracePeriod;
290+
}
291+
266292
// --------------------------------------------------
267293
// Message Transfer
268294
// --------------------------------------------------

0 commit comments

Comments
 (0)