Skip to content

Commit

Permalink
fixes gh-115 (#116)
Browse files Browse the repository at this point in the history
Root cause:
spring data scans base package of configuration for entities to be added to mapping context at template bean creation phase.
Since template is needed for index creation, entity index creator fails to create annotation based indexes on circular dependency to template.

Resolution summary:
accumulate indexes which comes before context is being inited and create all in batch after context is up and all beans are created. Futher creations will be based on persistence entity applicaton event
  • Loading branch information
tdanylchuk authored Jan 5, 2021
1 parent cba988d commit a5e16b9
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.aerospike.client.AerospikeClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.aerospike.convert.MappingAerospikeConverter;
import org.springframework.data.aerospike.core.AerospikeExceptionTranslator;
import org.springframework.data.aerospike.core.AerospikeTemplate;
Expand Down Expand Up @@ -38,7 +39,7 @@ public QueryEngine queryEngine(AerospikeClient aerospikeClient,

@Bean
public AerospikePersistenceEntityIndexCreator aerospikePersistenceEntityIndexCreator(AerospikeMappingContext aerospikeMappingContext,
AerospikeTemplate template) {
@Lazy AerospikeTemplate template) {
return new AerospikePersistenceEntityIndexCreator(aerospikeMappingContext, template);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.aerospike.client.reactor.AerospikeReactorClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.aerospike.convert.MappingAerospikeConverter;
import org.springframework.data.aerospike.core.AerospikeExceptionTranslator;
import org.springframework.data.aerospike.core.ReactiveAerospikeTemplate;
Expand Down Expand Up @@ -70,7 +71,7 @@ protected ClientPolicy getClientPolicy() {
@Bean
public ReactiveAerospikePersistenceEntityIndexCreator aerospikePersistenceEntityIndexCreator(
AerospikeMappingContext aerospikeMappingContext,
ReactiveAerospikeTemplate template) {
@Lazy ReactiveAerospikeTemplate template) {
return new ReactiveAerospikePersistenceEntityIndexCreator(aerospikeMappingContext, template);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,26 @@
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationListener;
import org.springframework.context.SmartLifecycle;
import org.springframework.data.aerospike.mapping.AerospikeMappingContext;
import org.springframework.data.aerospike.mapping.BasicAerospikePersistentEntity;
import org.springframework.data.mapping.context.MappingContextEvent;

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;

/**
* @author Taras Danylchuk
*/
@Slf4j
@RequiredArgsConstructor
public abstract class BaseAerospikePersistenceEntityIndexCreator implements ApplicationListener<MappingContextEvent<?, ?>> {
public abstract class BaseAerospikePersistenceEntityIndexCreator implements ApplicationListener<MappingContextEvent<?, ?>> , SmartLifecycle {

private final AerospikeIndexResolver aerospikeIndexDetector = new AerospikeIndexResolver();
private final AerospikeMappingContext aerospikeMappingContext;
private final Set<AerospikeIndexDefinition> initialIndexes = new HashSet<>();
private final AtomicBoolean initialized = new AtomicBoolean(false);

@Override
public void onApplicationEvent(MappingContextEvent<?, ?> event) {
Expand All @@ -49,11 +54,31 @@ public void onApplicationEvent(MappingContextEvent<?, ?> event) {
BasicAerospikePersistentEntity<?> persistentEntity = (BasicAerospikePersistentEntity<?>) event.getPersistentEntity();
Set<AerospikeIndexDefinition> indexes = aerospikeIndexDetector.detectIndexes(persistentEntity);
if (!indexes.isEmpty()) {
if (!initialized.get()) {
//gh-115: prevent creating indexes on startup phase when aerospike template have not been created yet
initialIndexes.addAll(indexes);
return;
}
log.debug("Creating {} indexes for entity[{}]...", indexes, event.getPersistentEntity().getName());
installIndexes(indexes);
}
}

@Override
public void start() {
initialized.set(true);
installIndexes(initialIndexes);
initialIndexes.clear();
}

protected abstract void installIndexes(Set<AerospikeIndexDefinition> indexes);

@Override
public void stop() {
}

@Override
public boolean isRunning() {
return initialized.get();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.springframework.data.aerospike.config;

import com.aerospike.client.query.IndexType;
import lombok.Value;
import org.springframework.data.aerospike.annotation.Indexed;
import org.springframework.data.aerospike.mapping.Document;
import org.springframework.data.annotation.Id;

@Value
@Document(collection = "config-package-document-set")
public class ConfigPackageDocument {

@Id
String id;

@Indexed(type = IndexType.STRING, name = "config-package-document-index")
String indexedField;
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import org.springframework.data.aerospike.IndexNotFoundException;
import org.springframework.data.aerospike.mapping.Document;
import org.springframework.data.aerospike.query.model.Index;
import org.springframework.data.aerospike.sample.AutoIndexedDocument;

import java.util.concurrent.atomic.AtomicInteger;

Expand Down Expand Up @@ -139,9 +138,7 @@ public void deleteIndex_deletesExistingIndex() {

@Test
void indexedAnnotation_createsIndexes() {
String setName = template.getSetName(AutoIndexedDocument.class);

AutoIndexedDocumentAssert.assertIndexesCreated(additionalAerospikeTestOperations, namespace, setName);
AutoIndexedDocumentAssert.assertIndexesCreated(additionalAerospikeTestOperations, namespace);
}

@Value
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,13 @@
@UtilityClass
public class AutoIndexedDocumentAssert {

public void assertIndexesCreated(AdditionalAerospikeTestOperations operations, String namespace, String setName) {
public void assertIndexesCreated(AdditionalAerospikeTestOperations operations, String namespace) {
assertAutoIndexedDocumentIndexesCreated(operations, namespace);
assertConfigPackageDocumentIndexesCreated(operations, namespace);
}

public void assertAutoIndexedDocumentIndexesCreated(AdditionalAerospikeTestOperations operations, String namespace) {
String setName = "auto-indexed-set";
List<Index> indexes = operations.getIndexes(setName);

assertThat(indexes).containsExactlyInAnyOrder(
Expand All @@ -30,6 +36,15 @@ public void assertIndexesCreated(AdditionalAerospikeTestOperations operations, S
);
}

public void assertConfigPackageDocumentIndexesCreated(AdditionalAerospikeTestOperations operations, String namespace) {
String setName = "config-package-document-set";
List<Index> indexes = operations.getIndexes(setName);

assertThat(indexes).containsExactlyInAnyOrder(
index(namespace, setName, "config-package-document-index", "indexedField", IndexType.STRING, IndexCollectionType.DEFAULT)
);
}

private static Index index(String namespace, String setName, String name, String bin, IndexType indexType, IndexCollectionType collectionType) {
return Index.builder()
.namespace(namespace)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,7 @@ public void deleteIndex_deletesExistingIndex() {

@Test
void indexedAnnotation_createsIndexes() {
String setName = reactiveTemplate.getSetName(AutoIndexedDocument.class);

AutoIndexedDocumentAssert.assertIndexesCreated(additionalAerospikeTestOperations, namespace, setName);
AutoIndexedDocumentAssert.assertIndexesCreated(additionalAerospikeTestOperations, namespace);
}

private boolean indexExists(String indexName, String binName) {
Expand Down

0 comments on commit a5e16b9

Please sign in to comment.