INT-3387: MessageGroupStore Improvements
JIRA: https://jira.spring.io/browse/INT-3387, https://jira.spring.io/browse/INT-3806 * Introduce ``` MessageGroupStore void addMessagesToGroup(Object groupId, Message<?>... messages); ``` And implement it in all stores. * Use new `addMessagesToGroup` where it is reasonable, e.g. `DelayHandler` * Optimize test-case to use a new store method (where it is possible) * Fix timing delays in the `JdbcMessageStoreTests` * Introduce `PersistentMessageGroup` * Add `AbstractMessageGroupStore#proxyMessageGroupForLazyLoad` to wrap the raw `MessageGroup` to the `PersistentMessageGroup` for lazy-load * Rework `MessageGroupMetadata` do not be `immutable` and allow to store/restore in the `AbstractKeyValueMessageStore` only the `MessageGroupMetadata` * Refactor `ResequencingMessageHandler` and `SequenceSizeReleaseStrategy` a bit for better performance when interact with the `MessageGroup` * Add `AbstractMessageGroupStore#setLazyLoadMessageGroups` to switch off the `lazy-load` behavior and restore the previous full `MessageGroup` logic * Add `What's New` note and `message-store.adoc` paragraph for the lazy-load functionality `GroupType.PERSISTENT` and not lazy by default PR Comments Fix `JdbcMessageStoreTests` timing issues Address PR comments * Add performance test to the `ConfigurableMongoDbMessageGroupStoreTests` * Add JavaDocs for the `MessageGroupFactory` methods * Add `log4j.properties` into the `test` MongoDB module for better traceability * Fix `JdbcMessageStore#getOneMessageFromGroup()` over the `doPollForMessage()` delegation. The `jdbcTemplate.queryForObject()` requires exactly one and only one raw in `resultSet` * Add performance test results into the `message-store.adoc`
This commit is contained in:
committed by
Gary Russell
parent
4e4763d24f
commit
286c421c1a
@@ -17,7 +17,9 @@
|
||||
package org.springframework.integration.mongodb.store;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -49,8 +51,9 @@ import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
import org.springframework.data.mongodb.core.query.Criteria;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.data.mongodb.core.query.Update;
|
||||
import org.springframework.integration.store.AbstractBatchingMessageGroupStore;
|
||||
import org.springframework.integration.store.AbstractMessageGroupStore;
|
||||
import org.springframework.integration.store.BasicMessageGroupStore;
|
||||
import org.springframework.integration.store.MessageGroup;
|
||||
import org.springframework.integration.support.DefaultMessageBuilderFactory;
|
||||
import org.springframework.integration.support.MessageBuilderFactory;
|
||||
import org.springframework.integration.support.utils.IntegrationUtils;
|
||||
@@ -66,7 +69,7 @@ import org.springframework.util.Assert;
|
||||
* @since 4.0
|
||||
*/
|
||||
|
||||
public abstract class AbstractConfigurableMongoDbMessageStore extends AbstractBatchingMessageGroupStore
|
||||
public abstract class AbstractConfigurableMongoDbMessageStore extends AbstractMessageGroupStore
|
||||
implements BasicMessageGroupStore, InitializingBean, ApplicationContextAware {
|
||||
|
||||
public final static String SEQUENCE_NAME = "messagesSequence";
|
||||
@@ -219,6 +222,47 @@ public abstract class AbstractConfigurableMongoDbMessageStore extends AbstractBa
|
||||
return Query.query(Criteria.where(MessageDocumentFields.GROUP_ID).is(groupId));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public MessageGroup removeMessageFromGroup(Object key, Message<?> messageToRemove) {
|
||||
throw new UnsupportedOperationException("The operation isn't implemented for this class.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeMessagesFromGroup(Object key, Collection<Message<?>> messages) {
|
||||
throw new UnsupportedOperationException("The operation isn't implemented for this class.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLastReleasedSequenceNumberForGroup(Object groupId, int sequenceNumber) {
|
||||
throw new UnsupportedOperationException("The operation isn't implemented for this class.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<MessageGroup> iterator() {
|
||||
throw new UnsupportedOperationException("The operation isn't implemented for this class.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void completeGroup(Object groupId) {
|
||||
throw new UnsupportedOperationException("The operation isn't implemented for this class.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message<?> getOneMessageFromGroup(Object groupId) {
|
||||
throw new UnsupportedOperationException("The operation isn't implemented for this class.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addMessagesToGroup(Object groupId, Message<?>... messages) {
|
||||
throw new UnsupportedOperationException("The operation isn't implemented for this class.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Message<?>> getMessagesForGroup(Object groupId) {
|
||||
throw new UnsupportedOperationException("The operation isn't implemented for this class.");
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link GenericConverter} implementation to convert {@link Message} to
|
||||
* serialized {@link byte[]} to store {@link Message} to the MongoDB.
|
||||
|
||||
@@ -35,6 +35,7 @@ import org.springframework.integration.store.MessageGroup;
|
||||
import org.springframework.integration.store.MessageGroupMetadata;
|
||||
import org.springframework.integration.store.MessageGroupStore;
|
||||
import org.springframework.integration.store.MessageStore;
|
||||
import org.springframework.integration.store.SimpleMessageGroup;
|
||||
import org.springframework.jmx.export.annotation.ManagedAttribute;
|
||||
import org.springframework.jmx.export.annotation.ManagedOperation;
|
||||
import org.springframework.messaging.Message;
|
||||
@@ -53,7 +54,7 @@ import org.springframework.util.Assert;
|
||||
* @since 3.0
|
||||
*/
|
||||
public class ConfigurableMongoDbMessageStore extends AbstractConfigurableMongoDbMessageStore
|
||||
implements MessageStore, MessageGroupStore, Iterable<MessageGroup> {
|
||||
implements MessageStore {
|
||||
|
||||
public final static String DEFAULT_COLLECTION_NAME = "configurableStoreMessages";
|
||||
|
||||
@@ -141,40 +142,39 @@ public class ConfigurableMongoDbMessageStore extends AbstractConfigurableMongoDb
|
||||
Assert.notNull(groupId, "'groupId' must not be null");
|
||||
|
||||
Query query = groupOrderQuery(groupId);
|
||||
List<MessageDocument> messageDocuments = this.mongoTemplate.find(query, MessageDocument.class,
|
||||
this.collectionName);
|
||||
MessageDocument messageDocument = this.mongoTemplate.findOne(query, MessageDocument.class, this.collectionName);
|
||||
|
||||
long createdTime = 0;
|
||||
long lastModifiedTime = 0;
|
||||
int lastReleasedSequence = 0;
|
||||
boolean complete = false;
|
||||
if (messageDocument != null) {
|
||||
long createdTime = messageDocument.getCreatedTime();
|
||||
long lastModifiedTime = messageDocument.getLastModifiedTime();
|
||||
boolean complete = messageDocument.isComplete();
|
||||
int lastReleasedSequence = messageDocument.getLastReleasedSequence();
|
||||
|
||||
MessageGroup messageGroup = getMessageGroupFactory()
|
||||
.create(this, groupId, createdTime, complete);
|
||||
messageGroup.setLastModified(lastModifiedTime);
|
||||
messageGroup.setLastReleasedMessageSequenceNumber(lastReleasedSequence);
|
||||
return messageGroup;
|
||||
|
||||
if (messageDocuments.size() > 0) {
|
||||
MessageDocument document = messageDocuments.get(0);
|
||||
createdTime = document.getCreatedTime();
|
||||
lastModifiedTime = document.getLastModifiedTime();
|
||||
complete = document.isComplete();
|
||||
lastReleasedSequence = document.getLastReleasedSequence();
|
||||
}
|
||||
|
||||
List<Message<?>> messages = new ArrayList<Message<?>>();
|
||||
for (MessageDocument document : messageDocuments) {
|
||||
messages.add(document.getMessage());
|
||||
else {
|
||||
return new SimpleMessageGroup(groupId);
|
||||
}
|
||||
MessageGroup group = getMessageGroupFactory().create(messages, groupId, createdTime, complete);
|
||||
group.setLastReleasedMessageSequenceNumber(lastReleasedSequence);
|
||||
group.setLastModified(lastModifiedTime);
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageGroup addMessageToGroup(final Object groupId, final Message<?> message) {
|
||||
public MessageGroup addMessageToGroup(Object groupId, Message<?> message) {
|
||||
addMessagesToGroup(groupId, message);
|
||||
return getMessageGroup(groupId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addMessagesToGroup(Object groupId, Message<?>... messages) {
|
||||
Assert.notNull(groupId, "'groupId' must not be null");
|
||||
Assert.notNull(message, "'message' must not be null");
|
||||
Assert.notNull(messages, "'message' must not be null");
|
||||
|
||||
Query query = groupOrderQuery(groupId);
|
||||
MessageDocument messageDocument = mongoTemplate.findOne(query, MessageDocument.class, collectionName);
|
||||
MessageDocument messageDocument = this.mongoTemplate.findOne(query, MessageDocument.class, this.collectionName);
|
||||
|
||||
long createdTime = 0;
|
||||
int lastReleasedSequence = 0;
|
||||
@@ -186,18 +186,17 @@ public class ConfigurableMongoDbMessageStore extends AbstractConfigurableMongoDb
|
||||
complete = messageDocument.isComplete();
|
||||
}
|
||||
|
||||
MessageDocument document = new MessageDocument(message);
|
||||
document.setGroupId(groupId);
|
||||
document.setComplete(complete);
|
||||
document.setLastReleasedSequence(lastReleasedSequence);
|
||||
document.setCreatedTime(createdTime == 0 ? System.currentTimeMillis() : createdTime);
|
||||
document.setLastModifiedTime(System.currentTimeMillis());
|
||||
document.setSequence(getNextId());
|
||||
|
||||
addMessageDocument(document);
|
||||
|
||||
return getMessageGroup(groupId);
|
||||
for (Message<?> message : messages) {
|
||||
MessageDocument document = new MessageDocument(message);
|
||||
document.setGroupId(groupId);
|
||||
document.setComplete(complete);
|
||||
document.setLastReleasedSequence(lastReleasedSequence);
|
||||
document.setCreatedTime(createdTime == 0 ? System.currentTimeMillis() : createdTime);
|
||||
document.setLastModifiedTime(System.currentTimeMillis());
|
||||
document.setSequence(getNextId());
|
||||
|
||||
addMessageDocument(document);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -335,7 +334,28 @@ public class ConfigurableMongoDbMessageStore extends AbstractConfigurableMongoDb
|
||||
|
||||
@Override
|
||||
public Message<?> getOneMessageFromGroup(Object groupId) {
|
||||
throw new UnsupportedOperationException("Not yet implemented for this store");
|
||||
Assert.notNull(groupId, "'groupId' must not be null");
|
||||
Query query = groupOrderQuery(groupId);
|
||||
MessageDocument messageDocument = this.mongoTemplate.findOne(query, MessageDocument.class, this.collectionName);
|
||||
if (messageDocument != null) {
|
||||
return messageDocument.getMessage();
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Message<?>> getMessagesForGroup(Object groupId) {
|
||||
Assert.notNull(groupId, "'groupId' must not be null");
|
||||
Query query = groupOrderQuery(groupId);
|
||||
List<MessageDocument> documents = this.mongoTemplate.find(query, MessageDocument.class, this.collectionName);
|
||||
List<Message<?>> messages = new ArrayList<Message<?>>();
|
||||
|
||||
for (MessageDocument document : documents) {
|
||||
messages.add(document.getMessage());
|
||||
}
|
||||
return messages;
|
||||
}
|
||||
|
||||
private void expire(MessageGroup group) {
|
||||
|
||||
@@ -60,6 +60,7 @@ import org.springframework.integration.store.AbstractMessageGroupStore;
|
||||
import org.springframework.integration.store.MessageGroup;
|
||||
import org.springframework.integration.store.MessageGroupStore;
|
||||
import org.springframework.integration.store.MessageStore;
|
||||
import org.springframework.integration.store.SimpleMessageGroup;
|
||||
import org.springframework.integration.support.MutableMessage;
|
||||
import org.springframework.integration.support.MutableMessageBuilder;
|
||||
import org.springframework.jmx.export.annotation.ManagedAttribute;
|
||||
@@ -242,37 +243,30 @@ public class MongoDbMessageStore extends AbstractMessageGroupStore
|
||||
public MessageGroup getMessageGroup(Object groupId) {
|
||||
Assert.notNull(groupId, "'groupId' must not be null");
|
||||
Query query = whereGroupIdOrder(groupId);
|
||||
List<MessageWrapper> messageWrappers = this.template.find(query, MessageWrapper.class, this.collectionName);
|
||||
List<Message<?>> messages = new ArrayList<Message<?>>();
|
||||
long timestamp = 0;
|
||||
long lastModified = 0;
|
||||
int lastReleasedSequenceNumber = 0;
|
||||
boolean completeGroup = false;
|
||||
if (messageWrappers.size() > 0) {
|
||||
MessageWrapper messageWrapper = messageWrappers.get(0);
|
||||
timestamp = messageWrapper.get_Group_timestamp();
|
||||
lastModified = messageWrapper.get_Group_update_timestamp();
|
||||
completeGroup = messageWrapper.get_Group_complete();
|
||||
lastReleasedSequenceNumber = messageWrapper.get_LastReleasedSequenceNumber();
|
||||
}
|
||||
MessageWrapper messageWrapper = this.template.findOne(query, MessageWrapper.class, this.collectionName);
|
||||
|
||||
for (MessageWrapper messageWrapper : messageWrappers) {
|
||||
messages.add(messageWrapper.getMessage());
|
||||
}
|
||||
if (messageWrapper != null) {
|
||||
long createdTime = messageWrapper.get_Group_timestamp();
|
||||
long lastModifiedTime = messageWrapper.get_Group_update_timestamp();
|
||||
boolean complete = messageWrapper.get_Group_complete();
|
||||
int lastReleasedSequence = messageWrapper.get_LastReleasedSequenceNumber();
|
||||
|
||||
MessageGroup messageGroup = getMessageGroupFactory().create(messages, groupId, timestamp, completeGroup);
|
||||
messageGroup.setLastModified(lastModified);
|
||||
if (lastReleasedSequenceNumber > 0) {
|
||||
messageGroup.setLastReleasedMessageSequenceNumber(lastReleasedSequenceNumber);
|
||||
}
|
||||
MessageGroup messageGroup = getMessageGroupFactory()
|
||||
.create(this, groupId, createdTime, complete);
|
||||
messageGroup.setLastModified(lastModifiedTime);
|
||||
messageGroup.setLastReleasedMessageSequenceNumber(lastReleasedSequence);
|
||||
return messageGroup;
|
||||
|
||||
return messageGroup;
|
||||
}
|
||||
else {
|
||||
return new SimpleMessageGroup(groupId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageGroup addMessageToGroup(final Object groupId, final Message<?> message) {
|
||||
public void addMessagesToGroup(Object groupId, Message<?>... messages) {
|
||||
Assert.notNull(groupId, "'groupId' must not be null");
|
||||
Assert.notNull(message, "'message' must not be null");
|
||||
Assert.notNull(messages, "'message' must not be null");
|
||||
Query query = whereGroupIdOrder(groupId);
|
||||
MessageWrapper messageDocument = this.template.findOne(query, MessageWrapper.class, this.collectionName);
|
||||
|
||||
@@ -286,18 +280,17 @@ public class MongoDbMessageStore extends AbstractMessageGroupStore
|
||||
complete = messageDocument.get_Group_complete();
|
||||
}
|
||||
|
||||
for (Message<?> message : messages) {
|
||||
MessageWrapper wrapper = new MessageWrapper(message);
|
||||
wrapper.set_GroupId(groupId);
|
||||
wrapper.set_Group_timestamp(createdTime == 0 ? System.currentTimeMillis() : createdTime);
|
||||
wrapper.set_Group_update_timestamp(System.currentTimeMillis());
|
||||
wrapper.set_Group_complete(complete);
|
||||
wrapper.set_LastReleasedSequenceNumber(lastReleasedSequence);
|
||||
wrapper.setSequence(getNextId());
|
||||
|
||||
MessageWrapper wrapper = new MessageWrapper(message);
|
||||
wrapper.set_GroupId(groupId);
|
||||
wrapper.set_Group_timestamp(createdTime == 0 ? System.currentTimeMillis() : createdTime);
|
||||
wrapper.set_Group_update_timestamp(System.currentTimeMillis());
|
||||
wrapper.set_Group_complete(complete);
|
||||
wrapper.set_LastReleasedSequenceNumber(lastReleasedSequence);
|
||||
wrapper.setSequence(getNextId());
|
||||
|
||||
addMessageDocument(wrapper);
|
||||
return getMessageGroup(groupId);
|
||||
|
||||
addMessageDocument(wrapper);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -393,6 +386,32 @@ public class MongoDbMessageStore extends AbstractMessageGroupStore
|
||||
this.updateGroup(groupId, lastModifiedUpdate().set(GROUP_COMPLETE_KEY, true));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message<?> getOneMessageFromGroup(Object groupId) {
|
||||
Assert.notNull(groupId, "'groupId' must not be null");
|
||||
Query query = whereGroupIdOrder(groupId);
|
||||
MessageWrapper messageWrapper = this.template.findOne(query, MessageWrapper.class, this.collectionName);
|
||||
if (messageWrapper != null) {
|
||||
return messageWrapper.getMessage();
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Message<?>> getMessagesForGroup(Object groupId) {
|
||||
Assert.notNull(groupId, "'groupId' must not be null");
|
||||
Query query = whereGroupIdOrder(groupId);
|
||||
List<MessageWrapper> messageWrappers = this.template.find(query, MessageWrapper.class, this.collectionName);
|
||||
List<Message<?>> messages = new ArrayList<Message<?>>();
|
||||
|
||||
for (MessageWrapper messageWrapper : messageWrappers) {
|
||||
messages.add(messageWrapper.getMessage());
|
||||
}
|
||||
return messages;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ManagedAttribute
|
||||
public int getMessageCountForAllMessageGroups() {
|
||||
|
||||
@@ -16,10 +16,12 @@
|
||||
|
||||
package org.springframework.integration.mongodb.store;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -42,7 +44,6 @@ import org.springframework.integration.store.AbstractBatchingMessageGroupStore;
|
||||
import org.springframework.integration.store.MessageGroup;
|
||||
import org.springframework.integration.store.MessageGroupStore;
|
||||
import org.springframework.integration.store.MessageStore;
|
||||
import org.springframework.integration.store.SimpleMessageGroup;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
@@ -63,10 +64,11 @@ public abstract class AbstractMongoDbMessageGroupStoreTests extends MongoDbAvail
|
||||
public void testNonExistingEmptyMessageGroup() throws Exception {
|
||||
this.cleanupCollections(new SimpleMongoDbFactory(new MongoClient(), "test"));
|
||||
MessageGroupStore store = getMessageGroupStore();
|
||||
store.addMessagesToGroup(1, new GenericMessage<Object>("foo"));
|
||||
MessageGroup messageGroup = store.getMessageGroup(1);
|
||||
assertNotNull(messageGroup);
|
||||
assertTrue(messageGroup instanceof SimpleMessageGroup);
|
||||
assertEquals(0, messageGroup.size());
|
||||
assertThat(messageGroup.getClass().getName(), containsString("PersistentMessageGroup"));
|
||||
assertEquals(1, messageGroup.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -78,7 +80,7 @@ public abstract class AbstractMongoDbMessageGroupStoreTests extends MongoDbAvail
|
||||
MessageGroup messageGroup = store.getMessageGroup(1);
|
||||
Message<?> messageA = new GenericMessage<String>("A");
|
||||
Message<?> messageB = new GenericMessage<String>("B");
|
||||
store.addMessageToGroup(1, messageA);
|
||||
store.addMessagesToGroup(1, messageA);
|
||||
messageGroup = store.addMessageToGroup(1, messageB);
|
||||
assertNotNull(messageGroup);
|
||||
assertEquals(2, messageGroup.size());
|
||||
@@ -101,7 +103,7 @@ public abstract class AbstractMongoDbMessageGroupStoreTests extends MongoDbAvail
|
||||
Message<?> messageA = MessageBuilder.withPayload("A").setHeader("foo", uuidA).build();
|
||||
UUID uuidB = UUID.randomUUID();
|
||||
Message<?> messageB = MessageBuilder.withPayload("B").setHeader("foo", uuidB).build();
|
||||
store.addMessageToGroup(id, messageA);
|
||||
store.addMessagesToGroup(id, messageA);
|
||||
messageGroup = store.addMessageToGroup(id, messageB);
|
||||
assertNotNull(messageGroup);
|
||||
assertEquals(2, messageGroup.size());
|
||||
@@ -122,8 +124,7 @@ public abstract class AbstractMongoDbMessageGroupStoreTests extends MongoDbAvail
|
||||
MessageGroupStore store = this.getMessageGroupStore();
|
||||
Message<?> messageA = new GenericMessage<String>("A");
|
||||
Message<?> messageB = new GenericMessage<String>("B");
|
||||
store.addMessageToGroup(1, messageA);
|
||||
store.addMessageToGroup(1, messageB);
|
||||
store.addMessagesToGroup(1, messageA, messageB);
|
||||
assertEquals(2, store.messageGroupSize(1));
|
||||
}
|
||||
|
||||
@@ -134,9 +135,9 @@ public abstract class AbstractMongoDbMessageGroupStoreTests extends MongoDbAvail
|
||||
MessageGroupStore store = this.getMessageGroupStore();
|
||||
Message<?> messageA = new GenericMessage<String>("A");
|
||||
Message<?> messageB = new GenericMessage<String>("B");
|
||||
store.addMessageToGroup(1, messageA);
|
||||
store.addMessagesToGroup(1, messageA);
|
||||
Thread.sleep(10);
|
||||
store.addMessageToGroup(1, messageB);
|
||||
store.addMessagesToGroup(1, messageB);
|
||||
assertEquals(2, store.messageGroupSize(1));
|
||||
Message<?> out = store.pollMessageFromGroup(1);
|
||||
assertNotNull(out);
|
||||
@@ -153,10 +154,10 @@ public abstract class AbstractMongoDbMessageGroupStoreTests extends MongoDbAvail
|
||||
this.cleanupCollections(new SimpleMongoDbFactory(new MongoClient(), "test"));
|
||||
MessageGroupStore store = this.getMessageGroupStore();
|
||||
Message<?> messageA = new GenericMessage<String>("A");
|
||||
store.addMessageToGroup(1, messageA);
|
||||
store.addMessageToGroup(2, messageA);
|
||||
store.addMessageToGroup(3, messageA);
|
||||
store.addMessageToGroup(4, messageA);
|
||||
store.addMessagesToGroup(1, messageA);
|
||||
store.addMessagesToGroup(2, messageA);
|
||||
store.addMessagesToGroup(3, messageA);
|
||||
store.addMessagesToGroup(4, messageA);
|
||||
assertEquals(1, store.messageGroupSize(1));
|
||||
assertEquals(1, store.messageGroupSize(2));
|
||||
assertEquals(1, store.messageGroupSize(3));
|
||||
@@ -190,10 +191,10 @@ public abstract class AbstractMongoDbMessageGroupStoreTests extends MongoDbAvail
|
||||
MessageGroupStore store = this.getMessageGroupStore();
|
||||
|
||||
Message<?> messageA = new GenericMessage<String>("A");
|
||||
store.addMessageToGroup(1, messageA);
|
||||
store.addMessageToGroup(2, messageA);
|
||||
store.addMessageToGroup(3, messageA);
|
||||
store.addMessageToGroup(4, messageA);
|
||||
store.addMessagesToGroup(1, messageA);
|
||||
store.addMessagesToGroup(2, messageA);
|
||||
store.addMessagesToGroup(3, messageA);
|
||||
store.addMessagesToGroup(4, messageA);
|
||||
assertEquals(1, store.messageGroupSize(1));
|
||||
assertEquals(1, store.messageGroupSize(2));
|
||||
assertEquals(1, store.messageGroupSize(3));
|
||||
@@ -258,7 +259,7 @@ public abstract class AbstractMongoDbMessageGroupStoreTests extends MongoDbAvail
|
||||
MessageGroup messageGroup = store.getMessageGroup(1);
|
||||
Message<?> messageA = new GenericMessage<String>("A");
|
||||
Message<?> messageB = new GenericMessage<String>("B");
|
||||
store.addMessageToGroup(1, messageA);
|
||||
store.addMessagesToGroup(1, messageA);
|
||||
messageGroup = store.addMessageToGroup(1, messageB);
|
||||
assertNotNull(messageGroup);
|
||||
assertEquals(2, messageGroup.size());
|
||||
@@ -306,7 +307,7 @@ public abstract class AbstractMongoDbMessageGroupStoreTests extends MongoDbAvail
|
||||
MessageGroup messageGroup = store.getMessageGroup(1);
|
||||
assertNotNull(messageGroup);
|
||||
Message<?> message = new GenericMessage<String>("Hello");
|
||||
store.addMessageToGroup(messageGroup.getGroupId(), message);
|
||||
store.addMessagesToGroup(messageGroup.getGroupId(), message);
|
||||
store.completeGroup(messageGroup.getGroupId());
|
||||
messageGroup = store.getMessageGroup(1);
|
||||
assertTrue(messageGroup.isComplete());
|
||||
@@ -321,7 +322,7 @@ public abstract class AbstractMongoDbMessageGroupStoreTests extends MongoDbAvail
|
||||
MessageGroup messageGroup = store.getMessageGroup(1);
|
||||
assertNotNull(messageGroup);
|
||||
Message<?> message = new GenericMessage<String>("Hello");
|
||||
store.addMessageToGroup(messageGroup.getGroupId(), message);
|
||||
store.addMessagesToGroup(messageGroup.getGroupId(), message);
|
||||
store.setLastReleasedSequenceNumberForGroup(messageGroup.getGroupId(), 5);
|
||||
messageGroup = store.getMessageGroup(1);
|
||||
assertEquals(5, messageGroup.getLastReleasedMessageSequenceNumber());
|
||||
@@ -335,8 +336,7 @@ public abstract class AbstractMongoDbMessageGroupStoreTests extends MongoDbAvail
|
||||
|
||||
MessageGroup messageGroup = store.getMessageGroup(1);
|
||||
Message<?> message = new GenericMessage<String>("2");
|
||||
store.addMessageToGroup(1, new GenericMessage<String>("1"));
|
||||
store.addMessageToGroup(1, message);
|
||||
store.addMessagesToGroup(1, new GenericMessage<String>("1"), message);
|
||||
messageGroup = store.addMessageToGroup(1, new GenericMessage<String>("3"));
|
||||
assertNotNull(messageGroup);
|
||||
assertEquals(3, messageGroup.size());
|
||||
@@ -355,9 +355,7 @@ public abstract class AbstractMongoDbMessageGroupStoreTests extends MongoDbAvail
|
||||
MessageGroupStore store2 = this.getMessageGroupStore();
|
||||
|
||||
Message<?> message = new GenericMessage<String>("1");
|
||||
store1.addMessageToGroup(1, message);
|
||||
store2.addMessageToGroup(1, new GenericMessage<String>("2"));
|
||||
store1.addMessageToGroup(1, new GenericMessage<String>("3"));
|
||||
store1.addMessagesToGroup(1, message, new GenericMessage<String>("2"), new GenericMessage<String>("3"));
|
||||
|
||||
MessageGroupStore store3 = this.getMessageGroupStore();
|
||||
|
||||
@@ -380,9 +378,9 @@ public abstract class AbstractMongoDbMessageGroupStoreTests extends MongoDbAvail
|
||||
MessageGroupStore store2 = this.getMessageGroupStore();
|
||||
|
||||
Message<?> message = new GenericMessage<String>("1");
|
||||
store2.addMessageToGroup(1, message);
|
||||
store1.addMessageToGroup(2, new GenericMessage<String>("2"));
|
||||
store2.addMessageToGroup(3, new GenericMessage<String>("3"));
|
||||
store2.addMessagesToGroup(1, message);
|
||||
store1.addMessagesToGroup(2, new GenericMessage<String>("2"));
|
||||
store2.addMessagesToGroup(3, new GenericMessage<String>("3"));
|
||||
|
||||
MessageGroupStore store3 = this.getMessageGroupStore();
|
||||
Iterator<MessageGroup> iterator = store3.iterator();
|
||||
@@ -415,7 +413,7 @@ public abstract class AbstractMongoDbMessageGroupStoreTests extends MongoDbAvail
|
||||
List<Message<?>> messages = new ArrayList<Message<?>>();
|
||||
for (int i = 0; i < 25; i++) {
|
||||
Message<String> message = MessageBuilder.withPayload("foo").setCorrelationId(groupId).build();
|
||||
messageStore.addMessageToGroup(groupId, message);
|
||||
messageStore.addMessagesToGroup(groupId, message);
|
||||
messages.add(message);
|
||||
}
|
||||
MessageGroup group = messageStore.getMessageGroup(groupId);
|
||||
@@ -477,20 +475,41 @@ public abstract class AbstractMongoDbMessageGroupStoreTests extends MongoDbAvail
|
||||
MessageChannel input = context.getBean("inputChannel", MessageChannel.class);
|
||||
QueueChannel output = context.getBean("outputChannel", QueueChannel.class);
|
||||
|
||||
Message<?> m1 = MessageBuilder.withPayload("1").setSequenceNumber(1).setSequenceSize(3).setCorrelationId(1).build();
|
||||
Message<?> m2 = MessageBuilder.withPayload("2").setSequenceNumber(2).setSequenceSize(3).setCorrelationId(1).build();
|
||||
Message<?> m1 = MessageBuilder.withPayload("1")
|
||||
.setSequenceNumber(1)
|
||||
.setSequenceSize(10)
|
||||
.setCorrelationId(1)
|
||||
.build();
|
||||
Message<?> m2 = MessageBuilder.withPayload("2")
|
||||
.setSequenceNumber(2)
|
||||
.setSequenceSize(10)
|
||||
.setCorrelationId(1)
|
||||
.build();
|
||||
input.send(m1);
|
||||
assertNull(output.receive(1000));
|
||||
input.send(m2);
|
||||
assertNull(output.receive(1000));
|
||||
|
||||
for (int i = 3; i < 10; i++) {
|
||||
input.send(MessageBuilder.withPayload("" + i)
|
||||
.setSequenceNumber(i)
|
||||
.setSequenceSize(10)
|
||||
.setCorrelationId(1)
|
||||
.build());
|
||||
}
|
||||
|
||||
context.close();
|
||||
|
||||
context = new ClassPathXmlApplicationContext(config, this.getClass());
|
||||
input = context.getBean("inputChannel", MessageChannel.class);
|
||||
output = context.getBean("outputChannel", QueueChannel.class);
|
||||
|
||||
Message<?> m3 = MessageBuilder.withPayload("3").setSequenceNumber(3).setSequenceSize(3).setCorrelationId(1).build();
|
||||
input.send(m3);
|
||||
Message<?> m10 = MessageBuilder.withPayload("10")
|
||||
.setSequenceNumber(10)
|
||||
.setSequenceSize(10)
|
||||
.setCorrelationId(1)
|
||||
.build();
|
||||
input.send(m10);
|
||||
assertNotNull(output.receive(2000));
|
||||
context.close();
|
||||
}
|
||||
@@ -511,7 +530,7 @@ public abstract class AbstractMongoDbMessageGroupStoreTests extends MongoDbAvail
|
||||
|
||||
message = MessageHistory.write(message, fooChannel);
|
||||
message = MessageHistory.write(message, barChannel);
|
||||
store.addMessageToGroup(1, message);
|
||||
store.addMessagesToGroup(1, message);
|
||||
MessageGroup group = store.getMessageGroup(1);
|
||||
assertNotNull(group);
|
||||
Collection<Message<?>> messages = group.getMessages();
|
||||
|
||||
@@ -23,6 +23,7 @@ import static org.junit.Assert.assertThat;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
@@ -34,10 +35,13 @@ import org.springframework.integration.IntegrationMessageHeaderAccessor;
|
||||
import org.springframework.integration.channel.PriorityChannel;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.mongodb.rules.MongoDbAvailable;
|
||||
import org.springframework.integration.store.AbstractMessageGroupStore;
|
||||
import org.springframework.integration.store.MessageStore;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.util.StopWatch;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.MongoClient;
|
||||
@@ -68,7 +72,49 @@ public class ConfigurableMongoDbMessageGroupStoreTests extends AbstractMongoDbMe
|
||||
@Test
|
||||
@MongoDbAvailable
|
||||
public void testWithAggregatorWithShutdown() throws Exception {
|
||||
super.testWithAggregatorWithShutdown("mongo-aggregator-confugurable-config.xml");
|
||||
super.testWithAggregatorWithShutdown("mongo-aggregator-configurable-config.xml");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("The performance test. Enough slow. Also needs the release strategy changed to size() == 1000")
|
||||
@MongoDbAvailable
|
||||
public void messageGroupStoreLazyLoadPerformance() throws Exception {
|
||||
cleanupCollections(new SimpleMongoDbFactory(new MongoClient(), "test"));
|
||||
|
||||
StopWatch watch = new StopWatch("Lazy-Load Performance");
|
||||
|
||||
int sequenceSize = 1000;
|
||||
|
||||
performLazyLoadEagerTest(watch, sequenceSize, true);
|
||||
|
||||
performLazyLoadEagerTest(watch, sequenceSize, false);
|
||||
|
||||
System. out .println(watch.prettyPrint()); // checkstyle
|
||||
}
|
||||
|
||||
private void performLazyLoadEagerTest(StopWatch watch, int sequenceSize, boolean lazyLoad) {
|
||||
ClassPathXmlApplicationContext context =
|
||||
new ClassPathXmlApplicationContext("mongo-aggregator-configurable-config.xml", getClass());
|
||||
context.refresh();
|
||||
|
||||
AbstractMessageGroupStore messageGroupStore = context.getBean("mongoStore", AbstractMessageGroupStore.class);
|
||||
messageGroupStore.setLazyLoadMessageGroups(lazyLoad);
|
||||
MessageChannel input = context.getBean("inputChannel", MessageChannel.class);
|
||||
QueueChannel output = context.getBean("outputChannel", QueueChannel.class);
|
||||
|
||||
watch.start(lazyLoad ? "Lazy-Load" : "Eager");
|
||||
|
||||
for (int i = 0; i < sequenceSize; i++) {
|
||||
input.send(MessageBuilder.withPayload("" + i)
|
||||
.setCorrelationId(1)
|
||||
.build());
|
||||
}
|
||||
|
||||
assertNotNull(output.receive(20000));
|
||||
|
||||
watch.stop();
|
||||
|
||||
context.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -16,13 +16,14 @@
|
||||
|
||||
package org.springframework.integration.mongodb.store;
|
||||
|
||||
import com.mongodb.MongoClient;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
|
||||
import org.springframework.integration.mongodb.rules.MongoDbAvailable;
|
||||
import org.springframework.integration.store.MessageStore;
|
||||
|
||||
import com.mongodb.MongoClient;
|
||||
|
||||
/**
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Gary Russell
|
||||
@@ -33,7 +34,8 @@ public class MongoDbMessageGroupStoreTests extends AbstractMongoDbMessageGroupSt
|
||||
|
||||
@Override
|
||||
protected MongoDbMessageStore getMessageGroupStore() throws Exception {
|
||||
MongoDbMessageStore mongoDbMessageStore = new MongoDbMessageStore(new SimpleMongoDbFactory(new MongoClient(), "test"));
|
||||
MongoDbMessageStore mongoDbMessageStore =
|
||||
new MongoDbMessageStore(new SimpleMongoDbFactory(new MongoClient(), "test"));
|
||||
mongoDbMessageStore.afterPropertiesSet();
|
||||
return mongoDbMessageStore;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd">
|
||||
|
||||
<int:aggregator input-channel="inputChannel" output-channel="outputChannel" message-store="mongoStore"/>
|
||||
<int:aggregator input-channel="inputChannel" output-channel="outputChannel" message-store="mongoStore"
|
||||
release-strategy-expression="size() == 10"/>
|
||||
|
||||
<int:channel id="outputChannel">
|
||||
<int:queue/>
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd">
|
||||
|
||||
<int:aggregator input-channel="inputChannel" output-channel="outputChannel" message-store="mongoStore"/>
|
||||
<int:aggregator input-channel="inputChannel" output-channel="outputChannel" message-store="mongoStore"
|
||||
release-strategy-expression="size() == 10"/>
|
||||
|
||||
<int:channel id="outputChannel">
|
||||
<int:queue/>
|
||||
@@ -0,0 +1,8 @@
|
||||
log4j.rootCategory=WARN, stdout
|
||||
|
||||
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.stdout.layout.ConversionPattern=%d{HH:mm:ss.SSS} %-5p [%t][%c] %m%n
|
||||
|
||||
log4j.category.org.springframework.integration=WARN
|
||||
log4j.category.org.springframework.integration.mongodb=INFO
|
||||
Reference in New Issue
Block a user