DATACOUCH-1041 - Add withCas() method to RemoveById. (#1051)

Add withCas() method to RemoveById.

Co-authored-by: mikereiche <michael.reiche@couchbase.com>
This commit is contained in:
Michael Reiche
2021-02-16 15:16:12 -08:00
committed by GitHub
parent 1329cae703
commit 6ab350df35
5 changed files with 76 additions and 26 deletions

View File

@@ -50,6 +50,11 @@ public interface ExecutableRemoveByIdOperation {
}
interface ExecutableRemoveById extends RemoveByIdWithDurability {}
interface RemoveByIdWithCas extends RemoveByIdWithDurability {
RemoveByIdWithDurability withCas(Long cas);
}
interface ExecutableRemoveById extends RemoveByIdWithCas {}
}

View File

@@ -35,7 +35,8 @@ public class ExecutableRemoveByIdOperationSupport implements ExecutableRemoveByI
@Override
public ExecutableRemoveById removeById() {
return new ExecutableRemoveByIdSupport(template, null, PersistTo.NONE, ReplicateTo.NONE, DurabilityLevel.NONE);
return new ExecutableRemoveByIdSupport(template, null, PersistTo.NONE, ReplicateTo.NONE, DurabilityLevel.NONE,
null);
}
static class ExecutableRemoveByIdSupport implements ExecutableRemoveById {
@@ -45,17 +46,19 @@ public class ExecutableRemoveByIdOperationSupport implements ExecutableRemoveByI
private final PersistTo persistTo;
private final ReplicateTo replicateTo;
private final DurabilityLevel durabilityLevel;
private final Long cas;
private final ReactiveRemoveByIdSupport reactiveRemoveByIdSupport;
ExecutableRemoveByIdSupport(final CouchbaseTemplate template, final String collection, final PersistTo persistTo,
final ReplicateTo replicateTo, final DurabilityLevel durabilityLevel) {
final ReplicateTo replicateTo, final DurabilityLevel durabilityLevel, Long cas) {
this.template = template;
this.collection = collection;
this.persistTo = persistTo;
this.replicateTo = replicateTo;
this.durabilityLevel = durabilityLevel;
this.cas = cas;
this.reactiveRemoveByIdSupport = new ReactiveRemoveByIdSupport(template.reactive(), collection, persistTo,
replicateTo, durabilityLevel);
replicateTo, durabilityLevel, cas);
}
@Override
@@ -71,20 +74,26 @@ public class ExecutableRemoveByIdOperationSupport implements ExecutableRemoveByI
@Override
public TerminatingRemoveById inCollection(final String collection) {
Assert.hasText(collection, "Collection must not be null nor empty.");
return new ExecutableRemoveByIdSupport(template, collection, persistTo, replicateTo, durabilityLevel);
return new ExecutableRemoveByIdSupport(template, collection, persistTo, replicateTo, durabilityLevel, null);
}
@Override
public RemoveByIdWithCollection withDurability(final DurabilityLevel durabilityLevel) {
Assert.notNull(durabilityLevel, "Durability Level must not be null.");
return new ExecutableRemoveByIdSupport(template, collection, persistTo, replicateTo, durabilityLevel);
return new ExecutableRemoveByIdSupport(template, collection, persistTo, replicateTo, durabilityLevel, null);
}
@Override
public RemoveByIdWithCollection withDurability(final PersistTo persistTo, final ReplicateTo replicateTo) {
Assert.notNull(persistTo, "PersistTo must not be null.");
Assert.notNull(replicateTo, "ReplicateTo must not be null.");
return new ExecutableRemoveByIdSupport(template, collection, persistTo, replicateTo, durabilityLevel);
return new ExecutableRemoveByIdSupport(template, collection, persistTo, replicateTo, durabilityLevel, null);
}
@Override
public RemoveByIdWithCas withCas(final Long cas) {
Assert.notNull(cas, "CAS must not be null.");
return new ExecutableRemoveByIdSupport(template, collection, persistTo, replicateTo, durabilityLevel, cas);
}
}

View File

@@ -42,6 +42,7 @@ public interface ReactiveRemoveByIdOperation {
interface RemoveByIdWithCollection extends TerminatingRemoveById, WithCollection<RemoveResult> {
TerminatingRemoveById inCollection(String collection);
}
interface RemoveByIdWithDurability extends RemoveByIdWithCollection, WithDurability<RemoveResult> {
@@ -52,6 +53,12 @@ public interface ReactiveRemoveByIdOperation {
}
interface ReactiveRemoveById extends RemoveByIdWithDurability {}
interface RemoveByIdWithCas extends RemoveByIdWithDurability {
RemoveByIdWithDurability withCas(Long cas);
}
interface ReactiveRemoveById extends RemoveByIdWithCas {}
}

View File

@@ -37,7 +37,7 @@ public class ReactiveRemoveByIdOperationSupport implements ReactiveRemoveByIdOpe
@Override
public ReactiveRemoveById removeById() {
return new ReactiveRemoveByIdSupport(template, null, PersistTo.NONE, ReplicateTo.NONE, DurabilityLevel.NONE);
return new ReactiveRemoveByIdSupport(template, null, PersistTo.NONE, ReplicateTo.NONE, DurabilityLevel.NONE, null);
}
static class ReactiveRemoveByIdSupport implements ReactiveRemoveById {
@@ -47,14 +47,16 @@ public class ReactiveRemoveByIdOperationSupport implements ReactiveRemoveByIdOpe
private final PersistTo persistTo;
private final ReplicateTo replicateTo;
private final DurabilityLevel durabilityLevel;
private final Long cas;
ReactiveRemoveByIdSupport(final ReactiveCouchbaseTemplate template, final String collection,
final PersistTo persistTo, final ReplicateTo replicateTo, final DurabilityLevel durabilityLevel) {
final PersistTo persistTo, final ReplicateTo replicateTo, final DurabilityLevel durabilityLevel, Long cas) {
this.template = template;
this.collection = collection;
this.persistTo = persistTo;
this.replicateTo = replicateTo;
this.durabilityLevel = durabilityLevel;
this.cas = cas;
}
@Override
@@ -81,28 +83,36 @@ public class ReactiveRemoveByIdOperationSupport implements ReactiveRemoveByIdOpe
} else if (durabilityLevel != DurabilityLevel.NONE) {
options.durability(durabilityLevel);
}
if (cas != null) {
options.cas(cas);
}
return options;
}
@Override
public RemoveByIdWithDurability inCollection(final String collection) {
Assert.hasText(collection, "Collection must not be null nor empty.");
return new ReactiveRemoveByIdSupport(template, collection, persistTo, replicateTo, durabilityLevel, null);
}
@Override
public RemoveByIdWithCollection withDurability(final DurabilityLevel durabilityLevel) {
Assert.notNull(durabilityLevel, "Durability Level must not be null.");
return new ReactiveRemoveByIdSupport(template, collection, persistTo, replicateTo, durabilityLevel);
return new ReactiveRemoveByIdSupport(template, collection, persistTo, replicateTo, durabilityLevel, null);
}
@Override
public RemoveByIdWithCollection withDurability(final PersistTo persistTo, final ReplicateTo replicateTo) {
Assert.notNull(persistTo, "PersistTo must not be null.");
Assert.notNull(replicateTo, "ReplicateTo must not be null.");
return new ReactiveRemoveByIdSupport(template, collection, persistTo, replicateTo, durabilityLevel);
return new ReactiveRemoveByIdSupport(template, collection, persistTo, replicateTo, durabilityLevel, null);
}
@Override
public RemoveByIdWithDurability inCollection(final String collection) {
Assert.hasText(collection, "Collection must not be null nor empty.");
return new ReactiveRemoveByIdSupport(template, collection, persistTo, replicateTo, durabilityLevel);
public RemoveByIdWithDurability withCas(final Long cas) {
Assert.notNull(cas, "CAS must not be null.");
return new ReactiveRemoveByIdSupport(template, collection, persistTo, replicateTo, durabilityLevel, cas);
}
}
}

View File

@@ -45,10 +45,10 @@ import org.springframework.data.couchbase.domain.UserAnnotated2;
import org.springframework.data.couchbase.domain.UserAnnotated3;
import org.springframework.data.couchbase.util.ClusterType;
import org.springframework.data.couchbase.util.IgnoreWhen;
import org.springframework.data.couchbase.util.JavaIntegrationTests;
import com.couchbase.client.java.kv.PersistTo;
import com.couchbase.client.java.kv.ReplicateTo;
import org.springframework.data.couchbase.util.JavaIntegrationTests;
;
@@ -103,7 +103,8 @@ class CouchbaseTemplateKeyValueIntegrationTests extends JavaIntegrationTests {
"firstname", "lastname");
if (clazz.equals(User.class)) { // User.java doesn't have an durability annotation
operator = (OneAndAllEntity) ((WithDurability<User>) operator).withDurability(PersistTo.ACTIVE, ReplicateTo.NONE);
operator = (OneAndAllEntity) ((WithDurability<User>) operator).withDurability(PersistTo.ACTIVE,
ReplicateTo.NONE);
}
// if replace, we need to insert a document to replace
@@ -194,16 +195,34 @@ class CouchbaseTemplateKeyValueIntegrationTests extends JavaIntegrationTests {
@Test
void upsertAndRemoveById() {
User user = new User(UUID.randomUUID().toString(), "firstname", "lastname");
User modified = couchbaseTemplate.upsertById(User.class).one(user);
assertEquals(user, modified);
{
User user = new User(UUID.randomUUID().toString(), "firstname", "lastname");
User modified = couchbaseTemplate.upsertById(User.class).one(user);
assertEquals(user, modified);
RemoveResult removeResult = couchbaseTemplate.removeById().one(user.getId());
assertEquals(user.getId(), removeResult.getId());
assertTrue(removeResult.getCas() != 0);
assertTrue(removeResult.getMutationToken().isPresent());
RemoveResult removeResult = couchbaseTemplate.removeById().one(user.getId());
assertEquals(user.getId(), removeResult.getId());
assertTrue(removeResult.getCas() != 0);
assertTrue(removeResult.getMutationToken().isPresent());
assertNull(couchbaseTemplate.findById(User.class).one(user.getId()));
assertNull(couchbaseTemplate.findById(User.class).one(user.getId()));
}
{
User user = new User(UUID.randomUUID().toString(), "firstname", "lastname");
User modified = couchbaseTemplate.upsertById(User.class).one(user);
System.out.println(reactiveCouchbaseTemplate.support().getCas(user));
System.out.println(reactiveCouchbaseTemplate.support().getCas(modified));
assertEquals(user, modified);
// careful now - user and modified are the same object. The object has the new cas (@Version version)
Long savedCas = modified.getVersion();
modified.setVersion(123);
assertThrows(DataIntegrityViolationException.class, () -> couchbaseTemplate.removeById()
.withCas(reactiveCouchbaseTemplate.support().getCas(modified)).one(modified.getId()));
modified.setVersion(savedCas);
couchbaseTemplate.removeById().withCas(reactiveCouchbaseTemplate.support().getCas(modified))
.one(modified.getId());
}
}
@Test