Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into release/2.5.0
Browse files Browse the repository at this point in the history
# Conflicts:
#	pom.xml
  • Loading branch information
roimenashe committed May 19, 2021
2 parents acda293 + 528be06 commit fa6ed97
Show file tree
Hide file tree
Showing 22 changed files with 667 additions and 95 deletions.
18 changes: 10 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,16 @@ The Spring Data Aerospike project aims to provide a familiar and consistent Spri
3. [Basic error handling in spring-data-aerospike](https://medium.com/aerospike-developer-blog/basic-error-handling-in-spring-data-aerospike-5edd580d77d9?source=friends_link&sk=cff71ea1539b36e5a89b2c3411b58a06)
4. [How to create secondary index in Spring Data Aerospike](https://medium.com/aerospike-developer-blog/how-to-create-secondary-index-in-spring-data-aerospike-e19d7e343d7c?source=friends_link&sk=413619a568f9aac51ed2f2611ee70aba)

## Spring Boot compatibility
## Spring Data Aerospike compatibility

|`spring-data-aerospike` Version | Spring Boot Version
| :----------- | :----: |
|2.4.2.RELEASE | 2.3.x
|2.3.5.RELEASE | 2.2.x
|2.1.1.RELEASE | 2.1.x, 2.0.x
|1.2.1.RELEASE | 1.5.x
|`spring-data-aerospike` Version | Spring Boot Version | Aerospike Client | Aerospike Reactor Client
| :----------- | :----: | :----------- | :-----------
|3.0.0 | 2.5.X | 5.1.x | 5.0.x
|2.5.0 | 2.5.X | 4.4.x | 4.4.x
|2.4.2.RELEASE | 2.3.x | 4.4.x | 4.4.x
|2.3.5.RELEASE | 2.2.x | 4.4.x | 4.4.x
|2.1.1.RELEASE | 2.1.x, 2.0.x | 4.4.x | 3.2.x
|1.2.1.RELEASE | 1.5.x | 4.1.x |

## Quick Start

Expand All @@ -41,7 +43,7 @@ Add the Maven dependency:
<dependency>
<groupId>com.aerospike</groupId>
<artifactId>spring-data-aerospike</artifactId>
<version>2.4.2.RELEASE</version>
<version>3.0.0</version>
</dependency>
```

Expand Down
20 changes: 10 additions & 10 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>com.aerospike</groupId>
<artifactId>spring-data-aerospike</artifactId>
<version>2.4.2.RELEASE</version>
<version>2.5.0</version>
<name>Spring Data Aerospike</name>
<organization>
<name>Aerospike Inc.</name>
Expand All @@ -16,25 +16,25 @@
<parent>
<groupId>org.springframework.data.build</groupId>
<artifactId>spring-data-parent</artifactId>
<version>2.4.6</version>
<version>2.5.1</version>
</parent>

<properties>
<source.level>1.8</source.level>
<aerospike>4.4.18</aerospike>
<aerospike-reactor>4.4.10</aerospike-reactor>

<springdata.commons>2.4.6</springdata.commons>
<springdata.keyvalue>2.4.6</springdata.keyvalue>
<springdata.commons>2.5.1</springdata.commons>
<springdata.keyvalue>2.5.1</springdata.keyvalue>
<dist.key>DATAAERO</dist.key>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

<spring-boot-starter-test.version>2.4.4</spring-boot-starter-test.version>
<spring-boot-starter-test.version>2.4.5</spring-boot-starter-test.version>
<spring-cloud-starter-bootstrap.version>3.0.2</spring-cloud-starter-bootstrap.version>
<embedded-aerospike.version>2.0.3</embedded-aerospike.version>
<awaitility.version>4.0.3</awaitility.version>
<blockhound.version>1.0.4.RELEASE</blockhound.version>
<lombok.version>1.18.18</lombok.version>
<embedded-aerospike.version>2.0.8</embedded-aerospike.version>
<awaitility.version>4.1.0</awaitility.version>
<blockhound.version>1.0.6.RELEASE</blockhound.version>
<lombok.version>1.18.20</lombok.version>
</properties>

<licenses>
Expand Down Expand Up @@ -311,7 +311,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.6</version>
<version>3.0.1</version>
<executions>
<execution>
<id>sign-artifacts</id>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import org.springframework.beans.factory.FactoryBean;

import com.aerospike.client.policy.Policy;
import com.aerospike.client.policy.Priority;

/**
* A {@link FactoryBean} implementation that exposes the setters necessary to configure a read policy via XML.
Expand Down Expand Up @@ -73,15 +72,6 @@ public void setSleepBetweenRetries(int sleepBetweenRetries){
this.policy.sleepBetweenRetries = sleepBetweenRetries;
}

/**
* Configures the priority of request relative to other transactions.
* Currently, only used for scans.
* @param priority The priority configuration value.
*/
public void setPriority(Priority priority){
this.policy.priority = priority;
}

/*
* (non-Javadoc)
* @see org.springframework.beans.factory.FactoryBean#getObject()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,6 @@ public void setConcurrentNodes(boolean concurrentNodes){
this.policy.concurrentNodes = concurrentNodes;
}

/**
* Configures termination of scan if cluster in fluctuating state.
* @param failOnClusterChange The failOnClusterChange configuration value.
*/
public void setFailOnClusterChange(boolean failOnClusterChange){
this.policy.failOnClusterChange = failOnClusterChange;
}

/**
* Indicates if bin data is retrieved. If false, only record digests are retrieved.
* @param includeBinData The includeBinData configuration value.
Expand All @@ -72,15 +64,6 @@ public void setIncludeBinData(boolean includeBinData){
public void setMaxConcurrentNodes(int maxConcurrentNodes){
this.policy.maxConcurrentNodes = maxConcurrentNodes;
}

/**
* Configure the percent of data to scan. Valid integer range is 1 to 100.
* Default is 100.
* @param scanPercent The scanPercent configuration value.
*/
public void setScanPercent(int scanPercent){
this.policy.scanPercent = scanPercent;
}

/*
* (non-Javadoc)
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import com.aerospike.client.query.IndexCollectionType;
import com.aerospike.client.query.IndexType;
import org.springframework.data.aerospike.IndexAlreadyExistsException;
import org.springframework.data.aerospike.core.model.GroupedEntities;
import org.springframework.data.aerospike.core.model.GroupedKeys;
import org.springframework.data.aerospike.repository.query.Query;
import org.springframework.data.domain.Sort;
import org.springframework.data.mapping.context.MappingContext;
Expand Down Expand Up @@ -109,6 +111,8 @@ public interface AerospikeOperations {

<T> List<T> findByIds(Iterable<?> ids, Class<T> entityClass);

GroupedEntities findByIds(GroupedKeys groupedKeys);

<T> T add(T objectToAddTo, Map<String, Long> values);

<T> T add(T objectToAddTo, String binName, long value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,31 @@
*/
package org.springframework.data.aerospike.core;

import com.aerospike.client.AerospikeException;
import com.aerospike.client.Bin;
import com.aerospike.client.IAerospikeClient;
import com.aerospike.client.Info;
import com.aerospike.client.Key;
import com.aerospike.client.Operation;
import com.aerospike.client.Record;
import com.aerospike.client.*;
import com.aerospike.client.ResultCode;
import com.aerospike.client.Value;
import com.aerospike.client.cluster.Node;
import com.aerospike.client.policy.RecordExistsAction;
import com.aerospike.client.policy.WritePolicy;
import com.aerospike.client.query.*;
import com.aerospike.client.query.Filter;
import com.aerospike.client.query.IndexCollectionType;
import com.aerospike.client.query.IndexType;
import com.aerospike.client.query.KeyRecord;
import com.aerospike.client.query.ResultSet;
import com.aerospike.client.query.Statement;
import com.aerospike.client.task.IndexTask;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.InvalidDataAccessResourceUsageException;
import org.springframework.data.aerospike.convert.AerospikeWriteData;
import org.springframework.data.aerospike.convert.MappingAerospikeConverter;
import org.springframework.data.aerospike.core.model.GroupedEntities;
import org.springframework.data.aerospike.core.model.GroupedKeys;
import org.springframework.data.aerospike.mapping.AerospikeMappingContext;
import org.springframework.data.aerospike.mapping.AerospikePersistentEntity;
import org.springframework.data.aerospike.query.KeyRecordIterator;
Expand All @@ -39,7 +53,14 @@
import org.springframework.data.util.StreamUtils;
import org.springframework.util.Assert;

import java.util.*;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Random;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
Expand Down Expand Up @@ -334,6 +355,35 @@ private <T> List<T> findByIdsInternal(Collection<?> ids, Class<T> entityClass) {
}
}


/**
* Executes a single batch request to get results for several entities.
*
* Aerospike provides functionality to get records from different sets in 1 batch
* request. The methods allows to put grouped keys by entity type as parameter and
* get result as spring data aerospike entities grouped by entity type.
*
* @param groupedKeys will never be {@literal null}.
* @return GroupedEntities grouped entities
*/
@Override
public GroupedEntities findByIds(GroupedKeys groupedKeys) {
Assert.notNull(groupedKeys, "Grouped keys must not be null!");

if (groupedKeys.getEntitiesKeys().isEmpty()) {
return GroupedEntities.builder().build();
}

return findEntitiesByIdsInternal(groupedKeys);
}

private GroupedEntities findEntitiesByIdsInternal(GroupedKeys groupedKeys) {
EntitiesKeys entitiesKeys = EntitiesKeys.of(toEntitiesKeyMap(groupedKeys));
Record[] records = client.get(null, entitiesKeys.getKeys());

return toGroupedEntities(entitiesKeys, records);
}

@SuppressWarnings("unchecked")
@Override
public <T> Iterable<T> aggregate(Filter filter, Class<T> entityClass,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,29 @@
import org.springframework.data.aerospike.convert.AerospikeTypeAliasAccessor;
import org.springframework.data.aerospike.convert.AerospikeWriteData;
import org.springframework.data.aerospike.convert.MappingAerospikeConverter;
import org.springframework.data.aerospike.core.model.GroupedEntities;
import org.springframework.data.aerospike.core.model.GroupedKeys;
import org.springframework.data.aerospike.mapping.AerospikeMappingContext;
import org.springframework.data.aerospike.mapping.AerospikePersistentEntity;
import org.springframework.data.aerospike.mapping.AerospikePersistentProperty;
import org.springframework.data.aerospike.mapping.BasicAerospikePersistentEntity;
import org.springframework.data.aerospike.repository.query.Query;
import org.springframework.data.convert.CustomConversions;
import org.springframework.data.domain.Sort;
import org.springframework.data.keyvalue.core.IterableConverter;
import org.springframework.data.mapping.PersistentPropertyAccessor;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mapping.model.ConvertingPropertyAccessor;
import org.springframework.util.Assert;

import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
* Base class for creation Aerospike templates
Expand Down Expand Up @@ -232,6 +241,35 @@ Key getKey(Object id, AerospikePersistentEntity<?> entity) {
return new Key(this.namespace, entity.getSetName(), userKey);
}

GroupedEntities toGroupedEntities(EntitiesKeys entitiesKeys, Record[] records) {
GroupedEntities.GroupedEntitiesBuilder builder = GroupedEntities.builder();

IntStream.range(0, entitiesKeys.getKeys().length)
.filter(index -> records[index] != null)
.mapToObj(index -> mapToEntity(entitiesKeys.getKeys()[index], entitiesKeys.getEntityClasses()[index], records[index]))
.filter(Objects::nonNull)
.forEach(entity -> builder.entity(getEntityClass(entity), entity));

return builder.build();
}

Map<Class<?>, List<Key>> toEntitiesKeyMap(GroupedKeys groupedKeys) {
return groupedKeys.getEntitiesKeys().entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, entry -> toKeysList(entry.getKey(), entry.getValue())));
}

private <T> List<Key> toKeysList(Class<T> entityClass, Collection<?> ids) {
Assert.notNull(entityClass, "Entity class must not be null!");
Assert.notNull(ids, "List of ids must not be null!");

AerospikePersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(entityClass);
List<?> idsList = IterableConverter.toList(ids);

return idsList.stream()
.map(id -> getKey(id, entity))
.collect(Collectors.toList());
}

@SuppressWarnings("unchecked")
private <S> S convertIfNecessary(Object source, Class<S> type) {
return type.isAssignableFrom(source.getClass()) ? (S) source : converter.getConversionService().convert(source, type);
Expand Down
Loading

0 comments on commit fa6ed97

Please sign in to comment.