spring-data-cassandra
spring-data-cassandra copied to clipboard
ConsistencyLevel for batchOps does not work
Hello, I noticed consistencyLevel cannot be set when using batchOps.
- spring-data-cassandra 3.2.2 and 3.3.0
- Cassandra 4.0.1 (3 nodes, replication factor:2)
For example, try executing this code that uses batchOps
.
Right after this batch process finished, run a query(ONE) to read the deleted data(*1). Even though ALL is specified in queries in batchOps, the read query sometimes returns the data that was deleted a while ago.
In a few seconds, the same read request always returns empty. It looks like "ALL" for writing doesn't work.
cassandraTemplate.batchOps()
.insert(..., InsertOptions.builder().consistencyLevel(ConsistencyLevel.ALL).build())
.delete(..., DeleteOptions.builder().consistencyLevel(ConsistencyLevel.ALL).build()) // (*1)
.insert(..., InsertOptions.builder().consistencyLevel(ConsistencyLevel.ALL).build())
.execute();
Next, I tried running this code that set ConsistencyLevel.ALL
via BatchStatementBuilder.
it worked as expected.
Queries to read the deleted data(*1) never find data even if right after this batch process finished.
var batchOperations = cassandraTemplate.batchOps();
BatchStatementBuilder batch = (BatchStatementBuilder) getField(batchOperations, "batch");
batch.setConsistencyLevel(ConsistencyLevel.ALL);
batchOperations.insert(..., InsertOptions.builder().consistencyLevel(ConsistencyLevel.ALL).build())
.delete(..., DeleteOptions.builder().consistencyLevel(ConsistencyLevel.ALL).build()) // (*1)
.insert(..., InsertOptions.builder().consistencyLevel(ConsistencyLevel.ALL).build())
.execute();
//private static Object getField(Object obj, String fieldName) {
// Field privateStringField;
// try {
// privateStringField = obj.getClass().getDeclaredField(fieldName);
// privateStringField.setAccessible(true);
// return privateStringField.get(obj);
// } catch (NoSuchFieldException | IllegalAccessException e) {
// throw new RuntimeException("Failed to getField", e);
// }
//}
However, the code above accesses the private "batch" field, so I don't think this is "legal" code.
Although StatementBuilder in DataStax Java Driver has public setConsistencyLevel
, I cannot call it via Spring Data. Is there any reason it is not exposed to Spring Data users?
Another trial is here. https://github.com/wtetsu/spring-data-cassandra/commit/d806d32e38dac71a68775dd75375d73deac8e99d
I tried to implement batchOps that can accept ConsistencyLevel. It worked as expected.
cassandraTemplate.batchOps(ConsistencyLevel.ALL)
.insert(..., InsertOptions.builder().consistencyLevel(ConsistencyLevel.ALL).build())
.delete(..., DeleteOptions.builder().consistencyLevel(ConsistencyLevel.ALL).build()) // (*1)
.insert(..., InsertOptions.builder().consistencyLevel(ConsistencyLevel.ALL).build())
.execute();
Here are my questions:
- Is there a formal way to specify consistencyLevel when using batchOps?
- If no, is it possible to expand batchOps features in order to realize it?
Thank you.
I'm not sure how much consistency levels apply to individual statements within a batch. Likely, not at all. However, we're properly propagating the consistency level into each statement. The batch statement is executed through CqlTemplate.queryForResultSet(…)
so you could hook in there to update the consistency level.
We could consider applying generally QueryOptions
to BatchStatementBuilder
for setting options on the batch itself.