This is the sequence of operations I am trying to do:
WATCH somekey
MULTI
...
SET somekey somevalue
EXEC
I do this via the execute(SessionCallback)
method of RedisTemplate
(pseudocode):
l = template.execute({
ops.watch("somekey");
ops.multi()
ops.opsForValue().set("somekey", "somevalue")
return ops.exec()
})
My problem is that when using jedis, l
is not null
but an empty list, and thus exec failures are indistinguishable from exec successes as there are no operations inside multi that return results.
This seems to be confirmed by the unit tests here: https://github.com/spring-projects/spring-data-redis/blob/1.8.4.RELEASE/src/test/java/org/springframework/data/redis/core/RedisTemplateTests.java#L740 where to test failure this is done:
if (redisTemplate.getConnectionFactory() instanceof JedisConnectionFactory) {
assertThat(results, is(empty()));
} else {
assertNull(results);
}
Compare to the testUnwatch
test just below it that tests successful exec after unwatch and also expects an empty list (results.isEmpty()
).
How do I distinguish between these two cases when using Jedis?
You can't detect a transaction rollback using Jedis.
Jedis returns, in any case, a List
object in the currently available versions (2.8.2, 2.9.0). This change was part of code cleanup to prevent Jedis from returning null
on exec(…)
if the Redis transaction was rolled back.
Right now, Jedis rolled back the change but there was no Jedis release for about a year now.
If detecting transaction rollbacks are essential to your requirements, try a different Redis client.