GH-3464: Treat 0 as special for polling endpoint (#3487)
* GH-3464: Treat 0 as special for polling endpoint Fixes https://github.com/spring-projects/spring-integration/issues/3464 The `maxMessagePerPoll <= 0` is considered as an unbound `receive()` call. End-users would like to have a special treatment for `0` value - skip the `receive()` call altogether for the current polling cycle. * Change the logic for a scheduled poller to not call `pollForMessage()` and just log an INFO when `maxMessagePerPoll == 0` * Fix reactive poller to deal with `maxMessagePerPoll == 0` properly * Expose `maxMessagesPerPoll` as a `@ManagedAttribute` to let it to be modified via Control Bus and JMX * Test and document a new behavior * * Fix unused imports in the test class * Fix language in docs accoridng PR review Co-authored-by: Gary Russell <grussell@vmware.com> Co-authored-by: Gary Russell <grussell@vmware.com>
This commit is contained in:
@@ -62,7 +62,7 @@ However, what happens if the configuration looks like the following example:
|
||||
====
|
||||
|
||||
Note that there is no `max-messages-per-poll` specified.
|
||||
As we cover later, the identical poller configuration in the `PollingConsumer` (for example, service-activator, filter, router, and others) would have a default value of -1 for `max-messages-per-poll`, which means "`execute the polling task non-stop unless the polling method returns null (perhaps because there are no more messages in the `QueueChannel`)`" and then sleep for one second.
|
||||
As we cover later, the identical poller configuration in the `PollingConsumer` (for example, `service-activator`, `filter`, `router`, and others) would have a default value of `-1` for `max-messages-per-poll`, which means "`execute the polling task non-stop unless the polling method returns null (perhaps because there are no more messages in the `QueueChannel`)`" and then sleep for one second.
|
||||
|
||||
However, in the `SourcePollingChannelAdapter`, it is a bit different.
|
||||
The default value for `max-messages-per-poll` is `1`, unless you explicitly set it to a negative value (such as `-1`).
|
||||
@@ -76,6 +76,8 @@ However, if you are sure that your method can return null and you need to poll f
|
||||
<int:poller max-messages-per-poll="-1" fixed-rate="1000"/>
|
||||
----
|
||||
====
|
||||
|
||||
Starting with version 5.5, a `0` value for `max-messages-per-poll` has a special meaning - skip the `MessageSource.receive()` call altogether, which may be considered as pausing for this inbound channel adapter until the `maxMessagesPerPoll` is changed to a non-zero value at a later time, e.g. via a Control Bus.
|
||||
=====
|
||||
|
||||
[[channel-adapter-namespace-outbound]]
|
||||
|
||||
@@ -141,9 +141,11 @@ consumer.setReceiveTimeout(5000);
|
||||
====
|
||||
|
||||
The `maxMessagesPerPoll` property specifies the maximum number of messages to receive within a given poll operation.
|
||||
This means that the poller continues calling receive() without waiting, until either `null` is returned or the maximum value is reached.
|
||||
This means that the poller continues calling `receive()` without waiting, until either `null` is returned or the maximum value is reached.
|
||||
For example, if a poller has a ten-second interval trigger and a `maxMessagesPerPoll` setting of `25`, and it is polling a channel that has 100 messages in its queue, all 100 messages can be retrieved within 40 seconds.
|
||||
It grabs 25, waits ten seconds, grabs the next 25, and so on.
|
||||
If `maxMessagesPerPoll` is configured with a negative value, then `MessageSource.receive()` is called within a single polling cycle until it returns `null`.
|
||||
Starting with version 5.5, a `0` value has a special meaning - skip the `MessageSource.receive()` call altogether, which may be considered as pausing for this polling endpoint until the `maxMessagesPerPoll` is changed to a n non-zero value at a later time, e.g. via a Control Bus.
|
||||
|
||||
The `receiveTimeout` property specifies the amount of time the poller should wait if no messages are available when it invokes the receive operation.
|
||||
For example, consider two options that seem similar on the surface but are actually quite different: The first has an interval trigger of 5 seconds and a receive timeout of 50 milliseconds, while the second has an interval trigger of 50 milliseconds and a receive timeout of 5 seconds.
|
||||
|
||||
@@ -73,6 +73,7 @@ A polling trigger is built from the provided options and used for periodic sched
|
||||
When an `outputChannel` is a `ReactiveStreamsSubscribableChannel`, the same `Trigger` is used to determine the next time for execution, but instead of scheduling tasks, the `SourcePollingChannelAdapter` creates a `Flux<Message<?>>` based on the `Flux.generate()` for the `nextExecutionTime` values and `Mono.delay()` for a duration from the previous step.
|
||||
A `Flux.flatMapMany()` is used then to poll `maxMessagesPerPoll` and sink them into an output `Flux`.
|
||||
This generator `Flux` is subscribed by the provided `ReactiveStreamsSubscribableChannel` honoring a back-pressure downstream.
|
||||
Starting with version 5.5, when `maxMessagesPerPoll == 0`, the source is not called at all, and `flatMapMany()` is completed immediately via a `Mono.empty()` result until the `maxMessagesPerPoll` is changed to non-zero value at a later time, e.g. via a Control Bus.
|
||||
This way, any `MessageSource` implementation can be turned into a reactive hot source.
|
||||
|
||||
See <<./polling-consumer.adoc#polling-consumer,Polling Consumer>> for more information.
|
||||
|
||||
@@ -25,6 +25,10 @@ The `spring.integration.channels.error.requireSubscribers=true` global property
|
||||
The `spring.integration.channels.error.ignoreFailures=true` global property is added to indicate that the global default `errorChannel` must ignore (or not) dispatching errors and pass the message to the next handler.
|
||||
See <<./configuration.adoc#global-properties,Global Properties>> for more information.
|
||||
|
||||
An `AbstractPollingEndpoint` (source polling channel adapter and polling consumer) treats `maxMessagesPerPoll == 0` as to skip calling the source.
|
||||
It can be changed to different value later on, e.g. via a Control Bus.
|
||||
See <<./endpoint.adoc#endpoint-pollingconsumer,Polling Consumer>> for more information.
|
||||
|
||||
[[x5.5-amqp]]
|
||||
==== AMQP Changes
|
||||
|
||||
|
||||
Reference in New Issue
Block a user