-
Notifications
You must be signed in to change notification settings - Fork 190
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
Bump couchbase sdk to 3_4_3. #1663
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,8 @@ | |
*/ | ||
package org.springframework.data.couchbase.core; | ||
|
||
import com.couchbase.client.core.api.query.CoreQueryContext; | ||
import com.couchbase.client.core.io.CollectionIdentifier; | ||
import reactor.core.publisher.Flux; | ||
|
||
import java.util.Optional; | ||
|
@@ -28,7 +30,6 @@ | |
import org.springframework.data.couchbase.core.support.TemplateUtils; | ||
import org.springframework.util.Assert; | ||
|
||
import com.couchbase.client.core.deps.com.fasterxml.jackson.databind.node.ObjectNode; | ||
import com.couchbase.client.java.ReactiveScope; | ||
import com.couchbase.client.java.json.JsonObject; | ||
import com.couchbase.client.java.query.QueryOptions; | ||
|
@@ -100,11 +101,10 @@ public Flux<RemoveResult> all() { | |
} else { | ||
TransactionQueryOptions opts = OptionsBuilder | ||
.buildTransactionQueryOptions(buildQueryOptions(pArgs.getOptions())); | ||
ObjectNode convertedOptions = com.couchbase.client.java.transactions.internal.OptionsUtil | ||
.createTransactionOptions(pArgs.getScope() == null ? null : rs, statement, opts); | ||
CoreQueryContext queryContext = CollectionIdentifier.DEFAULT_SCOPE.equals(rs.name()) ? null : CoreQueryContext.of(rs.bucketName(), rs.name()); | ||
return transactionContext.get().getCore() | ||
.queryBlocking(statement, template.getBucketName(), pArgs.getScope(), convertedOptions, false) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I forgot that Spring was using these internals directly. Let's get these methods annotated with the new annotation so breakage like this doesn't happen again. |
||
.flatMapIterable(result -> result.rows).map(row -> { | ||
.queryBlocking(statement, queryContext, opts.builder().build(), false) | ||
.flatMapIterable(result -> result.collectRows()).map(row -> { | ||
JsonObject json = JsonObject.fromJson(row.data()); | ||
return new RemoveResult(json.getString(TemplateUtils.SELECT_ID), json.getLong(TemplateUtils.SELECT_CAS), | ||
Optional.empty()); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,7 @@ | |
*/ | ||
package org.springframework.data.couchbase.core.query; | ||
|
||
import static com.couchbase.client.core.util.Validators.notNull; | ||
import static org.springframework.data.couchbase.core.query.Meta.MetaKey.RETRY_STRATEGY; | ||
import static org.springframework.data.couchbase.core.query.Meta.MetaKey.SCAN_CONSISTENCY; | ||
import static org.springframework.data.couchbase.core.query.Meta.MetaKey.TIMEOUT; | ||
|
@@ -24,9 +25,13 @@ | |
import java.lang.reflect.InvocationTargetException; | ||
import java.lang.reflect.Method; | ||
import java.time.Duration; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.Optional; | ||
|
||
import com.couchbase.client.core.api.query.CoreQueryScanConsistency; | ||
import com.couchbase.client.core.classic.query.ClassicCoreQueryOps; | ||
import com.couchbase.client.core.error.InvalidArgumentException; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.springframework.core.annotation.AnnotatedElementUtils; | ||
|
@@ -67,21 +72,21 @@ public class OptionsBuilder { | |
static QueryOptions buildQueryOptions(Query query, QueryOptions options, QueryScanConsistency scanConsistency) { | ||
options = options != null ? options : QueryOptions.queryOptions(); | ||
if (query.getParameters() != null) { | ||
if (query.getParameters() instanceof JsonArray) { | ||
if (query.getParameters() instanceof JsonArray && !((JsonArray) query.getParameters()).isEmpty()) { | ||
options.parameters((JsonArray) query.getParameters()); | ||
} else { | ||
} else if( query.getParameters() instanceof JsonObject && !((JsonObject)query.getParameters()).isEmpty()){ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NIT: formatting IntelliJ tip: Command-Option-Shift-L, then select "Only changes uncommitted to VCS" There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's sorcery!! |
||
options.parameters((JsonObject) query.getParameters()); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was previously broken - it was overwriting options.parameters() with empty query.parameters() |
||
} | ||
|
||
Meta meta = query.getMeta() != null ? query.getMeta() : new Meta(); | ||
QueryOptions.Built optsBuilt = options.build(); | ||
JsonObject optsJson = getQueryOpts(optsBuilt); | ||
|
||
QueryScanConsistency metaQueryScanConsistency = meta.get(SCAN_CONSISTENCY) != null | ||
? ((ScanConsistency) meta.get(SCAN_CONSISTENCY)).query() | ||
: null; | ||
QueryScanConsistency qsc = fromFirst(QueryScanConsistency.NOT_BOUNDED, query.getScanConsistency(), | ||
getScanConsistency(optsJson), scanConsistency, metaQueryScanConsistency); | ||
scanConsistency(optsBuilt), scanConsistency, metaQueryScanConsistency); | ||
Duration timeout = fromFirst(Duration.ofSeconds(0), getTimeout(optsBuilt), meta.get(TIMEOUT)); | ||
RetryStrategy retryStrategy = fromFirst(null, getRetryStrategy(optsBuilt), meta.get(RETRY_STRATEGY)); | ||
|
||
|
@@ -100,6 +105,21 @@ static QueryOptions buildQueryOptions(Query query, QueryOptions options, QuerySc | |
return options; | ||
} | ||
|
||
private static QueryScanConsistency scanConsistency(QueryOptions.Built optsBuilt){ | ||
CoreQueryScanConsistency scanConsistency = optsBuilt.scanConsistency(); | ||
if (scanConsistency == null){ | ||
return null; | ||
} | ||
switch (scanConsistency) { | ||
case NOT_BOUNDED: | ||
return QueryScanConsistency.NOT_BOUNDED; | ||
case REQUEST_PLUS: | ||
return QueryScanConsistency.REQUEST_PLUS; | ||
default: | ||
throw new InvalidArgumentException("Unknown scan consistency type " + scanConsistency, null, null); | ||
} | ||
} | ||
|
||
public static TransactionQueryOptions buildTransactionQueryOptions(QueryOptions options) { | ||
QueryOptions.Built built = options.build(); | ||
TransactionQueryOptions txOptions = TransactionQueryOptions.queryOptions(); | ||
|
@@ -110,8 +130,21 @@ public static TransactionQueryOptions buildTransactionQueryOptions(QueryOptions | |
throw new IllegalArgumentException("QueryOptions.flexIndex is not supported in a transaction"); | ||
} | ||
|
||
Object value = optsJson.get("args"); | ||
if(value instanceof JsonObject){ | ||
txOptions.parameters((JsonObject)value); | ||
}else if(value instanceof JsonArray) { | ||
txOptions.parameters((JsonArray) value); | ||
} else if(value != null) { | ||
throw InvalidArgumentException.fromMessage( | ||
"non-null args property was neither JsonObject(namedParameters) nor JsonArray(positionalParameters) " | ||
+ value); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. else throw if not null? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good idea. |
||
|
||
for (Map.Entry<String, Object> entry : optsJson.toMap().entrySet()) { | ||
txOptions.raw(entry.getKey(), entry.getValue()); | ||
if(!entry.getKey().equals("args")) { | ||
txOptions.raw(entry.getKey(), entry.getValue()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Continue to not feel good about this approach to clone a QueryOptions into a TransactionQueryOptions... It won't handle things like the JsonSerializer, for example. |
||
} | ||
} | ||
|
||
if (LOG.isDebugEnabled()) { | ||
|
@@ -370,10 +403,8 @@ static String toString(MutateInOptions o) { | |
return s.toString(); | ||
} | ||
|
||
private static JsonObject getQueryOpts(QueryOptions.Built optsBuilt) { | ||
JsonObject jo = JsonObject.create(); | ||
optsBuilt.injectParams(jo); | ||
return jo; | ||
public static JsonObject getQueryOpts(QueryOptions.Built optsBuilt) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It doesn't feel great turning QueryOptions into JSON, and it also calls into the internal method ClassicCoreQueryOps.convertOptions, Luckily, I don't think this getQueryOpts is necessary anymore. It's called from two places:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I removed the getQueryOptions() method as it is only needed in buildTransactionQueryOptions. |
||
return JsonObject.fromJson(ClassicCoreQueryOps.convertOptions(optsBuilt).toString().getBytes()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. getBytes(StandardCharsets.UTF_8) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've removed getQueryOpts() method completely as it is only needed in one place. (to transform GetOptions into TransactionGetOptions) |
||
} | ||
|
||
/** | ||
|
@@ -396,18 +427,6 @@ public static <T> T fromFirst(T deflt, Object... choice) { | |
return chosen; | ||
} | ||
|
||
private static QueryScanConsistency getScanConsistency(JsonObject opts) { | ||
String str = opts.getString("scan_consistency"); | ||
if ("at_plus".equals(str)) { | ||
return null; | ||
} | ||
return str == null ? null : QueryScanConsistency.valueOf(str.toUpperCase()); | ||
} | ||
|
||
private static JsonObject getScanVectors(JsonObject opts) { | ||
return opts.getObject("scan_vectors"); | ||
} | ||
|
||
private static Duration getTimeout(QueryOptions.Built optsBuilt) { | ||
Optional<Duration> timeout = optsBuilt.timeout(); | ||
return timeout.isPresent() ? timeout.get() : null; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -55,7 +55,7 @@ | |
import com.couchbase.client.java.query.QueryScanConsistency; | ||
|
||
/** | ||
* KV tests Theses tests rely on a cb server running. | ||
* KV test - these tests rely on a cb server running. | ||
* | ||
* @author Michael Nitschinger | ||
* @author Michael Reiche | ||
|
@@ -81,11 +81,11 @@ public void beforeEach() { | |
@Test | ||
void findByIdWithLock() { | ||
try { | ||
User user = new User(UUID.randomUUID().toString(), "user1", "user1"); | ||
User user = new User("1", "user1", "user1"); | ||
|
||
couchbaseTemplate.upsertById(User.class).one(user); | ||
|
||
User foundUser = couchbaseTemplate.findById(User.class).withLock(Duration.ofSeconds(2)).one(user.getId()); | ||
User foundUser = couchbaseTemplate.findById(User.class).withLock(Duration.ofSeconds(5)).one(user.getId()); | ||
user.setVersion(foundUser.getVersion());// version will have changed | ||
assertEquals(user, foundUser); | ||
|
||
|
@@ -94,8 +94,15 @@ void findByIdWithLock() { | |
); | ||
assertTrue(exception.retryReasons().contains(RetryReason.KV_LOCKED), "should have been locked"); | ||
} finally { | ||
sleepSecs(2); | ||
couchbaseTemplate.removeByQuery(User.class).withConsistency(QueryScanConsistency.REQUEST_PLUS).all(); | ||
for(int i=0; i< 10; i++) { | ||
sleepSecs(2); | ||
try { | ||
couchbaseTemplate.removeByQuery(User.class).withConsistency(QueryScanConsistency.REQUEST_PLUS).all(); | ||
break; | ||
} catch (Exception e) { | ||
e.printStackTrace(); // gives IndexFailureException if the lock is still active | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this hide other exceptions that aren't expected? (Sure, it logs the stack trace, but nobody's going to look at it if the test "passes".) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
It prevents an exception in the finally() from showing instead of the actual test failure showing. |
||
} | ||
} | ||
} | ||
|
||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's always necessary to send a CoreQueryContext to satisfy The Platform That Shall Not Be Publically Named. This is what ultimately causes a query_context to be sent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Noted. I opened a separate ticket for this #1671.