Fixed - collection fields aren't deleted when RLiveObject expires or is deleted. #5103

pull/5139/head
Nikita Koksharov 2 years ago
parent 329de345f1
commit e0a510bf26

@ -33,6 +33,7 @@ import org.redisson.api.annotation.*;
import org.redisson.api.condition.Condition; import org.redisson.api.condition.Condition;
import org.redisson.client.codec.StringCodec; import org.redisson.client.codec.StringCodec;
import org.redisson.client.protocol.RedisCommand; import org.redisson.client.protocol.RedisCommand;
import org.redisson.client.protocol.RedisCommands;
import org.redisson.client.protocol.convertor.Convertor; import org.redisson.client.protocol.convertor.Convertor;
import org.redisson.client.protocol.decoder.ListMultiDecoder2; import org.redisson.client.protocol.decoder.ListMultiDecoder2;
import org.redisson.client.protocol.decoder.ListScanResult; import org.redisson.client.protocol.decoder.ListScanResult;
@ -65,7 +66,6 @@ public class RedissonLiveObjectService implements RLiveObjectService {
private final ConcurrentMap<Class<?>, Class<?>> classCache; private final ConcurrentMap<Class<?>, Class<?>> classCache;
private final CommandAsyncExecutor commandExecutor; private final CommandAsyncExecutor commandExecutor;
private final LiveObjectSearch seachEngine; private final LiveObjectSearch seachEngine;
private static final AtomicBoolean LISTENER_LATCH = new AtomicBoolean();
public RedissonLiveObjectService(ConcurrentMap<Class<?>, Class<?>> classCache, public RedissonLiveObjectService(ConcurrentMap<Class<?>, Class<?>> classCache,
CommandAsyncExecutor commandExecutor) { CommandAsyncExecutor commandExecutor) {
@ -73,7 +73,7 @@ public class RedissonLiveObjectService implements RLiveObjectService {
this.commandExecutor = commandExecutor; this.commandExecutor = commandExecutor;
this.seachEngine = new LiveObjectSearch(commandExecutor); this.seachEngine = new LiveObjectSearch(commandExecutor);
if (LISTENER_LATCH.compareAndSet(false, true)) { if (commandExecutor.getServiceManager().getLiveObjectLatch().compareAndSet(false, true)) {
RPatternTopic topic = new RedissonPatternTopic(StringCodec.INSTANCE, commandExecutor, "__keyevent@*:expired"); RPatternTopic topic = new RedissonPatternTopic(StringCodec.INSTANCE, commandExecutor, "__keyevent@*:expired");
topic.addListenerAsync(String.class, (pattern, channel, msg) -> { topic.addListenerAsync(String.class, (pattern, channel, msg) -> {
if (msg.contains("redisson_live_object:")) { if (msg.contains("redisson_live_object:")) {
@ -617,6 +617,8 @@ public class RedissonLiveObjectService implements RLiveObjectService {
String mapName = namingScheme.getName(entityClass, id); String mapName = namingScheme.getName(entityClass, id);
Object liveObjectId = namingScheme.resolveId(mapName); Object liveObjectId = namingScheme.resolveId(mapName);
deleteCollections(id, entityClass, ce);
RMap<String, Object> liveMap = new RedissonMap<>(namingScheme.getCodec(), commandExecutor, RMap<String, Object> liveMap = new RedissonMap<>(namingScheme.getCodec(), commandExecutor,
mapName, null, null, null); mapName, null, null, null);
Map<String, ?> values = liveMap.getAll(fieldNames); Map<String, ?> values = liveMap.getAll(fieldNames);
@ -642,6 +644,8 @@ public class RedissonLiveObjectService implements RLiveObjectService {
CommandBatchService ce = new CommandBatchService(commandExecutor); CommandBatchService ce = new CommandBatchService(commandExecutor);
FieldList<InDefinedShape> fields = Introspectior.getFieldsWithAnnotation(entityClass, RIndex.class); FieldList<InDefinedShape> fields = Introspectior.getFieldsWithAnnotation(entityClass, RIndex.class);
deleteCollections(id, entityClass, ce);
NamingScheme namingScheme = commandExecutor.getObjectBuilder().getNamingScheme(entityClass); NamingScheme namingScheme = commandExecutor.getObjectBuilder().getNamingScheme(entityClass);
String mapName = namingScheme.getName(entityClass, id); String mapName = namingScheme.getName(entityClass, id);
Object liveObjectId = namingScheme.resolveId(mapName); Object liveObjectId = namingScheme.resolveId(mapName);
@ -661,6 +665,21 @@ public class RedissonLiveObjectService implements RLiveObjectService {
ce.execute(); ce.execute();
} }
private void deleteCollections(Object id, Class<?> entityClass, CommandBatchService ce) {
for (InDefinedShape field : Introspectior.getAllFields(entityClass)) {
try {
Field f = ClassUtils.getDeclaredField(entityClass, field.getName());
RObject rObject = commandExecutor.getObjectBuilder().createObject(id, entityClass, f.getType(), field.getName());
if (rObject != null) {
RedissonObject ro = (RedissonObject) rObject;
ce.writeAsync(ro.getRawName(), RedisCommands.DEL, ro.getRawName());
}
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
}
}
}
public RFuture<Long> delete(Object id, Class<?> entityClass, NamingScheme namingScheme, CommandBatchService ce) { public RFuture<Long> delete(Object id, Class<?> entityClass, NamingScheme namingScheme, CommandBatchService ce) {
FieldList<InDefinedShape> fields = Introspectior.getFieldsWithAnnotation(entityClass, RIndex.class); FieldList<InDefinedShape> fields = Introspectior.getFieldsWithAnnotation(entityClass, RIndex.class);
Set<String> fieldNames = fields.stream().map(f -> f.getName()).collect(Collectors.toSet()); Set<String> fieldNames = fields.stream().map(f -> f.getName()).collect(Collectors.toSet());

@ -58,6 +58,7 @@ import java.net.UnknownHostException;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.util.*; import java.util.*;
import java.util.concurrent.*; import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier; import java.util.function.Supplier;
@ -432,4 +433,9 @@ public class ServiceManager {
return id; return id;
} }
private final AtomicBoolean liveObjectLatch = new AtomicBoolean();
public AtomicBoolean getLiveObjectLatch() {
return liveObjectLatch;
}
} }

@ -328,6 +328,8 @@ public class RedissonLiveObjectServiceTest extends BaseTest {
@RIndex @RIndex
private int num2; private int num2;
private List<Long> coll;
protected TestIndexed() { protected TestIndexed() {
} }
@ -340,6 +342,14 @@ public class RedissonLiveObjectServiceTest extends BaseTest {
return id; return id;
} }
public List<Long> getColl() {
return coll;
}
public void setColl(List<Long> coll) {
this.coll = coll;
}
public Boolean getBool1() { public Boolean getBool1() {
return bool1; return bool1;
} }
@ -1716,11 +1726,11 @@ public class RedissonLiveObjectServiceTest extends BaseTest {
myObject = service.persist(myObject); myObject = service.persist(myObject);
myObject.setName1("123345"); myObject.setName1("123345");
myObject.setNum1(455); myObject.setNum1(455);
assertThat(redisson.getKeys().count()).isEqualTo(5); myObject.setColl(Arrays.asList(1L, 2L));
assertThat(redisson.getKeys().count()).isEqualTo(6);
assertTrue(service.asLiveObject(myObject).isExists()); assertTrue(service.asLiveObject(myObject).isExists());
service.asRMap(myObject).expire(Duration.ofSeconds(1)); service.asRMap(myObject).expire(Duration.ofSeconds(1));
Thread.sleep(2000); Thread.sleep(2000);
assertFalse(service.asLiveObject(myObject).isExists());
assertThat(redisson.getKeys().count()).isZero(); assertThat(redisson.getKeys().count()).isZero();
redisson.shutdown(); redisson.shutdown();

Loading…
Cancel
Save