Author: btellier Date: Mon Jun 29 08:34:21 2015 New Revision: 1688129 URL: http://svn.apache.org/r1688129 Log: MAILBOX-155 Update index content without reading messages in base
Added: james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/json/MessageUpdateJson.java james/mailbox/trunk/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/EmbeddedElasticSearch.java Modified: james/mailbox/trunk/elasticsearch/pom.xml james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/ElasticSearchIndexer.java james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/NodeProvider.java james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndex.java james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/json/MessageToElasticSearchJson.java james/mailbox/trunk/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/ElasticSearchIndexerTest.java james/mailbox/trunk/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndexTest.java james/mailbox/trunk/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/json/MessageToElasticSearchJsonTest.java james/mailbox/trunk/lucene/src/main/java/org/apache/james/mailbox/lucene/search/LuceneMessageSearchIndex.java james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/search/LazyMessageSearchIndex.java james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/search/ListeningMessageSearchIndex.java Modified: james/mailbox/trunk/elasticsearch/pom.xml URL: http://svn.apache.org/viewvc/james/mailbox/trunk/elasticsearch/pom.xml?rev=1688129&r1=1688128&r2=1688129&view=diff ============================================================================== --- james/mailbox/trunk/elasticsearch/pom.xml (original) +++ james/mailbox/trunk/elasticsearch/pom.xml Mon Jun 29 08:34:21 2015 @@ -139,6 +139,11 @@ <artifactId>slf4j-simple</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>org.codehaus.groovy</groupId> + <artifactId>groovy-all</artifactId> + <version>2.3.2</version> + </dependency> </dependencies> <profiles> Modified: james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/ElasticSearchIndexer.java URL: http://svn.apache.org/viewvc/james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/ElasticSearchIndexer.java?rev=1688129&r1=1688128&r2=1688129&view=diff ============================================================================== --- james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/ElasticSearchIndexer.java (original) +++ james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/ElasticSearchIndexer.java Mon Jun 29 08:34:21 2015 @@ -47,12 +47,12 @@ public class ElasticSearchIndexer { .get(); } } - - public UpdateResponse updateMessage(String id, String content) { - checkArgument(content); + + public UpdateResponse updateMessage(String id, String docUpdated) { + checkArgument(docUpdated); try (Client client = node.client()) { return client.prepareUpdate(MAILBOX_INDEX, MESSAGE_TYPE, id) - .setDoc(content) + .setDoc(docUpdated) .get(); } } Modified: james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/NodeProvider.java URL: http://svn.apache.org/viewvc/james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/NodeProvider.java?rev=1688129&r1=1688128&r2=1688129&view=diff ============================================================================== --- james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/NodeProvider.java (original) +++ james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/NodeProvider.java Mon Jun 29 08:34:21 2015 @@ -33,7 +33,7 @@ public class NodeProvider { .clusterName(clusterName) .settings(ImmutableSettings.builder() .put(GLOBAL_NETWORK_HOST_SETTING, masterHost) - .put(SCRIPT_DISABLE_DYNAMIC, false)) + .put(SCRIPT_DISABLE_DYNAMIC, true)) .client(true) .node() .start(); Modified: james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndex.java URL: http://svn.apache.org/viewvc/james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndex.java?rev=1688129&r1=1688128&r2=1688129&view=diff ============================================================================== --- james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndex.java (original) +++ james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndex.java Mon Jun 29 08:34:21 2015 @@ -30,7 +30,6 @@ import org.apache.james.mailbox.exceptio import org.apache.james.mailbox.model.MessageRange; import org.apache.james.mailbox.model.MessageRange.Type; import org.apache.james.mailbox.model.SearchQuery; -import org.apache.james.mailbox.store.mail.MessageMapper.FetchType; import org.apache.james.mailbox.store.mail.MessageMapperFactory; import org.apache.james.mailbox.store.mail.model.Mailbox; import org.apache.james.mailbox.store.mail.model.MailboxId; @@ -86,17 +85,17 @@ public class ElasticSearchListeningMessa } @Override - public void update(MailboxSession session, Mailbox<Id> mailbox, MessageRange range, Flags flags) throws MailboxException { - getFactory().getMessageMapper(session) - .findInMailbox(mailbox, range, FetchType.Full, NO_LIMIT) - .forEachRemaining(message -> { - try { - message.setFlags(flags); - indexer.updateMessage(indexIdFor(mailbox, message.getUid()), messageToElasticSearchJson.convertToJson(message)); - } catch (Exception e) { - LOGGER.error("Error when updating index for message " + message.getUid(), e); - } - }); + public void update(MailboxSession session, Mailbox<Id> mailbox, MessageRange range, Flags flags, long modseq) throws MailboxException { + range.forEach(messageId -> { + try { + indexer.updateMessage( + indexIdFor(mailbox, messageId), + messageToElasticSearchJson.getUpdatedJsonMessagePart(flags, modseq)); + } catch (Exception e) { + LOGGER.error("Error when updating index for message " + messageId, e); + } + }); + } private String indexIdFor(Mailbox<Id> mailbox, long messageId) { Modified: james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/json/MessageToElasticSearchJson.java URL: http://svn.apache.org/viewvc/james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/json/MessageToElasticSearchJson.java?rev=1688129&r1=1688128&r2=1688129&view=diff ============================================================================== --- james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/json/MessageToElasticSearchJson.java (original) +++ james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/json/MessageToElasticSearchJson.java Mon Jun 29 08:34:21 2015 @@ -19,6 +19,8 @@ package org.apache.james.mailbox.elasticsearch.json; +import javax.mail.Flags; + import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.guava.GuavaModule; @@ -41,4 +43,9 @@ public class MessageToElasticSearchJson return mapper.writeValueAsString(IndexableMessage.from(message)); } + public String getUpdatedJsonMessagePart(Flags flags, long modSeq) throws JsonProcessingException { + Preconditions.checkNotNull(flags); + return mapper.writeValueAsString(new MessageUpdateJson(flags, modSeq)); + } + } Added: james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/json/MessageUpdateJson.java URL: http://svn.apache.org/viewvc/james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/json/MessageUpdateJson.java?rev=1688129&view=auto ============================================================================== --- james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/json/MessageUpdateJson.java (added) +++ james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/json/MessageUpdateJson.java Mon Jun 29 08:34:21 2015 @@ -0,0 +1,59 @@ + + +package org.apache.james.mailbox.elasticsearch.json; + +import javax.mail.Flags; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class MessageUpdateJson { + + private final Flags flags; + private final long modSeq; + + public MessageUpdateJson(Flags flags, long modSeq) { + this.flags = flags; + this.modSeq = modSeq; + } + + @JsonProperty(JsonMessageConstants.IS_ANSWERED) + public boolean isAnswered() { + return flags.contains(Flags.Flag.ANSWERED); + } + + @JsonProperty(JsonMessageConstants.IS_DELETED) + public boolean isDeleted() { + return flags.contains(Flags.Flag.DELETED); + } + + @JsonProperty(JsonMessageConstants.IS_DRAFT) + public boolean isDraft() { + return flags.contains(Flags.Flag.DRAFT); + } + + @JsonProperty(JsonMessageConstants.IS_FLAGGED) + public boolean isFlagged() { + return flags.contains(Flags.Flag.FLAGGED); + } + + @JsonProperty(JsonMessageConstants.IS_RECENT) + public boolean isRecent() { + return flags.contains(Flags.Flag.RECENT); + } + + @JsonProperty(JsonMessageConstants.IS_UNREAD) + public boolean isUnRead() { + return ! flags.contains(Flags.Flag.SEEN); + } + + + @JsonProperty(JsonMessageConstants.USER_FLAGS) + public String[] getUserFlags() { + return flags.getUserFlags(); + } + + @JsonProperty(JsonMessageConstants.MODSEQ) + public long getModSeq() { + return modSeq; + } + +} Modified: james/mailbox/trunk/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/ElasticSearchIndexerTest.java URL: http://svn.apache.org/viewvc/james/mailbox/trunk/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/ElasticSearchIndexerTest.java?rev=1688129&r1=1688128&r2=1688129&view=diff ============================================================================== --- james/mailbox/trunk/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/ElasticSearchIndexerTest.java (original) +++ james/mailbox/trunk/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/ElasticSearchIndexerTest.java Mon Jun 29 08:34:21 2015 @@ -49,6 +49,7 @@ public class ElasticSearchIndexerTest { node = nodeBuilder().local(true) .settings(ImmutableSettings.builder() .put("path.data", temporaryFolder.newFolder().getAbsolutePath()) + .put("script.disable_dynamic",false) .build()) .node(); node.start(); @@ -87,20 +88,27 @@ public class ElasticSearchIndexerTest { @Test public void updateMessage() throws Exception { String messageId = "1"; - String content = "{\"message\": \"trying out Elasticsearch\"}"; - + String content = "{\"message\": \"trying out Elasticsearch\",\"field\":\"Should be unchanged\"}"; + testee.indexMessage(messageId, content); awaitForElasticSearch(); - - String updatedContent = "{\"message\": \"mastering out Elasticsearch\"}"; - testee.updateMessage(messageId, updatedContent); - awaitForElasticSearch(); - + + testee.updateMessage(messageId, "{\"message\": \"mastering out Elasticsearch\"}"); + EmbeddedElasticSearch.awaitForElasticSearch(node); + try (Client client = node.client()) { SearchResponse searchResponse = client.prepareSearch(ElasticSearchIndexer.MAILBOX_INDEX) - .setTypes(ElasticSearchIndexer.MESSAGE_TYPE) - .setQuery(QueryBuilders.matchQuery("message", "mastering")) - .get(); + .setTypes(ElasticSearchIndexer.MESSAGE_TYPE) + .setQuery(QueryBuilders.matchQuery("message", "mastering")) + .get(); + assertThat(searchResponse.getHits().getTotalHits()).isEqualTo(1); + } + + try (Client client = node.client()) { + SearchResponse searchResponse = client.prepareSearch(ElasticSearchIndexer.MAILBOX_INDEX) + .setTypes(ElasticSearchIndexer.MESSAGE_TYPE) + .setQuery(QueryBuilders.matchQuery("field", "unchanged")) + .get(); assertThat(searchResponse.getHits().getTotalHits()).isEqualTo(1); } } Added: james/mailbox/trunk/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/EmbeddedElasticSearch.java URL: http://svn.apache.org/viewvc/james/mailbox/trunk/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/EmbeddedElasticSearch.java?rev=1688129&view=auto ============================================================================== --- james/mailbox/trunk/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/EmbeddedElasticSearch.java (added) +++ james/mailbox/trunk/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/EmbeddedElasticSearch.java Mon Jun 29 08:34:21 2015 @@ -0,0 +1,87 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.mailbox.elasticsearch; + + + +import java.io.IOException; + +import com.jayway.awaitility.Duration; +import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; +import org.elasticsearch.action.admin.indices.flush.FlushRequestBuilder; +import org.elasticsearch.client.Client; +import org.elasticsearch.common.settings.ImmutableSettings; +import org.elasticsearch.index.query.QueryBuilders; +import org.elasticsearch.node.Node; +import org.junit.rules.TemporaryFolder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static com.jayway.awaitility.Awaitility.await; +import static org.elasticsearch.node.NodeBuilder.nodeBuilder; + +public class EmbeddedElasticSearch { + + private static Logger LOGGER = LoggerFactory.getLogger(EmbeddedElasticSearch.class); + + public static Node provideNode(TemporaryFolder temporaryFolder) throws IOException { + Node node = nodeBuilder().local(true) + .settings(ImmutableSettings.builder() + .put("path.data", temporaryFolder.newFolder().getAbsolutePath()) + .put("script.disable_dynamic",true) + .build()) + .node(); + node.start(); + awaitForElasticSearch(node); + return node; + } + + public static void shutDown(Node node) { + EmbeddedElasticSearch.awaitForElasticSearch(node); + try (Client client = node.client()) { + node.client() + .admin() + .indices() + .delete(new DeleteIndexRequest(ElasticSearchIndexer.MAILBOX_INDEX)) + .actionGet(); + } catch (Exception e) { + LOGGER.warn("Error while closing ES connection", e); + } + node.close(); + } + + /** + * Sometimes, tests are too fast. + * This method ensure that ElasticSearch service is up and indices are updated + */ + public static void awaitForElasticSearch(Node node) { + await().atMost(Duration.TEN_SECONDS).until(() -> flush(node)); + } + + private static boolean flush(Node node) { + try (Client client = node.client()) { + new FlushRequestBuilder(client.admin().indices()).setForce(true).get(); + return true; + } catch (Exception e) { + return false; + } + } + +} Modified: james/mailbox/trunk/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndexTest.java URL: http://svn.apache.org/viewvc/james/mailbox/trunk/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndexTest.java?rev=1688129&r1=1688128&r2=1688129&view=diff ============================================================================== --- james/mailbox/trunk/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndexTest.java (original) +++ james/mailbox/trunk/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndexTest.java Mon Jun 29 08:34:21 2015 @@ -18,6 +18,7 @@ ****************************************************************/ package org.apache.james.mailbox.elasticsearch.events; +import static org.easymock.EasyMock.anyLong; import static org.easymock.EasyMock.anyObject; import static org.easymock.EasyMock.anyString; import static org.easymock.EasyMock.createControl; @@ -26,8 +27,7 @@ import static org.easymock.EasyMock.expe import static org.easymock.EasyMock.expectLastCall; import java.io.IOException; -import java.util.List; -import java.util.concurrent.atomic.AtomicLong; +import java.util.stream.IntStream; import java.util.stream.LongStream; import javax.mail.Flags; @@ -38,8 +38,6 @@ import org.apache.james.mailbox.elastics import org.apache.james.mailbox.elasticsearch.json.MessageToElasticSearchJson; import org.apache.james.mailbox.model.MessageRange; import org.apache.james.mailbox.store.TestId; -import org.apache.james.mailbox.store.mail.MessageMapper; -import org.apache.james.mailbox.store.mail.MessageMapper.FetchType; import org.apache.james.mailbox.store.mail.MessageMapperFactory; import org.apache.james.mailbox.store.mail.model.Mailbox; import org.apache.james.mailbox.store.mail.model.Message; @@ -53,10 +51,10 @@ import org.junit.Test; import com.fasterxml.jackson.core.JsonProcessingException; import com.google.common.base.Throwables; -import com.google.common.collect.ImmutableList; public class ElasticSearchListeningMessageSearchIndexTest { + public static final long MODSEQ = 18L; private IMocksControl control; private MessageMapperFactory<TestId> mapperFactory; @@ -74,8 +72,9 @@ public class ElasticSearchListeningMessa indexer = control.createMock(ElasticSearchIndexer.class); messageToElasticSearchJson = control.createMock(MessageToElasticSearchJson.class); expect(messageToElasticSearchJson.convertToJson(anyObject(Message.class))).andReturn("json content").anyTimes(); - - testee = new ElasticSearchListeningMessageSearchIndex<TestId>(mapperFactory, indexer, messageToElasticSearchJson); + expect(messageToElasticSearchJson.getUpdatedJsonMessagePart(anyObject(Flags.class), anyLong())).andReturn("json updated content").anyTimes(); + + testee = new ElasticSearchListeningMessageSearchIndex<>(mapperFactory, indexer, messageToElasticSearchJson); } @Test(expected=NotImplementedException.class) @@ -190,25 +189,19 @@ public class ElasticSearchListeningMessa testee.delete(session, mailbox, messageRange); control.verify(); } - + @Test @SuppressWarnings("unchecked") public void updateShouldWork() throws Exception { MailboxSession session = control.createMock(MailboxSession.class); + Mailbox<TestId> mailbox = control.createMock(Mailbox.class); - Flags flags = control.createMock(Flags.class); + Flags flags = new Flags(); + long messageId = 1; TestId mailboxId = TestId.of(12); MessageRange messageRange = MessageRange.one(messageId); - Message<TestId> message = mockedMessage(messageId, mailboxId); - - MessageMapper<TestId> messageMapper = control.createMock(MessageMapper.class); - expect(mapperFactory.getMessageMapper(session)) - .andReturn(messageMapper); - expect(messageMapper.findInMailbox(mailbox, messageRange, FetchType.Full, -1)) - .andReturn(ImmutableList.of(message).iterator()); - - message.setFlags(flags); + expectLastCall(); expect(mailbox.getMailboxId()).andReturn(mailboxId); @@ -217,83 +210,60 @@ public class ElasticSearchListeningMessa .andReturn(expectedUpdateResponse); control.replay(); - testee.update(session, mailbox, messageRange, flags); + testee.update(session, mailbox, messageRange, flags, MODSEQ); control.verify(); } - + @Test @SuppressWarnings("unchecked") public void updateShouldWorkWhenMultipleMessageIds() throws Exception { MailboxSession session = control.createMock(MailboxSession.class); + Mailbox<TestId> mailbox = control.createMock(Mailbox.class); - Flags flags = control.createMock(Flags.class); + Flags flags = new Flags(); + long firstMessageId = 1; long lastMessageId = 10; MessageRange messageRange = MessageRange.range(firstMessageId, lastMessageId); - MessageMapper<TestId> messageMapper = control.createMock(MessageMapper.class); - expect(mapperFactory.getMessageMapper(session)) - .andReturn(messageMapper); - TestId mailboxId = TestId.of(12); - Message<TestId> message1 = mockedMessage(1, mailboxId); - Message<TestId> message2 = mockedMessage(2, mailboxId); - Message<TestId> message3 = mockedMessage(3, mailboxId); - Message<TestId> message4 = mockedMessage(4, mailboxId); - Message<TestId> message5 = mockedMessage(5, mailboxId); - Message<TestId> message6 = mockedMessage(6, mailboxId); - Message<TestId> message7 = mockedMessage(7, mailboxId); - Message<TestId> message8 = mockedMessage(8, mailboxId); - Message<TestId> message9 = mockedMessage(9, mailboxId); - Message<TestId> message10 = mockedMessage(10, mailboxId); - - List<Message<TestId>> messages = ImmutableList.of(message1, message2, message3, message4, message5, message6, message7, message8, message9, message10); - expect(messageMapper.findInMailbox(mailbox, messageRange, FetchType.Full, -1)) - .andReturn(messages.iterator()); - - AtomicLong messageId = new AtomicLong(0); - messages - .forEach(message -> { + + IntStream.range(1, 11).forEach( + (uid) -> { try { - message.setFlags(flags); + expectLastCall(); - - long messageIdAsLong = messageId.incrementAndGet(); + expect(mailbox.getMailboxId()).andReturn(mailboxId); - + UpdateResponse expectedUpdateResponse = control.createMock(UpdateResponse.class); - expect(indexer.updateMessage(eq(mailboxId.serialize() + ":" + messageIdAsLong), anyString())) + expect(indexer.updateMessage(eq(mailboxId.serialize() + ":" + uid), anyString())) + .andReturn(expectedUpdateResponse); } catch (Exception e) { Throwables.propagate(e); - } finally { } - }); + } + ); control.replay(); - testee.update(session, mailbox, messageRange, flags); + testee.update(session, mailbox, messageRange, flags, MODSEQ); control.verify(); } - + @Test @SuppressWarnings("unchecked") public void updateShouldNotPropagateExceptionWhenExceptionOccurs() throws Exception { MailboxSession session = control.createMock(MailboxSession.class); + Mailbox<TestId> mailbox = control.createMock(Mailbox.class); - Flags flags = control.createMock(Flags.class); + Flags flags = new Flags(); + long messageId = 1; TestId mailboxId = TestId.of(12); MessageRange messageRange = MessageRange.one(messageId); - Message<TestId> message = mockedMessage(messageId, mailboxId); - - MessageMapper<TestId> messageMapper = control.createMock(MessageMapper.class); - expect(mapperFactory.getMessageMapper(session)) - .andReturn(messageMapper); - expect(messageMapper.findInMailbox(mailbox, messageRange, FetchType.Full, -1)) - .andReturn(ImmutableList.of(message).iterator()); - - message.setFlags(flags); + expectLastCall(); expect(mailbox.getMailboxId()).andReturn(mailboxId); @@ -301,7 +271,7 @@ public class ElasticSearchListeningMessa .andThrow(new ElasticsearchException("")); control.replay(); - testee.update(session, mailbox, messageRange, flags); + testee.update(session, mailbox, messageRange, flags, MODSEQ); control.verify(); } } Modified: james/mailbox/trunk/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/json/MessageToElasticSearchJsonTest.java URL: http://svn.apache.org/viewvc/james/mailbox/trunk/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/json/MessageToElasticSearchJsonTest.java?rev=1688129&r1=1688128&r2=1688129&view=diff ============================================================================== --- james/mailbox/trunk/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/json/MessageToElasticSearchJsonTest.java (original) +++ james/mailbox/trunk/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/json/MessageToElasticSearchJsonTest.java Mon Jun 29 08:34:21 2015 @@ -181,4 +181,21 @@ public class MessageToElasticSearchJsonT messageToElasticSearchJson.convertToJson(mailWithNoMailboxId); } + @Test + public void getUpdatedJsonMessagePartShouldBehaveWellOnEmptyFlags() throws Exception { + assertThatJson(messageToElasticSearchJson.getUpdatedJsonMessagePart(new Flags(), MOD_SEQ)) + .isEqualTo("{\"modSeq\":42,\"isAnswered\":false,\"isDeleted\":false,\"isDraft\":false,\"isFlagged\":false,\"isRecent\":false,\"userFlags\":[],\"isUnread\":true}"); + } + + @Test + public void getUpdatedJsonMessagePartShouldBehaveWellOnNonEmptyFlags() throws Exception { + assertThatJson(messageToElasticSearchJson.getUpdatedJsonMessagePart(new FlagsBuilder().add(Flags.Flag.DELETED, Flags.Flag.FLAGGED).add("user").build(), MOD_SEQ)) + .isEqualTo("{\"modSeq\":42,\"isAnswered\":false,\"isDeleted\":true,\"isDraft\":false,\"isFlagged\":true,\"isRecent\":false,\"userFlags\":[\"user\"],\"isUnread\":true}"); + } + + @Test(expected = NullPointerException.class) + public void getUpdatedJsonMessagePartShouldThrowIfFlagsIsNull() throws Exception { + messageToElasticSearchJson.getUpdatedJsonMessagePart(null, MOD_SEQ); + } + } Modified: james/mailbox/trunk/lucene/src/main/java/org/apache/james/mailbox/lucene/search/LuceneMessageSearchIndex.java URL: http://svn.apache.org/viewvc/james/mailbox/trunk/lucene/src/main/java/org/apache/james/mailbox/lucene/search/LuceneMessageSearchIndex.java?rev=1688129&r1=1688128&r2=1688129&view=diff ============================================================================== --- james/mailbox/trunk/lucene/src/main/java/org/apache/james/mailbox/lucene/search/LuceneMessageSearchIndex.java (original) +++ james/mailbox/trunk/lucene/src/main/java/org/apache/james/mailbox/lucene/search/LuceneMessageSearchIndex.java Mon Jun 29 08:34:21 2015 @@ -1202,7 +1202,7 @@ public class LuceneMessageSearchIndex<Id /** * @see org.apache.james.mailbox.store.search.ListeningMessageSearchIndex#update(org.apache.james.mailbox.MailboxSession, org.apache.james.mailbox.store.mail.model.Mailbox, org.apache.james.mailbox.model.MessageRange, javax.mail.Flags) */ - public void update(MailboxSession session, Mailbox<Id> mailbox, MessageRange range, Flags f) throws MailboxException { + public void update(MailboxSession session, Mailbox<Id> mailbox, MessageRange range, Flags f, long modSeq) throws MailboxException { try { IndexSearcher searcher = new IndexSearcher(IndexReader.open(writer, true)); BooleanQuery query = new BooleanQuery(); Modified: james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/search/LazyMessageSearchIndex.java URL: http://svn.apache.org/viewvc/james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/search/LazyMessageSearchIndex.java?rev=1688129&r1=1688128&r2=1688129&view=diff ============================================================================== --- james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/search/LazyMessageSearchIndex.java (original) +++ james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/search/LazyMessageSearchIndex.java Mon Jun 29 08:34:21 2015 @@ -101,8 +101,8 @@ public class LazyMessageSearchIndex<Id e @Override - public void update(MailboxSession session, Mailbox<Id> mailbox, MessageRange range, Flags flags) throws MailboxException { - index.update(session, mailbox, range, flags); + public void update(MailboxSession session, Mailbox<Id> mailbox, MessageRange range, Flags flags, long modSeq) throws MailboxException { + index.update(session, mailbox, range, flags, modSeq); } } Modified: james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/search/ListeningMessageSearchIndex.java URL: http://svn.apache.org/viewvc/james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/search/ListeningMessageSearchIndex.java?rev=1688129&r1=1688128&r2=1688129&view=diff ============================================================================== --- james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/search/ListeningMessageSearchIndex.java (original) +++ james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/search/ListeningMessageSearchIndex.java Mon Jun 29 08:34:21 2015 @@ -114,7 +114,7 @@ public abstract class ListeningMessageSe while(flags.hasNext()) { UpdatedFlags uFlags = flags.next(); try { - update(session, mailbox, MessageRange.one(uFlags.getUid()), uFlags.getNewFlags()); + update(session, mailbox, MessageRange.one(uFlags.getUid()), uFlags.getNewFlags(), uFlags.getModSeq()); } catch (MailboxException e) { session.getLog().debug("Unable to update flags for message " + uFlags.getUid() + " in index for mailbox " + mailbox, e); } @@ -167,5 +167,5 @@ public abstract class ListeningMessageSe * @param flags * @throws MailboxException */ - public abstract void update(MailboxSession session, Mailbox<Id> mailbox, MessageRange range, Flags flags) throws MailboxException; + public abstract void update(MailboxSession session, Mailbox<Id> mailbox, MessageRange range, Flags flags, long modseq) throws MailboxException; } --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org