Commit Graph

2044 Commits

Author SHA1 Message Date
Artem Bilan
cb0d43db6b Fix JDBC tests and some upgrades
https://build.spring.io/browse/INT-FATS5IC-430

Looks like there is a race condition when our polling rate around
data base is too fast and we have access to the DB files even during
application context close.

* Stop polling channel adapter in the tests explicitly after test methods
* Increase some tests performance decreasing timeouts to wait
* Upgrade to Reactor-3.1.5, AssertJ-3.9.1, Derby-10.14.1.0 and some
Gradle plugins

* Upgrade to `reactor-netty-0.7.5`
* Remove workaround from the `StompServerIntegrationTests`

* Upgrade to Spring Data Kay SR5

* Upgrade to Spring Security 5.0.3
* Increase timeouts and performance in the `StreamTransformerParserTests`
2018-02-28 11:57:21 -05:00
Gary Russell
792b8fe6d1 INT-4416: Rework Micrometer Metrics
JIRA: https://jira.spring.io/browse/INT-4416

Metrics should be under a common name, discriminated with tags.
2018-02-27 16:52:28 -05:00
Artem Bilan
2c3ee7d68c MMIH: Convert from JSON only if SpELInvoker
If there is `json`-aware `contentType` header in the message to process
and payload type is `String` or `byte[]` and it isn't equal to the
expected exclusive method argument type (even generic from the `Message<>`),
the conversion should happen only if SpelInvoker is no method.

The regular `InvocableHandlerMethod` takes care about payload conversion
via configured `MessageConverter` in the `PayloadArgumentResolver`

* Fix `MessagingMethodInvokerHelper` to call JSON conversion only when
`this.handlerMethod.spelOnly`

NOTE: We can't do generics conversion right now because it is going
to be a breaking change around
`org.springframework.integration.support.json.JsonObjectMapper` property
in the `MessagingMethodInvokerHelper`.
We can do that only in `5.1` and rely there only on the functionality
from the Jackson Object mapper

* Convert from JSON only in the `invokeExpression()`
* Optimize message recreation only if target param type is `Message`.
Otherwise override just `payload` property of the `ParametersWrapper`
2018-02-24 13:40:16 -05:00
Artem Bilan
d5303ca4f3 INT-4413: Don't register flow under the same id
JIRA: https://jira.spring.io/browse/INT-4413

When we override entity in the `IntegrationFlowContext.registry`,
we may get dangling beans in the application context,
when the structure of a new `IntegrationFlow` is different.

* Fix `IntegrationFlowContext` to disallow to override the flow
registration under the same name
* Add JavaDocs to the `IntegrationFlowRegistrationBuilder` methods
* Add `toString()` to the `IntegrationFlowRegistration` and
`StandardIntegrationFlow` to make the logging of these components
friendlier
2018-02-23 15:07:31 -05:00
Artem Bilan
7d1680534f INT-4411: DSL: Fix sub-flows for dynamic routers
JIRA: https://jira.spring.io/browse/INT-4411

The `RouterSpec.RouterMappingProvider` relies on the
`ContextRefreshedEvent` which happens only during application start up.
When we register `IntegrationFlow` at runtime, this event doesn't
happen and therefore sub-flow mappings don't populated.

* Fix `RouterSpec.RouterMappingProvider` to parse sub-flow mappings in
the `onInit()`
* Reorder components registration for the router in the
`IntegrationFlowDefinition` to let lately sub-flows to start earlier,
then lifecycles in the main flow
2018-02-21 17:09:25 -05:00
Gary Russell
f6084939cc Add Pausable
See https://github.com/spring-projects/spring-integration-kafka/issues/198
2018-02-21 11:50:23 -05:00
Kiel Boatman
4bb4a0187a GH-2364 fix intermittent failing test
Resolves https://github.com/spring-projects/spring-integration/issues/2364
2018-02-20 14:52:37 -05:00
Artem Bilan
00c983d97a INT-4410 CollArgResolver only for group processor
JIRA: https://jira.spring.io/browse/INT-4410

The `CollectionArgumentResolver` has been introduced especially for the
cases to work with `MessageGroupProcessor` (an aggregator)
when the payload is a `Collection<Message<?>>`.

This use-case doesn't apply for the general collection parameter use-case.

* Register `CollectionArgumentResolver` only when `listCapable` option.
For all other collection-based use-cases fallback to the standard
`PayloadArgumentResolver` with an appropriate configured `MessageConverter`

Note: this is for backward compatibility.
In the `5.1` we may reconsider to use `MessageConverter` in the
`CollectionArgumentResolver` as well, or just remove it altogether with
an appropriate logic in the `PayloadArgumentResolver`, since this
`CollectionArgumentResolver` solution isn't robust
2018-02-20 13:59:14 -05:00
Artem Bilan
800184270a INT-4402: Apply global interceptors at runtime
JIRA: https://jira.spring.io/browse/INT-4402

Make `GlobalChannelInterceptorProcessor` as a `BeanPostProcessor`,
so it can apply global `ChannelInterceptor`s to any initialized channel
beans, even those created at runtime, like in case of dynamic flows with
Java DSL

**Cherry-pick to 4.3.x**

* Add `postProcessDynamicBeans` global property with `false` by default
* Rely on the `postProcessDynamicBeans` property in the
`GlobalChannelInterceptorProcessor.postProcessAfterInitialization()`
*  Add `postProcessDynamicBeans=true` to the
`GlobalChannelInterceptorTests-context.xml` to be sure in the test-case
that option works
* Document the option and effect from the global channel interceptors
2018-02-16 11:33:19 -05:00
Gary Russell
a77def1cdf INT-4403: Micrometer and Dynamic Components
JIRA: https://jira.spring.io/browse/INT-4402

Previously, Micrometer instrumentation was only applied to components during
ApplicationContext initialization.

`IntegrationManagementConfigurer` is now a `BeanPostProcessor` as well as a
`SmartInitializingSingleton`, but only acts as a BPP after the context is
initialized. This enables Micrometer instrumentation to beans added later,
either via a new `BeanDefinition` or `bf.initializeBean`.

NOTE: destroying and re-creating a bean will use the same `Meters`.
2018-02-15 10:30:21 -05:00
Kiel Boatman
78b80ef79f GH-2354 Injection Executor to LockLeaderInitiator
Fixes https://github.com/spring-projects/spring-integration/issues/2354

INT-2354 missed file in previous commit

INT-2354 fix failing test

INT-2354 changes following feedback

INT-2354 feedback changes

INT-2354 feedback changes

* Simple code style polishing
2018-02-13 14:14:56 -05:00
Artem Bilan
d361eefa0c Add missed options and JavaDocs to AMQP Java DSL 2018-02-12 11:43:36 -05:00
Artem Bilan
09aeaac4da INT-4396: Add retrying lock in case of exception
JIRA: https://jira.spring.io/browse/INT-4396

When target distributed `Lock` implementation throws an exception, e.g.
in case of no connection to the service, the `LockRegistryLeaderInitiator`
exists the loop and can come back to the elections only after restart

* Catch all the exception on `this.lock.tryLock()` and resubmit
`LeaderSelector` for a new locking cycle if
`LockRegistryLeaderInitiator.isRunning()` and `InterruptedException`

* Remove diagnostics from the `JdbcLockRegistryLeaderInitiatorTests`
since this fix confirms that we just didn't have a reconnect logic before
when this test failed sporadically

**Cherry-pick to 4.3.x**
2018-02-09 16:09:22 -05:00
Gary Russell
e53e8941a1 Add ObjectStringMapBuilder
Convenient builder for DSL `getComponentsToRegister()`.
2018-02-07 10:55:46 -05:00
Gary Russell
f4fbfa116a INT-4395: More micrometer meters
JIRA: https://jira.spring.io/browse/INT-4395

- pollable channel counts
- component counts (gauges)

Polishing - PR comments

Fix switch in test

* Simple code style polishing and fix JavaDocs
2018-02-05 16:36:18 -05:00
Artem Bilan
5f509ac02e INT-4394: Fix compatibility with Jackson JSON
JIRA: https://jira.spring.io/browse/INT-4394

Looks like Jackson has became much smarter and now it stores
the target type for the object, not returned interface.

We can't use Jackson annotations on the Framework classes and
we can't restrict the `messagingAwareMapper()` `ObjectMapper` just
to use fields for all the object passed through it.

As a compromise solution we shouldn't use
`Collections.unmodifiableList()` in the getter.
The copy of the internal collection is pretty enough to protect
our object from mutation.

**Cherry-pick to 4.3.x (excluding `build.gradle` change)**
2018-02-05 11:51:07 -05:00
Gary Russell
51397ec141 Make updateNotPropagatedHeaders protected final 2018-02-03 13:08:54 -05:00
Gary Russell
54754743a5 INT-4384: Micrometer Support
JIRA: https://jira.spring.io/browse/INT-4384

Add support for micrometer metrics collection.

Initial commit.

* Rebase; upgrade to Micrometer rc.8

* Polishing - PR Comments

* Final Polishing
2018-02-02 15:30:48 -05:00
Gary Russell
3bd4930813 Fix UDP Tangles
- Class tangle in new event
- Package tangle udp <-> util

* Fix JacksonJsonUtils class tangle

* Fix HTTP class tangle
2018-02-01 15:12:53 -05:00
Artem Bilan
9f6457fc31 INT-4383: Add test for EnricherSpec.errorChannel
JIRA: https://jira.spring.io/browse/INT-4383
2018-01-23 12:42:38 -05:00
Alexis Hafner
061dcb1b87 INT-4383 Expose errorChannel in EnricherSpec
JIRA: https://jira.spring.io/browse/INT-4383
2018-01-23 12:31:27 -05:00
Gary Russell
8aa91d1db0 Shutdown test executors in -core
- don't use `ExecutorService` as `@Bean` - spring can't stop them
- also add log adjuster for ftp test that sometimes fails
2018-01-19 10:21:55 -05:00
Artem Bilan
7e263aa618 GH-2301: Add SimpMessageGrFactory.GroupType.LIST
Fixes https://github.com/spring-projects/spring-integration/issues/2301

* For non-ordered, without deduplication logic use-case the `ArrayList`
option for internal `SimpleMessageGroup` collection is added
* Make `SimpleMessageGroup` `protected` ctor as `public` for better
reuse in case of custom `MessageGroupFactory`
2018-01-18 11:56:25 -05:00
Artem Bilan
86c76999f6 Optimize AbstractMessageSources
To avoid `Message` re-creation during `AbstractMessageSource.receive()`
logic, refactor `AbstractMessageSource` implementations
to return `AbstractIntegrationMessageBuilder`

* Add `AbstractIntegrationMessageBuilder<File> doReceive()` to the
`FileReadingMessageSource` to be called from the `AbstractInboundFileSynchronizingMessageSource`
to avoid message recreation in its `doReceive()`
* Some code style refactoring in the `AbstractMessageSource`
2018-01-18 11:17:03 -05:00
Yilin Wei
e6ec86c505 INT-3945: Add async to the @ServiceActivator
JIRA: https://jira.spring.io/browse/INT-3945

Adding test for async annotated ServiceActivator

fix whitespace

Address comments

Change copyright and author

* Some code style polishing
* Rename `Log4j2LevelAdjuster.level()` to more friendly `forLevel()`
factory method name.
* Add `@param level` to the `Log4j2LevelAdjuster.forLevel()` to fix
JavaDoc warning
2018-01-18 09:48:22 -05:00
Gary Russell
1bb4f86151 Minor Fixes
- use passive mode for FTP tests
(active fails on one of my machines for some reason)

* Fix generic args instead of `@SuppressWarnings("rawtypes")`
2018-01-16 16:37:50 -05:00
Artem Bilan
c4c4e51627 Some JsonPropertyAccessor polishing
* Add `WrappedJsonNode.getTarget()` API to let target users to get
access to the target `JsonNode` for their logic
* Some code style and JavaDocs improvements in the `JsonPropertyAccessor`
2018-01-12 11:54:02 -05:00
Artem Bilan
a4eb55bf7a Fix SpelPropertyAccessorRegistrar
The `SpelPropertyAccessorRegistrar` ctor and
`add(PropertyAccessor... propertyAccessors)` method use wrong variable
to build a key for the provided `PropertyAccessor`.
Therefore during iteration the next `PropertyAccessor` overrides the
previous and we end up just only with one instance in the registry

* Extract `private static obtainAccessorKey()` method to build
decapitalized key for the `PropertyAccessor`
* Change the map store to the `LinkedHashMap` to keep order of the
provided `PropertyAccessor` s
* Modify `EnableIntegrationTests` to ensure that we support several
`PropertyAccessor` s and in the proper order

**Cherry-pick to 4.3.x**
2018-01-12 11:50:33 -05:00
Artem Bilan
30450c48be INT-4376: Upgage to Log4J 2 (#2321)
* INT-4376: Upgage to Log4J 2

JIRA: https://jira.spring.io/browse/INT-4376

* Deprecate Log4J 1.x components in favor of newly added
a `Log4j2LevelAdjuster` JUnit `@Rule`
* Update all the logging configuration to Log4J 2

* Polishing after testing
2018-01-11 10:59:55 -05:00
Gary Russell
422f651113 DSL: Polishing AMQP ICA Spec
Also add `messageHeaders()` to `MessageSourceSpec`.
2018-01-05 16:36:02 -05:00
Gary Russell
bab850595a INT-4371: Add MessageSource Acknowlegment support
JIRA: https://jira.spring.io/browse/INT-4371

Add an abstract message source that populates the message with a header containing
an abstraction that allows the application to acknowledge/reject/requeue the message.
(In amqp, for example, this would map to channel.basicAck(tag),
channel.basicReject(tag, false), and channel.basicReject(tag, true).

With some brokers (such as kafka), acknowledge and reject might be equivalent
since there is no automatic DLQ processing in kafka both would simply commit the offset.

Also include a strategy interface for a factory to provide the acknowledgment header.

Add MessageSourcePollableChannel

Fix typo

Polishing - PR Comments

- remove marker interface; just use presence of the header for auto-ack
- remove the MessageSourcePollableChannel - users can use a MethodInterceptor to enhance the message
- other PR comments

Save entire response to allow customization of the ack/nack actions.

Docs, Copyrights; add MessageSourcePollingTemplate

Polishing - PR Comments - support disabling auto-ack, when possible.

More Utilities

* Simple code style polishing
2018-01-04 17:28:21 -05:00
Gary Russell
f21f81092d INT-4369: Add DeliveryAttempt header
JIRA: https://jira.spring.io/browse/INT-4369

Also add `StaticMessageHeaderAccessor`

- avoids object creation when getting type-safe well-known headers.

* Docs
2018-01-02 16:17:32 -05:00
Gary Russell
1724aecb24 GH-2313: IdempotentReceiver Discard Channel Name
Resolves: https://github.com/spring-projects/spring-integration/issues/2313

Allow configuration of the discard channel by name.

Refactor the interceptor to extend `IntegrationObjectSupport` and use
a channel resolver, if necessary.

* Polishing
2018-01-02 12:53:50 -05:00
krizsan
d273345234 INT-4373: Fix channel error count
JIRA: https://jira.spring.io/browse/INT-4373

Error count is wrong when just counts enabled.

CheckStyle fix.

Reduce send timeout in test.
2017-12-28 09:45:41 -05:00
Artem Bilan
34ffd9654d Fix SimpleJsonSerializer when exception on prop
When the target Java Bean reader throws an exception it is wrapped to
the `InvocationTargetException` which `getMessage()` returns `null`.

* Extract the `cause` when `InvocationTargetException` and check the
`message` for null anyway.
* Also check for `null` before calling `toString()` in the
`SimpleJsonSerializer.toElement()`
2017-12-20 16:15:41 -05:00
Artem Bilan
21bf69b7f8 INT-4367: Fix MessagingMethodInvHelper for CGLIB
JIRA: https://jira.spring.io/browse/INT-4367

When CGLIB proxy is used for messaging POJO invocation,
the `InvocableHandlerMethod` doesn't recognize method parameter
annotations and therefore the logic is wrong at runtime or just
rejected during method processing

* Use `AopUtils.selectInvocableMethod()` to select the proper method to
call according the provided proxy type
2017-12-19 09:29:55 -05:00
Oleg Zhurakousky
b58087881a INT-4365 Fixed NPE generated by previous commit
JIRA: https://jira.spring.io/browse/INT-4365
2017-11-28 09:21:28 -05:00
Artem Bilan
90c46f5a79 INT-4365: Improve notPropagatedHeaders function
JIRA: https://jira.spring.io/browse/INT-4365

It is much useful to configure the `notPropagatedHeaders` as a set of
patterns to match.
In this case we can filter a group of headers with the common prefix or
suffix

* Allow to configure `AbstractMessageProducingHandler.setNotPropagatedHeaders`
as simple patterns; the `*` means filter all - not copy request headers
at all - similar to `transformer` behavior
* Add `ConsumerEndpointSpec.notPropagatedHeaders()` for Java DSL
* Add `not-propagated-headers` to the `<service-activator>`

Address PR comments; some other improvements

* Fix `ConsumerEndpointSpec#notPropagatedHeaders()` log message
* Improve `AbstractMessageProducingHandler.notPropagatedHeaders() logic
so any `*` in the set of patterns eliminates all others since it has
a highest priority
* Expose `requires-reply` for the `<transformer>` as a `true` by default
* Refactor a bit `AbstractStandardMessageHandlerFactoryBean` hierarchy to
avoid duplicated code

* Fix `message.adoc`
* Add `noHeadersPropagation` flag to the `AbstractMessageProducingHandler`
* Rework logic in the `updateNotPropagatedHeaders()` to store the array
of patterns instead of `Set` to avoid extra operation on each message
* Combine `noHeadersPropagation` with the `shouldCopyRequestHeaders()`
in the `createOutputMessage()` for logic to determine if we should start
the copy-headers procedure at all

* Revert `AbstractMessageProducingHandler.selectiveHeaderPropagation`
* Optimize `AmqpOutboundGatewayParserTests` performance from 3 secs to 0.5

Fix more NPEs in the `AbstractMessageProducingHandler`
2017-11-27 16:56:41 -05:00
Artem Bilan
c3ca61d4a0 Don't wrap SpEL result message to another message
The `ExpressionEvaluatingTransactionSynchronizationProcessor` wraps
an expression evaluation result to the `Message` unconditionally

* Don't wrap one message to another if SpEL result is a `Message` per se
* Don't wrap the received message to another if the `expression` isn't
configured.

**Cherry-pick to 4.3.x**
2017-11-27 16:04:41 -05:00
Meherzad Lahewala
96aa7280a0 INT-3876: Track groups in correlation endpoints
JIRA: https://jira.spring.io/browse/INT-3876

INT-3876 track groups ids in AbstractCorrelatingMessageHandler and docs

INT-3876 Fix merge conflict and add missing link in doc

INT-3876 Move groupId check in message group processor and rework on docs

INT-3876 Remove extra space from the doc

INT-3876 Fix checkstyle refer instance variable groupid correctly

INT-3876 Update aggregator doc with more details

* Polishing `aggregator.adoc`
* Rework `AbstractCorrelatingMessageHandlerTests.testDontReapMessageOfOtherHandler`
do not use redundant options
2017-11-20 14:51:50 -05:00
Artem Bilan
f3072af192 INT-550: Optimize AbstractIntNamespaceHandler
JIRA: https://jira.spring.io/browse/INT-550

* We need verify schema version and register `IntegrationRegistrar`
only once, not on parsing each element
* `@Ignore` time-sensitive `GroovyScriptExecutingMessageProcessorTests`
* Upgrade to Gradle-4.3.1 to overcome NPE with caches
2017-11-20 13:58:59 -05:00
Artem Bilan
1244c6c22a The log() in the end IMPORTANT note in dsl.adoc 2017-11-15 15:21:14 -05:00
Artem Bilan
89614f7ff6 Upgrade to SF-5.0.2.B-S to ensure compatibility
* Fix `EnableIntegrationTests.testMessagingGateway()` do not check for
compiled SpEL since it isn't compilable any more for the Proxy classes
2017-11-15 14:52:35 -05:00
Artem Bilan
9414ceef86 Post merge polishing
JIRA: https://jira.spring.io/browse/INT-4363

* Register `HandlerMethodArgumentResolver`s in the
`IntegrationRegistrar` as `BeanDefinition`s to let them be configured by
the `BeanFactory` callback.
The direct instance doesn't call callbacks
* Use `JacksonPresent` in the `IntegrationRegistrar` instead of local
property
* Some code style polishing for the `IntegrationRegistrar`
* Add `JsonPathTests.testJsonPathOnPayloadAnnotation()` to ensure
that `PayloadExpressionArgumentResolver` is properly configured by the
`BeanFactory` and `#jsonPath()` SpEL-function is properly evaluated on
the `@Payload` for method `@ServiceActivator` method argument
2017-11-15 14:07:46 -05:00
Gary Russell
986d5fc0cd INT-4363: Configurable MessageHandlerMethodFactory
JIRA: https://jira.spring.io/browse/INT-4363

The JIRA requests making the `MessageHandlerMethodFactory` a bean.
This is not possible without a major rework of the `MessagingMethodInvokerHelper`.

The problem is that the `InvokerHandlerMethod` s are created before the factory
is initialized. In fact, it only works at all since the IHMs have a hard reference
to the factory's argument resolvers so, when they are initialized in `initialize()`
each handler sees the resolvers.

This really needs to be improved but, since we are so close to GA, the compromise
was to add a `HandlerMethodArgumentResolversHolder` which holds the standard resolvers
which are then wired into the factory (along with the message converter).

Delaying the creation of the `InvokerHandlerMethod` is not trivial; today they are
built in the CTOR; moving it to `initialize()` would prevent the fast failure for
a badly configured bean; the proper solution might be to make the MMIHs beans themselves.

Polishing - PR Comments
2017-11-15 14:07:14 -05:00
Artem Bilan
7ca20e53f7 GH-2268: Add RedisHeaders.MESSAGE_SOURCE header
Resolves: /spring-projects/spring-integration#2268

* To indicate the source the Redis message in the `RedisInboundChannelAdapter`
populate the `RedisHeaders.MESSAGE_SOURCE` header to the messages to produce
* Fix the `SimpleMessageConverter` to populate the provided `MessageHeaders`
to the message to produce

* Add `toMessage(T object, @Nullable Map<String, Object> headers)`
to the `InboundMessageMapper` to propagate additional header
to the message to create
* Rework all the out-of-the-box `InboundMessageMapper` implementations
to properly propagate additional headers via `toMessage()`
from the `SimpleMessageConverter`
* Provide optimizations in the `InboundMessageMapper` implementations
do not re-create messages
* Refactor `MutableMessage.toString()` to align with the `GenericMessage`

* Add more `@Nullable` to method arguments
* Increase latch wait timeout in the `EndpointParserTests`
* Address `redis.adoc` PR comment
2017-11-15 11:06:18 -05:00
Gary Russell
70c166fbfd INT-4362: MMIH Catch Conversion Exception
JIRA: https://jira.spring.io/browse/INT-4362

INT-4312 added a JSON conversion when there is a single method with a non-String parameter.

Add more tests for parameters of type `Message`.

Catch conversion exceptions and use the message as-is if the conversion fails.
2017-11-13 16:53:40 -05:00
Artem Bilan
8c89d0ef98 Fix QueueChannelSpec.priority hook
* Since we already have `PriorityChannelSpec` that isn't
`QueueChannelSpec` responsibility to worry about `priority` option.
More over it has been done wrongly and `MessageGroupQueue.setPriority()`
has been called unconditionally by the provided `ChannelMessageStore` type

* Fix `PriorityChannelSpec` logic as well:
- set `this.messageGroupQueue.setPriority(true);` to check the state of
the provided `PriorityCapableChannelMessageStore`
- fix assert condition in the `doGet()`

* And simple compiled SpEL test-case for the JDK Proxy
2017-11-13 16:39:07 -05:00
Artem Bilan
f7e75223c7 INT-4361: Add a role() hook to Java DSL
JIRA: https://jira.spring.io/browse/INT-4361

* To get a gain of the method chain code flow and avoid extra annotation
parsing, add `.role(String)` hook to the `EndpointSpec`
* Delegate the provided `role` property to the `AbstractEndpoint`
* Register `AbstractEndpoint` as itself `SmartLifecycle` in the
`SmartLifecycleRoleController`
* Add `destroy()` to the `AbstractEndpoint` and remove it from the
`SmartLifecycleRoleController`
* Provide some Java 8 code style refactoring

* Rework XML parsers and Annotation processors to populate `role`
property on the `AbstractEndpoint`
* Wrap `roleController` bean extraction to the `NoSuchBeanDefinitionException` catch
* Fix several `AbstractEndpoint` implementation to properly call
`super.onInit()` which has been missed before
2017-11-10 13:58:28 -05:00
Artem Bilan
37daeae094 INT-4294: CorrelatingMHs: Improve JavaDocs
JIRA: https://jira.spring.io/browse/INT-4294

* Clarify the Aggregator and Resequencer behavior in the `afterRelease()`
implementation.
2017-11-10 11:24:52 -05:00