INT-3642: Improve MessageGroupStore Removal

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

Currently, `removeMessageFromGroup` rebuilds the group on every removal.

In every case where this method is used in the framework, the result is not used.

Add `removeMessagesFromGroup` that removes a collection of messages and returns no result.

INT-3642: Polishing - PR Comments

INT-3642: Polishing and Fix Group Metadata Size
This commit is contained in:
Gary Russell
2015-06-16 09:01:29 -04:00
committed by Artem Bilan
parent 0065ed8c49
commit f3d525a5e8
23 changed files with 472 additions and 107 deletions

View File

@@ -49,6 +49,7 @@ 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.BasicMessageGroupStore;
import org.springframework.integration.support.DefaultMessageBuilderFactory;
import org.springframework.integration.support.MessageBuilderFactory;
@@ -65,8 +66,8 @@ import org.springframework.util.Assert;
* @since 4.0
*/
public abstract class AbstractConfigurableMongoDbMessageStore implements BasicMessageGroupStore, InitializingBean,
ApplicationContextAware {
public abstract class AbstractConfigurableMongoDbMessageStore extends AbstractBatchingMessageGroupStore
implements BasicMessageGroupStore, InitializingBean, ApplicationContextAware {
public final static String SEQUENCE_NAME = "messagesSequence";

View File

@@ -17,6 +17,7 @@
package org.springframework.integration.mongodb.store;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashSet;
@@ -48,6 +49,7 @@ import org.springframework.util.Assert;
*
* @author Amol Nayak
* @author Artem Bilan
* @author Gary Russell
* @since 3.0
*/
public class ConfigurableMongoDbMessageStore extends AbstractConfigurableMongoDbMessageStore
@@ -205,10 +207,39 @@ public class ConfigurableMongoDbMessageStore extends AbstractConfigurableMongoDb
Query query = groupIdQuery(groupId)
.addCriteria(Criteria.where(MessageDocumentFields.MESSAGE_ID).is(messageToRemove.getHeaders().getId()));
mongoTemplate.remove(query, collectionName);
this.mongoTemplate.remove(query, this.collectionName);
updateGroup(groupId, lastModifiedUpdate());
return getMessageGroup(groupId);
}
@Override
public void removeMessagesFromGroup(Object groupId, Collection<Message<?>> messages) {
Assert.notNull(groupId, "'groupId' must not be null");
Assert.notNull(messages, "'messageToRemove' must not be null");
Collection<UUID> ids = new ArrayList<UUID>();
for (Message<?> messageToRemove : messages) {
ids.add(messageToRemove.getHeaders().getId());
if (ids.size() >= getRemoveBatchSize()) {
removeMessages(groupId, ids);
ids.clear();
}
}
if (ids.size() > 0) {
removeMessages(groupId, ids);
}
updateGroup(groupId, lastModifiedUpdate());
}
private void removeMessages(Object groupId, Collection<UUID> ids) {
Query query = groupIdQuery(groupId)
.addCriteria(Criteria.where(MessageDocumentFields.MESSAGE_ID).in(ids.toArray()));
this.mongoTemplate.remove(query, this.collectionName);
}
@Override
public void removeMessagesFromGroup(Object groupId, Message<?>... messages) {
removeMessagesFromGroup(groupId, Arrays.asList(messages));
}
@Override

View File

@@ -17,6 +17,7 @@
package org.springframework.integration.mongodb.store;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -76,6 +77,7 @@ import org.springframework.util.StringUtils;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.BulkWriteOperation;
import com.mongodb.DBObject;
@@ -313,6 +315,35 @@ public class MongoDbMessageStore extends AbstractMessageGroupStore
return getMessageGroup(groupId);
}
@Override
public void removeMessagesFromGroup(Object groupId, Collection<Message<?>> messages) {
Assert.notNull(groupId, "'groupId' must not be null");
Assert.notNull(messages, "'messageToRemove' must not be null");
Collection<UUID> ids = new ArrayList<UUID>();
for (Message<?> messageToRemove : messages) {
ids.add(messageToRemove.getHeaders().getId());
if (ids.size() >= getRemoveBatchSize()) {
bulkRemove(groupId, ids);
ids.clear();
}
}
if (ids.size() > 0) {
bulkRemove(groupId, ids);
}
updateGroup(groupId, lastModifiedUpdate());
}
private void bulkRemove(Object groupId, Collection<UUID> ids) {
BulkWriteOperation bulkOp = this.template.getCollection(this.collectionName)
.initializeOrderedBulkOperation();
for (UUID id : ids) {
bulkOp.find(whereMessageIdIsAndGroupIdIs(id, groupId).getQueryObject())
.remove();
}
bulkOp.execute();
}
@Override
public void removeMessageGroup(Object groupId) {
this.template.remove(whereGroupIdIs(groupId), this.collectionName);
@@ -400,7 +431,6 @@ public class MongoDbMessageStore extends AbstractMessageGroupStore
return new Query(Criteria.where("headers.id._value").is(id.toString()).and(GROUP_ID_KEY).is(groupId));
}
private static Query whereGroupIdOrder(Object groupId) {
return whereGroupIdIs(groupId).with(new Sort(Sort.Direction.DESC, GROUP_UPDATE_TIMESTAMP_KEY, SEQUENCE));
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,14 +15,19 @@
*/
package org.springframework.integration.mongodb.store;
import static org.junit.Assert.*;
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.assertTrue;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.UUID;
import com.mongodb.MongoClient;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
@@ -32,6 +37,7 @@ import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.history.MessageHistory;
import org.springframework.integration.mongodb.rules.MongoDbAvailable;
import org.springframework.integration.mongodb.rules.MongoDbAvailableTests;
import org.springframework.integration.store.AbstractBatchingMessageGroupStore;
import org.springframework.integration.store.MessageGroup;
import org.springframework.integration.store.MessageGroupStore;
import org.springframework.integration.store.MessageStore;
@@ -41,6 +47,8 @@ import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.support.GenericMessage;
import com.mongodb.MongoClient;
/**
* @author Oleg Zhurakousky
* @author Gary Russell
@@ -394,6 +402,26 @@ public abstract class AbstractMongoDbMessageGroupStoreTests extends MongoDbAvail
assertEquals(2, counter);
}
@Test
@MongoDbAvailable
public void testAddAndRemoveMessagesFromMessageGroup() throws Exception {
MessageGroupStore messageStore = (MessageGroupStore) this.getMessageStore();
String groupId = "X";
messageStore.removeMessageGroup("X");
((AbstractBatchingMessageGroupStore) messageStore).setRemoveBatchSize(10);
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);
messages.add(message);
}
MessageGroup group = messageStore.getMessageGroup(groupId);
assertEquals(25, group.size());
messageStore.removeMessagesFromGroup(groupId, messages);
group = messageStore.getMessageGroup(groupId);
assertEquals(0, group.size());
}
// @Test
// @MongoDbAvailable
// public void testConcurrentModifications() throws Exception{
@@ -461,6 +489,7 @@ public abstract class AbstractMongoDbMessageGroupStoreTests extends MongoDbAvail
Message<?> m3 = MessageBuilder.withPayload("3").setSequenceNumber(3).setSequenceSize(3).setCorrelationId(1).build();
input.send(m3);
assertNotNull(output.receive(2000));
context.close();
}
@Test

View File

@@ -15,12 +15,12 @@
*/
package org.springframework.integration.mongodb.store;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import java.util.Map;
import com.mongodb.DBObject;
import com.mongodb.MongoClient;
import org.hamcrest.Matchers;
import org.junit.Test;
@@ -38,6 +38,9 @@ import org.springframework.integration.support.MessageBuilder;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.messaging.Message;
import com.mongodb.DBObject;
import com.mongodb.MongoClient;
/**
* @author Amol Nayak
* @author Artem Bilan
@@ -45,9 +48,6 @@ import org.springframework.messaging.Message;
*/
public class ConfigurableMongoDbMessageGroupStoreTests extends AbstractMongoDbMessageGroupStoreTests {
/* (non-Javadoc)
* @see org.springframework.integration.mongodb.store.AbstractMongoDbMessageGroupStoreTests#getMessageGroupStore()
*/
@Override
protected ConfigurableMongoDbMessageStore getMessageGroupStore() throws Exception {
MongoDbFactory mongoDbFactory = new SimpleMongoDbFactory(new MongoClient(), "test");
@@ -59,9 +59,6 @@ public class ConfigurableMongoDbMessageGroupStoreTests extends AbstractMongoDbMe
return mongoDbMessageStore;
}
/* (non-Javadoc)
* @see org.springframework.integration.mongodb.store.AbstractMongoDbMessageGroupStoreTests#getMessageStore()
*/
@Override
protected MessageStore getMessageStore() throws Exception {
return this.getMessageGroupStore();