Added support of the PersistTo, ReplicateTo and DurabilityLevel via @Document annotation. (#1649)

Closes #1486
This commit is contained in:
Tigran Babloyan
2023-01-25 01:05:52 +04:00
committed by mikereiche
parent 09257b791a
commit 021e11a4ab
20 changed files with 477 additions and 98 deletions

View File

@@ -77,6 +77,9 @@ The `@Id` annotation needs to be present because every document in Couchbase nee
This key needs to be any string with a length of maximum 250 characters.
Feel free to use whatever fits your use case, be it a UUID, an email address or anything else.
Writes to Couchbase-Server buckets can optionally be assigned durability requirements; which instruct Couchbase Server to update the specified document on multiple nodes in memory and/or disk locations across the cluster; before considering the write to be committed.
Default durability requirements can also be configured through the `@Document` annotation.
For example: `@Document(durabilityLevel = DurabilityLevel.MAJORITY)` will force mutations to be replicated to a majority of the Data Service nodes.
[[datatypes]]
== Datatypes and Converters

View File

@@ -30,7 +30,7 @@ User found = couchbaseTemplate.findById(User.class).one(user.getId());
----
====
If you wanted to use a custom durability requirement for the `upsert` operation you can chain it in:
If you wanted to use a custom (by default durability options from the `@Document` annotation will be used) durability requirement for the `upsert` operation you can chain it in:
.Upsert with durability
====

View File

@@ -39,7 +39,8 @@ public class ExecutableInsertByIdOperationSupport implements ExecutableInsertByI
public <T> ExecutableInsertById<T> insertById(final Class<T> domainType) {
Assert.notNull(domainType, "DomainType must not be null!");
return new ExecutableInsertByIdSupport<>(template, domainType, OptionsBuilder.getScopeFrom(domainType),
OptionsBuilder.getCollectionFrom(domainType), null, PersistTo.NONE, ReplicateTo.NONE, DurabilityLevel.NONE,
OptionsBuilder.getCollectionFrom(domainType), null, OptionsBuilder.getPersistTo(domainType),
OptionsBuilder.getReplicateTo(domainType), OptionsBuilder.getDurabilityLevel(domainType),
null);
}

View File

@@ -31,6 +31,7 @@ import com.couchbase.client.java.kv.ReplicateTo;
* {@link ExecutableRemoveByIdOperation} implementations for Couchbase.
*
* @author Michael Reiche
* @author Tigran Babloyan
*/
public class ExecutableRemoveByIdOperationSupport implements ExecutableRemoveByIdOperation {
@@ -50,7 +51,8 @@ public class ExecutableRemoveByIdOperationSupport implements ExecutableRemoveByI
public ExecutableRemoveById removeById(Class<?> domainType) {
return new ExecutableRemoveByIdSupport(template, domainType, OptionsBuilder.getScopeFrom(domainType),
OptionsBuilder.getCollectionFrom(domainType), null, PersistTo.NONE, ReplicateTo.NONE, DurabilityLevel.NONE,
OptionsBuilder.getCollectionFrom(domainType), null, OptionsBuilder.getPersistTo(domainType),
OptionsBuilder.getReplicateTo(domainType), OptionsBuilder.getDurabilityLevel(domainType),
null);
}

View File

@@ -39,7 +39,8 @@ public class ExecutableReplaceByIdOperationSupport implements ExecutableReplaceB
public <T> ExecutableReplaceById<T> replaceById(final Class<T> domainType) {
Assert.notNull(domainType, "DomainType must not be null!");
return new ExecutableReplaceByIdSupport<>(template, domainType, OptionsBuilder.getScopeFrom(domainType),
OptionsBuilder.getCollectionFrom(domainType), null, PersistTo.NONE, ReplicateTo.NONE, DurabilityLevel.NONE,
OptionsBuilder.getCollectionFrom(domainType), null, OptionsBuilder.getPersistTo(domainType),
OptionsBuilder.getReplicateTo(domainType), OptionsBuilder.getDurabilityLevel(domainType),
null);
}

View File

@@ -39,7 +39,8 @@ public class ExecutableUpsertByIdOperationSupport implements ExecutableUpsertByI
public <T> ExecutableUpsertById<T> upsertById(final Class<T> domainType) {
Assert.notNull(domainType, "DomainType must not be null!");
return new ExecutableUpsertByIdSupport<>(template, domainType, OptionsBuilder.getScopeFrom(domainType),
OptionsBuilder.getCollectionFrom(domainType), null, PersistTo.NONE, ReplicateTo.NONE, DurabilityLevel.NONE,
OptionsBuilder.getCollectionFrom(domainType), null, OptionsBuilder.getPersistTo(domainType),
OptionsBuilder.getReplicateTo(domainType), OptionsBuilder.getDurabilityLevel(domainType),
null);
}

View File

@@ -45,6 +45,7 @@ import com.couchbase.client.java.kv.ReplicateTo;
* {@link ReactiveInsertByIdOperation} implementations for Couchbase.
*
* @author Michael Reiche
* @author Tigran Babloyan
*/
public class ReactiveInsertByIdOperationSupport implements ReactiveInsertByIdOperation {
@@ -59,7 +60,8 @@ public class ReactiveInsertByIdOperationSupport implements ReactiveInsertByIdOpe
public <T> ReactiveInsertById<T> insertById(final Class<T> domainType) {
Assert.notNull(domainType, "DomainType must not be null!");
return new ReactiveInsertByIdSupport<>(template, domainType, OptionsBuilder.getScopeFrom(domainType),
OptionsBuilder.getCollectionFrom(domainType), null, PersistTo.NONE, ReplicateTo.NONE, DurabilityLevel.NONE,
OptionsBuilder.getCollectionFrom(domainType), null, OptionsBuilder.getPersistTo(domainType),
OptionsBuilder.getReplicateTo(domainType), OptionsBuilder.getDurabilityLevel(domainType),
null, template.support());
}

View File

@@ -46,6 +46,7 @@ import com.couchbase.client.java.kv.ReplicateTo;
* {@link ReactiveRemoveByIdOperation} implementations for Couchbase.
*
* @author Michael Reiche
* @author Tigran Babloyan
*/
public class ReactiveRemoveByIdOperationSupport implements ReactiveRemoveByIdOperation {
@@ -65,7 +66,8 @@ public class ReactiveRemoveByIdOperationSupport implements ReactiveRemoveByIdOpe
@Override
public ReactiveRemoveById removeById(Class<?> domainType) {
return new ReactiveRemoveByIdSupport(template, domainType, OptionsBuilder.getScopeFrom(domainType),
OptionsBuilder.getCollectionFrom(domainType), null, PersistTo.NONE, ReplicateTo.NONE, DurabilityLevel.NONE,
OptionsBuilder.getCollectionFrom(domainType), null, OptionsBuilder.getPersistTo(domainType),
OptionsBuilder.getReplicateTo(domainType), OptionsBuilder.getDurabilityLevel(domainType),
null);
}

View File

@@ -48,6 +48,7 @@ import com.couchbase.client.java.kv.ReplicateTo;
* {@link ReactiveReplaceByIdOperation} implementations for Couchbase.
*
* @author Michael Reiche
* @author Tigran Babloyan
*/
public class ReactiveReplaceByIdOperationSupport implements ReactiveReplaceByIdOperation {
@@ -62,7 +63,8 @@ public class ReactiveReplaceByIdOperationSupport implements ReactiveReplaceByIdO
public <T> ReactiveReplaceById<T> replaceById(final Class<T> domainType) {
Assert.notNull(domainType, "DomainType must not be null!");
return new ReactiveReplaceByIdSupport<>(template, domainType, OptionsBuilder.getScopeFrom(domainType),
OptionsBuilder.getCollectionFrom(domainType), null, PersistTo.NONE, ReplicateTo.NONE, DurabilityLevel.NONE,
OptionsBuilder.getCollectionFrom(domainType), null, OptionsBuilder.getPersistTo(domainType),
OptionsBuilder.getReplicateTo(domainType), OptionsBuilder.getDurabilityLevel(domainType),
null, template.support());
}

View File

@@ -37,6 +37,7 @@ import com.couchbase.client.java.kv.UpsertOptions;
* {@link ReactiveUpsertByIdOperation} implementations for Couchbase.
*
* @author Michael Reiche
* @author Tigran Babloyan
*/
public class ReactiveUpsertByIdOperationSupport implements ReactiveUpsertByIdOperation {
@@ -51,7 +52,8 @@ public class ReactiveUpsertByIdOperationSupport implements ReactiveUpsertByIdOpe
public <T> ReactiveUpsertById<T> upsertById(final Class<T> domainType) {
Assert.notNull(domainType, "DomainType must not be null!");
return new ReactiveUpsertByIdSupport<>(template, domainType, OptionsBuilder.getScopeFrom(domainType),
OptionsBuilder.getCollectionFrom(domainType), null, PersistTo.NONE, ReplicateTo.NONE, DurabilityLevel.NONE,
OptionsBuilder.getCollectionFrom(domainType), null, OptionsBuilder.getPersistTo(domainType),
OptionsBuilder.getReplicateTo(domainType), OptionsBuilder.getDurabilityLevel(domainType),
null, template.support());
}

View File

@@ -23,6 +23,9 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.concurrent.TimeUnit;
import com.couchbase.client.core.msg.kv.DurabilityLevel;
import com.couchbase.client.java.kv.PersistTo;
import com.couchbase.client.java.kv.ReplicateTo;
import org.springframework.core.annotation.AliasFor;
import org.springframework.data.annotation.Persistent;
import org.springframework.data.couchbase.repository.Collection;
@@ -36,6 +39,7 @@ import com.couchbase.client.java.query.QueryScanConsistency;
*
* @author Michael Nitschinger
* @author Andrey Rubtsov
* @author Tigran Babloyan
*/
@Persistent
@Inherited
@@ -84,4 +88,22 @@ public @interface Document {
*/
@AliasFor(annotation = ScanConsistency.class, attribute = "query")
QueryScanConsistency queryScanConsistency() default QueryScanConsistency.NOT_BOUNDED;
/**
* How many persisted copies of the modified record must exist on the given document. Default is {@link PersistTo#NONE}.
* For Couchbase version >= 6.5 see {@link #durabilityLevel()}.
*/
PersistTo persistTo() default PersistTo.NONE;
/**
* How many replicas must this documents operations be propagated to. Default is {@link ReplicateTo#NONE}.
* For Couchbase version >= 6.5 see {@link #durabilityLevel()}.
*/
ReplicateTo replicateTo() default ReplicateTo.NONE;
/**
* The optional durabilityLevel for all mutating operations, allows the application to wait until this replication
* (or persistence) is successful before proceeding
*/
DurabilityLevel durabilityLevel() default DurabilityLevel.NONE;
}

View File

@@ -31,6 +31,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.data.couchbase.core.mapping.CouchbaseDocument;
import org.springframework.data.couchbase.core.mapping.Document;
import org.springframework.data.couchbase.core.mapping.Expiry;
import org.springframework.data.couchbase.repository.Collection;
import org.springframework.data.couchbase.repository.ScanConsistency;
import org.springframework.data.couchbase.repository.Scope;
@@ -56,6 +58,7 @@ import com.couchbase.client.java.transactions.TransactionQueryOptions;
* Methods for building Options objects for Couchbae APIs.
*
* @author Michael Reiche
* @author Tigran Babloyan
*/
public class OptionsBuilder {
@@ -225,6 +228,30 @@ public class OptionsBuilder {
}
return null;
}
public static DurabilityLevel getDurabilityLevel(Class<?> domainType) {
if (domainType == null) {
return DurabilityLevel.NONE;
}
Document document = AnnotatedElementUtils.findMergedAnnotation(domainType, Document.class);
return document != null ? document.durabilityLevel() : DurabilityLevel.NONE;
}
public static PersistTo getPersistTo(Class<?> domainType) {
if (domainType == null) {
return PersistTo.NONE;
}
Document document = AnnotatedElementUtils.findMergedAnnotation(domainType, Document.class);
return document != null ? document.persistTo() : PersistTo.NONE;
}
public static ReplicateTo getReplicateTo(Class<?> domainType) {
if (domainType == null) {
return ReplicateTo.NONE;
}
Document document = AnnotatedElementUtils.findMergedAnnotation(domainType, Document.class);
return document != null ? document.replicateTo() : ReplicateTo.NONE;
}
/**
* collection annotation