Skip to content

Commit 6ab350d

Browse files
authored
DATACOUCH-1041 - Add withCas() method to RemoveById. (#1051)
Add withCas() method to RemoveById. Co-authored-by: mikereiche <[email protected]>
1 parent 1329cae commit 6ab350d

File tree

5 files changed

+76
-26
lines changed

5 files changed

+76
-26
lines changed

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ interface RemoveByIdWithDurability extends RemoveByIdWithCollection, WithDurabil
5050

5151
}
5252

53-
interface ExecutableRemoveById extends RemoveByIdWithDurability {}
53+
interface RemoveByIdWithCas extends RemoveByIdWithDurability {
54+
55+
RemoveByIdWithDurability withCas(Long cas);
56+
}
57+
58+
interface ExecutableRemoveById extends RemoveByIdWithCas {}
5459

5560
}

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

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ public ExecutableRemoveByIdOperationSupport(final CouchbaseTemplate template) {
3535

3636
@Override
3737
public ExecutableRemoveById removeById() {
38-
return new ExecutableRemoveByIdSupport(template, null, PersistTo.NONE, ReplicateTo.NONE, DurabilityLevel.NONE);
38+
return new ExecutableRemoveByIdSupport(template, null, PersistTo.NONE, ReplicateTo.NONE, DurabilityLevel.NONE,
39+
null);
3940
}
4041

4142
static class ExecutableRemoveByIdSupport implements ExecutableRemoveById {
@@ -45,17 +46,19 @@ static class ExecutableRemoveByIdSupport implements ExecutableRemoveById {
4546
private final PersistTo persistTo;
4647
private final ReplicateTo replicateTo;
4748
private final DurabilityLevel durabilityLevel;
49+
private final Long cas;
4850
private final ReactiveRemoveByIdSupport reactiveRemoveByIdSupport;
4951

5052
ExecutableRemoveByIdSupport(final CouchbaseTemplate template, final String collection, final PersistTo persistTo,
51-
final ReplicateTo replicateTo, final DurabilityLevel durabilityLevel) {
53+
final ReplicateTo replicateTo, final DurabilityLevel durabilityLevel, Long cas) {
5254
this.template = template;
5355
this.collection = collection;
5456
this.persistTo = persistTo;
5557
this.replicateTo = replicateTo;
5658
this.durabilityLevel = durabilityLevel;
59+
this.cas = cas;
5760
this.reactiveRemoveByIdSupport = new ReactiveRemoveByIdSupport(template.reactive(), collection, persistTo,
58-
replicateTo, durabilityLevel);
61+
replicateTo, durabilityLevel, cas);
5962
}
6063

6164
@Override
@@ -71,20 +74,26 @@ public List<RemoveResult> all(final Collection<String> ids) {
7174
@Override
7275
public TerminatingRemoveById inCollection(final String collection) {
7376
Assert.hasText(collection, "Collection must not be null nor empty.");
74-
return new ExecutableRemoveByIdSupport(template, collection, persistTo, replicateTo, durabilityLevel);
77+
return new ExecutableRemoveByIdSupport(template, collection, persistTo, replicateTo, durabilityLevel, null);
7578
}
7679

7780
@Override
7881
public RemoveByIdWithCollection withDurability(final DurabilityLevel durabilityLevel) {
7982
Assert.notNull(durabilityLevel, "Durability Level must not be null.");
80-
return new ExecutableRemoveByIdSupport(template, collection, persistTo, replicateTo, durabilityLevel);
83+
return new ExecutableRemoveByIdSupport(template, collection, persistTo, replicateTo, durabilityLevel, null);
8184
}
8285

8386
@Override
8487
public RemoveByIdWithCollection withDurability(final PersistTo persistTo, final ReplicateTo replicateTo) {
8588
Assert.notNull(persistTo, "PersistTo must not be null.");
8689
Assert.notNull(replicateTo, "ReplicateTo must not be null.");
87-
return new ExecutableRemoveByIdSupport(template, collection, persistTo, replicateTo, durabilityLevel);
90+
return new ExecutableRemoveByIdSupport(template, collection, persistTo, replicateTo, durabilityLevel, null);
91+
}
92+
93+
@Override
94+
public RemoveByIdWithCas withCas(final Long cas) {
95+
Assert.notNull(cas, "CAS must not be null.");
96+
return new ExecutableRemoveByIdSupport(template, collection, persistTo, replicateTo, durabilityLevel, cas);
8897
}
8998

9099
}

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ interface TerminatingRemoveById extends OneAndAllIdReactive<RemoveResult> {
4242
interface RemoveByIdWithCollection extends TerminatingRemoveById, WithCollection<RemoveResult> {
4343

4444
TerminatingRemoveById inCollection(String collection);
45+
4546
}
4647

4748
interface RemoveByIdWithDurability extends RemoveByIdWithCollection, WithDurability<RemoveResult> {
@@ -52,6 +53,12 @@ interface RemoveByIdWithDurability extends RemoveByIdWithCollection, WithDurabil
5253

5354
}
5455

55-
interface ReactiveRemoveById extends RemoveByIdWithDurability {}
56+
interface RemoveByIdWithCas extends RemoveByIdWithDurability {
57+
58+
RemoveByIdWithDurability withCas(Long cas);
59+
60+
}
61+
62+
interface ReactiveRemoveById extends RemoveByIdWithCas {}
5663

5764
}

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

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public ReactiveRemoveByIdOperationSupport(final ReactiveCouchbaseTemplate templa
3737

3838
@Override
3939
public ReactiveRemoveById removeById() {
40-
return new ReactiveRemoveByIdSupport(template, null, PersistTo.NONE, ReplicateTo.NONE, DurabilityLevel.NONE);
40+
return new ReactiveRemoveByIdSupport(template, null, PersistTo.NONE, ReplicateTo.NONE, DurabilityLevel.NONE, null);
4141
}
4242

4343
static class ReactiveRemoveByIdSupport implements ReactiveRemoveById {
@@ -47,14 +47,16 @@ static class ReactiveRemoveByIdSupport implements ReactiveRemoveById {
4747
private final PersistTo persistTo;
4848
private final ReplicateTo replicateTo;
4949
private final DurabilityLevel durabilityLevel;
50+
private final Long cas;
5051

5152
ReactiveRemoveByIdSupport(final ReactiveCouchbaseTemplate template, final String collection,
52-
final PersistTo persistTo, final ReplicateTo replicateTo, final DurabilityLevel durabilityLevel) {
53+
final PersistTo persistTo, final ReplicateTo replicateTo, final DurabilityLevel durabilityLevel, Long cas) {
5354
this.template = template;
5455
this.collection = collection;
5556
this.persistTo = persistTo;
5657
this.replicateTo = replicateTo;
5758
this.durabilityLevel = durabilityLevel;
59+
this.cas = cas;
5860
}
5961

6062
@Override
@@ -81,28 +83,36 @@ private RemoveOptions buildRemoveOptions() {
8183
} else if (durabilityLevel != DurabilityLevel.NONE) {
8284
options.durability(durabilityLevel);
8385
}
86+
if (cas != null) {
87+
options.cas(cas);
88+
}
8489
return options;
8590
}
8691

92+
@Override
93+
public RemoveByIdWithDurability inCollection(final String collection) {
94+
Assert.hasText(collection, "Collection must not be null nor empty.");
95+
return new ReactiveRemoveByIdSupport(template, collection, persistTo, replicateTo, durabilityLevel, null);
96+
}
97+
8798
@Override
8899
public RemoveByIdWithCollection withDurability(final DurabilityLevel durabilityLevel) {
89100
Assert.notNull(durabilityLevel, "Durability Level must not be null.");
90-
return new ReactiveRemoveByIdSupport(template, collection, persistTo, replicateTo, durabilityLevel);
101+
return new ReactiveRemoveByIdSupport(template, collection, persistTo, replicateTo, durabilityLevel, null);
91102
}
92103

93104
@Override
94105
public RemoveByIdWithCollection withDurability(final PersistTo persistTo, final ReplicateTo replicateTo) {
95106
Assert.notNull(persistTo, "PersistTo must not be null.");
96107
Assert.notNull(replicateTo, "ReplicateTo must not be null.");
97-
return new ReactiveRemoveByIdSupport(template, collection, persistTo, replicateTo, durabilityLevel);
108+
return new ReactiveRemoveByIdSupport(template, collection, persistTo, replicateTo, durabilityLevel, null);
98109
}
99110

100111
@Override
101-
public RemoveByIdWithDurability inCollection(final String collection) {
102-
Assert.hasText(collection, "Collection must not be null nor empty.");
103-
return new ReactiveRemoveByIdSupport(template, collection, persistTo, replicateTo, durabilityLevel);
112+
public RemoveByIdWithDurability withCas(final Long cas) {
113+
Assert.notNull(cas, "CAS must not be null.");
114+
return new ReactiveRemoveByIdSupport(template, collection, persistTo, replicateTo, durabilityLevel, cas);
104115
}
105-
106116
}
107117

108118
}

src/test/java/org/springframework/data/couchbase/core/CouchbaseTemplateKeyValueIntegrationTests.java

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,10 @@
4545
import org.springframework.data.couchbase.domain.UserAnnotated3;
4646
import org.springframework.data.couchbase.util.ClusterType;
4747
import org.springframework.data.couchbase.util.IgnoreWhen;
48+
import org.springframework.data.couchbase.util.JavaIntegrationTests;
4849

4950
import com.couchbase.client.java.kv.PersistTo;
5051
import com.couchbase.client.java.kv.ReplicateTo;
51-
import org.springframework.data.couchbase.util.JavaIntegrationTests;
5252

5353
;
5454

@@ -103,7 +103,8 @@ void withDurability()
103103
"firstname", "lastname");
104104

105105
if (clazz.equals(User.class)) { // User.java doesn't have an durability annotation
106-
operator = (OneAndAllEntity) ((WithDurability<User>) operator).withDurability(PersistTo.ACTIVE, ReplicateTo.NONE);
106+
operator = (OneAndAllEntity) ((WithDurability<User>) operator).withDurability(PersistTo.ACTIVE,
107+
ReplicateTo.NONE);
107108
}
108109

109110
// if replace, we need to insert a document to replace
@@ -194,16 +195,34 @@ void upsertAndReplaceById() {
194195

195196
@Test
196197
void upsertAndRemoveById() {
197-
User user = new User(UUID.randomUUID().toString(), "firstname", "lastname");
198-
User modified = couchbaseTemplate.upsertById(User.class).one(user);
199-
assertEquals(user, modified);
198+
{
199+
User user = new User(UUID.randomUUID().toString(), "firstname", "lastname");
200+
User modified = couchbaseTemplate.upsertById(User.class).one(user);
201+
assertEquals(user, modified);
200202

201-
RemoveResult removeResult = couchbaseTemplate.removeById().one(user.getId());
202-
assertEquals(user.getId(), removeResult.getId());
203-
assertTrue(removeResult.getCas() != 0);
204-
assertTrue(removeResult.getMutationToken().isPresent());
203+
RemoveResult removeResult = couchbaseTemplate.removeById().one(user.getId());
204+
assertEquals(user.getId(), removeResult.getId());
205+
assertTrue(removeResult.getCas() != 0);
206+
assertTrue(removeResult.getMutationToken().isPresent());
205207

206-
assertNull(couchbaseTemplate.findById(User.class).one(user.getId()));
208+
assertNull(couchbaseTemplate.findById(User.class).one(user.getId()));
209+
}
210+
{
211+
User user = new User(UUID.randomUUID().toString(), "firstname", "lastname");
212+
User modified = couchbaseTemplate.upsertById(User.class).one(user);
213+
System.out.println(reactiveCouchbaseTemplate.support().getCas(user));
214+
System.out.println(reactiveCouchbaseTemplate.support().getCas(modified));
215+
assertEquals(user, modified);
216+
217+
// careful now - user and modified are the same object. The object has the new cas (@Version version)
218+
Long savedCas = modified.getVersion();
219+
modified.setVersion(123);
220+
assertThrows(DataIntegrityViolationException.class, () -> couchbaseTemplate.removeById()
221+
.withCas(reactiveCouchbaseTemplate.support().getCas(modified)).one(modified.getId()));
222+
modified.setVersion(savedCas);
223+
couchbaseTemplate.removeById().withCas(reactiveCouchbaseTemplate.support().getCas(modified))
224+
.one(modified.getId());
225+
}
207226
}
208227

209228
@Test

0 commit comments

Comments
 (0)