org.hibernate.search.engine.common.impl.SearchIntegrationPartialBuildStateImpl Maven / Gradle / Ivy
/*
* SPDX-License-Identifier: Apache-2.0
* Copyright Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.search.engine.common.impl;
import static org.hibernate.search.engine.common.impl.SearchIntegrationImpl.INDEX_MANAGERS_KEY;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import org.hibernate.search.engine.backend.index.spi.IndexManagerImplementor;
import org.hibernate.search.engine.backend.spi.BackendImplementor;
import org.hibernate.search.engine.cfg.ConfigurationPropertySource;
import org.hibernate.search.engine.cfg.spi.ConfigurationPropertyChecker;
import org.hibernate.search.engine.common.resources.impl.EngineThreads;
import org.hibernate.search.engine.common.resources.spi.SavedState;
import org.hibernate.search.engine.common.spi.SearchIntegration;
import org.hibernate.search.engine.common.spi.SearchIntegrationEnvironment;
import org.hibernate.search.engine.common.spi.SearchIntegrationFinalizer;
import org.hibernate.search.engine.common.spi.SearchIntegrationPartialBuildState;
import org.hibernate.search.engine.common.timing.spi.TimingSource;
import org.hibernate.search.engine.environment.bean.BeanHolder;
import org.hibernate.search.engine.environment.bean.BeanResolver;
import org.hibernate.search.engine.environment.bean.spi.BeanProvider;
import org.hibernate.search.engine.environment.thread.impl.ThreadPoolProviderImpl;
import org.hibernate.search.engine.mapper.mapping.building.spi.MappingAbortedException;
import org.hibernate.search.engine.mapper.mapping.building.spi.MappingFinalizationContext;
import org.hibernate.search.engine.mapper.mapping.building.spi.MappingFinalizer;
import org.hibernate.search.engine.mapper.mapping.building.spi.MappingKey;
import org.hibernate.search.engine.mapper.mapping.building.spi.MappingPartialBuildState;
import org.hibernate.search.engine.mapper.mapping.spi.MappingImplementor;
import org.hibernate.search.engine.reporting.FailureHandler;
import org.hibernate.search.engine.reporting.impl.EngineEventContextMessages;
import org.hibernate.search.engine.reporting.spi.ContextualFailureCollector;
import org.hibernate.search.engine.reporting.spi.RootFailureCollector;
import org.hibernate.search.util.common.AssertionFailure;
import org.hibernate.search.util.common.impl.Closer;
import org.hibernate.search.util.common.impl.Futures;
class SearchIntegrationPartialBuildStateImpl implements SearchIntegrationPartialBuildState {
private final BeanProvider beanProvider;
private final BeanResolver beanResolver;
private final BeanHolder extends FailureHandler> failureHandlerHolder;
private final ThreadPoolProviderImpl threadPoolProvider;
private final Map, MappingPartialBuildState> partiallyBuiltMappings;
private final Map nonStartedBackends;
private final Map nonStartedIndexManagers;
private final ConfigurationPropertyChecker partialConfigurationPropertyChecker;
private final Map, MappingNonStartedState> fullyBuiltNonStartedMappings = new LinkedHashMap<>();
private final Map startedBackends = new LinkedHashMap<>();
private final Map startedIndexManagers = new LinkedHashMap<>();
private final Map, MappingImplementor>> fullyBuiltStartedMappings = new LinkedHashMap<>();
private final EngineThreads engineThreads;
private final TimingSource timingSource;
private final Optional previousIntegration;
SearchIntegrationPartialBuildStateImpl(
BeanProvider beanProvider, BeanResolver beanResolver,
BeanHolder extends FailureHandler> failureHandlerHolder,
ThreadPoolProviderImpl threadPoolProvider,
Map, MappingPartialBuildState> partiallyBuiltMappings,
Map nonStartedBackends,
Map nonStartedIndexManagers,
ConfigurationPropertyChecker partialConfigurationPropertyChecker,
EngineThreads engineThreads, TimingSource timingSource,
Optional previousIntegration) {
this.beanProvider = beanProvider;
this.beanResolver = beanResolver;
this.failureHandlerHolder = failureHandlerHolder;
this.threadPoolProvider = threadPoolProvider;
this.partiallyBuiltMappings = partiallyBuiltMappings;
this.nonStartedBackends = nonStartedBackends;
this.nonStartedIndexManagers = nonStartedIndexManagers;
this.partialConfigurationPropertyChecker = partialConfigurationPropertyChecker;
this.engineThreads = engineThreads;
this.timingSource = timingSource;
this.previousIntegration = previousIntegration;
}
@Override
public void closeOnFailure() {
try ( Closer closer = new Closer<>() ) {
closer.pushAll( MappingPartialBuildState::closeOnFailure, partiallyBuiltMappings.values() );
closer.pushAll( MappingNonStartedState::closeOnFailure, fullyBuiltNonStartedMappings.values() );
closer.pushAll( MappingImplementor::stop, fullyBuiltStartedMappings.values() );
closer.pushAll( IndexManagerNonStartedState::closeOnFailure, nonStartedIndexManagers.values() );
closer.pushAll( IndexManagerImplementor::stop, startedIndexManagers.values() );
closer.pushAll( BackendNonStartedState::closeOnFailure, nonStartedBackends.values() );
closer.pushAll( BackendImplementor::stop, startedBackends.values() );
closer.pushAll( ThreadPoolProviderImpl::close, threadPoolProvider );
closer.pushAll( BeanHolder::close, failureHandlerHolder );
closer.pushAll( BeanProvider::close, beanProvider );
closer.pushAll( EngineThreads::onStop, engineThreads );
closer.pushAll( TimingSource::stop, timingSource );
if ( previousIntegration.isPresent() ) {
closer.pushAll( SearchIntegration::close, previousIntegration.get() );
}
}
}
@Override
public BeanResolver beanResolver() {
return beanResolver;
}
@Override
public SearchIntegrationFinalizer finalizer(ConfigurationPropertySource propertySource,
ConfigurationPropertyChecker configurationPropertyChecker) {
return new SearchIntegrationFinalizerImpl(
SearchIntegrationEnvironment.rootPropertySource( propertySource, beanResolver ),
configurationPropertyChecker
);
}
private class SearchIntegrationFinalizerImpl implements SearchIntegrationFinalizer {
private final RootFailureCollector failureCollector =
new RootFailureCollector( EngineEventContextMessages.INSTANCE.bootstrap() );
private final ConfigurationPropertySource propertySource;
private final ConfigurationPropertyChecker propertyChecker;
private SearchIntegrationFinalizerImpl(ConfigurationPropertySource propertySource,
ConfigurationPropertyChecker propertyChecker) {
this.propertySource = propertySource;
this.propertyChecker = propertyChecker;
}
@Override
public M finalizeMapping(MappingKey mappingKey,
MappingFinalizer finalizer) {
// We know this cast will work because of how
@SuppressWarnings("unchecked")
PBM partiallyBuiltMapping = (PBM) partiallyBuiltMappings.get( mappingKey );
if ( partiallyBuiltMapping == null ) {
throw new AssertionFailure(
"Some partially built mapping could not be found during bootstrap. Key: " + mappingKey
);
}
ContextualFailureCollector mappingFailureCollector = failureCollector.withContext( mappingKey );
MappingFinalizationContext mappingFinalizationContext =
new MappingFinalizationContextImpl( mappingFailureCollector, propertySource, beanResolver );
MappingImplementor mapping = null;
try {
mapping = finalizer.finalizeMapping( mappingFinalizationContext, partiallyBuiltMapping );
}
catch (RuntimeException e) {
mappingFailureCollector.add( e );
}
catch (MappingAbortedException e) {
e.collectSilentlyAndCheck( mappingFailureCollector );
}
failureCollector.checkNoFailure();
fullyBuiltNonStartedMappings.put( mappingKey, new MappingNonStartedState( mappingKey, mapping ) );
partiallyBuiltMappings.remove( mappingKey );
return mapping.toConcreteType();
}
@Override
public SearchIntegration finalizeIntegration() {
failureCollector.checkNoFailure();
if ( !partiallyBuiltMappings.isEmpty() ) {
throw new AssertionFailure(
"Some mappings were not fully built. Partially built mappings: " + partiallyBuiltMappings
);
}
// Start backends
for ( Map.Entry entry : nonStartedBackends.entrySet() ) {
startedBackends.put(
entry.getKey(),
entry.getValue().start( failureCollector, beanResolver, propertySource, threadPoolProvider )
);
}
failureCollector.checkNoFailure();
// Pre-Start indexes
try ( SavedState previousIntegrationSavedState =
previousIntegration.map( SearchIntegrationImpl::saveForRestart ).orElse( SavedState.empty() ) ) {
for ( Map.Entry entry : nonStartedIndexManagers.entrySet() ) {
SavedState savedState = previousIntegrationSavedState.get( INDEX_MANAGERS_KEY )
.orElse( Collections.emptyMap() ).getOrDefault( entry.getKey(), SavedState.empty() );
entry.getValue().preStart( failureCollector, beanResolver, propertySource, savedState );
}
}
failureCollector.checkNoFailure();
if ( previousIntegration.isPresent() ) {
previousIntegration.get().close();
}
// Start indexes
for ( Map.Entry entry : nonStartedIndexManagers.entrySet() ) {
startedIndexManagers.put(
entry.getKey(),
entry.getValue().start()
);
}
failureCollector.checkNoFailure();
// Start mappings
SearchIntegrationHandle integrationHandle = new SearchIntegrationHandle();
CompletableFuture>[] mappingFutures = new CompletableFuture>[fullyBuiltNonStartedMappings.size()];
int mappingIndex = 0;
// Start
for ( MappingNonStartedState state : fullyBuiltNonStartedMappings.values() ) {
mappingFutures[mappingIndex] = state.start( failureCollector, beanResolver, propertySource,
threadPoolProvider, integrationHandle );
++mappingIndex;
}
// Wait for the starting operation to finish
Futures.unwrappedExceptionJoin( CompletableFuture.allOf( mappingFutures ) );
failureCollector.checkNoFailure();
// Everything went well: register the mappings
for ( Map.Entry, MappingNonStartedState> entry : fullyBuiltNonStartedMappings.entrySet() ) {
fullyBuiltStartedMappings.put( entry.getKey(), entry.getValue().getMapping() );
}
propertyChecker.afterBoot( partialConfigurationPropertyChecker );
SearchIntegrationImpl integration = new SearchIntegrationImpl(
beanProvider,
failureHandlerHolder,
threadPoolProvider,
fullyBuiltStartedMappings,
startedBackends,
startedIndexManagers,
engineThreads, timingSource
);
integrationHandle.initialize( integration );
return integration;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy