Skip to content

DATACOUCH-645 - Support Document(expiryExpression) annotation. #292

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

Closed
Closed
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
Original file line number Diff line number Diff line change
Expand Up @@ -26,29 +26,32 @@ public interface ExecutableInsertByIdOperation {

<T> ExecutableInsertById<T> insertById(Class<T> domainType);

interface TerminatingInsertById<T> {
interface TerminatingInsertById<T> extends OneAndAll<T>{

@Override
T one(T object);

@Override
Collection<? extends T> all(Collection<? extends T> objects);

}

interface InsertByIdWithCollection<T> extends TerminatingInsertById<T> {
interface InsertByIdWithCollection<T> extends TerminatingInsertById<T>, InCollection<T> {

TerminatingInsertById<T> inCollection(String collection);
}

interface InsertByIdWithDurability<T> extends InsertByIdWithCollection<T> {
interface InsertByIdWithDurability<T> extends InsertByIdWithCollection<T>, WithDurability<T> {

InsertByIdWithCollection<T> withDurability(DurabilityLevel durabilityLevel);

InsertByIdWithCollection<T> withDurability(PersistTo persistTo, ReplicateTo replicateTo);

}

interface InsertByIdWithExpiry<T> extends InsertByIdWithDurability<T> {
interface InsertByIdWithExpiry<T> extends InsertByIdWithDurability<T>, WithExpiry<T> {

@Override
InsertByIdWithDurability<T> withExpiry(Duration expiry);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ interface TerminatingRemoveById {

}

interface RemoveByIdWithCollection extends TerminatingRemoveById {
interface RemoveByIdWithCollection extends TerminatingRemoveById, InCollection {

TerminatingRemoveById inCollection(String collection);
}

interface RemoveByIdWithDurability extends RemoveByIdWithCollection {
interface RemoveByIdWithDurability extends RemoveByIdWithCollection, WithDurability {

RemoveByIdWithCollection withDurability(DurabilityLevel durabilityLevel);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,36 +19,40 @@
import java.util.Collection;

import com.couchbase.client.core.msg.kv.DurabilityLevel;
import com.couchbase.client.java.kv.IncrementOptions;
import com.couchbase.client.java.kv.PersistTo;
import com.couchbase.client.java.kv.ReplicateTo;

public interface ExecutableReplaceByIdOperation {

<T> ExecutableReplaceById<T> replaceById(Class<T> domainType);

interface TerminatingReplaceById<T> {
interface TerminatingReplaceById<T> extends OneAndAll<T> {

@Override
T one(T object);

@Override
Collection<? extends T> all(Collection<? extends T> objects);

}

interface ReplaceByIdWithCollection<T> extends TerminatingReplaceById<T> {
interface ReplaceByIdWithCollection<T> extends TerminatingReplaceById<T> , InCollection<T> {

TerminatingReplaceById<T> inCollection(String collection);
}

interface ReplaceByIdWithDurability<T> extends ReplaceByIdWithCollection<T> {
interface ReplaceByIdWithDurability<T> extends ReplaceByIdWithCollection<T>, WithDurability<T> {

ReplaceByIdWithCollection<T> withDurability(DurabilityLevel durabilityLevel);

ReplaceByIdWithCollection<T> withDurability(PersistTo persistTo, ReplicateTo replicateTo);

}

interface ReplaceByIdWithExpiry<T> extends ReplaceByIdWithDurability<T> {
interface ReplaceByIdWithExpiry<T> extends ReplaceByIdWithDurability<T>, WithExpiry<T> {

@Override
ReplaceByIdWithDurability<T> withExpiry(final Duration expiry);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,29 +26,32 @@ public interface ExecutableUpsertByIdOperation {

<T> ExecutableUpsertById<T> upsertById(Class<T> domainType);

interface TerminatingUpsertById<T> {
interface TerminatingUpsertById<T> extends OneAndAll<T>{

@Override
T one(T object);

@Override
Collection<? extends T> all(Collection<? extends T> objects);

}

interface UpsertByIdWithCollection<T> extends TerminatingUpsertById<T> {
interface UpsertByIdWithCollection<T> extends TerminatingUpsertById<T>, InCollection<T> {

TerminatingUpsertById<T> inCollection(String collection);
}

interface UpsertByIdWithDurability<T> extends UpsertByIdWithCollection<T> {
interface UpsertByIdWithDurability<T> extends UpsertByIdWithCollection<T>, WithDurability<T> {

UpsertByIdWithCollection<T> withDurability(DurabilityLevel durabilityLevel);

UpsertByIdWithCollection<T> withDurability(PersistTo persistTo, ReplicateTo replicateTo);

}

interface UpsertByIdWithExpiry<T> extends UpsertByIdWithDurability<T> {
interface UpsertByIdWithExpiry<T> extends UpsertByIdWithDurability<T>, WithExpiry<T> {

@Override
UpsertByIdWithDurability<T> withExpiry(Duration expiry);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright 2020 the original author or authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.couchbase.core;

/**
* A common interface for all of Insert, Replace, Upsert that take collection
*
* @author Michael Reiche
*
* @param <T> - the entity class
*/
public interface InCollection<T> {
Object inCollection(String collection);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mind the formatting. What's the reason for extracting all these interfaces into top-level ones? From a usage perspective, calling code would not mix replace and e.g. remove operations by reusing the same interface, would it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed the formatting in this and the other interfaces.
From a usage perspective, the interfaces are not helpful. However, from a testing perspective, they allow testing all the implementers of those interfaces more easily. For testing withExpiry(), @document( expiry), and @document(@expiryExpression) (which require three different entity classes) across insert, replace and upsert, that would take 3 X 3 = 9 test cases. By having insert, replace and upsert implement OneAndAll and WithExpiry, all these tests can be done in a loop as in withExpiryAndExpiryAnnotation()
https://github.com/spring-projects/spring-data-couchbase/blob/7815522d682fceb0f55082ff825e6dabbd8a9343/src/test/java/org/springframework/data/couchbase/core/CouchbaseTemplateKeyValueIntegrationTests.java
(I was not able to figure out how to define an interface that would be also satisfied by the one() and all() of Remove)
I did promise @daschl that I would split this into two branches - one for the interfaces followed by a second for expiry - but it's hard to explain the interfaces without showing how they would be used.

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright 2020 the original author or authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.couchbase.core;

import java.util.Collection;

/**
* A common interface for all of Insert, Replace, Upsert
*
* @author Michael Reiche
*
* @param <T> - the entity class
*/
public interface OneAndAll<T> {

T one(T object);

Collection<? extends T> all(Collection<? extends T> objects);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright 2020 the original author or authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.couchbase.core;

import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.Collection;

/**
* A common interface for all of Insert, Replace, Upsert
*
* @author Michael Reiche
*
* @param <T> - the entity class
*/

public interface OneAndAllReactive<T> {
Mono<T> one(T object);

Flux<? extends T> all(Collection<? extends T> objects);
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,28 +29,28 @@ public interface ReactiveInsertByIdOperation {

<T> ReactiveInsertById<T> insertById(Class<T> domainType);

interface TerminatingInsertById<T> {
interface TerminatingInsertById<T> extends OneAndAllReactive<T>{

Mono<T> one(T object);

Flux<? extends T> all(Collection<? extends T> objects);

}

interface InsertByIdWithCollection<T> extends TerminatingInsertById<T> {
interface InsertByIdWithCollection<T> extends TerminatingInsertById<T>, InCollection<T> {

TerminatingInsertById<T> inCollection(String collection);
}

interface InsertByIdWithDurability<T> extends InsertByIdWithCollection<T> {
interface InsertByIdWithDurability<T> extends InsertByIdWithCollection<T>, WithDurability<T> {

InsertByIdWithCollection<T> withDurability(DurabilityLevel durabilityLevel);

InsertByIdWithCollection<T> withDurability(PersistTo persistTo, ReplicateTo replicateTo);

}

interface InsertByIdWithExpiry<T> extends InsertByIdWithDurability<T> {
interface InsertByIdWithExpiry<T> extends InsertByIdWithDurability<T>, WithExpiry<T>{

InsertByIdWithDurability<T> withExpiry(Duration expiry);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
*/
package org.springframework.data.couchbase.core;

import org.springframework.data.couchbase.core.mapping.Document;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

Expand Down Expand Up @@ -72,7 +71,7 @@ public Mono<T> one(T object) {
return Mono.just(object).flatMap(o -> {
CouchbaseDocument converted = template.support().encodeEntity(o);
return template.getCollection(collection).reactive()
.insert(converted.getId(), converted.export(), buildInsertOptions()).map(result -> {
.insert(converted.getId(), converted.export(), buildInsertOptions(converted)).map(result -> {
Object updatedObject = template.support().applyUpdatedId(o, converted.getId());
return (T) template.support().applyUpdatedCas(updatedObject, result.cas());
});
Expand All @@ -90,7 +89,7 @@ public Flux<? extends T> all(Collection<? extends T> objects) {
return Flux.fromIterable(objects).flatMap(this::one);
}

private InsertOptions buildInsertOptions() {
private InsertOptions buildInsertOptions(CouchbaseDocument doc) { // CouchbaseDocument converted
final InsertOptions options = InsertOptions.insertOptions();
if (persistTo != PersistTo.NONE || replicateTo != ReplicateTo.NONE) {
options.durability(persistTo, replicateTo);
Expand All @@ -99,10 +98,8 @@ private InsertOptions buildInsertOptions() {
}
if (expiry != null && !expiry.isZero()) {
options.expiry(expiry);
} else if (domainType.isAnnotationPresent(Document.class)) {
Document documentAnn = domainType.getAnnotation(Document.class);
long durationSeconds = documentAnn.expiryUnit().toSeconds(documentAnn.expiry());
options.expiry(Duration.ofSeconds(durationSeconds));
} else if (doc.getExpiration() != 0) {
options.expiry(Duration.ofSeconds(doc.getExpiration()));
}
return options;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@ interface TerminatingRemoveById {

}

interface RemoveByIdWithCollection extends TerminatingRemoveById {
interface RemoveByIdWithCollection extends TerminatingRemoveById, InCollection {

TerminatingRemoveById inCollection(String collection);
}

interface RemoveByIdWithDurability extends RemoveByIdWithCollection {
interface RemoveByIdWithDurability extends RemoveByIdWithCollection, WithDurability {

RemoveByIdWithCollection withDurability(DurabilityLevel durabilityLevel);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,28 +29,28 @@ public interface ReactiveReplaceByIdOperation {

<T> ReactiveReplaceById<T> replaceById(Class<T> domainType);

interface TerminatingReplaceById<T> {
interface TerminatingReplaceById<T> extends OneAndAllReactive<T> {

Mono<T> one(T object);

Flux<? extends T> all(Collection<? extends T> objects);

}

interface ReplaceByIdWithCollection<T> extends TerminatingReplaceById<T> {
interface ReplaceByIdWithCollection<T> extends TerminatingReplaceById<T>, InCollection<T> {

TerminatingReplaceById<T> inCollection(String collection);
}

interface ReplaceByIdWithDurability<T> extends ReplaceByIdWithCollection<T> {
interface ReplaceByIdWithDurability<T> extends ReplaceByIdWithCollection<T>, WithDurability<T> {

ReplaceByIdWithCollection<T> withDurability(DurabilityLevel durabilityLevel);

ReplaceByIdWithCollection<T> withDurability(PersistTo persistTo, ReplicateTo replicateTo);

}

interface ReplaceByIdWithExpiry<T> extends ReplaceByIdWithDurability<T> {
interface ReplaceByIdWithExpiry<T> extends ReplaceByIdWithDurability<T>, WithExpiry<T> {

ReplaceByIdWithDurability<T> withExpiry(final Duration expiry);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import java.util.Collection;

import org.springframework.data.couchbase.core.mapping.CouchbaseDocument;
import org.springframework.data.couchbase.core.mapping.Document;
import org.springframework.util.Assert;

import com.couchbase.client.core.msg.kv.DurabilityLevel;
Expand Down Expand Up @@ -72,8 +71,8 @@ public Mono<T> one(T object) {
return Mono.just(object).flatMap(o -> {
CouchbaseDocument converted = template.support().encodeEntity(o);
return template.getCollection(collection).reactive()
.replace(converted.getId(), converted.export(), buildReplaceOptions(o)).map(result ->
(T)template.support().applyUpdatedCas(o, result.cas()));
.replace(converted.getId(), converted.export(), buildReplaceOptions(o, converted))
.map(result -> (T) template.support().applyUpdatedCas(o, result.cas()));
}).onErrorMap(throwable -> {
if (throwable instanceof RuntimeException) {
return template.potentiallyConvertRuntimeException((RuntimeException) throwable);
Expand All @@ -88,7 +87,7 @@ public Flux<? extends T> all(Collection<? extends T> objects) {
return Flux.fromIterable(objects).flatMap(this::one);
}

private ReplaceOptions buildReplaceOptions(T object) {
private ReplaceOptions buildReplaceOptions(T object, CouchbaseDocument doc) {
final ReplaceOptions options = ReplaceOptions.replaceOptions();
if (persistTo != PersistTo.NONE || replicateTo != ReplicateTo.NONE) {
options.durability(persistTo, replicateTo);
Expand All @@ -97,10 +96,8 @@ private ReplaceOptions buildReplaceOptions(T object) {
}
if (expiry != null && !expiry.isZero()) {
options.expiry(expiry);
} else if (domainType.isAnnotationPresent(Document.class)) {
Document documentAnn = domainType.getAnnotation(Document.class);
long durationSeconds = documentAnn.expiryUnit().toSeconds(documentAnn.expiry());
options.expiry(Duration.ofSeconds(durationSeconds));
} else if (doc.getExpiration() != 0) {
options.expiry(Duration.ofSeconds(doc.getExpiration()));
}
long cas = template.support().getCas(object);
options.cas(cas);
Expand Down
Loading