+ add atomic key/check/rename to abstract redis collection (sort of messy)

This commit is contained in:
Costin Leau
2011-03-15 23:43:02 +02:00
parent 0523430a45
commit 3d4d30e216
3 changed files with 71 additions and 28 deletions

View File

@@ -18,9 +18,12 @@ package org.springframework.data.keyvalue.redis.support.collections;
import java.util.AbstractCollection;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.springframework.dao.DataAccessException;
import org.springframework.data.keyvalue.redis.core.RedisOperations;
import org.springframework.data.keyvalue.redis.core.SessionCallback;
/**
* Base implementation for {@link RedisCollection}.
@@ -140,14 +143,57 @@ public abstract class AbstractRedisCollection<E> extends AbstractCollection<E> i
}
@Override
public void rename(String newKey) {
operations.rename(key, newKey);
public void rename(final String newKey) {
operations.execute(new SessionCallback<Object>() {
@SuppressWarnings("unchecked")
@Override
public Object execute(RedisOperations operations) throws DataAccessException {
do {
operations.watch(key);
if (operations.hasKey(key)) {
operations.multi();
operations.rename(key, newKey);
}
else {
operations.multi();
}
} while (operations.exec() == null);
return null;
}
});
key = newKey;
}
@Override
public Boolean renameIfAbsent(String newKey) {
Boolean result = operations.renameIfAbsent(key, newKey);
public Boolean renameIfAbsent(final String newKey) {
Boolean result = operations.execute(new SessionCallback<Boolean>() {
@Override
public Boolean execute(RedisOperations operations) throws DataAccessException {
List<Object> exec = null;
do {
operations.watch(key);
if (operations.hasKey(key)) {
operations.multi();
operations.renameIfAbsent(key, newKey);
}
else {
operations.watch(newKey);
operations.multi();
operations.hasKey(newKey);
operations.hasKey(newKey);
}
exec = operations.exec();
} while (exec == null);
boolean result = ((Long) exec.get(0) == 1);
if (exec.size()>1) {
result = !result;
}
return result;
}
});
if (Boolean.TRUE.equals(result)) {
key = newKey;

View File

@@ -27,9 +27,8 @@ import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.springframework.data.keyvalue.redis.ConnectionFactoryTracker;
import org.springframework.data.keyvalue.redis.connection.RedisConnection;
import org.springframework.data.keyvalue.redis.connection.RedisConnectionFactory;
import org.springframework.data.keyvalue.redis.core.BoundKeyOperations;
import org.springframework.data.keyvalue.redis.core.RedisTemplate;
import org.springframework.data.keyvalue.redis.support.collections.ObjectFactory;
/**
@@ -37,22 +36,20 @@ import org.springframework.data.keyvalue.redis.support.collections.ObjectFactory
*/
@RunWith(Parameterized.class)
public class BoundKeyOperationsTest {
private RedisConnectionFactory factory;
private BoundKeyOperations<Object> keyOps;
private ObjectFactory<Object> objFactory;
private RedisTemplate template;
public BoundKeyOperationsTest(BoundKeyOperations<Object> keyOps, ObjectFactory<Object> objFactory,
RedisConnectionFactory factory) {
this.factory = factory;
RedisTemplate template) {
this.objFactory = objFactory;
this.keyOps = keyOps;
ConnectionFactoryTracker.add(factory);
this.template = template;
ConnectionFactoryTracker.add(template.getConnectionFactory());
}
@After
public void stop() {
RedisConnection connection = factory.getConnection();
connection.close();
}
@AfterClass
@@ -81,7 +78,8 @@ public class BoundKeyOperationsTest {
Object key = keyOps.getKey();
assertNotNull(key);
Object newName = objFactory.instance();
keyOps.renameIfAbsent(newName);
assertFalse(template.hasKey(newName));
assertTrue("cannot rename to key " + newName, keyOps.renameIfAbsent(newName));
assertEquals(newName, keyOps.getKey());
keyOps.rename(key);
}
@@ -89,17 +87,20 @@ public class BoundKeyOperationsTest {
@Test
public void testExpire() throws Exception {
assertEquals(Long.valueOf(-1), keyOps.getExpire());
assertTrue(keyOps.expire(10, TimeUnit.SECONDS));
long expire = keyOps.getExpire().longValue();
assertTrue(expire <= 10 && expire > 5);
if (keyOps.expire(10, TimeUnit.SECONDS)) {
long expire = keyOps.getExpire().longValue();
assertTrue(expire <= 10 && expire > 5);
}
}
@Test
public void testPersist() throws Exception {
assertEquals(Long.valueOf(-1), keyOps.getExpire());
assertTrue(keyOps.expire(10, TimeUnit.SECONDS));
assertTrue(keyOps.getExpire().longValue() > 0);
keyOps.persist();
assertTrue(keyOps.getExpire().longValue() > 0);
assertEquals(Long.valueOf(-1), keyOps.getExpire());
if (keyOps.expire(10, TimeUnit.SECONDS)) {
assertTrue(keyOps.getExpire().longValue() > 0);
}
keyOps.persist();
assertEquals(-1, keyOps.getExpire().longValue());
}
}

View File

@@ -55,18 +55,14 @@ public class BoundKeyParams {
StringObjectFactory sof = new StringObjectFactory();
DefaultRedisMap mapJS = new DefaultRedisMap("bound:key:map", templateJS);
mapJS.put("foo", "bar");
DefaultRedisSet setJS = new DefaultRedisSet("bound:key:set", templateJS);
setJS.add("foo");
RedisList list = new DefaultRedisList("bound:key:list", templateJS);
list.add("foo");
return Arrays.asList(new Object[][] {
{ new RedisAtomicInteger("bound:key:int", jedisConnFactory), sof, jedisConnFactory },
{ new RedisAtomicLong("bound:key:long", jedisConnFactory), sof, jedisConnFactory },
{ list, sof, jedisConnFactory },
{ setJS, sof, jedisConnFactory }, { mapJS, sof, jedisConnFactory } });
{ new RedisAtomicInteger("bound:key:int", jedisConnFactory), sof, templateJS },
{ new RedisAtomicLong("bound:key:long", jedisConnFactory), sof, templateJS },
{ list, sof, templateJS }, { setJS, sof, templateJS }, { mapJS, sof, templateJS } });
}
}