Skip to content

Commit

Permalink
HSEARCH-4153 Merge the purge operation into the delete operation in P…
Browse files Browse the repository at this point in the history
…ojoIndexingPlan/PojoIndexer

Because a purge is just a delete with a null entity, and because we're
going to support passing a null entity for all operations in the next
few commits.

Signed-off-by: Yoann Rodière <yoann@hibernate.org>
  • Loading branch information
yrodiere authored and fax4ever committed Feb 10, 2021
1 parent 5a54ea8 commit 34e2280
Show file tree
Hide file tree
Showing 21 changed files with 48 additions and 111 deletions.
Expand Up @@ -177,26 +177,6 @@ public void purgeByEntityClass_invalidClass() {
} );
}

@Test
public void purgeByEntityClass_invalidClass_contained() {
SessionFactory sessionFactory = setup( AutomaticIndexingStrategyName.NONE );

Class<?> invalidClass = ContainedEntity.class;

withinTransaction( sessionFactory, session -> {
SearchIndexingPlan indexingPlan = Search.session( session ).indexingPlan();
assertThatThrownBy(
() -> indexingPlan.purge( invalidClass, 42, null )
)
.isInstanceOf( SearchException.class )
.hasMessageContainingAll(
"Unable to purge entity of type '" + ContainedEntity.class.getName()
+ "' with identifier '42': "
+ " this type is contained in an indexed type but is not itself indexed."
);
} );
}

@Test
public void purgeByEntityName() {
SessionFactory sessionFactory = setup( AutomaticIndexingStrategyName.NONE );
Expand Down
Expand Up @@ -64,7 +64,7 @@ public void success() {
session.indexingPlan().add( entity1 );
session.indexingPlan().addOrUpdate( entity2 );
session.indexingPlan().delete( entity3 );
session.indexingPlan().purge( IndexedEntity.class, 4, null );
session.indexingPlan().delete( IndexedEntity.class, 4, null );

backendMock.expectWorks( IndexedEntity.INDEX )
.add( b -> b
Expand Down
Expand Up @@ -27,31 +27,31 @@ protected void expectOperation(BackendMock.DocumentWorkCallListContext context,

@Override
protected void addTo(SearchIndexingPlan indexingPlan, int id) {
indexingPlan.purge( IndexedEntity.class, id, null );
indexingPlan.delete( IndexedEntity.class, id, null );
}

@Override
protected void addTo(SearchIndexingPlan indexingPlan, Object providedId, int id) {
indexingPlan.purge( IndexedEntity.class, providedId, null );
indexingPlan.delete( IndexedEntity.class, providedId, null );
}

@Override
protected void addTo(SearchIndexingPlan indexingPlan, Object providedId, String providedRoutingKey, int id) {
indexingPlan.purge( IndexedEntity.class, providedId, providedRoutingKey );
indexingPlan.delete( IndexedEntity.class, providedId, providedRoutingKey );
}

@Override
protected CompletionStage<?> execute(SearchIndexer indexer, int id) {
return indexer.purge( IndexedEntity.class, id, null );
return indexer.delete( IndexedEntity.class, id, null );
}

@Override
protected CompletionStage<?> execute(SearchIndexer indexer, Object providedId, int id) {
return indexer.purge( IndexedEntity.class, providedId, null );
return indexer.delete( IndexedEntity.class, providedId, null );
}

@Override
protected CompletionStage<?> execute(SearchIndexer indexer, Object providedId, String providedRoutingKey, int id) {
return indexer.purge( IndexedEntity.class, providedId, providedRoutingKey );
return indexer.delete( IndexedEntity.class, providedId, providedRoutingKey );
}
}
Expand Up @@ -204,7 +204,7 @@ private CompletionStage<?> executeWork(SearchIndexer indexer, Work w) {
case INDEX:
return indexer.addOrUpdate( w.providedId, w.entity );
case DELETE:
return indexer.purge( w.entityType, w.providedId, null );
return indexer.delete( w.entityType, w.providedId, null );
default:
throw new AssertionFailure( "Unexpected work type: " + w.workType );
}
Expand Down
Expand Up @@ -176,6 +176,6 @@ default CompletionStage<?> delete(Object providedId, Object entity) {
* Leave {@code null} if sharding is disabled or if you don't use a custom {@link org.hibernate.search.mapper.pojo.bridge.RoutingBridge}.
* @return A {@link CompletionStage} reflecting the completion state of the operation.
*/
CompletionStage<?> purge(Class<?> entityClass, Object providedId, String providedRoutingKey);
CompletionStage<?> delete(Class<?> entityClass, Object providedId, String providedRoutingKey);

}
Expand Up @@ -139,6 +139,6 @@ public interface SearchIndexingPlan {
* @throws org.hibernate.search.util.common.SearchException If the entity type is not indexed directly
* ({@link org.hibernate.search.mapper.pojo.mapping.definition.annotation.Indexed}).
*/
void purge(Class<?> entityClass, Object providedId, String providedRoutingKey);
void delete(Class<?> entityClass, Object providedId, String providedRoutingKey);

}
Expand Up @@ -50,8 +50,8 @@ public CompletionStage<?> delete(Object providedId, String providedRoutingKey, O
}

@Override
public CompletionStage<?> purge(Class<?> entityClass, Object providedId, String providedRoutingKey) {
return delegate.purge( getTypeIdentifier( entityClass ), providedId, providedRoutingKey,
public CompletionStage<?> delete(Class<?> entityClass, Object providedId, String providedRoutingKey) {
return delegate.delete( getTypeIdentifier( entityClass ), providedId, providedRoutingKey,
commitStrategy, refreshStrategy );
}

Expand Down
Expand Up @@ -73,8 +73,8 @@ public void delete(Object providedId, String providedRoutingKey, Object entity)
}

@Override
public void purge(Class<?> entityClass, Object providedId, String providedRoutingKey) {
delegate.purge( getTypeIdentifier( entityClass ), providedId, providedRoutingKey );
public void delete(Class<?> entityClass, Object providedId, String providedRoutingKey) {
delegate.delete( getTypeIdentifier( entityClass ), providedId, providedRoutingKey, null );
}

public CompletableFuture<?> execute() {
Expand Down
Expand Up @@ -37,13 +37,13 @@ public void delete(Object entity) {
@Override
public void purge(Class<?> entityClass, Object providedId, String providedRoutingKey) {
delegate( true )
.purge( getTypeIdentifier( entityClass ), providedId, providedRoutingKey );
.delete( getTypeIdentifier( entityClass ), providedId, providedRoutingKey, null );
}

@Override
public void purge(String entityName, Object providedId, String providedRoutingKey) {
delegate( true )
.purge( getTypeIdentifier( entityName ), providedId, providedRoutingKey );
.delete( getTypeIdentifier( entityName ), providedId, providedRoutingKey, null );
}

@Override
Expand Down
Expand Up @@ -21,8 +21,6 @@ public interface IdentifierMappingImplementor<I, E> extends IdentifierMapping, A
default void close() {
}

I getIdentifier(Object providedId);

I getIdentifier(Object providedId, Supplier<? extends E> entitySupplier);

String toDocumentIdentifier(I identifier, BridgeMappingContext context);
Expand Down
Expand Up @@ -6,19 +6,24 @@
*/
package org.hibernate.search.mapper.pojo.bridge.runtime.impl;

import java.lang.invoke.MethodHandles;
import java.util.function.Supplier;

import org.hibernate.search.engine.environment.bean.BeanHolder;
import org.hibernate.search.mapper.pojo.bridge.IdentifierBridge;
import org.hibernate.search.mapper.pojo.bridge.runtime.spi.BridgeMappingContext;
import org.hibernate.search.mapper.pojo.bridge.runtime.spi.BridgeSessionContext;
import org.hibernate.search.mapper.pojo.logging.impl.Log;
import org.hibernate.search.mapper.pojo.model.spi.PojoCaster;
import org.hibernate.search.util.common.logging.impl.LoggerFactory;
import org.hibernate.search.util.common.reflect.spi.ValueReadHandle;
import org.hibernate.search.util.common.impl.Closer;


public class PropertyIdentifierMapping<I, E> implements IdentifierMappingImplementor<I, E> {

private static final Log log = LoggerFactory.make( Log.class, MethodHandles.lookup() );

private final PojoCaster<? super I> caster;
private final ValueReadHandle<I> property;
private final BeanHolder<? extends IdentifierBridge<I>> bridgeHolder;
Expand Down Expand Up @@ -48,16 +53,14 @@ public void close() {

@Override
@SuppressWarnings( "unchecked" ) // We can only cast to the raw type, if I is generic we need an unchecked cast
public I getIdentifier(Object providedId) {
return (I) caster.cast( providedId );
}

@Override
public I getIdentifier(Object providedId, Supplier<? extends E> entitySupplier) {
public I getIdentifier(Object providedId, Supplier<? extends E> entitySupplierOrNull) {
if ( providedId != null ) {
return getIdentifier( providedId );
return (I) caster.cast( providedId );
}
if ( entitySupplierOrNull == null ) {
throw log.nullProvidedIdentifierAndEntity();
}
return property.get( entitySupplier.get() );
return property.get( entitySupplierOrNull.get() );
}

@Override
Expand Down
Expand Up @@ -49,18 +49,13 @@ public void close() {
}

@Override
public Object getIdentifier(Object providedId) {
public Object getIdentifier(Object providedId, Supplier<?> entityProvider) {
if ( providedId == null ) {
throw log.nullProvidedIdentifier();
}
return providedId;
}

@Override
public Object getIdentifier(Object providedId, Supplier<?> entityProvider) {
return getIdentifier( providedId );
}

@Override
public String toDocumentIdentifier(Object identifier, BridgeMappingContext context) {
return bridgeHolder.get().toDocumentIdentifier( identifier, context.identifierBridgeToDocumentIdentifierContext() );
Expand Down
Expand Up @@ -381,12 +381,6 @@ SearchException invalidFieldEncodingForScaledNumberFieldMapping(IndexFieldTypeOp
SearchException cannotResolveContainerExtractorName(String extractorName,
@FormatWith(ClassFormatter.class) Class<?> builtinExtractorConstantsClass);

@Message(id = ID_OFFSET + 55,
value = "Unable to purge entity of type '%1$s' with identifier '%2$s': "
+ " this type is contained in an indexed type but is not itself indexed."
)
SearchException cannotPurgeNonIndexedContainedType(PojoRawTypeIdentifier<?> type, Object providedId);

@Message(id = ID_OFFSET + 58,
value = "Incorrect binder implementation: binder '%1$s' did not call context.bridge(...).")
SearchException missingBridgeForBinder(Object binder);
Expand Down Expand Up @@ -552,4 +546,8 @@ void arbitraryMemberSelection(@FormatWith(PojoTypeModelFormatter.class) PojoRawT
value = "Unexpected entity name for entity loading: '%1$s'. Expected one of %2$s.")
SearchException unexpectedEntityNameForEntityLoading(String entityName, Collection<String> expectedNames);

@Message(id = ID_OFFSET + 87, value = "Invalid indexing request:"
+ " if the entity is null, the identifier must be provided explicitly." )
SearchException nullProvidedIdentifierAndEntity();

}
Expand Up @@ -51,13 +51,11 @@ void addOrUpdate(Object providedId, String providedRoutingKey, Object entity, Bi
}

void delete(Object providedId, String providedRoutingKey, Object entity) {
Supplier<E> entitySupplier = typeContext().toEntitySupplier( sessionContext, entity );
Supplier<E> entitySupplier = entity == null ? null : typeContext().toEntitySupplier( sessionContext, entity );
I identifier = toIdentifier( providedId, entitySupplier );
getState( identifier ).delete( entitySupplier, providedRoutingKey );
}

abstract void purge(Object providedId, String providedRoutingKey);

void resolveDirty(PojoReindexingCollector containingEntityCollector) {
for ( S state : statesPerId.values() ) {
state.resolveDirty( containingEntityCollector );
Expand Down
Expand Up @@ -6,21 +6,16 @@
*/
package org.hibernate.search.mapper.pojo.work.impl;

import java.lang.invoke.MethodHandles;
import java.util.function.Supplier;

import org.hibernate.search.mapper.pojo.logging.impl.Log;
import org.hibernate.search.mapper.pojo.work.spi.PojoWorkSessionContext;
import org.hibernate.search.util.common.logging.impl.LoggerFactory;

/**
* @param <E> The contained entity type.
*/
public class PojoContainedTypeIndexingPlan<E>
extends AbstractPojoTypeIndexingPlan<Object, E, PojoContainedTypeIndexingPlan<E>.ContainedEntityState> {

private static final Log log = LoggerFactory.make( Log.class, MethodHandles.lookup() );

private final PojoWorkContainedTypeContext<E> typeContext;

public PojoContainedTypeIndexingPlan(PojoWorkContainedTypeContext<E> typeContext,
Expand All @@ -29,11 +24,6 @@ public PojoContainedTypeIndexingPlan(PojoWorkContainedTypeContext<E> typeContext
this.typeContext = typeContext;
}

@Override
void purge(Object providedId, String providedRoutingKey) {
throw log.cannotPurgeNonIndexedContainedType( typeContext.typeIdentifier(), providedId );
}

@Override
PojoWorkContainedTypeContext<E> typeContext() {
return typeContext;
Expand Down
Expand Up @@ -37,12 +37,6 @@ public PojoIndexedTypeIndexingPlan(PojoWorkIndexedTypeContext<I, E> typeContext,
this.delegate = delegate;
}

@Override
void purge(Object providedId, String providedRoutingKey) {
I identifier = typeContext.identifierMapping().getIdentifier( providedId );
getState( identifier ).purge( providedRoutingKey );
}

void updateBecauseOfContained(Object entity) {
Supplier<E> entitySupplier = typeContext.toEntitySupplier( sessionContext, entity );
I identifier = typeContext.identifierMapping().getIdentifier( null, entitySupplier );
Expand Down Expand Up @@ -150,12 +144,6 @@ void delete(Supplier<E> entitySupplier, String providedRoutingKey) {
updatedBecauseOfContained = false;
}

void purge(String providedRoutingKey) {
// This is a purge: assume the document exists in order to force deletion.
this.initialStatus = EntityStatus.PRESENT;
delete( null, providedRoutingKey );
}

void sendCommandsToDelegate() {
switch ( currentStatus ) {
case UNKNOWN:
Expand Down
Expand Up @@ -55,10 +55,10 @@ public CompletableFuture<?> delete(PojoRawTypeIdentifier<?> typeIdentifier, Obje
}

@Override
public CompletableFuture<?> purge(PojoRawTypeIdentifier<?> typeIdentifier, Object providedId,
public CompletableFuture<?> delete(PojoRawTypeIdentifier<?> typeIdentifier, Object providedId,
String providedRoutingKey,
DocumentCommitStrategy commitStrategy, DocumentRefreshStrategy refreshStrategy) {
return getDelegate( typeIdentifier ).purge( providedId, providedRoutingKey, commitStrategy, refreshStrategy );
return getDelegate( typeIdentifier ).delete( providedId, providedRoutingKey, commitStrategy, refreshStrategy );
}

private PojoTypeIndexer<?, ?> getDelegate(PojoRawTypeIdentifier<?> typeIdentifier) {
Expand Down
Expand Up @@ -81,12 +81,6 @@ public void delete(PojoRawTypeIdentifier<?> typeIdentifier, Object providedId, S
delegate.delete( providedId, providedRoutingKey, entity );
}

@Override
public void purge(PojoRawTypeIdentifier<?> typeIdentifier, Object providedId, String providedRoutingKey) {
AbstractPojoTypeIndexingPlan<?, ?, ?> delegate = getDelegate( typeIdentifier );
delegate.purge( providedId, providedRoutingKey );
}

@Override
public void process() {
if ( isProcessing ) {
Expand Down
Expand Up @@ -110,9 +110,9 @@ CompletableFuture<?> delete(Object providedId, String providedRoutingKey, Object
(deletePreviousResult, deleteResult) -> deleteResult );
}

CompletableFuture<?> purge(Object providedId, String providedRoutingKey,
CompletableFuture<?> delete(Object providedId, String providedRoutingKey,
DocumentCommitStrategy commitStrategy, DocumentRefreshStrategy refreshStrategy) {
I identifier = typeContext.identifierMapping().getIdentifier( providedId );
I identifier = typeContext.identifierMapping().getIdentifier( providedId, null );
String documentIdentifier = typeContext.toDocumentIdentifier( sessionContext, identifier );
DocumentReferenceProvider referenceProvider = new PojoDocumentReferenceProvider( documentIdentifier,
providedRoutingKey, identifier );
Expand Down
Expand Up @@ -101,7 +101,7 @@ CompletableFuture<?> delete(PojoRawTypeIdentifier<?> typeIdentifier, Object prov
* @param refreshStrategy How to handle the refresh.
* @return A {@link CompletableFuture} reflecting the completion state of the operation.
*/
CompletableFuture<?> purge(PojoRawTypeIdentifier<?> typeIdentifier, Object providedId, String providedRoutingKey,
CompletableFuture<?> delete(PojoRawTypeIdentifier<?> typeIdentifier, Object providedId, String providedRoutingKey,
DocumentCommitStrategy commitStrategy, DocumentRefreshStrategy refreshStrategy);

}

0 comments on commit 34e2280

Please sign in to comment.