Skip to content

Commit 3879496

Browse files
committed
GH-1258: Add OOMHandler to the listener containers
Resolves #1258 (comment) **Backported to 2.2.x with a no-op default**
1 parent d73e6ae commit 3879496

File tree

5 files changed

+56
-5
lines changed

5 files changed

+56
-5
lines changed

spring-rabbit/src/main/java/org/springframework/amqp/rabbit/listener/AbstractMessageListenerContainer.java

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,10 +242,12 @@ public abstract class AbstractMessageListenerContainer extends RabbitAccessor
242242

243243
private boolean micrometerEnabled = true;
244244

245-
private volatile boolean lazyLoad;
246-
247245
private boolean isBatchListener;
248246

247+
private OOMHandler oOMHandler = error -> System.exit(99);
248+
249+
private volatile boolean lazyLoad;
250+
249251
@Override
250252
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
251253
this.applicationEventPublisher = applicationEventPublisher;
@@ -1123,6 +1125,21 @@ public void setMicrometerEnabled(boolean micrometerEnabled) {
11231125
this.micrometerEnabled = micrometerEnabled;
11241126
}
11251127

1128+
protected OOMHandler getOOMHandler() {
1129+
return this.oOMHandler;
1130+
}
1131+
1132+
/**
1133+
* Provide an OOMHandler implementation; by default, {@code System.exit(99)} is
1134+
* called.
1135+
* @param oOMHandler the handler.
1136+
* @since 2.2.12
1137+
*/
1138+
public void setOOMHandler(OOMHandler oOMHandler) {
1139+
Assert.notNull(oOMHandler, "'oOMHandler' cannot be null");
1140+
this.oOMHandler = oOMHandler;
1141+
}
1142+
11261143
/**
11271144
* Delegates to {@link #validateConfiguration()} and {@link #initialize()}.
11281145
*/
@@ -1950,6 +1967,22 @@ private interface ContainerDelegate {
19501967

19511968
}
19521969

1970+
/**
1971+
* A handler for {@link OutOfMemoryError} on the container thread(s).
1972+
* @since 2.2.12
1973+
*
1974+
*/
1975+
@FunctionalInterface
1976+
public interface OOMHandler {
1977+
1978+
/**
1979+
* Handle the error; typically, the JVM will be terminated.
1980+
* @param error the error.
1981+
*/
1982+
void handle(OutOfMemoryError error);
1983+
1984+
}
1985+
19531986
/**
19541987
* Exception that indicates that the initial setup of this container's shared Rabbit Connection failed. This is
19551988
* indicating to invokers that they need to establish the shared Connection themselves on first access.

spring-rabbit/src/main/java/org/springframework/amqp/rabbit/listener/DirectMessageListenerContainer.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1085,6 +1085,10 @@ private void callExecuteListener(Object data, long deliveryTag) {
10851085
}
10861086
}
10871087
}
1088+
catch (OutOfMemoryError e) { // NOSONAR
1089+
getOOMHandler().handle(e);
1090+
throw e;
1091+
}
10881092
}
10891093

10901094
private void handleAck(long deliveryTag, boolean channelLocallyTransacted) {

spring-rabbit/src/main/java/org/springframework/amqp/rabbit/listener/SimpleMessageListenerContainer.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1266,6 +1266,9 @@ public void run() { // NOSONAR - line count
12661266
catch (Error e) { //NOSONAR
12671267
// ok to catch Error - we're aborting so will stop
12681268
logger.error("Consumer thread error, thread abort.", e);
1269+
if (e instanceof OutOfMemoryError) { // NOSONAR
1270+
getOOMHandler().handle((OutOfMemoryError) e);
1271+
}
12691272
publishConsumerFailedEvent("Consumer threw an Error", true, e);
12701273
aborted = true;
12711274
}

src/reference/asciidoc/amqp.adoc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5430,6 +5430,16 @@ Default is a `SimpleAsyncTaskExecutor`, using internally managed threads.
54305430
a| image::images/tickmark.png[]
54315431
a| image::images/tickmark.png[]
54325432

5433+
| oOMHandler
5434+
(N/A)
5435+
5436+
| An `AbstractMessageListenerContainer.OOMHandler` implementation that is called when a container thread catches an `OutOfMemoryException`.
5437+
The default implementation does nothing, for backwards compatibility.
5438+
Normally, the JVM should be terminated; this will be the default action in a future release.
5439+
5440+
a| image::images/tickmark.png[]
5441+
a| image::images/tickmark.png[]
5442+
54335443
| errorHandler
54345444
(error-handler)
54355445

src/reference/asciidoc/whats-new.adoc

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ See <<exception-handling>> for more information.
3535
Listener performance can now be monitored using Micrometer `Timer` s.
3636
See <<micrometer>> for more information.
3737

38+
You can now configure an `OOMHandler` (out of memory handler); the default implementation does nothing, for backwards compatibility.
39+
Normally, the JVM should be terminated; this will be the default action in a future release.
40+
See <<containerAttributes>> for more information.
41+
3842
==== @RabbitListener Changes
3943

4044
You can now configure an `executor` on each listener, overriding the factory configuration, to more easily identify threads associated with the listener.
@@ -128,9 +132,6 @@ See <<message-properties-converters>> for more information.
128132
Recovery of failed producer-created batches is now supported.
129133
See <<batch-retry>> for more information.
130134

131-
A new listener container property `consumeDelay` is now available; it is helpful when using the https://github.com/rabbitmq/rabbitmq-sharding[RabbitMQ Sharding Plugin].
132-
See <<containerAttributes>> for more information.
133-
134135
==== MessagePostProcessor Changes
135136

136137
The compressing `MessagePostProcessor` s now can use a comma to separate multiple content encodings instead of a colon.

0 commit comments

Comments
 (0)