Skip to content

Commit

Permalink
parse hosts using Java client's method, documentation update
Browse files Browse the repository at this point in the history
  • Loading branch information
agrgr committed Jan 3, 2024
1 parent a3e0a0d commit 0a71d01
Show file tree
Hide file tree
Showing 9 changed files with 192 additions and 28 deletions.
2 changes: 1 addition & 1 deletion 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>4.6.0</version>
<version>4.7.7-local</version>
<name>Spring Data Aerospike</name>
<organization>
<name>Aerospike Inc.</name>
Expand Down
125 changes: 123 additions & 2 deletions src/main/asciidoc/reference/configuration.adoc
Original file line number Diff line number Diff line change
@@ -1,21 +1,107 @@
[[configuration]]
= Configuration

Configuration can be accessed via standard `application.properties`.
Configuration parameters can be set in the standard `application.properties` file using `spring-data-aerospike` prefix.

Here is an example:

[source,properties]
----
# application.properties
spring-data-aerospike.hosts=localhost:3000
spring-data-aerospike.namespace=TEST
spring-data-aerospike.namespace=test
spring-data-aerospike.scans-enabled=false
spring-data-aerospike.send-key=true
spring-data-aerospike.create-indexes-on-startup=true
spring-data-aerospike.index-cache-refresh-seconds=3600
spring-data-aerospike.server-version-refresh-seconds=3600
spring-data-aerospike.query-max-records=10000
spring-data-aerospike.batch-write-size=100
spring-data-aerospike.keep-original-key-types=false
----

Configuration class:

[source, java]
----
@Configuration
@EnableAerospikeRepositories(basePackageClasses = { PersonRepository.class})
public class AerospikeConfiguration extends AbstractAerospikeDataConfiguration {
}
----

In this case extending `AbstractAerospikeDataConfiguration` class is required to enable repositories.

`hosts` and `namespace` parameters can also be set by overriding `getHosts()` and `nameSpace()` methods of the `AbstractAerospikeDataConfiguration` class.

Here is an example:

[source,java]
----
@EnableAerospikeRepositories(basePackageClasses = PersonRepository.class)
class ApplicationConfig extends AbstractAerospikeDataConfiguration {
@Override
protected Collection<Host> getHosts() {
return Collections.singleton(new Host("localhost", 3000));
}
@Override
protected String nameSpace() {
return "test";
}
}
----

NOTE: `hosts` and `namespace` parameters set via application.properties have precedence over `getHosts()` and `nameSpace()` methods of the `AbstractAerospikeDataConfiguration` class.

[[configuration.parameters]]
== Configuration Parameters

[[configuration.hosts]]
=== hosts

[source,properties]
----
spring-data-aerospike.hosts=hostname1:3001, hostname2:tlsName2:3002
----

A String of hosts separated by `,` in form of `hostname1[:tlsName1][:port1],...`

IP addresses must be given in one of the following formats:

[source,text]
----
IPv4: xxx.xxx.xxx.xxx
IPv6: [xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx]
IPv6: [xxxx::xxxx]
----

IPv6 addresses must be enclosed by brackets. tlsName is optional.

*Default:* `null`.

[[configuration.namespace]]
=== namespace

[source,properties]
----
spring-data-aerospike.namespace=test
----

Aerospike DB namespace.

*Default:* `null`.

[[configuration.scans-enabled]]
=== scansEnabled

[source,properties]
----
spring-data-aerospike.scans-enabled=false
----

A scan can be an expensive operation as all records in the set must be read by the Aerospike server, and then the condition is applied to see if they match.

Due to the cost of performing this operation, scans from Spring Data Aerospike are disabled by default.
Expand All @@ -27,48 +113,83 @@ NOTE: Once this flag is enabled, scans run whenever needed with no warnings. Thi
[[configuration.send-key]]
=== sendKey

[source,properties]
----
spring-data-aerospike.send-key=true
----

Send user defined key in addition to hash digest on both reads and writes. If the key is sent on write, it will be stored with the record on the server.

Default: `false` (do not send the user defined key).

[[configuration.create-indexes-on-startup]]
=== createIndexesOnStartup

[source,properties]
----
spring-data-aerospike.create-indexes-on-startup=true
----

Create secondary indexes specified using `@Indexed` annotation on startup.

*Default*: `true`.

[[configuration.index-cache-refresh-frequency-seconds]]
=== indexCacheRefreshSeconds

[source,properties]
----
spring-data-aerospike.index-cache-refresh-seconds=3600
----

Automatically refresh indexes cache every <N> seconds.

*Default*: `3600`.

[[configuration.server-version-refresh-frequency-seconds]]
=== serverVersionRefreshSeconds

[source,properties]
----
spring-data-aerospike.server-version-refresh-seconds=3600
----

Automatically refresh cached server version every <N> seconds.

*Default*: `3600`.

[[configuration.query-max-records]]
=== queryMaxRecords

[source,properties]
----
spring-data-aerospike.query-max-records=10000
----

Limit amount of results returned by server. Non-positive value means no limit.

*Default*: `10 000`.

[[configuration.batch-write-size]]
=== batchWriteSize

[source,properties]
----
spring-data-aerospike.batch-write-size=100
----

Maximum batch size for batch write operations. Non-positive value means no limit.

*Default*: `100`.

[[configuration.keep-original-key-types]]
=== keepOriginalKeyTypes

[source,properties]
----
spring-data-aerospike.keep-original-key-types=false
----

Define how `@Id` fields (primary keys) and `Map` keys are stored in the Aerospike database: `false` - always as `String`, `true` - preserve original type if supported.

[width="100%",cols="<20%,<30%,<30%",options="header",]
Expand Down
41 changes: 39 additions & 2 deletions src/main/asciidoc/reference/installation-and-usage.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,51 @@ implementation group: 'com.aerospike', name: 'spring-data-aerospike', version: '

== Connecting to Aerospike DB

Configuring Spring Data Aerospike is easy, necessary configuration should be specified in `application.properties`.
There are two ways of configuring basic connection to Aerospike DB.

* Overriding `getHosts()` and `nameSpace()` methods of the `AbstractAerospikeDataConfiguration` class:

[source, java]
----
@Configuration
@EnableAerospikeRepositories(basePackageClasses = { PersonRepository.class})
public class AerospikeConfiguration extends AbstractAerospikeDataConfiguration {
@Override
protected Collection<Host> getHosts() {
return Collections.singleton(new Host("localhost", 3000));
}
@Override
protected String nameSpace() {
return "test";
}
}
----

* Using `application.properties`:

Basic configuration in this case requires enabling repositories and then setting `hosts` and `namespace` in the `application.properties` file.

[source, java]
----
@Configuration
@EnableAerospikeRepositories(basePackageClasses = { PersonRepository.class})
public class AerospikeConfiguration extends AbstractAerospikeDataConfiguration {
}
----

In `application.properties`:

[source, properties]
----
spring-data-aerospike.hosts=localhost:3000
spring-data-aerospike.namespace=TEST
spring-data-aerospike.namespace=test
----

NOTE: `hosts` and `namespace` parameters set via application.properties have precedence over `getHosts()` and `nameSpace()` methods of the `AbstractAerospikeDataConfiguration` class.

For more detailed settings see xref:#configuration[Configuration].

== Creating Functionality

The base functionality is provided by `AerospikeRepository` interface.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ public AerospikeTemplate aerospikeTemplate(IAerospikeClient aerospikeClient,
AerospikeExceptionTranslator aerospikeExceptionTranslator,
QueryEngine queryEngine, IndexRefresher indexRefresher,
ServerVersionSupport serverVersionSupport, AerospikeSettings settings) {
return new AerospikeTemplate(aerospikeClient, getNamespace(settings.getNamespace(), nameSpace()),
// namespace parameter from application.properties has precedence over nameSpace() return value
settings.setNamespace(getNamespace(settings.getNamespace(), nameSpace()));
return new AerospikeTemplate(aerospikeClient, settings.getNamespace(),
mappingAerospikeConverter, aerospikeMappingContext, aerospikeExceptionTranslator, queryEngine,
indexRefresher, serverVersionSupport);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,11 @@ public ReactiveAerospikeTemplate reactiveAerospikeTemplate(MappingAerospikeConve
ReactorIndexRefresher reactorIndexRefresher,
ServerVersionSupport serverVersionSupport,
AerospikeSettings settings) {
return new ReactiveAerospikeTemplate(aerospikeReactorClient, getNamespace(settings.getNamespace(),
nameSpace()), mappingAerospikeConverter, aerospikeMappingContext, aerospikeExceptionTranslator,
reactorQueryEngine, reactorIndexRefresher,
serverVersionSupport);
// namespace parameter from application.properties has precedence over nameSpace() return value
settings.setNamespace(getNamespace(settings.getNamespace(), nameSpace()));
return new ReactiveAerospikeTemplate(aerospikeReactorClient, settings.getNamespace(),
mappingAerospikeConverter, aerospikeMappingContext, aerospikeExceptionTranslator,
reactorQueryEngine, reactorIndexRefresher, serverVersionSupport);
}

@Bean(name = "reactiveAerospikeQueryEngine")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,6 @@
import java.util.List;
import java.util.Set;

import static org.springframework.data.aerospike.utility.Utils.parseHosts;

/**
* @author Taras Danylchuk
*/
Expand Down Expand Up @@ -110,9 +108,17 @@ public AerospikeExceptionTranslator aerospikeExceptionTranslator() {

@Bean(name = "aerospikeClient", destroyMethod = "close")
public AerospikeClient aerospikeClient(AerospikeSettings settings) {
Collection<Host> hosts;
if ((hosts = parseHosts(settings.getHosts())) == null) hosts = getHosts();
return new AerospikeClient(getClientPolicy(), hosts.toArray(new Host[0]));
// hosts parameter from application.properties has precedence over getHosts() return value
if (StringUtils.hasText(settings.getHosts())) {
settings.setHostsArray(Host.parseHosts(settings.getHosts(), getDefaultPort()));
} else {
settings.setHostsArray(getHosts().toArray(new Host[0]));
}
return new AerospikeClient(getClientPolicy(), settings.getHostsArray());
}

protected int getDefaultPort() {
return 3000;
}

@Bean(name = "filterExpressionsBuilder")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
package org.springframework.data.aerospike.config;

import com.aerospike.client.Host;
import lombok.Getter;
import lombok.Setter;

@Setter
@Getter
public class AerospikeSettings {

// Hosts separated by ',' in form of <address>:<port>
// String of hosts separated by ',' in form of hostname1[:tlsName1][:port1],...
// An IP address must be given in one of the following formats:
// IPv4: xxx.xxx.xxx.xxx
// IPv6: [xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx]
// IPv6: [xxxx::xxxx]
// IPv6 addresses must be enclosed by brackets. tlsName is optional.
String hosts;
// Namespace
String namespace;
Expand All @@ -28,4 +34,6 @@ public class AerospikeSettings {
// Define how @Id fields (primary keys) and Map keys are stored: false - always as String,
// true - preserve original type if supported
boolean keepOriginalKeyTypes = false;
// Storing hosts
Host[] hostsArray;
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
package org.springframework.data.aerospike.utility;

import com.aerospike.client.AerospikeException;
import com.aerospike.client.Host;
import com.aerospike.client.IAerospikeClient;
import com.aerospike.client.Info;
import com.aerospike.client.ResultCode;
Expand All @@ -26,11 +25,9 @@
import org.springframework.util.StringUtils;

import java.util.Arrays;
import java.util.Collection;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;

/**
* Utility class containing useful methods for interacting with Aerospike across the entire implementation
Expand Down Expand Up @@ -108,14 +105,6 @@ public static boolean allArrayElementsAreNull(Object[] array) {
return Arrays.stream(array).allMatch(Objects::isNull);
}

public static Collection<Host> parseHosts(String hostsString) {
if (StringUtils.hasText(hostsString)) return Arrays.stream(hostsString.split(","))
.map(host -> host.split(":"))
.map(hostArr -> new Host(hostArr[0], Integer.parseInt(hostArr[1])))
.collect(Collectors.toList());
return null;
}

public static String getNamespace(String prioritizedNamespace, String fallbackNamespace) {
String namespace;
if ((namespace = prioritizedNamespace) == null) namespace = fallbackNamespace;
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ spring-data-aerospike.scans-enabled=false
spring-data-aerospike.send-key=true
spring-data-aerospike.create-indexes-on-startup=true
spring-data-aerospike.index-cache-refresh-seconds=3600
spring-data-aerospike.server-version-refresh-seconds=1800
spring-data-aerospike.server-version-refresh-seconds=3600
spring-data-aerospike.query-max-records=10000
spring-data-aerospike.batch-write-size=100
spring-data-aerospike.keep-original-key-types=false

0 comments on commit 0a71d01

Please sign in to comment.