Skip to content

Durability via Annotations #1649

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/main/asciidoc/entity.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion src/main/asciidoc/template.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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
====
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ public ExecutableInsertByIdOperationSupport(final CouchbaseTemplate template) {
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);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
* {@link ExecutableRemoveByIdOperation} implementations for Couchbase.
*
* @author Michael Reiche
* @author Tigran Babloyan
*/
public class ExecutableRemoveByIdOperationSupport implements ExecutableRemoveByIdOperation {

Expand All @@ -50,7 +51,8 @@ public ExecutableRemoveById removeById() {
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);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ public ExecutableReplaceByIdOperationSupport(final CouchbaseTemplate template) {
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);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ public ExecutableUpsertByIdOperationSupport(final CouchbaseTemplate template) {
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);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
* {@link ReactiveInsertByIdOperation} implementations for Couchbase.
*
* @author Michael Reiche
* @author Tigran Babloyan
*/
public class ReactiveInsertByIdOperationSupport implements ReactiveInsertByIdOperation {

Expand All @@ -59,7 +60,8 @@ public ReactiveInsertByIdOperationSupport(final ReactiveCouchbaseTemplate templa
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());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
* {@link ReactiveRemoveByIdOperation} implementations for Couchbase.
*
* @author Michael Reiche
* @author Tigran Babloyan
*/
public class ReactiveRemoveByIdOperationSupport implements ReactiveRemoveByIdOperation {

Expand All @@ -65,7 +66,8 @@ public ReactiveRemoveById removeById() {
@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);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
* {@link ReactiveReplaceByIdOperation} implementations for Couchbase.
*
* @author Michael Reiche
* @author Tigran Babloyan
*/
public class ReactiveReplaceByIdOperationSupport implements ReactiveReplaceByIdOperation {

Expand All @@ -62,7 +63,8 @@ public ReactiveReplaceByIdOperationSupport(final ReactiveCouchbaseTemplate templ
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());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
* {@link ReactiveUpsertByIdOperation} implementations for Couchbase.
*
* @author Michael Reiche
* @author Tigran Babloyan
*/
public class ReactiveUpsertByIdOperationSupport implements ReactiveUpsertByIdOperation {

Expand All @@ -51,7 +52,8 @@ public ReactiveUpsertByIdOperationSupport(final ReactiveCouchbaseTemplate templa
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());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
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;
Expand All @@ -36,6 +39,7 @@
*
* @author Michael Nitschinger
* @author Andrey Rubtsov
* @author Tigran Babloyan
*/
@Persistent
@Inherited
Expand Down Expand Up @@ -84,4 +88,22 @@
*/
@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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
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;
Expand All @@ -56,6 +58,7 @@
* Methods for building Options objects for Couchbae APIs.
*
* @author Michael Reiche
* @author Tigran Babloyan
*/
public class OptionsBuilder {

Expand Down Expand Up @@ -225,6 +228,30 @@ public static String getScopeFrom(Class<?> domainType) {
}
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
Expand Down
Loading