INT-4193: Large Group Aggregation Performance

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

When using the internal `SequenceAwareMessageGroup` within an correlating
message handler, the messages were copied to a new collection before
checking for duplicate sequences in `canAdd()`.

This was unnecessary since we never add anything to this group, if `canAdd()`
returns true, the message is added to the store; this group is discarded.

Instead, use the message collection from the original group; although it is
not modifiable, this is not an issue because we don't need to modify it.

Conflicts:
	spring-integration-core/src/main/java/org/springframework/integration/store/SimpleMessageGroup.java
	spring-integration-core/src/main/java/org/springframework/integration/store/SimpleMessageGroupFactory.java
	src/reference/asciidoc/aggregator.adoc

* Polishing `aggregator.adoc` to reflect reality
This commit is contained in:
Gary Russell
2016-12-22 13:53:48 -05:00
committed by Artem Bilan
parent 168d91cbaa
commit 318bb4c4b7
5 changed files with 59 additions and 17 deletions

View File

@@ -753,13 +753,20 @@ public abstract class AbstractCorrelatingMessageHandler extends AbstractMessageP
protected static class SequenceAwareMessageGroup extends SimpleMessageGroup {
public SequenceAwareMessageGroup(MessageGroup messageGroup) {
super(messageGroup);
/*
* Since this group is temporary, and never added to, we simply use the
* supplied group's message collection for the lookup rather than creating a
* new group.
*/
super(messageGroup.getMessages(), null, messageGroup.getGroupId(), messageGroup.getTimestamp(),
messageGroup.isComplete(), true);
}
/**
* This method determines whether messages have been added to this group that supersede the given message based on
* its sequence id. This can be helpful to avoid ending up with sequences larger than their required sequence size
* or sequences that are missing certain sequence numbers.
* This method determines whether messages have been added to this group that
* supersede the given message based on its sequence id. This can be helpful to
* avoid ending up with sequences larger than their required sequence size or
* sequences that are missing certain sequence numbers.
*/
@Override
public boolean canAdd(Message<?> message) {

View File

@@ -67,20 +67,22 @@ public class SimpleMessageGroup implements MessageGroup {
public SimpleMessageGroup(Collection<? extends Message<?>> messages, Object groupId, long timestamp,
boolean complete) {
this(new LinkedHashSet<Message<?>>(), messages, groupId, timestamp, complete);
this(new LinkedHashSet<Message<?>>(), messages, groupId, timestamp, complete, false);
}
SimpleMessageGroup(Collection<Message<?>> internalStore, Collection<? extends Message<?>> messages, Object groupId,
long timestamp, boolean complete) {
protected SimpleMessageGroup(Collection<Message<?>> internalStore, Collection<? extends Message<?>> messages,
Object groupId, long timestamp, boolean complete, boolean storePreLoaded) {
Assert.notNull(internalStore, "'internalStore' must not be null");
Assert.notNull(messages, "'messages' must not be null");
this.messages = internalStore;
this.groupId = groupId;
this.timestamp = timestamp;
this.complete = complete;
for (Message<?> message : messages) {
if (message != null) { //see INT-2666
addMessage(message);
if (!storePreLoaded) {
Assert.notNull(messages, "'messages' must not be null");
for (Message<?> message : messages) {
if (message != null) { //see INT-2666
addMessage(message);
}
}
}
}

View File

@@ -56,7 +56,7 @@ public class SimpleMessageGroupFactory implements MessageGroupFactory {
@Override
public MessageGroup create(Collection<? extends Message<?>> messages, Object groupId, long timestamp,
boolean complete) {
return new SimpleMessageGroup(this.type.get(), messages, groupId, timestamp, complete);
return new SimpleMessageGroup(this.type.get(), messages, groupId, timestamp, complete, false);
}
@Override

View File

@@ -26,10 +26,12 @@ import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import org.junit.Test;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.GenericMessage;
@@ -40,6 +42,7 @@ import org.springframework.util.StopWatch;
* @author Oleg Zhurakousky
* @author Dave Syer
* @author Artem Bilan
* @author Gary Russell
*/
public class SimpleMessageGroupTests {
@@ -54,11 +57,12 @@ public class SimpleMessageGroupTests {
Constructor<SimpleMessageGroup> ctr = clazz.getDeclaredConstructor(MessageGroup.class);
ctr.setAccessible(true);
group = ctr.newInstance(group);
new DirectFieldAccessor(group).setPropertyValue("messages", new HashSet<Message<?>>());
}
@Test
public void shouldFindSupersedingMessagesIfSequenceAware() throws Exception {
this.prepareForSequenceAwareMessageGroup();
prepareForSequenceAwareMessageGroup();
final Message<?> message1 = MessageBuilder.withPayload("test").setSequenceNumber(1).build();
final Message<?> message2 = MessageBuilder.fromMessage(message1).setSequenceNumber(1).build();
assertThat(group.canAdd(message1), is(true));
@@ -69,7 +73,7 @@ public class SimpleMessageGroupTests {
@Test
public void shouldIgnoreMessagesWithZeroSequenceNumberIfSequenceAware() throws Exception {
this.prepareForSequenceAwareMessageGroup();
prepareForSequenceAwareMessageGroup();
final Message<?> message1 = MessageBuilder.withPayload("test").build();
final Message<?> message2 = MessageBuilder.fromMessage(message1).build();
assertThat(group.canAdd(message1), is(true));