This is an automated email from the ASF dual-hosted git repository. btellier pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/james-project.git
commit d7d1e58251a610f1f81eb759854ce41e070366e0 Author: Quan Tran <[email protected]> AuthorDate: Fri Jan 30 16:19:27 2026 +0700 JAMES-4166 Modify the search API with SearchOptions and push the offset onto the search engine --- mailbox/api/pom.xml | 4 ++ .../org/apache/james/mailbox/MailboxManager.java | 5 +- .../apache/james/mailbox/model/SearchOptions.java | 43 ++++++++++++++++ .../apache/james/mailbox/MailboxManagerTest.java | 4 +- .../lucene/search/LuceneMessageSearchIndex.java | 10 ++-- .../LuceneMailboxMessageSearchIndexTest.java | 6 ++- .../DisabledListeningMessageSearchIndex.java | 3 +- .../OpenSearchListeningMessageSearchIndex.java | 5 +- .../opensearch/search/OpenSearchSearcher.java | 14 +++--- .../opensearch/OpenSearchIntegrationTest.java | 6 ++- .../opensearch/search/OpenSearchSearcherTest.java | 4 +- .../james/mailbox/store/StoreMailboxManager.java | 5 +- .../mail/SearchThreadIdGuessingAlgorithm.java | 6 ++- .../store/search/LazyMessageSearchIndex.java | 3 +- .../mailbox/store/search/MessageSearchIndex.java | 3 +- .../store/search/SimpleMessageSearchIndex.java | 58 +++++++++++----------- .../store/AbstractCombinationManagerTest.java | 4 +- .../store/SystemMailboxesProviderImplTest.java | 3 +- .../search/AbstractMessageSearchIndexTest.java | 12 +++-- .../org/apache/james/modules/MailboxProbeImpl.java | 4 +- .../org/apache/james/FakeMessageSearchIndex.java | 3 +- .../java/org/apache/james/SearchModuleChooser.java | 3 +- .../mailbox/MailboxUserDeletionTaskStepTest.java | 6 ++- .../mailet/ExtractMDNOriginalJMAPMessageId.java | 4 +- .../james/jmap/method/EmailQueryMethod.scala | 7 ++- .../apache/james/jmap/method/MDNParseMethod.scala | 5 +- .../routes/DeletedMessagesVaultRoutesTest.java | 4 +- .../webadmin/service/ExpireMailboxServiceTest.java | 5 +- 28 files changed, 162 insertions(+), 77 deletions(-) diff --git a/mailbox/api/pom.xml b/mailbox/api/pom.xml index c651868e5a..59a9b76234 100644 --- a/mailbox/api/pom.xml +++ b/mailbox/api/pom.xml @@ -49,6 +49,10 @@ <artifactId>james-server-task-memory</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>${james.groupId}</groupId> + <artifactId>james-server-util</artifactId> + </dependency> <dependency> <groupId>${james.groupId}</groupId> <artifactId>metrics-tests</artifactId> diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/MailboxManager.java b/mailbox/api/src/main/java/org/apache/james/mailbox/MailboxManager.java index 26f1f9087b..ec9333e381 100644 --- a/mailbox/api/src/main/java/org/apache/james/mailbox/MailboxManager.java +++ b/mailbox/api/src/main/java/org/apache/james/mailbox/MailboxManager.java @@ -35,6 +35,7 @@ import org.apache.james.mailbox.model.MailboxPath; import org.apache.james.mailbox.model.MessageId; import org.apache.james.mailbox.model.MessageRange; import org.apache.james.mailbox.model.MultimailboxesSearchQuery; +import org.apache.james.mailbox.model.SearchOptions; import org.apache.james.mailbox.model.ThreadId; import org.apache.james.mailbox.model.search.MailboxQuery; import org.reactivestreams.Publisher; @@ -383,8 +384,10 @@ public interface MailboxManager extends RequestAware, RightManager, MailboxAnnot * not null * @param session * the context for this call, not null + * @param searchOptions + * options for the search */ - Publisher<MessageId> search(MultimailboxesSearchQuery expression, MailboxSession session, long limit); + Publisher<MessageId> search(MultimailboxesSearchQuery expression, MailboxSession session, SearchOptions searchOptions); /** * Returns the list of MessageId of messages belonging to that Thread diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/model/SearchOptions.java b/mailbox/api/src/main/java/org/apache/james/mailbox/model/SearchOptions.java new file mode 100644 index 0000000000..0ef1b77cc4 --- /dev/null +++ b/mailbox/api/src/main/java/org/apache/james/mailbox/model/SearchOptions.java @@ -0,0 +1,43 @@ +/**************************************************************** + * 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.model; + +import org.apache.james.util.streams.Limit; +import org.apache.james.util.streams.Offset; + +import com.google.common.base.Preconditions; + +public record SearchOptions(Offset offset, Limit limit) { + public static final SearchOptions FIRST = SearchOptions.limit(Limit.from(1)); + + public static SearchOptions limit(Limit limit) { + return SearchOptions.of(Offset.none(), limit); + } + + public static SearchOptions of(Offset offset, Limit limit) { + return new SearchOptions(offset, limit); + } + + public SearchOptions { + Preconditions.checkNotNull(offset, "'offset' is mandatory"); + Preconditions.checkNotNull(limit, "'limit' is mandatory"); + Preconditions.checkArgument(!limit.isUnlimited(), "'limit' cannot be unlimited"); + } +} diff --git a/mailbox/api/src/test/java/org/apache/james/mailbox/MailboxManagerTest.java b/mailbox/api/src/test/java/org/apache/james/mailbox/MailboxManagerTest.java index 76e747aba0..468f84105c 100644 --- a/mailbox/api/src/test/java/org/apache/james/mailbox/MailboxManagerTest.java +++ b/mailbox/api/src/test/java/org/apache/james/mailbox/MailboxManagerTest.java @@ -86,12 +86,14 @@ import org.apache.james.mailbox.model.MultimailboxesSearchQuery.AccessibleNamesp import org.apache.james.mailbox.model.MultimailboxesSearchQuery.PersonalNamespace; import org.apache.james.mailbox.model.Quota; import org.apache.james.mailbox.model.QuotaRoot; +import org.apache.james.mailbox.model.SearchOptions; import org.apache.james.mailbox.model.SearchQuery; import org.apache.james.mailbox.model.search.MailboxQuery; import org.apache.james.mailbox.util.EventCollector; import org.apache.james.mime4j.dom.Message; import org.apache.james.util.ClassLoaderUtils; import org.apache.james.util.concurrency.ConcurrentTestRunner; +import org.apache.james.util.streams.Limit; import org.assertj.core.api.SoftAssertions; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -118,7 +120,7 @@ import reactor.core.publisher.Mono; public abstract class MailboxManagerTest<T extends MailboxManager> { public static final Username USER_1 = Username.of("USER_1"); public static final Username USER_2 = Username.of("USER_2"); - private static final int DEFAULT_MAXIMUM_LIMIT = 256; + private static final SearchOptions DEFAULT_MAXIMUM_LIMIT = SearchOptions.limit(Limit.limit(256)); protected T mailboxManager; private SubscriptionManager subscriptionManager; diff --git a/mailbox/lucene/src/main/java/org/apache/james/mailbox/lucene/search/LuceneMessageSearchIndex.java b/mailbox/lucene/src/main/java/org/apache/james/mailbox/lucene/search/LuceneMessageSearchIndex.java index cceff65e36..60fc932240 100644 --- a/mailbox/lucene/src/main/java/org/apache/james/mailbox/lucene/search/LuceneMessageSearchIndex.java +++ b/mailbox/lucene/src/main/java/org/apache/james/mailbox/lucene/search/LuceneMessageSearchIndex.java @@ -89,6 +89,7 @@ import org.apache.james.mailbox.model.Mailbox; import org.apache.james.mailbox.model.MailboxId; import org.apache.james.mailbox.model.MessageId; import org.apache.james.mailbox.model.MessageRange; +import org.apache.james.mailbox.model.SearchOptions; import org.apache.james.mailbox.model.SearchQuery; import org.apache.james.mailbox.model.SearchQuery.AttachmentCriterion; import org.apache.james.mailbox.model.SearchQuery.ContainsOperator; @@ -301,18 +302,21 @@ public class LuceneMessageSearchIndex extends ListeningMessageSearchIndex { } @Override - public Flux<MessageId> search(MailboxSession session, Collection<MailboxId> mailboxIds, SearchQuery searchQuery, long limit) throws MailboxException { + public Flux<MessageId> search(MailboxSession session, Collection<MailboxId> mailboxIds, SearchQuery searchQuery, SearchOptions searchOptions) throws MailboxException { Preconditions.checkArgument(session != null, "'session' is mandatory"); if (mailboxIds.isEmpty()) { return Flux.empty(); } + long requestedLimit = Math.addExact(searchOptions.offset().getOffset(), searchOptions.limit().getLimit().orElseThrow()); + return Flux.fromIterable(searchMultimap(mailboxIds, searchQuery) .stream() .filter(searchResult -> searchResult.getMessageId().isPresent()) .map(searchResult -> searchResult.getMessageId().get()) .filter(SearchUtil.distinct()) - .limit(Long.valueOf(limit).intValue()) + .limit(requestedLimit) + .skip(searchOptions.offset().getOffset()) .collect(ImmutableList.toImmutableList())); } @@ -864,4 +868,4 @@ public class LuceneMessageSearchIndex extends ListeningMessageSearchIndex { default -> Optional.empty(); }; } -} \ No newline at end of file +} diff --git a/mailbox/lucene/src/test/java/org/apache/james/mailbox/lucene/search/LuceneMailboxMessageSearchIndexTest.java b/mailbox/lucene/src/test/java/org/apache/james/mailbox/lucene/search/LuceneMailboxMessageSearchIndexTest.java index fb2ff37c3c..01a26ee4bf 100644 --- a/mailbox/lucene/src/test/java/org/apache/james/mailbox/lucene/search/LuceneMailboxMessageSearchIndexTest.java +++ b/mailbox/lucene/src/test/java/org/apache/james/mailbox/lucene/search/LuceneMailboxMessageSearchIndexTest.java @@ -41,6 +41,7 @@ import org.apache.james.mailbox.MessageUid; import org.apache.james.mailbox.model.Mailbox; import org.apache.james.mailbox.model.MailboxPath; import org.apache.james.mailbox.model.MessageId; +import org.apache.james.mailbox.model.SearchOptions; import org.apache.james.mailbox.model.SearchQuery; import org.apache.james.mailbox.model.SearchQuery.AddressType; import org.apache.james.mailbox.model.SearchQuery.DateResolution; @@ -55,6 +56,7 @@ import org.apache.james.mailbox.store.MessageBuilder; import org.apache.james.mailbox.store.extractor.JsoupTextExtractor; import org.apache.james.mailbox.store.search.ListeningMessageSearchIndex; import org.apache.james.mailbox.store.search.ListeningMessageSearchIndexContract; +import org.apache.james.util.streams.Limit; import org.apache.lucene.store.ByteBuffersDirectory; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; @@ -64,7 +66,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; class LuceneMailboxMessageSearchIndexTest { - static final long LIMIT = 100L; + static final SearchOptions LIMIT = SearchOptions.limit(Limit.limit(100)); static final TestId TEST_ID_1 = TestId.of(0); static final TestId TEST_ID_2 = TestId.of(1); static final TestId TEST_ID_3 = TestId.of(2); @@ -359,7 +361,7 @@ class LuceneMailboxMessageSearchIndexTest { SearchQuery query = SearchQuery.of(SearchQuery.all()); int limit = 1; - List<MessageId> result = index.search(session, ImmutableList.of(mailbox.getMailboxId(), mailbox2.getMailboxId(), mailbox3.getMailboxId()), query, limit) + List<MessageId> result = index.search(session, ImmutableList.of(mailbox.getMailboxId(), mailbox2.getMailboxId(), mailbox3.getMailboxId()), query, SearchOptions.limit(Limit.limit(1))) .collectList().block(); assertThat(result).hasSize(limit); diff --git a/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/events/DisabledListeningMessageSearchIndex.java b/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/events/DisabledListeningMessageSearchIndex.java index c6fcc023cb..3909e83e0f 100644 --- a/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/events/DisabledListeningMessageSearchIndex.java +++ b/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/events/DisabledListeningMessageSearchIndex.java @@ -39,6 +39,7 @@ import org.apache.james.mailbox.events.MailboxEvents; import org.apache.james.mailbox.model.Mailbox; import org.apache.james.mailbox.model.MailboxId; import org.apache.james.mailbox.model.MessageId; +import org.apache.james.mailbox.model.SearchOptions; import org.apache.james.mailbox.model.SearchQuery; import org.apache.james.mailbox.model.UpdatedFlags; import org.apache.james.mailbox.store.MailboxSessionMapperFactory; @@ -126,7 +127,7 @@ public class DisabledListeningMessageSearchIndex extends ListeningMessageSearchI } @Override - public Flux<MessageId> search(MailboxSession session, Collection<MailboxId> mailboxIds, SearchQuery searchQuery, long limit) { + public Flux<MessageId> search(MailboxSession session, Collection<MailboxId> mailboxIds, SearchQuery searchQuery, SearchOptions searchOptions) { Preconditions.checkArgument(session != null, "'session' is mandatory"); return Flux.error(new NotImplementedException()); diff --git a/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/events/OpenSearchListeningMessageSearchIndex.java b/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/events/OpenSearchListeningMessageSearchIndex.java index 15a3227a99..cfbc448c7d 100644 --- a/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/events/OpenSearchListeningMessageSearchIndex.java +++ b/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/events/OpenSearchListeningMessageSearchIndex.java @@ -58,6 +58,7 @@ import org.apache.james.mailbox.model.Mailbox; import org.apache.james.mailbox.model.MailboxId; import org.apache.james.mailbox.model.MessageId; import org.apache.james.mailbox.model.MessageMetaData; +import org.apache.james.mailbox.model.SearchOptions; import org.apache.james.mailbox.model.SearchQuery; import org.apache.james.mailbox.model.UpdatedFlags; import org.apache.james.mailbox.opensearch.IndexBody; @@ -362,14 +363,14 @@ public class OpenSearchListeningMessageSearchIndex extends ListeningMessageSearc } @Override - public Flux<MessageId> search(MailboxSession session, Collection<MailboxId> mailboxIds, SearchQuery searchQuery, long limit) { + public Flux<MessageId> search(MailboxSession session, Collection<MailboxId> mailboxIds, SearchQuery searchQuery, SearchOptions searchOptions) { Preconditions.checkArgument(session != null, "'session' is mandatory"); if (mailboxIds.isEmpty()) { return Flux.empty(); } - return searcher.searchCollapsedByMessageId(mailboxIds, searchQuery, Math.toIntExact(limit), MESSAGE_ID_FIELD, !SEARCH_HIGHLIGHT) + return searcher.searchCollapsedByMessageId(mailboxIds, searchQuery, searchOptions, MESSAGE_ID_FIELD, !SEARCH_HIGHLIGHT) .handle(this::extractMessageIdFromHit); } diff --git a/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/search/OpenSearchSearcher.java b/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/search/OpenSearchSearcher.java index d11bdf8333..3643ddc1bf 100644 --- a/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/search/OpenSearchSearcher.java +++ b/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/search/OpenSearchSearcher.java @@ -33,6 +33,7 @@ import org.apache.james.backends.opensearch.ReadAliasName; import org.apache.james.backends.opensearch.RoutingKey; import org.apache.james.backends.opensearch.search.ScrolledSearch; import org.apache.james.mailbox.model.MailboxId; +import org.apache.james.mailbox.model.SearchOptions; import org.apache.james.mailbox.model.SearchQuery; import org.apache.james.mailbox.opensearch.json.JsonMessageConstants; import org.apache.james.mailbox.opensearch.query.QueryConverter; @@ -106,13 +107,9 @@ public class OpenSearchSearcher { } public Flux<Hit<ObjectNode>> searchCollapsedByMessageId(Collection<MailboxId> mailboxIds, SearchQuery query, - int limit, List<String> fields, + SearchOptions searchOptions, List<String> fields, boolean searchHighlight) { - if (limit == 0) { - return Flux.empty(); - } - - SearchRequest searchRequest = prepareCollapsedSearchByMessageId(mailboxIds, query, 0, limit, fields, searchHighlight); + SearchRequest searchRequest = prepareCollapsedSearchByMessageId(mailboxIds, query, searchOptions, fields, searchHighlight); try { return client.search(searchRequest) .flatMapMany(response -> Flux.fromIterable(response.hits().hits())); @@ -148,13 +145,16 @@ public class OpenSearchSearcher { } private SearchRequest prepareCollapsedSearchByMessageId(Collection<MailboxId> mailboxIds, SearchQuery query, - int from, int size, List<String> fields, boolean highlight) { + SearchOptions searchOptions, List<String> fields, boolean highlight) { List<SortOptions> sorts = query.getSorts() .stream() .flatMap(SortConverter::convertSort) .map(fieldSort -> new SortOptions.Builder().field(fieldSort).build()) .collect(Collectors.toList()); + int from = searchOptions.offset().getOffset(); + int size = searchOptions.limit().getLimit().orElseThrow(); + SearchRequest.Builder request = new SearchRequest.Builder() .index(aliasName.getValue()) .query(queryConverter.from(mailboxIds, query)) diff --git a/mailbox/opensearch/src/test/java/org/apache/james/mailbox/opensearch/OpenSearchIntegrationTest.java b/mailbox/opensearch/src/test/java/org/apache/james/mailbox/opensearch/OpenSearchIntegrationTest.java index 4a3182dafd..f8ff7175e7 100644 --- a/mailbox/opensearch/src/test/java/org/apache/james/mailbox/opensearch/OpenSearchIntegrationTest.java +++ b/mailbox/opensearch/src/test/java/org/apache/james/mailbox/opensearch/OpenSearchIntegrationTest.java @@ -47,6 +47,7 @@ import org.apache.james.mailbox.model.MailboxPath; import org.apache.james.mailbox.model.MessageId; import org.apache.james.mailbox.model.MessageRange; import org.apache.james.mailbox.model.MultimailboxesSearchQuery; +import org.apache.james.mailbox.model.SearchOptions; import org.apache.james.mailbox.model.SearchQuery; import org.apache.james.mailbox.opensearch.events.OpenSearchListeningMessageSearchIndex; import org.apache.james.mailbox.opensearch.json.MessageToOpenSearchJson; @@ -62,6 +63,7 @@ import org.apache.james.metrics.tests.RecordingMetricFactory; import org.apache.james.mime4j.dom.Message; import org.apache.james.mime4j.stream.RawField; import org.apache.james.util.ClassLoaderUtils; +import org.apache.james.util.streams.Limit; import org.awaitility.Awaitility; import org.awaitility.Durations; import org.awaitility.core.ConditionFactory; @@ -531,7 +533,7 @@ class OpenSearchIntegrationTest extends AbstractMessageSearchIndexTest { .blockLast(); MultimailboxesSearchQuery query = MultimailboxesSearchQuery.from(SearchQuery.of(SearchQuery.address(SearchQuery.AddressType.To, "other"))).build(); - assertThat(Flux.from(storeMailboxManager.search(query, session, 10)).collectList().block()) + assertThat(Flux.from(storeMailboxManager.search(query, session, SearchOptions.limit(Limit.limit(10)))).collectList().block()) .containsOnly(messageId2.getMessageId()); } @@ -716,7 +718,7 @@ class OpenSearchIntegrationTest extends AbstractMessageSearchIndexTest { private void awaitUntilAsserted(MailboxId mailboxId, long expectedCountResult) { CALMLY_AWAIT.atMost(Durations.TEN_SECONDS) - .untilAsserted(() -> assertThat(messageSearchIndex.search(session, List.of(mailboxId), SearchQuery.matchAll(), 100L).toStream().count()) + .untilAsserted(() -> assertThat(messageSearchIndex.search(session, List.of(mailboxId), SearchQuery.matchAll(), SearchOptions.limit(Limit.limit(100))).toStream().count()) .isEqualTo(expectedCountResult)); } } \ No newline at end of file diff --git a/mailbox/opensearch/src/test/java/org/apache/james/mailbox/opensearch/search/OpenSearchSearcherTest.java b/mailbox/opensearch/src/test/java/org/apache/james/mailbox/opensearch/search/OpenSearchSearcherTest.java index eb89876a7f..b62509fedf 100644 --- a/mailbox/opensearch/src/test/java/org/apache/james/mailbox/opensearch/search/OpenSearchSearcherTest.java +++ b/mailbox/opensearch/src/test/java/org/apache/james/mailbox/opensearch/search/OpenSearchSearcherTest.java @@ -47,6 +47,7 @@ import org.apache.james.mailbox.model.MailboxId; import org.apache.james.mailbox.model.MailboxPath; import org.apache.james.mailbox.model.MessageId; import org.apache.james.mailbox.model.MultimailboxesSearchQuery; +import org.apache.james.mailbox.model.SearchOptions; import org.apache.james.mailbox.model.SearchQuery; import org.apache.james.mailbox.opensearch.DefaultMailboxMappingFactory; import org.apache.james.mailbox.opensearch.IndexAttachments; @@ -64,6 +65,7 @@ import org.apache.james.mailbox.tika.TikaHttpClientImpl; import org.apache.james.mailbox.tika.TikaTextExtractor; import org.apache.james.metrics.tests.RecordingMetricFactory; import org.apache.james.mime4j.dom.Message; +import org.apache.james.util.streams.Limit; import org.awaitility.Awaitility; import org.awaitility.Durations; import org.awaitility.core.ConditionFactory; @@ -176,7 +178,7 @@ class OpenSearchSearcherTest { .stream() .map(ComposedMessageId::getMessageId) .collect(ImmutableList.toImmutableList()); - assertThat(storeMailboxManager.search(multimailboxesSearchQuery, session, numberOfMailboxes + 1) + assertThat(storeMailboxManager.search(multimailboxesSearchQuery, session, SearchOptions.limit(Limit.limit(numberOfMailboxes + 1))) .collectList().block()) .containsExactlyInAnyOrderElementsOf(expectedMessageIds); } diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java index b4a92f45e7..ba95f9a5e5 100644 --- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java +++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java @@ -72,6 +72,7 @@ import org.apache.james.mailbox.model.MessageId.Factory; import org.apache.james.mailbox.model.MessageRange; import org.apache.james.mailbox.model.MultimailboxesSearchQuery; import org.apache.james.mailbox.model.QuotaRoot; +import org.apache.james.mailbox.model.SearchOptions; import org.apache.james.mailbox.model.ThreadId; import org.apache.james.mailbox.model.UidValidity; import org.apache.james.mailbox.model.search.MailboxQuery; @@ -946,11 +947,11 @@ public class StoreMailboxManager implements MailboxManager { } @Override - public Flux<MessageId> search(MultimailboxesSearchQuery expression, MailboxSession session, long limit) { + public Flux<MessageId> search(MultimailboxesSearchQuery expression, MailboxSession session, SearchOptions searchOptions) { return getInMailboxIds(expression, session) .filter(id -> !expression.getNotInMailboxes().contains(id)) .collect(ImmutableSet.toImmutableSet()) - .flatMapMany(Throwing.function(ids -> index.search(session, ids, expression.getSearchQuery(), limit))); + .flatMapMany(Throwing.function(ids -> index.search(session, ids, expression.getSearchQuery(), searchOptions))); } @Override diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/SearchThreadIdGuessingAlgorithm.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/SearchThreadIdGuessingAlgorithm.java index f143ea0aa3..b47552115e 100644 --- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/SearchThreadIdGuessingAlgorithm.java +++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/SearchThreadIdGuessingAlgorithm.java @@ -34,11 +34,13 @@ import org.apache.james.mailbox.model.FetchGroup; import org.apache.james.mailbox.model.MessageId; import org.apache.james.mailbox.model.MessageResult; import org.apache.james.mailbox.model.MultimailboxesSearchQuery; +import org.apache.james.mailbox.model.SearchOptions; import org.apache.james.mailbox.model.SearchQuery; import org.apache.james.mailbox.model.ThreadId; import org.apache.james.mailbox.store.mail.model.MimeMessageId; import org.apache.james.mailbox.store.mail.model.Subject; import org.apache.james.mailbox.store.search.SearchUtil; +import org.apache.james.util.streams.Limit; import com.google.common.collect.ImmutableList; @@ -59,7 +61,7 @@ public class SearchThreadIdGuessingAlgorithm implements ThreadIdGuessingAlgorith public Mono<ThreadId> guessThreadIdReactive(MessageId messageId, Optional<MimeMessageId> mimeMessageId, Optional<MimeMessageId> inReplyTo, Optional<List<MimeMessageId>> references, Optional<Subject> subject, MailboxSession session) { MultimailboxesSearchQuery expression = buildSearchQuery(mimeMessageId, inReplyTo, references, subject); - return Flux.from(mailboxManager.search(expression, session, 1)) + return Flux.from(mailboxManager.search(expression, session, SearchOptions.limit(Limit.limit(1)))) .collectList() .flatMapMany(messageIds -> messageIdManager.getMessagesReactive(messageIds, FetchGroup.MINIMAL, session)) .map(MessageResult::getThreadId) @@ -78,7 +80,7 @@ public class SearchThreadIdGuessingAlgorithm implements ThreadIdGuessingAlgorith .from(searchQuery) .build(); - return Flux.from(mailboxManager.search(expression, session, Integer.MAX_VALUE)) + return Flux.from(mailboxManager.search(expression, session, SearchOptions.limit(Limit.limit(Integer.MAX_VALUE)))) .switchIfEmpty(Mono.error(() -> new ThreadNotFoundException(threadId))); } diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/search/LazyMessageSearchIndex.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/search/LazyMessageSearchIndex.java index 2f71a4969a..f3b0c63481 100644 --- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/search/LazyMessageSearchIndex.java +++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/search/LazyMessageSearchIndex.java @@ -38,6 +38,7 @@ import org.apache.james.mailbox.model.Mailbox; import org.apache.james.mailbox.model.MailboxId; import org.apache.james.mailbox.model.MessageId; import org.apache.james.mailbox.model.MessageRange; +import org.apache.james.mailbox.model.SearchOptions; import org.apache.james.mailbox.model.SearchQuery; import org.apache.james.mailbox.model.UpdatedFlags; import org.apache.james.mailbox.store.MailboxSessionMapperFactory; @@ -150,7 +151,7 @@ public class LazyMessageSearchIndex extends ListeningMessageSearchIndex { @Override - public Flux<MessageId> search(MailboxSession session, Collection<MailboxId> mailboxIds, SearchQuery searchQuery, long limit) throws MailboxException { + public Flux<MessageId> search(MailboxSession session, Collection<MailboxId> mailboxIds, SearchQuery searchQuery, SearchOptions searchOptions) throws MailboxException { throw new UnsupportedSearchException(); } diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/search/MessageSearchIndex.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/search/MessageSearchIndex.java index 30269adcd2..dc15e12cff 100644 --- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/search/MessageSearchIndex.java +++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/search/MessageSearchIndex.java @@ -30,6 +30,7 @@ import org.apache.james.mailbox.exception.MailboxException; import org.apache.james.mailbox.model.Mailbox; import org.apache.james.mailbox.model.MailboxId; import org.apache.james.mailbox.model.MessageId; +import org.apache.james.mailbox.model.SearchOptions; import org.apache.james.mailbox.model.SearchQuery; import reactor.core.publisher.Flux; @@ -50,7 +51,7 @@ public interface MessageSearchIndex { /** * Return all uids of all {@link Mailbox}'s the current user has access to which match the {@link SearchQuery} */ - Flux<MessageId> search(MailboxSession session, Collection<MailboxId> mailboxIds, SearchQuery searchQuery, long limit) throws MailboxException; + Flux<MessageId> search(MailboxSession session, Collection<MailboxId> mailboxIds, SearchQuery searchQuery, SearchOptions searchOptions) throws MailboxException; EnumSet<MailboxManager.SearchCapabilities> getSupportedCapabilities(EnumSet<MailboxManager.MessageCapabilities> messageCapabilities); diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/search/SimpleMessageSearchIndex.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/search/SimpleMessageSearchIndex.java index 4d053aa2a0..22d65668be 100644 --- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/search/SimpleMessageSearchIndex.java +++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/search/SimpleMessageSearchIndex.java @@ -38,15 +38,16 @@ import org.apache.james.mailbox.MailboxSession; import org.apache.james.mailbox.MessageUid; import org.apache.james.mailbox.exception.MailboxException; import org.apache.james.mailbox.extractor.TextExtractor; -import org.apache.james.mailbox.model.Mailbox; -import org.apache.james.mailbox.model.MailboxId; -import org.apache.james.mailbox.model.MessageId; -import org.apache.james.mailbox.model.MessageRange; -import org.apache.james.mailbox.model.SearchQuery; -import org.apache.james.mailbox.model.SearchQuery.ConjunctionCriterion; -import org.apache.james.mailbox.model.SearchQuery.Criterion; -import org.apache.james.mailbox.model.SearchQuery.UidCriterion; -import org.apache.james.mailbox.model.SearchQuery.UidRange; +import org.apache.james.mailbox.model.Mailbox; +import org.apache.james.mailbox.model.MailboxId; +import org.apache.james.mailbox.model.MessageId; +import org.apache.james.mailbox.model.MessageRange; +import org.apache.james.mailbox.model.SearchOptions; +import org.apache.james.mailbox.model.SearchQuery; +import org.apache.james.mailbox.model.SearchQuery.ConjunctionCriterion; +import org.apache.james.mailbox.model.SearchQuery.Criterion; +import org.apache.james.mailbox.model.SearchQuery.UidCriterion; +import org.apache.james.mailbox.model.SearchQuery.UidRange; import org.apache.james.mailbox.store.mail.MailboxMapper; import org.apache.james.mailbox.store.mail.MailboxMapperFactory; import org.apache.james.mailbox.store.mail.MessageMapper; @@ -210,17 +211,17 @@ public class SimpleMessageSearchIndex implements MessageSearchIndex { } return hitSet; } - - @Override - public Flux<MessageId> search(MailboxSession session, final Collection<MailboxId> mailboxIds, SearchQuery searchQuery, long limit) throws MailboxException { - MailboxMapper mailboxMapper = mailboxMapperFactory.getMailboxMapper(session); - - Flux<Mailbox> filteredMailboxes = - Flux.fromIterable(mailboxIds) - .concatMap(mailboxMapper::findMailboxById); - - return getAsMessageIds(searchResults(session, filteredMailboxes, searchQuery), limit); - } + + @Override + public Flux<MessageId> search(MailboxSession session, final Collection<MailboxId> mailboxIds, SearchQuery searchQuery, SearchOptions searchOptions) throws MailboxException { + MailboxMapper mailboxMapper = mailboxMapperFactory.getMailboxMapper(session); + + Flux<Mailbox> filteredMailboxes = + Flux.fromIterable(mailboxIds) + .concatMap(mailboxMapper::findMailboxById); + + return getAsMessageIds(searchResults(session, filteredMailboxes, searchQuery), searchOptions); + } private Flux<? extends SearchResult> searchResults(MailboxSession session, Flux<Mailbox> mailboxes, SearchQuery query) { return mailboxes.concatMap(mailbox -> Mono.fromCallable(() -> getSearchResultStream(session, query, mailbox)) @@ -238,11 +239,12 @@ public class SimpleMessageSearchIndex implements MessageSearchIndex { throw new RuntimeException(e); } } - - private Flux<MessageId> getAsMessageIds(Flux<? extends SearchResult> temp, long limit) { - return temp.map(searchResult -> searchResult.getMessageId().get()) - .filter(SearchUtil.distinct()) - .take(Long.valueOf(limit).intValue()); - } - -} + + private Flux<MessageId> getAsMessageIds(Flux<? extends SearchResult> temp, SearchOptions searchOptions) { + return temp.map(searchResult -> searchResult.getMessageId().get()) + .filter(SearchUtil.distinct()) + .skip(searchOptions.offset().getOffset()) + .transform(searchOptions.limit()::applyOnFlux); + } + +} diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractCombinationManagerTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractCombinationManagerTest.java index 2bd8f3a00e..b8800d519e 100644 --- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractCombinationManagerTest.java +++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractCombinationManagerTest.java @@ -46,8 +46,10 @@ import org.apache.james.mailbox.model.MessageId; import org.apache.james.mailbox.model.MessageRange; import org.apache.james.mailbox.model.MessageResult; import org.apache.james.mailbox.model.MultimailboxesSearchQuery; +import org.apache.james.mailbox.model.SearchOptions; import org.apache.james.mailbox.model.SearchQuery; import org.apache.james.mime4j.dom.Message; +import org.apache.james.util.streams.Limit; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -60,7 +62,7 @@ import reactor.core.scheduler.Schedulers; public abstract class AbstractCombinationManagerTest { - private static final int DEFAULT_MAXIMUM_LIMIT = 256; + private static final SearchOptions DEFAULT_MAXIMUM_LIMIT = SearchOptions.limit(Limit.limit(256)); private static final String USER_FLAGS_VALUE = "User Flags"; private static final String ANOTHER_USER_FLAGS_VALUE = "Another User Flags"; diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/SystemMailboxesProviderImplTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/SystemMailboxesProviderImplTest.java index 8d38d96266..311ecc218b 100644 --- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/SystemMailboxesProviderImplTest.java +++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/SystemMailboxesProviderImplTest.java @@ -32,6 +32,7 @@ import org.apache.james.mailbox.MessageManager; import org.apache.james.mailbox.Role; import org.apache.james.mailbox.exception.MailboxNotFoundException; import org.apache.james.mailbox.fixture.MailboxFixture; +import org.apache.james.mailbox.model.search.MailboxQuery; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -60,7 +61,7 @@ class SystemMailboxesProviderImplTest { when(mailboxManager.createSystemSession(MailboxFixture.ALICE)).thenReturn(mailboxSession); when(mailboxManager.getMailboxReactive(eq(MailboxFixture.INBOX_ALICE), eq(mailboxSession))) .thenReturn(Mono.error(new MailboxNotFoundException("Not found"))); - when(mailboxManager.search(any(), any(), any())).thenReturn(Flux.empty()); + when(mailboxManager.search(any(MailboxQuery.class), any(), any(MailboxSession.class))).thenReturn(Flux.empty()); assertThat(Flux.from(systemMailboxProvider.getMailboxByRole(Role.INBOX, mailboxSession.getUser())).toStream()) .isEmpty(); diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/search/AbstractMessageSearchIndexTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/search/AbstractMessageSearchIndexTest.java index ca66422660..3e4a35a7a6 100644 --- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/search/AbstractMessageSearchIndexTest.java +++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/search/AbstractMessageSearchIndexTest.java @@ -56,6 +56,7 @@ import org.apache.james.mailbox.model.MailboxPath; import org.apache.james.mailbox.model.MessageId; import org.apache.james.mailbox.model.MessageMetaData; import org.apache.james.mailbox.model.MessageRange; +import org.apache.james.mailbox.model.SearchOptions; import org.apache.james.mailbox.model.SearchQuery; import org.apache.james.mailbox.model.SearchQuery.AddressType; import org.apache.james.mailbox.model.SearchQuery.DateResolution; @@ -76,6 +77,7 @@ import org.apache.james.mime4j.message.BodyPartBuilder; import org.apache.james.mime4j.message.MultipartBuilder; import org.apache.james.mime4j.message.SingleBodyBuilder; import org.apache.james.util.ClassLoaderUtils; +import org.apache.james.util.streams.Limit; import org.apache.james.utils.UpdatableTickingClock; import org.awaitility.Awaitility; import org.awaitility.core.ConditionFactory; @@ -92,7 +94,7 @@ public abstract class AbstractMessageSearchIndexTest { .with().pollInterval(ONE_HUNDRED_MILLISECONDS) .and().pollDelay(ONE_HUNDRED_MILLISECONDS) .await(); - private static final long LIMIT = 100L; + private static final SearchOptions LIMIT = SearchOptions.limit(Limit.limit(100)); private static final boolean RECENT = true; private static final boolean NOT_RECENT = false; @@ -372,7 +374,7 @@ public abstract class AbstractMessageSearchIndexTest { List<MessageId> result = messageSearchIndex.search(session, ImmutableList.of(mailbox2.getMailboxId(), mailbox.getMailboxId()), searchQuery, - limit) + SearchOptions.limit(Limit.limit(limit))) .collectList().block(); assertThat(result) @@ -410,7 +412,7 @@ public abstract class AbstractMessageSearchIndexTest { List<MessageId> result = messageSearchIndex.search(session, ImmutableList.of(mailbox2.getMailboxId(), mailbox.getMailboxId()), searchQuery, - limit) + SearchOptions.limit(Limit.limit(limit))) .collectList().block(); assertThat(result) @@ -771,7 +773,7 @@ public abstract class AbstractMessageSearchIndexTest { session, ImmutableList.of(mailbox.getMailboxId(), mailbox2.getMailboxId()), searchQuery, - limit) + SearchOptions.limit(Limit.limit(Math.toIntExact(limit)))) .collectList().block(); // Two messages matches this query : mOther and m6 @@ -788,7 +790,7 @@ public abstract class AbstractMessageSearchIndexTest { session, ImmutableList.of(otherMailbox.getMailboxId()), searchQuery, - limit) + SearchOptions.limit(Limit.limit(Math.toIntExact(limit)))) .collectList().block(); assertThat(actual).contains(m10.getMessageId()); diff --git a/server/container/guice/mailbox/src/main/java/org/apache/james/modules/MailboxProbeImpl.java b/server/container/guice/mailbox/src/main/java/org/apache/james/modules/MailboxProbeImpl.java index 27c3cb4d61..b7ec9c59f9 100644 --- a/server/container/guice/mailbox/src/main/java/org/apache/james/modules/MailboxProbeImpl.java +++ b/server/container/guice/mailbox/src/main/java/org/apache/james/modules/MailboxProbeImpl.java @@ -47,9 +47,11 @@ import org.apache.james.mailbox.model.MailboxPath; import org.apache.james.mailbox.model.MessageId; import org.apache.james.mailbox.model.MessageRange; import org.apache.james.mailbox.model.MultimailboxesSearchQuery; +import org.apache.james.mailbox.model.SearchOptions; import org.apache.james.mailbox.model.search.MailboxQuery; import org.apache.james.mailbox.model.search.Wildcard; import org.apache.james.mailbox.probe.MailboxProbe; +import org.apache.james.util.streams.Limit; import org.apache.james.utils.GuiceProbe; import com.google.common.collect.ImmutableList; @@ -216,7 +218,7 @@ public class MailboxProbeImpl implements GuiceProbe, MailboxProbe { MailboxSession mailboxSession = null; try { mailboxSession = mailboxManager.createSystemSession(Username.of(user)); - return block(Flux.from(mailboxManager.search(expression, mailboxSession, limit)).collectList()); + return block(Flux.from(mailboxManager.search(expression, mailboxSession, SearchOptions.limit(Limit.limit(Math.toIntExact(limit))))).collectList()); } catch (MailboxException e) { throw new RuntimeException(e); } finally { diff --git a/server/container/guice/memory/src/main/java/org/apache/james/FakeMessageSearchIndex.java b/server/container/guice/memory/src/main/java/org/apache/james/FakeMessageSearchIndex.java index 0e2d947125..9e55bcad44 100644 --- a/server/container/guice/memory/src/main/java/org/apache/james/FakeMessageSearchIndex.java +++ b/server/container/guice/memory/src/main/java/org/apache/james/FakeMessageSearchIndex.java @@ -34,6 +34,7 @@ import org.apache.james.mailbox.exception.MailboxException; import org.apache.james.mailbox.model.Mailbox; import org.apache.james.mailbox.model.MailboxId; import org.apache.james.mailbox.model.MessageId; +import org.apache.james.mailbox.model.SearchOptions; import org.apache.james.mailbox.model.SearchQuery; import org.apache.james.mailbox.model.UpdatedFlags; import org.apache.james.mailbox.store.mail.model.MailboxMessage; @@ -91,7 +92,7 @@ public class FakeMessageSearchIndex extends ListeningMessageSearchIndex { } @Override - public Flux<MessageId> search(MailboxSession session, Collection<MailboxId> mailboxIds, SearchQuery searchQuery, long limit) { + public Flux<MessageId> search(MailboxSession session, Collection<MailboxId> mailboxIds, SearchQuery searchQuery, SearchOptions searchOptions) { throw new NotImplementedException("not implemented"); } diff --git a/server/container/guice/opensearch/src/main/java/org/apache/james/SearchModuleChooser.java b/server/container/guice/opensearch/src/main/java/org/apache/james/SearchModuleChooser.java index 51a0477372..aa01b9744d 100644 --- a/server/container/guice/opensearch/src/main/java/org/apache/james/SearchModuleChooser.java +++ b/server/container/guice/opensearch/src/main/java/org/apache/james/SearchModuleChooser.java @@ -35,6 +35,7 @@ import org.apache.james.mailbox.model.Mailbox; import org.apache.james.mailbox.model.MailboxId; import org.apache.james.mailbox.model.MessageId; import org.apache.james.mailbox.model.MultimailboxesSearchQuery; +import org.apache.james.mailbox.model.SearchOptions; import org.apache.james.mailbox.model.SearchQuery; import org.apache.james.mailbox.model.UpdatedFlags; import org.apache.james.mailbox.searchhighligt.SearchHighlighter; @@ -118,7 +119,7 @@ public class SearchModuleChooser { } @Override - public Flux<MessageId> search(MailboxSession session, Collection<MailboxId> mailboxIds, SearchQuery searchQuery, long limit) { + public Flux<MessageId> search(MailboxSession session, Collection<MailboxId> mailboxIds, SearchQuery searchQuery, SearchOptions searchOptions) { throw new NotImplementedException("not implemented"); } diff --git a/server/container/mailbox-adapter/src/test/java/org/apache/james/adapter/mailbox/MailboxUserDeletionTaskStepTest.java b/server/container/mailbox-adapter/src/test/java/org/apache/james/adapter/mailbox/MailboxUserDeletionTaskStepTest.java index 4040a4050b..d42efb1336 100644 --- a/server/container/mailbox-adapter/src/test/java/org/apache/james/adapter/mailbox/MailboxUserDeletionTaskStepTest.java +++ b/server/container/mailbox-adapter/src/test/java/org/apache/james/adapter/mailbox/MailboxUserDeletionTaskStepTest.java @@ -33,9 +33,11 @@ import org.apache.james.mailbox.model.MailboxACL; import org.apache.james.mailbox.model.MailboxMetaData; import org.apache.james.mailbox.model.MailboxPath; import org.apache.james.mailbox.model.MultimailboxesSearchQuery; +import org.apache.james.mailbox.model.SearchOptions; import org.apache.james.mailbox.model.SearchQuery; import org.apache.james.mailbox.model.search.MailboxQuery; import org.apache.james.mailbox.store.StoreSubscriptionManager; +import org.apache.james.util.streams.Limit; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -122,7 +124,7 @@ class MailboxUserDeletionTaskStepTest { Mono.from(testee.deleteUserData(ALICE)).block(); - assertThat(mailboxManager.search(MultimailboxesSearchQuery.from(SearchQuery.matchAll()).build(), session, 100L) + assertThat(mailboxManager.search(MultimailboxesSearchQuery.from(SearchQuery.matchAll()).build(), session, SearchOptions.limit(Limit.limit(100))) .collectList().block()) .isEmpty(); } @@ -150,7 +152,7 @@ class MailboxUserDeletionTaskStepTest { Mono.from(testee.deleteUserData(ALICE)).block(); - assertThat(mailboxManager.search(MultimailboxesSearchQuery.from(SearchQuery.matchAll()).build(), session, 100L) + assertThat(mailboxManager.search(MultimailboxesSearchQuery.from(SearchQuery.matchAll()).build(), session, SearchOptions.limit(Limit.limit(100))) .collectList().block()) .isEmpty(); } diff --git a/server/protocols/jmap-rfc-8621/src/main/java/org/apache/james/jmap/mailet/ExtractMDNOriginalJMAPMessageId.java b/server/protocols/jmap-rfc-8621/src/main/java/org/apache/james/jmap/mailet/ExtractMDNOriginalJMAPMessageId.java index 8f1a4f187e..13d8ccff99 100644 --- a/server/protocols/jmap-rfc-8621/src/main/java/org/apache/james/jmap/mailet/ExtractMDNOriginalJMAPMessageId.java +++ b/server/protocols/jmap-rfc-8621/src/main/java/org/apache/james/jmap/mailet/ExtractMDNOriginalJMAPMessageId.java @@ -29,6 +29,7 @@ import org.apache.james.mailbox.MailboxManager; import org.apache.james.mailbox.MailboxSession; import org.apache.james.mailbox.model.MessageId; import org.apache.james.mailbox.model.MultimailboxesSearchQuery; +import org.apache.james.mailbox.model.SearchOptions; import org.apache.james.mailbox.model.SearchQuery; import org.apache.james.mdn.MDN; import org.apache.james.mdn.MDNReport; @@ -101,11 +102,10 @@ public class ExtractMDNOriginalJMAPMessageId extends GenericMailet { LOGGER.debug("Searching message {} for recipient {}", messageId, recipient.asPrettyString()); try { MailboxSession session = mailboxManager.createSystemSession(usersRepository.getUsername(recipient)); - int limit = 1; MultimailboxesSearchQuery searchByRFC822MessageId = MultimailboxesSearchQuery .from(SearchQuery.of(SearchQuery.mimeMessageID(messageId))) .build(); - return Flux.from(mailboxManager.search(searchByRFC822MessageId, session, limit)).toStream().findFirst(); + return Flux.from(mailboxManager.search(searchByRFC822MessageId, session, SearchOptions.FIRST)).toStream().findFirst(); } catch (UsersRepositoryException e) { LOGGER.error("unable to find message with Message-Id: " + messageId, e); } diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailQueryMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailQueryMethod.scala index e164e3bba3..5a7672a8a6 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailQueryMethod.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailQueryMethod.scala @@ -38,10 +38,10 @@ import org.apache.james.jmap.utils.search.MailboxFilter import org.apache.james.jmap.utils.search.MailboxFilter.QueryFilter import org.apache.james.mailbox.exception.MailboxNotFoundException import org.apache.james.mailbox.model.MultimailboxesSearchQuery.Namespace -import org.apache.james.mailbox.model.{MailboxId, MessageId, MultimailboxesSearchQuery, SearchQuery} +import org.apache.james.mailbox.model.{MailboxId, MessageId, MultimailboxesSearchQuery, SearchOptions, SearchQuery} import org.apache.james.mailbox.{MailboxManager, MailboxSession} import org.apache.james.metrics.api.MetricFactory -import org.apache.james.util.streams.{Limit => JavaLimit} +import org.apache.james.util.streams.{Offset, Limit => JavaLimit} import reactor.core.scala.publisher.{SFlux, SMono} import scala.jdk.CollectionConverters._ @@ -203,8 +203,7 @@ class EmailQueryMethod @Inject() (serializer: EmailQuerySerializer, SFlux.fromPublisher(mailboxManager.search( searchQuery.addCriterion(SearchQuery.flagIsUnSet(DELETED)), mailboxSession, - position.value + limitToUse)) - .drop(position.value) + SearchOptions.of(Offset.from(position.value), JavaLimit.limit(limitToUse.value)))) .collectSeq() private def searchQueryFromRequest(request: EmailQueryRequest, capabilities: Set[CapabilityIdentifier], session: MailboxSession): Either[UnsupportedOperationException, MultimailboxesSearchQuery] = { diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MDNParseMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MDNParseMethod.scala index 356016babc..063aff436d 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MDNParseMethod.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MDNParseMethod.scala @@ -29,13 +29,14 @@ import org.apache.james.jmap.core.{Invocation, JmapRfc8621Configuration, Session import org.apache.james.jmap.json.MDNSerializer import org.apache.james.jmap.mail.{BlobId, BlobUnParsableException, MDNParseRequest, MDNParseResponse, MDNParseResults, MDNParsed} import org.apache.james.jmap.routes.{BlobNotFoundException, BlobResolvers, SessionSupplier} -import org.apache.james.mailbox.model.{MessageId, MultimailboxesSearchQuery, SearchQuery} +import org.apache.james.mailbox.model.{MessageId, MultimailboxesSearchQuery, SearchOptions, SearchQuery} import org.apache.james.mailbox.{MailboxManager, MailboxSession} import org.apache.james.mdn.MDN import org.apache.james.mdn.fields.OriginalMessageId import org.apache.james.metrics.api.MetricFactory import org.apache.james.mime4j.dom.Message import org.apache.james.mime4j.message.DefaultMessageBuilder +import org.apache.james.util.streams.{Limit => JavaLimit} import play.api.libs.json.JsObject import reactor.core.scala.publisher.{SFlux, SMono} @@ -132,7 +133,7 @@ case class MDNEmailIdResolver @Inject()(mailboxManager: MailboxManager) { def resolveForEmailId(originalMessageId: Option[OriginalMessageId], session: MailboxSession): SMono[Option[MessageId]] = originalMessageId.map(originalMsg => { val searchByRFC822MessageId: MultimailboxesSearchQuery = MultimailboxesSearchQuery.from(SearchQuery.of(SearchQuery.mimeMessageID(originalMsg.getOriginalMessageId))).build - SFlux.fromPublisher(mailboxManager.search(searchByRFC822MessageId, session, NUMBER_OF_ORIGINAL_MESSAGE_ID_VALID + 1)).collectSeq().map { + SFlux.fromPublisher(mailboxManager.search(searchByRFC822MessageId, session, SearchOptions.limit(JavaLimit.limit(NUMBER_OF_ORIGINAL_MESSAGE_ID_VALID + 1)))).collectSeq().map { case Seq(first) => Some(first) case _ => None } diff --git a/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/test/java/org/apache/james/webadmin/vault/routes/DeletedMessagesVaultRoutesTest.java b/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/test/java/org/apache/james/webadmin/vault/routes/DeletedMessagesVaultRoutesTest.java index 33b7539449..b1d8e0f26e 100644 --- a/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/test/java/org/apache/james/webadmin/vault/routes/DeletedMessagesVaultRoutesTest.java +++ b/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/test/java/org/apache/james/webadmin/vault/routes/DeletedMessagesVaultRoutesTest.java @@ -102,12 +102,14 @@ import org.apache.james.mailbox.model.MessageId; import org.apache.james.mailbox.model.MessageRange; import org.apache.james.mailbox.model.MessageResult; import org.apache.james.mailbox.model.MultimailboxesSearchQuery; +import org.apache.james.mailbox.model.SearchOptions; import org.apache.james.mailbox.model.SearchQuery; import org.apache.james.metrics.tests.RecordingMetricFactory; import org.apache.james.server.blob.deduplication.BlobStoreFactory; import org.apache.james.task.Hostname; import org.apache.james.task.MemoryTaskManager; import org.apache.james.user.memory.MemoryUsersRepository; +import org.apache.james.util.streams.Limit; import org.apache.james.utils.UpdatableTickingClock; import org.apache.james.vault.DeletedMessage; import org.apache.james.vault.DeletedMessageVault; @@ -2321,7 +2323,7 @@ class DeletedMessagesVaultRoutesTest { MailboxSession session = mailboxManager.createSystemSession(username); int limitToOneMessage = 1; - return !Flux.from(mailboxManager.search(MultimailboxesSearchQuery.from(SearchQuery.of()).build(), session, limitToOneMessage)) + return !Flux.from(mailboxManager.search(MultimailboxesSearchQuery.from(SearchQuery.of()).build(), session, SearchOptions.limit(Limit.limit(limitToOneMessage)))) .collectList().block() .isEmpty(); } diff --git a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/service/ExpireMailboxServiceTest.java b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/service/ExpireMailboxServiceTest.java index c65ae91667..a8750da432 100644 --- a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/service/ExpireMailboxServiceTest.java +++ b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/service/ExpireMailboxServiceTest.java @@ -45,6 +45,7 @@ import org.apache.james.mailbox.model.MailboxConstants; import org.apache.james.mailbox.model.MailboxId; import org.apache.james.mailbox.model.MailboxPath; import org.apache.james.mailbox.model.MessageId; +import org.apache.james.mailbox.model.SearchOptions; import org.apache.james.mailbox.model.SearchQuery; import org.apache.james.mailbox.store.extractor.DefaultTextExtractor; import org.apache.james.mailbox.store.search.MessageSearchIndex; @@ -90,9 +91,9 @@ class ExpireMailboxServiceTest { } @Override - public Flux<MessageId> search(MailboxSession session, Collection<MailboxId> mailboxIds, SearchQuery searchQuery, long limit) throws MailboxException { + public Flux<MessageId> search(MailboxSession session, Collection<MailboxId> mailboxIds, SearchQuery searchQuery, SearchOptions searchOptions) throws MailboxException { handleFailure(); - return delegate.search(session, mailboxIds, searchQuery, limit); + return delegate.search(session, mailboxIds, searchQuery, searchOptions); } @Override --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
