Skip to content

Commit 40fdcf5

Browse files
authored
Add a Guice shutdown listener (#56)
1 parent 795d646 commit 40fdcf5

File tree

3 files changed

+109
-2
lines changed

3 files changed

+109
-2
lines changed
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/**
2+
* Copyright 2017 Inscope Metrics, Inc
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.arpnetworking.metrics.mad;
17+
18+
import com.arpnetworking.steno.Logger;
19+
import com.arpnetworking.steno.LoggerFactory;
20+
21+
import java.util.concurrent.CompletableFuture;
22+
import java.util.concurrent.CompletionStage;
23+
import java.util.concurrent.ConcurrentLinkedQueue;
24+
import java.util.concurrent.ExecutionException;
25+
import java.util.function.Supplier;
26+
27+
/**
28+
* Assists Guice-instantiated classes in shutting down.
29+
*
30+
* @author Brandon Arp (brandon dot arp at inscopemetrics dot com)
31+
*/
32+
public class AppShutdown implements LifecycleRegistration {
33+
/**
34+
* {@inheritDoc}
35+
*/
36+
@Override
37+
public void registerShutdown(final Supplier<CompletionStage<Void>> callback) {
38+
_shutdownCallbacks.offer(callback);
39+
}
40+
41+
/**
42+
* Executes all of the registered shutdown hooks and waits for them to complete.
43+
*/
44+
public void shutdown() {
45+
final CompletableFuture<?>[] completionStages = _shutdownCallbacks.stream()
46+
.map(Supplier::get)
47+
.map(CompletionStage::toCompletableFuture)
48+
.toArray(CompletableFuture[]::new);
49+
50+
try {
51+
CompletableFuture.allOf(completionStages).get();
52+
} catch (final InterruptedException | ExecutionException e) {
53+
LOGGER.error()
54+
.setMessage("Exception in application shutdown")
55+
.setThrowable(e)
56+
.log();
57+
}
58+
}
59+
60+
private final ConcurrentLinkedQueue<Supplier<CompletionStage<Void>>> _shutdownCallbacks = new ConcurrentLinkedQueue<>();
61+
62+
private static final Logger LOGGER = LoggerFactory.getLogger(AppShutdown.class);
63+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/**
2+
* Copyright 2017 Inscope Metrics, Inc
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.arpnetworking.metrics.mad;
17+
18+
import java.util.concurrent.CompletionStage;
19+
import java.util.function.Supplier;
20+
21+
/**
22+
* Provides a way to register for lifecycle events, ensuring that Guice-instantiated classes can be notified.
23+
*
24+
* @author Brandon Arp (brandon dot arp at inscopemetrics dot com)
25+
*/
26+
public interface LifecycleRegistration {
27+
/**
28+
* Registers a method to be called when the application is shutting down. The shutdown
29+
* will wait for all CompletionStages to complete before shutting down.
30+
*
31+
* @param callback The callback to register
32+
*/
33+
void registerShutdown(Supplier<CompletionStage<Void>> callback);
34+
}

src/main/java/com/arpnetworking/metrics/mad/Main.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -273,8 +273,11 @@ private Injector launchGuice(final ActorSystem actorSystem) {
273273
.build()))
274274
.build();
275275

276+
final AppShutdown shutdown = new AppShutdown();
277+
_guiceAppShutdown = shutdown;
278+
276279
// Instantiate Guice
277-
return Guice.createInjector(new MainModule(actorSystem, metricsFactory));
280+
return Guice.createInjector(new MainModule(actorSystem, metricsFactory, shutdown));
278281
}
279282

280283
private ActorSystem launchAkka() {
@@ -319,6 +322,9 @@ private void shutdownAkka() {
319322

320323
private void shutdownGuice() {
321324
LOGGER.info().setMessage("Stopping guice").log();
325+
if (_guiceAppShutdown != null) {
326+
_guiceAppShutdown.shutdown();
327+
}
322328
}
323329

324330
private static Builder<? extends JsonNodeSource> getFileSourceBuilder(final File configurationFile) {
@@ -338,6 +344,7 @@ private static Builder<? extends JsonNodeSource> getFileSourceBuilder(final File
338344
private volatile ScheduledExecutorService _jvmMetricsCollector;
339345

340346
private volatile ActorSystem _actorSystem;
347+
private volatile AppShutdown _guiceAppShutdown;
341348

342349
private static final Long INITIAL_DELAY_IN_MILLIS = 0L;
343350
private static final TimeUnit TIME_UNIT = TimeUnit.MILLISECONDS;
@@ -480,18 +487,21 @@ public void run() {
480487

481488
private static final class MainModule extends AbstractModule {
482489

483-
MainModule(final ActorSystem actorSystem, final MetricsFactory metricsFactory) {
490+
MainModule(final ActorSystem actorSystem, final MetricsFactory metricsFactory, final AppShutdown shutdown) {
484491
this._actorSystem = actorSystem;
485492
this._metricsFactory = metricsFactory;
493+
this._shutdown = shutdown;
486494
}
487495

488496
@Override
489497
public void configure() {
490498
bind(ActorSystem.class).toInstance(_actorSystem);
491499
bind(MetricsFactory.class).toInstance(_metricsFactory);
500+
bind(LifecycleRegistration.class).toInstance(_shutdown);
492501
}
493502

494503
private final ActorSystem _actorSystem;
495504
private final MetricsFactory _metricsFactory;
505+
private final AppShutdown _shutdown;
496506
}
497507
}

0 commit comments

Comments
 (0)