From 452f7eee71828bf7457bfac660813c113d3351e5 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Tue, 10 Sep 2024 19:03:48 +0200 Subject: [PATCH] HSEARCH-2945 Use a default mass indexing monitor configurer --- .../MassIndexingDefaultMonitorIT.java | 236 ++++++++++++++++++ .../massindexing/MassIndexingMonitorIT.java | 27 +- .../mapper/orm/massindexing/MassIndexer.java | 19 +- .../impl/HibernateOrmMassIndexer.java | 6 +- .../search/mapper/pojo/logging/impl/Log.java | 5 + ...ssIndexingMonitorConfigurationContext.java | 43 ++++ .../massindexing/MassIndexingMonitor.java | 24 ++ .../impl/PojoDefaultMassIndexer.java | 13 +- .../PojoMassIndexingBatchCoordinator.java | 8 +- ...ojoMassIndexingBatchIndexingWorkspace.java | 36 ++- ...dexingEntityIdentifierLoadingRunnable.java | 8 +- .../impl/PojoMassIndexingLoggingMonitor.java | 112 ++++++++- .../impl/PojoMassIndexingNotifier.java | 8 +- ...dexingMonitorConfigurationContextImpl.java | 42 ++++ .../massindexing/spi/PojoMassIndexer.java | 14 +- .../standalone/massindexing/MassIndexer.java | 19 +- .../impl/StandalonePojoMassIndexer.java | 6 +- 17 files changed, 547 insertions(+), 79 deletions(-) create mode 100644 integrationtest/mapper/pojo-base/src/test/java/org/hibernate/search/integrationtest/mapper/pojo/massindexing/MassIndexingDefaultMonitorIT.java create mode 100644 mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/DefaultMassIndexingMonitorConfigurationContext.java create mode 100644 mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/spi/DefaultMassIndexingMonitorConfigurationContextImpl.java diff --git a/integrationtest/mapper/pojo-base/src/test/java/org/hibernate/search/integrationtest/mapper/pojo/massindexing/MassIndexingDefaultMonitorIT.java b/integrationtest/mapper/pojo-base/src/test/java/org/hibernate/search/integrationtest/mapper/pojo/massindexing/MassIndexingDefaultMonitorIT.java new file mode 100644 index 00000000000..8717456a8f1 --- /dev/null +++ b/integrationtest/mapper/pojo-base/src/test/java/org/hibernate/search/integrationtest/mapper/pojo/massindexing/MassIndexingDefaultMonitorIT.java @@ -0,0 +1,236 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.search.integrationtest.mapper.pojo.massindexing; + +import static org.assertj.core.api.Fail.fail; + +import java.lang.invoke.MethodHandles; +import java.util.concurrent.CompletableFuture; + +import org.hibernate.search.engine.backend.work.execution.DocumentCommitStrategy; +import org.hibernate.search.engine.backend.work.execution.DocumentRefreshStrategy; +import org.hibernate.search.engine.cfg.EngineSettings; +import org.hibernate.search.integrationtest.mapper.pojo.testsupport.loading.PersistenceTypeKey; +import org.hibernate.search.integrationtest.mapper.pojo.testsupport.loading.StubEntityLoadingBinder; +import org.hibernate.search.integrationtest.mapper.pojo.testsupport.loading.StubLoadingContext; +import org.hibernate.search.mapper.pojo.loading.mapping.annotation.EntityLoadingBinderRef; +import org.hibernate.search.mapper.pojo.mapping.definition.annotation.DocumentId; +import org.hibernate.search.mapper.pojo.mapping.definition.annotation.GenericField; +import org.hibernate.search.mapper.pojo.mapping.definition.annotation.Indexed; +import org.hibernate.search.mapper.pojo.mapping.definition.annotation.SearchEntity; +import org.hibernate.search.mapper.pojo.standalone.mapping.SearchMapping; +import org.hibernate.search.mapper.pojo.standalone.massindexing.MassIndexer; +import org.hibernate.search.mapper.pojo.standalone.session.SearchSession; +import org.hibernate.search.util.impl.integrationtest.common.extension.BackendMock; +import org.hibernate.search.util.impl.integrationtest.mapper.pojo.standalone.StandalonePojoMappingSetupHelper; +import org.hibernate.search.util.impl.test.extension.ExpectedLog4jLog; + +import org.junit.jupiter.api.extension.RegisterExtension; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import org.apache.logging.log4j.Level; + +class MassIndexingDefaultMonitorIT { + + private static final int COUNT = 100; + @RegisterExtension + public final BackendMock backendMock = BackendMock.create(); + + @RegisterExtension + public final StandalonePojoMappingSetupHelper setupHelper = + StandalonePojoMappingSetupHelper.withBackendMock( MethodHandles.lookup(), backendMock ); + + @RegisterExtension + public ExpectedLog4jLog logged = ExpectedLog4jLog.create(); + + private final StubLoadingContext loadingContext = new StubLoadingContext(); + + private SearchMapping setup(String failureHandler) { + backendMock.expectAnySchema( Book.NAME ); + + SearchMapping mapping = setupHelper.start() + .expectCustomBeans() + .withPropertyRadical( EngineSettings.BACKGROUND_FAILURE_HANDLER, failureHandler ) + .setup( Book.class ); + + backendMock.verifyExpectationsMet(); + + initData(); + + return mapping; + } + + @ValueSource(booleans = { true, false }) + @ParameterizedTest + void skipTotalCount(boolean doCounts) { + SearchMapping mapping = setup( null ); + + logged.expectEvent( Level.INFO, "Mass indexing complete in ", ". Indexed 100/100 entities" ); + if ( doCounts ) { + logged.expectEvent( Level.INFO, "Mass indexing is going to index 100 entities" ).once(); + } + else { + logged.expectEvent( Level.INFO, "Mass indexing is going to index 100 entities" ).never(); + } + + try ( SearchSession searchSession = mapping.createSession() ) { + MassIndexer indexer = searchSession.massIndexer() + // Simulate passing information to connect to a DB, ... + .context( StubLoadingContext.class, loadingContext ); + + CompletableFuture indexingFuture = new CompletableFuture<>(); + indexingFuture.completeExceptionally( new SimulatedFailure( "Indexing error" ) ); + + // add operations on indexes can follow any random order, + // since they are executed by different threads + BackendMock.DocumentWorkCallListContext expectWorks = backendMock.expectWorks( + Book.NAME, DocumentCommitStrategy.NONE, DocumentRefreshStrategy.NONE + ); + for ( int i = 0; i < COUNT; i++ ) { + final String id = Integer.toString( i ); + expectWorks + .add( id, b -> b + .field( "title", "TITLE_" + id ) + .field( "author", "AUTHOR_" + id ) + ); + } + + // purgeAtStart and mergeSegmentsAfterPurge are enabled by default, + // so we expect 1 purge, 1 mergeSegments and 1 flush calls in this order: + backendMock.expectIndexScaleWorks( Book.NAME, searchSession.tenantIdentifierValue() ) + .purge() + .mergeSegments() + .flush() + .refresh(); + + try { + indexer.monitor( f -> f.countEntitiesToIndexOnStart( doCounts ) ) + .startAndWait(); + } + catch (InterruptedException e) { + fail( "Unexpected InterruptedException: " + e.getMessage() ); + } + } + + backendMock.verifyExpectationsMet(); + } + + @ValueSource(booleans = { true, false }) + @ParameterizedTest + void totalCountAtStart(boolean doCounts) { + SearchMapping mapping = setup( null ); + + logged.expectEvent( Level.INFO, "Mass indexing complete in ", ". Indexed 100/100 entities" ); + logged.expectEvent( Level.INFO, "Mass indexing is going to index 100 entities" ).once(); + if ( doCounts ) { + logged.expectEvent( Level.INFO, + "Mass indexing is going to index approx. 100 entities ([ Book ]). Actual number may change once the indexing starts." ) + .once(); + } + else { + logged.expectEvent( Level.INFO, + "Mass indexing is going to index approx. 100 entities ([ Book ]). Actual number may change once the indexing starts." ) + .never(); + } + + try ( SearchSession searchSession = mapping.createSession() ) { + MassIndexer indexer = searchSession.massIndexer() + // Simulate passing information to connect to a DB, ... + .context( StubLoadingContext.class, loadingContext ); + + CompletableFuture indexingFuture = new CompletableFuture<>(); + indexingFuture.completeExceptionally( new SimulatedFailure( "Indexing error" ) ); + + // add operations on indexes can follow any random order, + // since they are executed by different threads + BackendMock.DocumentWorkCallListContext expectWorks = backendMock.expectWorks( + Book.NAME, DocumentCommitStrategy.NONE, DocumentRefreshStrategy.NONE + ); + for ( int i = 0; i < COUNT; i++ ) { + final String id = Integer.toString( i ); + expectWorks + .add( id, b -> b + .field( "title", "TITLE_" + id ) + .field( "author", "AUTHOR_" + id ) + ); + } + + // purgeAtStart and mergeSegmentsAfterPurge are enabled by default, + // so we expect 1 purge, 1 mergeSegments and 1 flush calls in this order: + backendMock.expectIndexScaleWorks( Book.NAME, searchSession.tenantIdentifierValue() ) + .purge() + .mergeSegments() + .flush() + .refresh(); + + try { + indexer.monitor( f -> f.countAllEntitiesBeforeStart( doCounts ) ) + .startAndWait(); + } + catch (InterruptedException e) { + fail( "Unexpected InterruptedException: " + e.getMessage() ); + } + } + + backendMock.verifyExpectationsMet(); + } + + private void initData() { + for ( int i = 0; i < COUNT; i++ ) { + persist( new Book( i, "TITLE_" + i, "AUTHOR_" + i ) ); + } + } + + private void persist(Book book) { + loadingContext.persistenceMap( Book.PERSISTENCE_KEY ).put( book.id, book ); + } + + @SearchEntity(name = Book.NAME, + loadingBinder = @EntityLoadingBinderRef(type = StubEntityLoadingBinder.class)) + @Indexed(index = Book.NAME) + public static class Book { + + public static final String NAME = "Book"; + public static final PersistenceTypeKey PERSISTENCE_KEY = + new PersistenceTypeKey<>( Book.class, Integer.class ); + + @DocumentId + private Integer id; + + @GenericField + private String title; + + @GenericField + private String author; + + public Book() { + } + + public Book(Integer id, String title, String author) { + this.id = id; + this.title = title; + this.author = author; + } + + public Integer getId() { + return id; + } + + public String getTitle() { + return title; + } + + public String getAuthor() { + return author; + } + } + + private static class SimulatedFailure extends RuntimeException { + SimulatedFailure(String message) { + super( message ); + } + } +} diff --git a/integrationtest/mapper/pojo-base/src/test/java/org/hibernate/search/integrationtest/mapper/pojo/massindexing/MassIndexingMonitorIT.java b/integrationtest/mapper/pojo-base/src/test/java/org/hibernate/search/integrationtest/mapper/pojo/massindexing/MassIndexingMonitorIT.java index b1421346146..42646a2d41f 100644 --- a/integrationtest/mapper/pojo-base/src/test/java/org/hibernate/search/integrationtest/mapper/pojo/massindexing/MassIndexingMonitorIT.java +++ b/integrationtest/mapper/pojo-base/src/test/java/org/hibernate/search/integrationtest/mapper/pojo/massindexing/MassIndexingMonitorIT.java @@ -83,8 +83,8 @@ void simple() { // add operations on indexes can follow any random order, // since they are executed by different threads backendMock.expectWorks( - Book.NAME, DocumentCommitStrategy.NONE, DocumentRefreshStrategy.NONE - ) + Book.NAME, DocumentCommitStrategy.NONE, DocumentRefreshStrategy.NONE + ) .add( "1", b -> b .field( "title", TITLE_1 ) .field( "author", AUTHOR_1 ) @@ -134,7 +134,6 @@ void skipTotalCount() { try ( SearchSession searchSession = mapping.createSession() ) { MassIndexer indexer = searchSession.massIndexer() - .countEntitiesToIndexOnStart( false ) // Simulate passing information to connect to a DB, ... .context( StubLoadingContext.class, loadingContext ); @@ -144,8 +143,8 @@ void skipTotalCount() { // add operations on indexes can follow any random order, // since they are executed by different threads backendMock.expectWorks( - Book.NAME, DocumentCommitStrategy.NONE, DocumentRefreshStrategy.NONE - ) + Book.NAME, DocumentCommitStrategy.NONE, DocumentRefreshStrategy.NONE + ) .add( "1", b -> b .field( "title", TITLE_1 ) .field( "author", AUTHOR_1 ) @@ -169,7 +168,7 @@ void skipTotalCount() { .refresh(); try { - indexer.monitor( new StaticCountersMonitor() ) + indexer.monitor( new StaticCountersMonitor( false ) ) .startAndWait(); } catch (SearchException ignored) { @@ -247,6 +246,22 @@ public static class StaticCountersMonitor implements MassIndexingMonitor { public static StaticCounters.Key TOTAL = StaticCounters.createKey(); public static StaticCounters.Key INDEXING_COMPLETED = StaticCounters.createKey(); + + private final boolean requiresTotalCount; + + public StaticCountersMonitor() { + this( true ); + } + + public StaticCountersMonitor(boolean requiresTotalCount) { + this.requiresTotalCount = requiresTotalCount; + } + + @Override + public boolean requiresTotalCount() { + return requiresTotalCount; + } + @Override public void documentsAdded(long increment) { StaticCounters.get().add( ADDED, (int) increment ); diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/massindexing/MassIndexer.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/massindexing/MassIndexer.java index 178f3dbef0b..ac5f6812392 100644 --- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/massindexing/MassIndexer.java +++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/massindexing/MassIndexer.java @@ -4,16 +4,15 @@ */ package org.hibernate.search.mapper.orm.massindexing; -import java.util.OptionalLong; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; +import java.util.function.Consumer; import org.hibernate.CacheMode; -import org.hibernate.search.mapper.pojo.loading.spi.PojoMassIdentifierLoader; +import org.hibernate.search.mapper.pojo.massindexing.DefaultMassIndexingMonitorConfigurationContext; import org.hibernate.search.mapper.pojo.massindexing.MassIndexingEnvironment; import org.hibernate.search.mapper.pojo.massindexing.MassIndexingFailureHandler; import org.hibernate.search.mapper.pojo.massindexing.MassIndexingMonitor; -import org.hibernate.search.mapper.pojo.massindexing.spi.PojoMassIndexer; import org.hibernate.search.util.common.annotation.Incubating; /** @@ -241,19 +240,13 @@ public interface MassIndexer { MassIndexer failFast(boolean failFast); /** - * Allows specifying whether to try determining the total number of entities of the particular type to index - * and passing that information to the monitor, or skipping the counting and passing an {@link OptionalLong#empty() empty optional} instead. - * as a count. + * Configures the default {@link MassIndexingMonitor}. *

- * It may be helpful to skip the counting of entities and start the ID fetching right away to save some time. - *

- * Defaults to {@code true}. - * @param countEntitiesToIndexOnStart If {@code true}, the mass indexer will try determining the total number of entities, - * otherwise the mass indexer will not try obtaining the total count. + * The default monitor just logs the progress. This configurer allows to influence the logging behavior. * + * @param configurer The monitor that will track mass indexing progress. * @return {@code this} for method chaining */ - @Incubating - MassIndexer countEntitiesToIndexOnStart(boolean countEntitiesToIndexOnStart); + MassIndexer monitor(Consumer configurer); } diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/massindexing/impl/HibernateOrmMassIndexer.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/massindexing/impl/HibernateOrmMassIndexer.java index f58c491e2ae..2d463703361 100644 --- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/massindexing/impl/HibernateOrmMassIndexer.java +++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/massindexing/impl/HibernateOrmMassIndexer.java @@ -5,11 +5,13 @@ package org.hibernate.search.mapper.orm.massindexing.impl; import java.util.concurrent.CompletionStage; +import java.util.function.Consumer; import org.hibernate.CacheMode; import org.hibernate.search.mapper.orm.loading.spi.ConditionalExpression; import org.hibernate.search.mapper.orm.massindexing.MassIndexer; import org.hibernate.search.mapper.orm.massindexing.MassIndexerFilteringTypeStep; +import org.hibernate.search.mapper.pojo.massindexing.DefaultMassIndexingMonitorConfigurationContext; import org.hibernate.search.mapper.pojo.massindexing.MassIndexingEnvironment; import org.hibernate.search.mapper.pojo.massindexing.MassIndexingFailureHandler; import org.hibernate.search.mapper.pojo.massindexing.MassIndexingMonitor; @@ -132,8 +134,8 @@ public MassIndexer failFast(boolean failFast) { } @Override - public MassIndexer countEntitiesToIndexOnStart(boolean countEntitiesToIndexOnStart) { - delegate.countEntitiesToIndexOnStart( countEntitiesToIndexOnStart ); + public MassIndexer monitor(Consumer configurer) { + delegate.monitor( configurer ); return this; } diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/logging/impl/Log.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/logging/impl/Log.java index 3708acc19e6..8c0ce99e737 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/logging/impl/Log.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/logging/impl/Log.java @@ -1042,4 +1042,9 @@ void indexingProgressWithRemainingTime(float estimatePercentileComplete, long do @LogMessage(level = INFO) @Message(id = ID_OFFSET + 168, value = "Mass indexing complete in %3$s. Indexed %1$d/%2$d entities.") void indexingEntitiesCompleted(long indexed, long total, Duration indexingTime); + + @LogMessage(level = INFO) + @Message(id = ID_OFFSET + 169, + value = "Mass indexing is going to index approx. %1$d entities (%2$s). Actual number may change once the indexing starts.") + void indexingEntitiesApprox(long count, String types); } diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/DefaultMassIndexingMonitorConfigurationContext.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/DefaultMassIndexingMonitorConfigurationContext.java new file mode 100644 index 00000000000..f3a33ae39fe --- /dev/null +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/DefaultMassIndexingMonitorConfigurationContext.java @@ -0,0 +1,43 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.search.mapper.pojo.massindexing; + +import java.util.OptionalLong; + +import org.hibernate.search.util.common.annotation.Incubating; + +@Incubating +public interface DefaultMassIndexingMonitorConfigurationContext { + + /** + * Allows specifying whether the mass indexer should try obtaining the total number of all entities to index before the indexing even starts. + *

+ * This means that the default monitor will make an attempt to get the counts in the main thread and only then start the indexing. + * Then, at index time, the mass indexer may attempt to recalculate the total for a currently indexed type (see {@link #countEntitiesToIndexOnStart(boolean)}. + *

+ * Defaults to {@code false}. + * @param countAllEntitiesBeforeStart If {@code true}, the mass indexer will try determining the total number of all entities to index + * before the actual indexing starts. + * + * @return {@code this} for method chaining + */ + DefaultMassIndexingMonitorConfigurationContext countAllEntitiesBeforeStart(boolean countAllEntitiesBeforeStart); + + /** + * Allows specifying whether to try determining the total number of entities of the particular type to index + * and passing that information to the monitor, or skipping the counting and passing an {@link OptionalLong#empty() empty optional} instead. + * as a count. + *

+ * It may be helpful to skip the counting of entities and start the ID fetching right away to save some time. + *

+ * Defaults to {@code true}. + * @param countEntitiesToIndexOnStart If {@code true}, the mass indexer will try determining the total number of entities, + * otherwise the mass indexer will not try obtaining the total count. + * + * @return {@code this} for method chaining + */ + DefaultMassIndexingMonitorConfigurationContext countEntitiesToIndexOnStart(boolean countEntitiesToIndexOnStart); + +} diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/MassIndexingMonitor.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/MassIndexingMonitor.java index 313ad1ebebd..bb0fb0c3852 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/MassIndexingMonitor.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/MassIndexingMonitor.java @@ -21,11 +21,35 @@ */ public interface MassIndexingMonitor { + /** + * Creates a type-group-specific monitor. + *

+ * The mass indexer may group some of the types it has to index or index them separately. + * The type group represents this combination of types that are retrieved for indexing + * in the same pipeline. + * When a particular type group is about to get indexed the mass indexer will request to create a type group monitor. + * + * @param context Describes the type group for which the monitor is requested. + * @return A type group mass indexing monitor. By default, a no-op monitor is returned. + * @see MassIndexingTypeGroupMonitor + */ @Incubating default MassIndexingTypeGroupMonitor typeGroupMonitor(MassIndexingTypeGroupMonitorContext context) { return NoOpMassIndexingTypeGroupMonitor.INSTANCE; } + /** + * Whether this mass indexing monitor expects that {@link #addToTotalCount(long)} is called on it or not. + *

+ * Some monitor implementations may decide to optimize the indexing process by skipping the total count computations, + * which may improve the overall execution time. + * @return {@code true} if the mass indexer should attempt computing the total number of entities to index, {@code false} otherwise. + */ + @Incubating + default boolean requiresTotalCount() { + return true; + } + /** * Notify the monitor that {@code increment} more documents have been added to the index. *

diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoDefaultMassIndexer.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoDefaultMassIndexer.java index abbe60c35c8..37e1fdc33ba 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoDefaultMassIndexer.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoDefaultMassIndexer.java @@ -9,13 +9,16 @@ import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; +import java.util.function.Consumer; import org.hibernate.search.engine.tenancy.spi.TenancyMode; import org.hibernate.search.mapper.pojo.logging.impl.Log; +import org.hibernate.search.mapper.pojo.massindexing.DefaultMassIndexingMonitorConfigurationContext; import org.hibernate.search.mapper.pojo.massindexing.MassIndexingDefaultCleanOperation; import org.hibernate.search.mapper.pojo.massindexing.MassIndexingEnvironment; import org.hibernate.search.mapper.pojo.massindexing.MassIndexingFailureHandler; import org.hibernate.search.mapper.pojo.massindexing.MassIndexingMonitor; +import org.hibernate.search.mapper.pojo.massindexing.spi.DefaultMassIndexingMonitorConfigurationContextImpl; import org.hibernate.search.mapper.pojo.massindexing.spi.PojoMassIndexer; import org.hibernate.search.mapper.pojo.massindexing.spi.PojoMassIndexingContext; import org.hibernate.search.mapper.pojo.massindexing.spi.PojoMassIndexingMappingContext; @@ -61,7 +64,6 @@ public void afterExecution(Context context) { private Boolean purgeAtStart; private Boolean mergeSegmentsAfterPurge; private Boolean failFast; - private Boolean countEntitiesToIndexOnStart; private Long failureFloodingThreshold = null; private MassIndexingFailureHandler failureHandler; @@ -206,8 +208,7 @@ private PojoMassIndexingBatchCoordinator createCoordinator() { actualDropAndCreateSchemaOnStart, // false if not set explicitly and dropAndCreateSchemaOnStart is set to true, otherwise true by default: purgeAtStart == null ? !actualDropAndCreateSchemaOnStart : purgeAtStart, - mergeSegmentsAfterPurge, - !Boolean.FALSE.equals( countEntitiesToIndexOnStart ) + mergeSegmentsAfterPurge ); } @@ -236,8 +237,10 @@ public PojoMassIndexer failFast(boolean failFast) { } @Override - public PojoMassIndexer countEntitiesToIndexOnStart(boolean countEntitiesToIndexOnStart) { - this.countEntitiesToIndexOnStart = countEntitiesToIndexOnStart; + public PojoMassIndexer monitor(Consumer configurer) { + var context = DefaultMassIndexingMonitorConfigurationContextImpl.configure(); + configurer.accept( context ); + this.monitor = context.create(); return this; } diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingBatchCoordinator.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingBatchCoordinator.java index d34d5268c62..7e33c4bdea7 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingBatchCoordinator.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingBatchCoordinator.java @@ -50,7 +50,6 @@ public class PojoMassIndexingBatchCoordinator extends PojoMassIndexingFailureHan private final boolean dropAndCreateSchemaOnStart; private final boolean purgeAtStart; private final Boolean mergeSegmentsAfterPurge; - private final boolean countEntitiesToIndexOnStart; private final List> indexingFutures = new ArrayList<>(); @@ -65,8 +64,7 @@ public PojoMassIndexingBatchCoordinator(PojoMassIndexingMappingContext mappingCo PojoScopeDelegate pojoScopeDelegate, MassIndexingEnvironment environment, int typesToIndexInParallel, int documentBuilderThreads, Boolean mergeSegmentsOnFinish, - boolean dropAndCreateSchemaOnStart, Boolean purgeAtStart, Boolean mergeSegmentsAfterPurge, - boolean countEntitiesToIndexOnStart) { + boolean dropAndCreateSchemaOnStart, Boolean purgeAtStart, Boolean mergeSegmentsAfterPurge) { super( notifier, environment ); this.mappingContext = mappingContext; this.typeGroupsToIndex = typeGroupsToIndex; @@ -80,7 +78,6 @@ public PojoMassIndexingBatchCoordinator(PojoMassIndexingMappingContext mappingCo this.dropAndCreateSchemaOnStart = dropAndCreateSchemaOnStart; this.purgeAtStart = purgeAtStart; this.mergeSegmentsAfterPurge = mergeSegmentsAfterPurge; - this.countEntitiesToIndexOnStart = countEntitiesToIndexOnStart; this.agentStartContext = new PojoMassIndexerAgentStartContextImpl( mappingContext.threadPoolProvider(), @@ -196,8 +193,7 @@ private void doBatchWork() throws InterruptedException { mappingContext, getNotifier(), getMassIndexingEnvironment(), typeGroup, typeGroup.loadingStrategy(), massIndexingContext, documentBuilderThreads, - context.tenantIdentifier(), - countEntitiesToIndexOnStart + context.tenantIdentifier() ); } diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingBatchIndexingWorkspace.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingBatchIndexingWorkspace.java index c3f1fcf41d3..29d61958595 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingBatchIndexingWorkspace.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingBatchIndexingWorkspace.java @@ -49,7 +49,6 @@ public class PojoMassIndexingBatchIndexingWorkspace extends PojoMassIndexi private final int entityExtractingThreads; private final String tenantId; - private final boolean countEntitiesToIndexOnStart; private final MassIndexingTypeGroupMonitor typeGroupMonitor; PojoMassIndexingBatchIndexingWorkspace(PojoMassIndexingMappingContext mappingContext, @@ -58,8 +57,7 @@ public class PojoMassIndexingBatchIndexingWorkspace extends PojoMassIndexi PojoMassIndexingIndexedTypeGroup typeGroup, PojoMassLoadingStrategy loadingStrategy, PojoMassIndexingContext massIndexingContext, - int entityExtractingThreads, String tenantId, - boolean countEntitiesToIndexOnStart) { + int entityExtractingThreads, String tenantId) { super( notifier, environment ); this.mappingContext = mappingContext; this.typeGroup = typeGroup; @@ -67,8 +65,8 @@ public class PojoMassIndexingBatchIndexingWorkspace extends PojoMassIndexi this.massIndexingContext = massIndexingContext; this.entityExtractingThreads = entityExtractingThreads; this.tenantId = tenantId; - this.countEntitiesToIndexOnStart = countEntitiesToIndexOnStart; - this.typeGroupMonitor = notifier.typeGroupMonitor( new MassIndexingTypeGroupMonitorContextImpl( typeGroup ) ); + this.typeGroupMonitor = notifier + .typeGroupMonitor( new MassIndexingTypeGroupMonitorContextImpl<>( typeGroup, massIndexingContext, tenantId ) ); } @Override @@ -116,8 +114,7 @@ private void startProducingPrimaryKeys(PojoProducerConsumerQueue> identi typeGroupMonitor, massIndexingContext, getMassIndexingEnvironment(), typeGroup, loadingStrategy, - identifierQueue, tenantId, - countEntitiesToIndexOnStart + identifierQueue, tenantId ); //execIdentifiersLoader has size 1 and is not configurable: ensures the list is consistent as produced by one transaction final ThreadPoolExecutor identifierProducingExecutor = mappingContext.threadPoolProvider().newFixedThreadPool( @@ -156,20 +153,39 @@ massIndexingContext, getMassIndexingEnvironment(), } } - private static class MassIndexingTypeGroupMonitorContextImpl implements MassIndexingTypeGroupMonitorContext { + static class MassIndexingTypeGroupMonitorContextImpl implements MassIndexingTypeGroupMonitorContext { private final Set includedTypes; + private final PojoMassIndexingIndexedTypeGroup typeGroup; + private final PojoMassIndexingContext massIndexingContext; + private final String tenantId; - public MassIndexingTypeGroupMonitorContextImpl(PojoMassIndexingIndexedTypeGroup typeGroup) { - includedTypes = typeGroup.includedTypes().stream().map( PojoLoadingTypeContext::entityName ) + public MassIndexingTypeGroupMonitorContextImpl(PojoMassIndexingIndexedTypeGroup typeGroup, + PojoMassIndexingContext massIndexingContext, String tenantId) { + this.includedTypes = typeGroup.includedTypes().stream().map( PojoLoadingTypeContext::entityName ) .map( MassIndexingTypeImpl::new ) .collect( Collectors.toSet() ); + this.typeGroup = typeGroup; + this.massIndexingContext = massIndexingContext; + this.tenantId = tenantId; } @Override public Set includedTypes() { return includedTypes; } + + public PojoMassIndexingIndexedTypeGroup typeGroup() { + return typeGroup; + } + + public PojoMassIndexingContext massIndexingContext() { + return massIndexingContext; + } + + public String tenantId() { + return tenantId; + } } diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingEntityIdentifierLoadingRunnable.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingEntityIdentifierLoadingRunnable.java index 3385b299d38..e32da06c860 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingEntityIdentifierLoadingRunnable.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingEntityIdentifierLoadingRunnable.java @@ -32,15 +32,13 @@ public class PojoMassIndexingEntityIdentifierLoadingRunnable private final PojoProducerConsumerQueue> identifierQueue; private final String tenantId; private final MassIndexingEnvironment.EntityIdentifierLoadingContext identifierLoadingContext; - private final boolean countEntitiesToIndexOnStart; public PojoMassIndexingEntityIdentifierLoadingRunnable(PojoMassIndexingNotifier notifier, MassIndexingTypeGroupMonitor typeGroupMonitor, PojoMassIndexingContext massIndexingContext, MassIndexingEnvironment environment, PojoMassIndexingIndexedTypeGroup typeGroup, PojoMassLoadingStrategy loadingStrategy, - PojoProducerConsumerQueue> identifierQueue, String tenantId, - boolean countEntitiesToIndexOnStart) { + PojoProducerConsumerQueue> identifierQueue, String tenantId) { super( notifier, environment ); this.typeGroupMonitor = typeGroupMonitor; this.massIndexingContext = massIndexingContext; @@ -48,7 +46,6 @@ public PojoMassIndexingEntityIdentifierLoadingRunnable(PojoMassIndexingNotifier this.typeGroup = typeGroup; this.identifierQueue = identifierQueue; this.tenantId = tenantId; - this.countEntitiesToIndexOnStart = countEntitiesToIndexOnStart; this.identifierLoadingContext = new EntityIdentifierLoadingContextImpl(); } @@ -58,7 +55,7 @@ protected void runWithFailureHandler() throws InterruptedException { log.trace( "started" ); LoadingContext context = new LoadingContext(); try ( PojoMassIdentifierLoader loader = loadingStrategy.createIdentifierLoader( typeGroup.includedTypes(), context ) ) { - OptionalLong count = countEntitiesToIndexOnStart ? loader.totalCount() : OptionalLong.empty(); + OptionalLong count = getNotifier().requiresTotalCount() ? loader.totalCount() : OptionalLong.empty(); typeGroupMonitor.indexingStarted( count ); if ( count.isPresent() ) { getNotifier().reportAddedTotalCount( count.getAsLong() ); @@ -136,4 +133,5 @@ public String tenantIdentifier() { private static final class EntityIdentifierLoadingContextImpl implements MassIndexingEnvironment.EntityIdentifierLoadingContext { } + } diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingLoggingMonitor.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingLoggingMonitor.java index 0a2fe864288..886df54ade6 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingLoggingMonitor.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingLoggingMonitor.java @@ -6,16 +6,25 @@ import java.lang.invoke.MethodHandles; import java.time.Duration; +import java.util.List; import java.util.OptionalLong; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.LongAdder; import java.util.function.BinaryOperator; +import java.util.stream.Collectors; +import org.hibernate.search.mapper.pojo.loading.spi.PojoMassIdentifierLoader; +import org.hibernate.search.mapper.pojo.loading.spi.PojoMassIdentifierLoadingContext; +import org.hibernate.search.mapper.pojo.loading.spi.PojoMassIdentifierSink; +import org.hibernate.search.mapper.pojo.loading.spi.PojoMassLoadingContext; import org.hibernate.search.mapper.pojo.logging.impl.Log; import org.hibernate.search.mapper.pojo.massindexing.MassIndexingMonitor; +import org.hibernate.search.mapper.pojo.massindexing.MassIndexingType; import org.hibernate.search.mapper.pojo.massindexing.MassIndexingTypeGroupMonitor; import org.hibernate.search.mapper.pojo.massindexing.MassIndexingTypeGroupMonitorContext; +import org.hibernate.search.mapper.pojo.massindexing.impl.PojoMassIndexingBatchIndexingWorkspace.MassIndexingTypeGroupMonitorContextImpl; +import org.hibernate.search.util.common.AssertionFailure; import org.hibernate.search.util.common.logging.impl.LoggerFactory; /** @@ -32,6 +41,8 @@ public class PojoMassIndexingLoggingMonitor implements MassIndexingMonitor { private final LongAdder totalCounter = new LongAdder(); private volatile long startTime; private final int logAfterNumberOfDocuments; + private boolean countAllEntitiesBeforeStart; + private boolean countEntitiesToIndexOnStart; private final AtomicLong typesToIndex = new AtomicLong(); private final AtomicLong groupsWithUnknownTotal = new AtomicLong(); @@ -50,13 +61,35 @@ public PojoMassIndexingLoggingMonitor() { * @param logAfterNumberOfDocuments log each time the specified number of documents has been added */ public PojoMassIndexingLoggingMonitor(int logAfterNumberOfDocuments) { + this( logAfterNumberOfDocuments, false, true ); + } + + public PojoMassIndexingLoggingMonitor(boolean countAllEntitiesBeforeStart, boolean countEntitiesToIndexOnStart) { + this( 50, countAllEntitiesBeforeStart, countEntitiesToIndexOnStart ); + } + + public PojoMassIndexingLoggingMonitor(int logAfterNumberOfDocuments, boolean countAllEntitiesBeforeStart, + boolean countEntitiesToIndexOnStart) { this.logAfterNumberOfDocuments = logAfterNumberOfDocuments; + this.countAllEntitiesBeforeStart = countAllEntitiesBeforeStart; + this.countEntitiesToIndexOnStart = countEntitiesToIndexOnStart; } @Override - public MassIndexingTypeGroupMonitor typeGroupMonitor(MassIndexingTypeGroupMonitorContext context) { - typesToIndex.addAndGet( context.includedTypes().size() ); - return new MassIndexingTypeGroupMonitorImpl(); + public MassIndexingTypeGroupMonitor typeGroupMonitor(MassIndexingTypeGroupMonitorContext monitorContext) { + if ( monitorContext instanceof MassIndexingTypeGroupMonitorContextImpl context ) { + typesToIndex.addAndGet( context.includedTypes().size() ); + return new MassIndexingTypeGroupMonitorImpl( context ); + } + else { + throw new AssertionFailure( + "Unexpected type of the mass indexing type group monitor context: " + monitorContext.getClass() ); + } + } + + @Override + public boolean requiresTotalCount() { + return countEntitiesToIndexOnStart; } @Override @@ -96,13 +129,12 @@ public void documentsBuilt(long number) { @Override public void entitiesLoaded(long size) { - //not used + } @Override public void addToTotalCount(long count) { - totalCounter.add( count ); - log.indexingEntities( count ); + //not used } @Override @@ -185,8 +217,28 @@ public boolean isMoreUpToDateThan(StatusMessageInfo other) { private class MassIndexingTypeGroupMonitorImpl implements MassIndexingTypeGroupMonitor { + private final long numberOfTypes; + private final OptionalLong totalBefore; private boolean totalUnknown = false; + public MassIndexingTypeGroupMonitorImpl(MassIndexingTypeGroupMonitorContextImpl context) { + this.numberOfTypes = context.includedTypes().size(); + if ( countAllEntitiesBeforeStart ) { + try ( PojoMassIdentifierLoader loader = createLoader( context ) ) { + totalBefore = loader.totalCount(); + if ( totalBefore.isPresent() ) { + long count = totalBefore.getAsLong(); + totalCounter.add( count ); + log.indexingEntitiesApprox( count, context.includedTypes().stream().map( MassIndexingType::entityName ) + .collect( Collectors.joining( ", ", "[ ", " ]" ) ) ); + } + } + } + else { + totalBefore = OptionalLong.empty(); + } + } + @Override public void documentsAdded(long increment) { if ( totalUnknown ) { @@ -196,11 +248,16 @@ public void documentsAdded(long increment) { @Override public void indexingStarted(OptionalLong totalCount) { - typesToIndex.decrementAndGet(); + typesToIndex.addAndGet( -numberOfTypes ); if ( totalCount.isEmpty() ) { groupsWithUnknownTotal.incrementAndGet(); totalUnknown = true; } + else { + long actual = totalCount.getAsLong(); + totalCounter.add( actual - totalBefore.orElse( 0 ) ); + log.indexingEntities( actual ); + } } @Override @@ -209,5 +266,46 @@ public void indexingCompleted() { groupsWithUnknownTotal.decrementAndGet(); } } + + private PojoMassIdentifierLoader createLoader( + MassIndexingTypeGroupMonitorContextImpl context) { + return context.typeGroup().loadingStrategy().createIdentifierLoader( context.typeGroup().includedTypes(), + new IdentifierLoadingContext<>( context ) + ); + } + + private static class IdentifierLoadingContext implements PojoMassIdentifierLoadingContext { + private final MassIndexingTypeGroupMonitorContextImpl context; + + public IdentifierLoadingContext(MassIndexingTypeGroupMonitorContextImpl context) { + this.context = context; + } + + @Override + public PojoMassLoadingContext parent() { + return context.massIndexingContext(); + } + + @Override + public PojoMassIdentifierSink createSink() { + // this sink should never be called by Hibernate Search: + return new PojoMassIdentifierSink() { + @Override + public void accept(List batch) throws InterruptedException { + throw new AssertionFailure( "An unexpected call to a sink method." ); + } + + @Override + public void complete() { + throw new AssertionFailure( "An unexpected call to a sink method." ); + } + }; + } + + @Override + public String tenantIdentifier() { + return context.tenantId(); + } + } } } diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingNotifier.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingNotifier.java index fd51711284a..c548316ea4f 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingNotifier.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingNotifier.java @@ -21,7 +21,6 @@ import org.hibernate.search.mapper.pojo.massindexing.MassIndexingFailureHandler; import org.hibernate.search.mapper.pojo.massindexing.MassIndexingMonitor; import org.hibernate.search.mapper.pojo.massindexing.MassIndexingTypeGroupMonitor; -import org.hibernate.search.mapper.pojo.massindexing.MassIndexingTypeGroupMonitorContext; import org.hibernate.search.mapper.pojo.massindexing.spi.PojoMassIndexingSessionContext; import org.hibernate.search.util.common.logging.impl.LoggerFactory; @@ -54,10 +53,15 @@ void reportAddedTotalCount(long totalCount) { monitor.addToTotalCount( totalCount ); } - public MassIndexingTypeGroupMonitor typeGroupMonitor(MassIndexingTypeGroupMonitorContext context) { + MassIndexingTypeGroupMonitor typeGroupMonitor( + PojoMassIndexingBatchIndexingWorkspace.MassIndexingTypeGroupMonitorContextImpl context) { return monitor.typeGroupMonitor( context ); } + boolean requiresTotalCount() { + return monitor.requiresTotalCount(); + } + void reportError(Error error) { // Don't report the error anywhere: an Error is serious enough that we want to report it directly by bubbling up. // We're just recording that the first failure was an error so that later interruptions diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/spi/DefaultMassIndexingMonitorConfigurationContextImpl.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/spi/DefaultMassIndexingMonitorConfigurationContextImpl.java new file mode 100644 index 00000000000..6cb232ee237 --- /dev/null +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/spi/DefaultMassIndexingMonitorConfigurationContextImpl.java @@ -0,0 +1,42 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.search.mapper.pojo.massindexing.spi; + +import org.hibernate.search.mapper.pojo.massindexing.DefaultMassIndexingMonitorConfigurationContext; +import org.hibernate.search.mapper.pojo.massindexing.MassIndexingMonitor; +import org.hibernate.search.mapper.pojo.massindexing.impl.PojoMassIndexingLoggingMonitor; +import org.hibernate.search.util.common.annotation.Incubating; + +@Incubating +public final class DefaultMassIndexingMonitorConfigurationContextImpl + implements DefaultMassIndexingMonitorConfigurationContext { + + private boolean countAllEntitiesBeforeStart = false; + private boolean countEntitiesToIndexOnStart = true; + + private DefaultMassIndexingMonitorConfigurationContextImpl() { + } + + @Override + public DefaultMassIndexingMonitorConfigurationContextImpl countAllEntitiesBeforeStart(boolean countAllEntitiesBeforeStart) { + this.countAllEntitiesBeforeStart = countAllEntitiesBeforeStart; + return this; + } + + @Override + public DefaultMassIndexingMonitorConfigurationContextImpl countEntitiesToIndexOnStart(boolean countEntitiesToIndexOnStart) { + this.countEntitiesToIndexOnStart = countEntitiesToIndexOnStart; + return this; + } + + public MassIndexingMonitor create() { + return new PojoMassIndexingLoggingMonitor( countAllEntitiesBeforeStart, countEntitiesToIndexOnStart ); + } + + public static DefaultMassIndexingMonitorConfigurationContextImpl configure() { + return new DefaultMassIndexingMonitorConfigurationContextImpl(); + } + +} diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/spi/PojoMassIndexer.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/spi/PojoMassIndexer.java index cf3fb847e48..c27f5852b4e 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/spi/PojoMassIndexer.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/spi/PojoMassIndexer.java @@ -6,8 +6,9 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; +import java.util.function.Consumer; -import org.hibernate.search.mapper.pojo.loading.spi.PojoMassIdentifierLoader; +import org.hibernate.search.mapper.pojo.massindexing.DefaultMassIndexingMonitorConfigurationContext; import org.hibernate.search.mapper.pojo.massindexing.MassIndexingEnvironment; import org.hibernate.search.mapper.pojo.massindexing.MassIndexingFailureHandler; import org.hibernate.search.mapper.pojo.massindexing.MassIndexingMonitor; @@ -176,16 +177,13 @@ public interface PojoMassIndexer { PojoMassIndexer failFast(boolean failFast); /** - * Allows specifying whether to skip the counting of entities to index before starting retrieving the entity IDs. + * Configures the default {@link MassIndexingMonitor}. *

- * It may be helpful to skip the counting of entities and start the ID fetching right away to save some time. - *

- * Defaults to {@code true}. - * @param countEntitiesToIndexOnStart If {@code true}, the mass indexer will try calling {@link PojoMassIdentifierLoader#totalCount()} - * and passing the returned value to the monitors, otherwise the total count call will not be made and an empty optional will be passed to the monitors. + * The default monitor just logs the progress. This configurer allows to influence the logging behavior. * + * @param configurer The monitor that will track mass indexing progress. * @return {@code this} for method chaining */ @Incubating - PojoMassIndexer countEntitiesToIndexOnStart(boolean countEntitiesToIndexOnStart); + PojoMassIndexer monitor(Consumer configurer); } diff --git a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/massindexing/MassIndexer.java b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/massindexing/MassIndexer.java index a361f96d4cc..3f79cafdda5 100644 --- a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/massindexing/MassIndexer.java +++ b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/massindexing/MassIndexer.java @@ -4,15 +4,14 @@ */ package org.hibernate.search.mapper.pojo.standalone.massindexing; -import java.util.OptionalLong; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; +import java.util.function.Consumer; -import org.hibernate.search.mapper.pojo.loading.spi.PojoMassIdentifierLoader; +import org.hibernate.search.mapper.pojo.massindexing.DefaultMassIndexingMonitorConfigurationContext; import org.hibernate.search.mapper.pojo.massindexing.MassIndexingEnvironment; import org.hibernate.search.mapper.pojo.massindexing.MassIndexingFailureHandler; import org.hibernate.search.mapper.pojo.massindexing.MassIndexingMonitor; -import org.hibernate.search.mapper.pojo.massindexing.spi.PojoMassIndexer; import org.hibernate.search.mapper.pojo.standalone.loading.MassLoadingOptions; import org.hibernate.search.util.common.annotation.Incubating; @@ -200,18 +199,12 @@ public interface MassIndexer { MassIndexer failFast(boolean failFast); /** - * Allows specifying whether to try determining the total number of entities of the particular type to index - * and passing that information to the monitor, or skipping the counting and passing an {@link OptionalLong#empty() empty optional} instead. - * as a count. + * Configures the default {@link MassIndexingMonitor}. *

- * It may be helpful to skip the counting of entities and start the ID fetching right away to save some time. - *

- * Defaults to {@code true}. - * @param countEntitiesToIndexOnStart If {@code true}, the mass indexer will try determining the total number of entities, - * otherwise the mass indexer will not try obtaining the total count. + * The default monitor just logs the progress. This configurer allows to influence the logging behavior. * + * @param configurer The monitor that will track mass indexing progress. * @return {@code this} for method chaining */ - @Incubating - MassIndexer countEntitiesToIndexOnStart(boolean countEntitiesToIndexOnStart); + MassIndexer monitor(Consumer configurer); } diff --git a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/massindexing/impl/StandalonePojoMassIndexer.java b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/massindexing/impl/StandalonePojoMassIndexer.java index 6c27d119e6d..bb2a6cdd0d8 100644 --- a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/massindexing/impl/StandalonePojoMassIndexer.java +++ b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/massindexing/impl/StandalonePojoMassIndexer.java @@ -5,7 +5,9 @@ package org.hibernate.search.mapper.pojo.standalone.massindexing.impl; import java.util.concurrent.CompletionStage; +import java.util.function.Consumer; +import org.hibernate.search.mapper.pojo.massindexing.DefaultMassIndexingMonitorConfigurationContext; import org.hibernate.search.mapper.pojo.massindexing.MassIndexingEnvironment; import org.hibernate.search.mapper.pojo.massindexing.MassIndexingFailureHandler; import org.hibernate.search.mapper.pojo.massindexing.MassIndexingMonitor; @@ -112,8 +114,8 @@ public MassIndexer failFast(boolean failFast) { } @Override - public MassIndexer countEntitiesToIndexOnStart(boolean countEntitiesToIndexOnStart) { - delegate.countEntitiesToIndexOnStart( countEntitiesToIndexOnStart ); + public MassIndexer monitor(Consumer configurer) { + delegate.monitor( configurer ); return this; } }