Skip to content

Commit ad89525

Browse files
committed
Added support of the PersistTo, ReplicateTo and DurabilityLevel via @document annotation.
Closes #1486
1 parent 0e76118 commit ad89525

20 files changed

+479
-100
lines changed

src/main/asciidoc/entity.adoc

+3
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ The `@Id` annotation needs to be present because every document in Couchbase nee
7777
This key needs to be any string with a length of maximum 250 characters.
7878
Feel free to use whatever fits your use case, be it a UUID, an email address or anything else.
7979

80+
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.
81+
Default durability requirements can also be configured through the `@Document` annotation.
82+
For example: `@Document(durabilityLevel = DurabilityLevel.MAJORITY)` will force mutations to be replicated to a majority of the Data Service nodes.
8083
[[datatypes]]
8184
== Datatypes and Converters
8285

src/main/asciidoc/template.adoc

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ User found = couchbaseTemplate.findById(User.class).one(user.getId());
3030
----
3131
====
3232

33-
If you wanted to use a custom durability requirement for the `upsert` operation you can chain it in:
33+
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:
3434

3535
.Upsert with durability
3636
====

src/main/java/org/springframework/data/couchbase/core/ExecutableInsertByIdOperationSupport.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ public ExecutableInsertByIdOperationSupport(final CouchbaseTemplate template) {
3939
public <T> ExecutableInsertById<T> insertById(final Class<T> domainType) {
4040
Assert.notNull(domainType, "DomainType must not be null!");
4141
return new ExecutableInsertByIdSupport<>(template, domainType, OptionsBuilder.getScopeFrom(domainType),
42-
OptionsBuilder.getCollectionFrom(domainType), null, PersistTo.NONE, ReplicateTo.NONE, DurabilityLevel.NONE,
42+
OptionsBuilder.getCollectionFrom(domainType), null, OptionsBuilder.getPersistTo(domainType),
43+
OptionsBuilder.getReplicateTo(domainType), OptionsBuilder.getDurabilityLevel(domainType),
4344
null);
4445
}
4546

src/main/java/org/springframework/data/couchbase/core/ExecutableRemoveByIdOperationSupport.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
* {@link ExecutableRemoveByIdOperation} implementations for Couchbase.
3232
*
3333
* @author Michael Reiche
34+
* @author Tigran Babloyan
3435
*/
3536
public class ExecutableRemoveByIdOperationSupport implements ExecutableRemoveByIdOperation {
3637

@@ -50,7 +51,8 @@ public ExecutableRemoveById removeById() {
5051
public ExecutableRemoveById removeById(Class<?> domainType) {
5152

5253
return new ExecutableRemoveByIdSupport(template, domainType, OptionsBuilder.getScopeFrom(domainType),
53-
OptionsBuilder.getCollectionFrom(domainType), null, PersistTo.NONE, ReplicateTo.NONE, DurabilityLevel.NONE,
54+
OptionsBuilder.getCollectionFrom(domainType), null, OptionsBuilder.getPersistTo(domainType),
55+
OptionsBuilder.getReplicateTo(domainType), OptionsBuilder.getDurabilityLevel(domainType),
5456
null);
5557
}
5658

src/main/java/org/springframework/data/couchbase/core/ExecutableReplaceByIdOperationSupport.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ public ExecutableReplaceByIdOperationSupport(final CouchbaseTemplate template) {
3939
public <T> ExecutableReplaceById<T> replaceById(final Class<T> domainType) {
4040
Assert.notNull(domainType, "DomainType must not be null!");
4141
return new ExecutableReplaceByIdSupport<>(template, domainType, OptionsBuilder.getScopeFrom(domainType),
42-
OptionsBuilder.getCollectionFrom(domainType), null, PersistTo.NONE, ReplicateTo.NONE, DurabilityLevel.NONE,
42+
OptionsBuilder.getCollectionFrom(domainType), null, OptionsBuilder.getPersistTo(domainType),
43+
OptionsBuilder.getReplicateTo(domainType), OptionsBuilder.getDurabilityLevel(domainType),
4344
null);
4445
}
4546

src/main/java/org/springframework/data/couchbase/core/ExecutableUpsertByIdOperationSupport.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ public ExecutableUpsertByIdOperationSupport(final CouchbaseTemplate template) {
3939
public <T> ExecutableUpsertById<T> upsertById(final Class<T> domainType) {
4040
Assert.notNull(domainType, "DomainType must not be null!");
4141
return new ExecutableUpsertByIdSupport<>(template, domainType, OptionsBuilder.getScopeFrom(domainType),
42-
OptionsBuilder.getCollectionFrom(domainType), null, PersistTo.NONE, ReplicateTo.NONE, DurabilityLevel.NONE,
42+
OptionsBuilder.getCollectionFrom(domainType), null, OptionsBuilder.getPersistTo(domainType),
43+
OptionsBuilder.getReplicateTo(domainType), OptionsBuilder.getDurabilityLevel(domainType),
4344
null);
4445
}
4546

src/main/java/org/springframework/data/couchbase/core/ReactiveInsertByIdOperationSupport.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
* {@link ReactiveInsertByIdOperation} implementations for Couchbase.
4646
*
4747
* @author Michael Reiche
48+
* @author Tigran Babloyan
4849
*/
4950
public class ReactiveInsertByIdOperationSupport implements ReactiveInsertByIdOperation {
5051

@@ -59,7 +60,8 @@ public ReactiveInsertByIdOperationSupport(final ReactiveCouchbaseTemplate templa
5960
public <T> ReactiveInsertById<T> insertById(final Class<T> domainType) {
6061
Assert.notNull(domainType, "DomainType must not be null!");
6162
return new ReactiveInsertByIdSupport<>(template, domainType, OptionsBuilder.getScopeFrom(domainType),
62-
OptionsBuilder.getCollectionFrom(domainType), null, PersistTo.NONE, ReplicateTo.NONE, DurabilityLevel.NONE,
63+
OptionsBuilder.getCollectionFrom(domainType), null, OptionsBuilder.getPersistTo(domainType),
64+
OptionsBuilder.getReplicateTo(domainType), OptionsBuilder.getDurabilityLevel(domainType),
6365
null, template.support());
6466
}
6567

src/main/java/org/springframework/data/couchbase/core/ReactiveRemoveByIdOperationSupport.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
* {@link ReactiveRemoveByIdOperation} implementations for Couchbase.
4747
*
4848
* @author Michael Reiche
49+
* @author Tigran Babloyan
4950
*/
5051
public class ReactiveRemoveByIdOperationSupport implements ReactiveRemoveByIdOperation {
5152

@@ -65,7 +66,8 @@ public ReactiveRemoveById removeById() {
6566
@Override
6667
public ReactiveRemoveById removeById(Class<?> domainType) {
6768
return new ReactiveRemoveByIdSupport(template, domainType, OptionsBuilder.getScopeFrom(domainType),
68-
OptionsBuilder.getCollectionFrom(domainType), null, PersistTo.NONE, ReplicateTo.NONE, DurabilityLevel.NONE,
69+
OptionsBuilder.getCollectionFrom(domainType), null, OptionsBuilder.getPersistTo(domainType),
70+
OptionsBuilder.getReplicateTo(domainType), OptionsBuilder.getDurabilityLevel(domainType),
6971
null);
7072
}
7173

src/main/java/org/springframework/data/couchbase/core/ReactiveReplaceByIdOperationSupport.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
* {@link ReactiveReplaceByIdOperation} implementations for Couchbase.
4949
*
5050
* @author Michael Reiche
51+
* @author Tigran Babloyan
5152
*/
5253
public class ReactiveReplaceByIdOperationSupport implements ReactiveReplaceByIdOperation {
5354

@@ -62,7 +63,8 @@ public ReactiveReplaceByIdOperationSupport(final ReactiveCouchbaseTemplate templ
6263
public <T> ReactiveReplaceById<T> replaceById(final Class<T> domainType) {
6364
Assert.notNull(domainType, "DomainType must not be null!");
6465
return new ReactiveReplaceByIdSupport<>(template, domainType, OptionsBuilder.getScopeFrom(domainType),
65-
OptionsBuilder.getCollectionFrom(domainType), null, PersistTo.NONE, ReplicateTo.NONE, DurabilityLevel.NONE,
66+
OptionsBuilder.getCollectionFrom(domainType), null, OptionsBuilder.getPersistTo(domainType),
67+
OptionsBuilder.getReplicateTo(domainType), OptionsBuilder.getDurabilityLevel(domainType),
6668
null, template.support());
6769
}
6870

src/main/java/org/springframework/data/couchbase/core/ReactiveUpsertByIdOperationSupport.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
* {@link ReactiveUpsertByIdOperation} implementations for Couchbase.
3838
*
3939
* @author Michael Reiche
40+
* @author Tigran Babloyan
4041
*/
4142
public class ReactiveUpsertByIdOperationSupport implements ReactiveUpsertByIdOperation {
4243

@@ -51,7 +52,8 @@ public ReactiveUpsertByIdOperationSupport(final ReactiveCouchbaseTemplate templa
5152
public <T> ReactiveUpsertById<T> upsertById(final Class<T> domainType) {
5253
Assert.notNull(domainType, "DomainType must not be null!");
5354
return new ReactiveUpsertByIdSupport<>(template, domainType, OptionsBuilder.getScopeFrom(domainType),
54-
OptionsBuilder.getCollectionFrom(domainType), null, PersistTo.NONE, ReplicateTo.NONE, DurabilityLevel.NONE,
55+
OptionsBuilder.getCollectionFrom(domainType), null, OptionsBuilder.getPersistTo(domainType),
56+
OptionsBuilder.getReplicateTo(domainType), OptionsBuilder.getDurabilityLevel(domainType),
5557
null, template.support());
5658
}
5759

src/main/java/org/springframework/data/couchbase/core/mapping/Document.java

+22
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
import java.lang.annotation.Target;
2424
import java.util.concurrent.TimeUnit;
2525

26+
import com.couchbase.client.core.msg.kv.DurabilityLevel;
27+
import com.couchbase.client.java.kv.PersistTo;
28+
import com.couchbase.client.java.kv.ReplicateTo;
2629
import org.springframework.core.annotation.AliasFor;
2730
import org.springframework.data.annotation.Persistent;
2831
import org.springframework.data.couchbase.repository.Collection;
@@ -36,6 +39,7 @@
3639
*
3740
* @author Michael Nitschinger
3841
* @author Andrey Rubtsov
42+
* @author Tigran Babloyan
3943
*/
4044
@Persistent
4145
@Inherited
@@ -84,4 +88,22 @@
8488
*/
8589
@AliasFor(annotation = ScanConsistency.class, attribute = "query")
8690
QueryScanConsistency queryScanConsistency() default QueryScanConsistency.NOT_BOUNDED;
91+
92+
/**
93+
* How many persisted copies of the modified record must exist on the given document. Default is {@link PersistTo#NONE}.
94+
* For Couchbase version >= 6.5 see {@link #durabilityLevel()}.
95+
*/
96+
PersistTo persistTo() default PersistTo.NONE;
97+
98+
/**
99+
* How many replicas must this documents operations be propagated to. Default is {@link ReplicateTo#NONE}.
100+
* For Couchbase version >= 6.5 see {@link #durabilityLevel()}.
101+
*/
102+
ReplicateTo replicateTo() default ReplicateTo.NONE;
103+
104+
/**
105+
* The optional durabilityLevel for all mutating operations, allows the application to wait until this replication
106+
* (or persistence) is successful before proceeding
107+
*/
108+
DurabilityLevel durabilityLevel() default DurabilityLevel.NONE;
87109
}

src/main/java/org/springframework/data/couchbase/core/query/OptionsBuilder.java

+27
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
import org.slf4j.LoggerFactory;
3232
import org.springframework.core.annotation.AnnotatedElementUtils;
3333
import org.springframework.data.couchbase.core.mapping.CouchbaseDocument;
34+
import org.springframework.data.couchbase.core.mapping.Document;
35+
import org.springframework.data.couchbase.core.mapping.Expiry;
3436
import org.springframework.data.couchbase.repository.Collection;
3537
import org.springframework.data.couchbase.repository.ScanConsistency;
3638
import org.springframework.data.couchbase.repository.Scope;
@@ -56,6 +58,7 @@
5658
* Methods for building Options objects for Couchbae APIs.
5759
*
5860
* @author Michael Reiche
61+
* @author Tigran Babloyan
5962
*/
6063
public class OptionsBuilder {
6164

@@ -225,6 +228,30 @@ public static String getScopeFrom(Class<?> domainType) {
225228
}
226229
return null;
227230
}
231+
232+
public static DurabilityLevel getDurabilityLevel(Class<?> domainType) {
233+
if (domainType == null) {
234+
return null;
235+
}
236+
Document document = AnnotatedElementUtils.findMergedAnnotation(domainType, Document.class);
237+
return document.durabilityLevel();
238+
}
239+
240+
public static PersistTo getPersistTo(Class<?> domainType) {
241+
if (domainType == null) {
242+
return null;
243+
}
244+
Document document = AnnotatedElementUtils.findMergedAnnotation(domainType, Document.class);
245+
return document.persistTo();
246+
}
247+
248+
public static ReplicateTo getReplicateTo(Class<?> domainType) {
249+
if (domainType == null) {
250+
return null;
251+
}
252+
Document document = AnnotatedElementUtils.findMergedAnnotation(domainType, Document.class);
253+
return document.replicateTo();
254+
}
228255

229256
/**
230257
* collection annotation

0 commit comments

Comments
 (0)