Skip to content

Commit 6009a6a

Browse files
authored
feat: supports the redisTemplate component provided by spring data redis (#433)
1 parent 7831d54 commit 6009a6a

File tree

18 files changed

+610
-54
lines changed

18 files changed

+610
-54
lines changed

arex-agent/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,11 @@
106106
<artifactId>arex-redission-v3</artifactId>
107107
<version>${project.version}</version>
108108
</dependency>
109+
<dependency>
110+
<groupId>${project.groupId}</groupId>
111+
<artifactId>arex-spring-data-redis</artifactId>
112+
<version>${project.version}</version>
113+
</dependency>
109114
<dependency>
110115
<groupId>${project.groupId}</groupId>
111116
<artifactId>arex-dynamic</artifactId>

arex-instrumentation/pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
<module>redis/arex-lettuce-v5</module>
3333
<module>redis/arex-lettuce-v6</module>
3434
<module>redis/arex-redission-v3</module>
35+
<module>redis/arex-spring-data-redis</module>
3536
<module>dynamic/arex-dynamic</module>
3637
<module>dynamic/arex-dynamic-common</module>
3738
<module>dynamic/arex-cache</module>

arex-instrumentation/redis/arex-jedis-v2/src/main/java/io/arex/inst/jedis/v2/JedisWrapper.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import io.arex.agent.bootstrap.model.MockResult;
44
import io.arex.agent.bootstrap.util.ArrayUtils;
55
import io.arex.inst.runtime.context.ContextManager;
6+
import io.arex.inst.runtime.context.RepeatedCollectManager;
67
import io.arex.inst.runtime.serializer.Serializer;
78
import io.arex.inst.redis.common.RedisExtractor;
89
import io.arex.inst.redis.common.RedisKeyUtil;
@@ -546,6 +547,9 @@ private <U> U call(String command, Object key, Callable<U> callable, U defaultVa
546547
}
547548

548549
private <U> U call(String command, Object key, Object field, Callable<U> callable, U defaultValue) {
550+
if (ContextManager.needRecord()) {
551+
RepeatedCollectManager.enter();
552+
}
549553
if (ContextManager.needReplay()) {
550554
RedisExtractor extractor = new RedisExtractor(this.url, command, key, field);
551555
MockResult mockResult = extractor.replay();
@@ -561,7 +565,7 @@ private <U> U call(String command, Object key, Object field, Callable<U> callabl
561565
try {
562566
result = callable.call();
563567
} catch (Exception e) {
564-
if (ContextManager.needRecord()) {
568+
if (ContextManager.needRecord() && RepeatedCollectManager.exitAndValidate()) {
565569
RedisExtractor extractor = new RedisExtractor(this.url, command, key, field);
566570
extractor.record(e);
567571
}
@@ -573,7 +577,7 @@ private <U> U call(String command, Object key, Object field, Callable<U> callabl
573577
return defaultValue;
574578
}
575579

576-
if (ContextManager.needRecord()) {
580+
if (ContextManager.needRecord() && RepeatedCollectManager.exitAndValidate()) {
577581
RedisExtractor extractor = new RedisExtractor(this.url, command, key, field);
578582
extractor.record(result);
579583
}

arex-instrumentation/redis/arex-jedis-v4/src/main/java/io/arex/inst/jedis/v4/JedisWrapper.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import io.arex.agent.bootstrap.util.ArrayUtils;
44
import io.arex.inst.runtime.context.ContextManager;
5+
import io.arex.inst.runtime.context.RepeatedCollectManager;
56
import io.arex.inst.runtime.serializer.Serializer;
67
import io.arex.agent.bootstrap.model.MockResult;
78
import io.arex.inst.redis.common.RedisExtractor;
@@ -598,6 +599,10 @@ private <U> U call(String command, String key, Callable<U> callable, U defaultVa
598599
}
599600

600601
private <U> U call(String command, String key, String field, Callable<U> callable, U defaultValue) {
602+
if (ContextManager.needRecord()) {
603+
RepeatedCollectManager.enter();
604+
}
605+
601606
if (ContextManager.needReplay()) {
602607
RedisExtractor extractor = new RedisExtractor(this.url, command, key, field);
603608
MockResult mockResult = extractor.replay();
@@ -613,7 +618,7 @@ private <U> U call(String command, String key, String field, Callable<U> callabl
613618
try {
614619
result = callable.call();
615620
} catch (Exception e) {
616-
if (ContextManager.needRecord()) {
621+
if (ContextManager.needRecord() && RepeatedCollectManager.exitAndValidate()) {
617622
RedisExtractor extractor = new RedisExtractor(this.url, command, key, field);
618623
extractor.record(e);
619624
}
@@ -625,7 +630,7 @@ private <U> U call(String command, String key, String field, Callable<U> callabl
625630
return defaultValue;
626631
}
627632

628-
if (ContextManager.needRecord()) {
633+
if (ContextManager.needRecord() && RepeatedCollectManager.exitAndValidate()) {
629634
RedisExtractor extractor = new RedisExtractor(this.url, command, key, field);
630635
extractor.record(result);
631636
}

arex-instrumentation/redis/arex-redis-common/src/main/java/io/arex/inst/redis/common/RedisKeyUtil.java

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,12 @@
11
package io.arex.inst.redis.common;
22

3-
43
import io.arex.agent.bootstrap.util.StringUtil;
4+
import java.util.Collection;
55
import java.util.Iterator;
66
import java.util.Map;
77

88
public class RedisKeyUtil {
99

10-
public static <K> String generate(Iterable<K> keys) {
11-
StringBuilder builder = new StringBuilder();
12-
Iterator<K> iterator = keys.iterator();
13-
if (iterator.hasNext()) {
14-
builder.append(toString(iterator.next()));
15-
}
16-
while (iterator.hasNext()) {
17-
builder.append(";").append(toString(iterator.next()));
18-
}
19-
return builder.toString();
20-
}
21-
22-
public static <K, V> String generate(Map<K, V> map) {
23-
return generate(map.keySet());
24-
}
25-
2610
@SafeVarargs
2711
public static <K> String generate(K... keys) {
2812
switch (keys.length) {
@@ -51,6 +35,10 @@ private static <K> void generateMultiple(StringBuilder builder, K... keys) {
5135
}
5236

5337
private static <K> String toString(K value) {
38+
if (value == null) {
39+
return null;
40+
}
41+
5442
if (value instanceof byte[]) {
5543
return new String((byte[]) value);
5644
}
@@ -59,6 +47,34 @@ private static <K> String toString(K value) {
5947
return String.valueOf((char[]) value);
6048
}
6149

50+
if (value instanceof String) {
51+
return (String) value;
52+
}
53+
54+
if (value instanceof Collection) {
55+
return generate((Collection<?>) value);
56+
}
57+
58+
if (value instanceof Map) {
59+
return generate((Map<?, ?>) value);
60+
}
61+
6262
return String.valueOf(value);
6363
}
64+
65+
private static <K> String generate(Iterable<K> keys) {
66+
StringBuilder builder = new StringBuilder();
67+
Iterator<K> iterator = keys.iterator();
68+
if (iterator.hasNext()) {
69+
builder.append(toString(iterator.next()));
70+
}
71+
while (iterator.hasNext()) {
72+
builder.append(";").append(toString(iterator.next()));
73+
}
74+
return builder.toString();
75+
}
76+
77+
private static <K, V> String generate(Map<K, V> map) {
78+
return generate(map.keySet());
79+
}
6480
}

arex-instrumentation/redis/arex-redis-common/src/main/java/io/arex/inst/redis/common/lettuce/wrapper/RedisCommandWrapper.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import io.arex.inst.redis.common.RedisKeyUtil;
77
import io.arex.inst.redis.common.lettuce.RedisCommandBuilderImpl;
88
import io.arex.inst.runtime.context.ContextManager;
9+
import io.arex.inst.runtime.context.RepeatedCollectManager;
910
import io.lettuce.core.AbstractRedisAsyncCommands;
1011
import io.lettuce.core.GetExArgs;
1112
import io.lettuce.core.KeyValue;
@@ -704,6 +705,10 @@ public <T> RedisFuture<T> dispatch(Supplier<RedisFuture<T>> supplier, RedisComma
704705
}
705706

706707
public <T> RedisFuture<T> dispatch(Supplier<RedisFuture<T>> supplier, RedisCommand<K, V, T> cmd, String key, String redisUri, String field) {
708+
if (ContextManager.needRecord()) {
709+
RepeatedCollectManager.enter();
710+
}
711+
707712
if (ContextManager.needReplay()) {
708713
AsyncCommand<K, V, T> asyncCommand = new AsyncCommand<>(cmd);
709714
RedisExtractor extractor = new RedisExtractor(redisUri, cmd.getType().name(), key, field);
@@ -720,7 +725,7 @@ public <T> RedisFuture<T> dispatch(Supplier<RedisFuture<T>> supplier, RedisComma
720725

721726
RedisFuture<T> resultFuture = supplier.get();
722727

723-
if (ContextManager.needRecord()) {
728+
if (ContextManager.needRecord() && RepeatedCollectManager.exitAndValidate()) {
724729
try (TraceTransmitter traceTransmitter = TraceTransmitter.create()) {
725730
resultFuture.whenComplete((v, throwable) -> {
726731
RedisExtractor extractor = new RedisExtractor(redisUri, cmd.getType().name(), key, field);

arex-instrumentation/redis/arex-redis-common/src/test/java/io/arex/inst/redis/common/RedisKeyUtilTest.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
import static org.junit.jupiter.api.Assertions.*;
44

5+
import com.google.common.collect.Lists;
56
import java.util.Arrays;
67
import java.util.HashMap;
8+
import java.util.List;
79
import java.util.Map;
810
import org.junit.jupiter.api.Test;
911

@@ -57,4 +59,14 @@ void generateWithCharValue() {
5759
String result = RedisKeyUtil.generate(new char[]{'k', 'e', 'y'});
5860
assertEquals("key", result);
5961
}
62+
63+
@Test
64+
void generateWithCombinationKeys() {
65+
Map<String, String> map = new HashMap<>();
66+
map.put("key1", "value1");
67+
map.put("key2", "value2");
68+
List<String> list = Lists.newArrayList("key4", "key5");
69+
String result = RedisKeyUtil.generate(map, "key3", list, map);
70+
assertEquals("key1;key2;key3;key4;key5;key1;key2", result);
71+
}
6072
}

arex-instrumentation/redis/arex-redission-v3/src/main/java/io/arex/inst/redisson/v3/RedissonWrapperCommon.java

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,24 @@
55
import io.arex.inst.redisson.v3.common.RFutureWrapper;
66
import io.arex.inst.runtime.context.ContextManager;
77
import io.arex.inst.redis.common.RedisExtractor;
8+
import io.arex.inst.runtime.context.RepeatedCollectManager;
9+
import java.util.function.Supplier;
810
import org.redisson.api.RFuture;
911

10-
import java.util.concurrent.Callable;
11-
1212
/**
1313
* RedissonWrapperCommon
1414
*/
1515
public class RedissonWrapperCommon {
1616
public static <R> RFuture<R> delegateCall(String redisUri, String cmd, String key,
17-
Callable<RFuture<R>> resultFuture) {
18-
return delegateCall(redisUri, cmd, key, null, resultFuture);
17+
Supplier<RFuture<R>> futureSupplier) {
18+
return delegateCall(redisUri, cmd, key, null, futureSupplier);
1919
}
2020

2121
public static <R> RFuture<R> delegateCall(String redisUri, String cmd, String key, String field,
22-
Callable<RFuture<R>> futureCallable) {
22+
Supplier<RFuture<R>> futureSupplier) {
23+
if (ContextManager.needRecord()) {
24+
RepeatedCollectManager.enter();
25+
}
2326
if (ContextManager.needReplay()) {
2427
RedisExtractor extractor = new RedisExtractor(redisUri, cmd, key, field);
2528
MockResult mockResult = extractor.replay();
@@ -31,20 +34,9 @@ public static <R> RFuture<R> delegateCall(String redisUri, String cmd, String ke
3134
}
3235
}
3336

34-
RFuture<R> resultFuture = null;
35-
try {
36-
resultFuture = futureCallable.call();
37-
} catch (Exception e) {
38-
// The following codes may not execute, just catch checked exception
39-
if (ContextManager.needRecord()) {
40-
RedisExtractor extractor = new RedisExtractor(redisUri, cmd, key, field);
41-
extractor.record(e);
42-
}
43-
44-
return resultFuture;
45-
}
37+
RFuture<R> resultFuture = futureSupplier.get();
4638

47-
if (resultFuture != null && ContextManager.needRecord()) {
39+
if (resultFuture != null && ContextManager.needRecord() && RepeatedCollectManager.exitAndValidate()) {
4840
try (TraceTransmitter traceTransmitter = TraceTransmitter.create()) {
4941
resultFuture.whenComplete((v, throwable) -> {
5042
traceTransmitter.transmit();

arex-instrumentation/redis/arex-redission-v3/src/test/java/io/arex/inst/redisson/v3/RedissonWrapperCommonTest.java

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import io.arex.inst.runtime.context.ContextManager;
44
import io.arex.agent.bootstrap.model.MockResult;
55
import io.arex.inst.redis.common.RedisExtractor;
6+
import java.util.function.Supplier;
67
import org.junit.jupiter.api.AfterAll;
78
import org.junit.jupiter.api.BeforeAll;
89
import org.junit.jupiter.api.extension.ExtendWith;
@@ -16,7 +17,6 @@
1617
import org.redisson.misc.CompletableFutureWrapper;
1718

1819
import java.util.Objects;
19-
import java.util.concurrent.Callable;
2020
import java.util.function.Predicate;
2121
import java.util.stream.Stream;
2222

@@ -38,28 +38,28 @@ static void tearDown() {
3838

3939
@ParameterizedTest
4040
@MethodSource("delegateCallCase")
41-
void delegateCall(Runnable mocker, Callable<RFuture<String>> futureCallable, Predicate<RFuture> predicate) {
41+
void delegateCall(Runnable mocker, Supplier<RFuture<String>> futureSupplier, Predicate<RFuture> predicate) {
4242
try(MockedConstruction<RedisExtractor> extractor = Mockito.mockConstruction(RedisExtractor.class, (mock, context) -> {
4343
Mockito.when(mock.replay()).thenReturn(MockResult.success(true,"mock"));
4444
})) {
4545
mocker.run();
46-
RFuture result = RedissonWrapperCommon.delegateCall("", "", "", futureCallable);
46+
RFuture result = RedissonWrapperCommon.delegateCall("", "", "", futureSupplier);
4747
assertTrue(predicate.test(result));
4848
}
4949

5050
try(MockedConstruction<RedisExtractor> extractor = Mockito.mockConstruction(RedisExtractor.class, (mock, context) -> {
5151
Mockito.when(mock.replay()).thenReturn(MockResult.success(false,"mock"));
5252
})) {
5353
mocker.run();
54-
RFuture result = RedissonWrapperCommon.delegateCall("", "", "", futureCallable);
54+
RFuture result = RedissonWrapperCommon.delegateCall("", "", "", futureSupplier);
5555
assertTrue(predicate.test(result));
5656
}
5757

5858
try(MockedConstruction<RedisExtractor> extractor = Mockito.mockConstruction(RedisExtractor.class, (mock, context) -> {
5959
Mockito.when(mock.replay()).thenReturn(MockResult.success(new Throwable()));
6060
})) {
6161
mocker.run();
62-
RFuture result = RedissonWrapperCommon.delegateCall("", "", "", futureCallable);
62+
RFuture result = RedissonWrapperCommon.delegateCall("", "", "", futureSupplier);
6363
assertTrue(predicate.test(result));
6464
}
6565
}
@@ -72,16 +72,13 @@ static Stream<Arguments> delegateCallCase() {
7272
Mockito.when(ContextManager.needReplay()).thenReturn(false);
7373
Mockito.when(ContextManager.needRecord()).thenReturn(true);
7474
};
75-
Callable<RFuture<String>> futureCallable = () -> new CompletableFutureWrapper<>("mock");
76-
Callable<RFuture<String>> futureCallable1 = () -> new CompletableFutureWrapper<>(new NullPointerException());
77-
Callable futureCallable2 = NullPointerException::new;
78-
Predicate<RFuture> predicate1 = Objects::isNull;
75+
Supplier<RFuture<String>> futureSupplier = () -> new CompletableFutureWrapper<>("mock");
76+
Supplier<RFuture<String>> futureSupplier1 = () -> new CompletableFutureWrapper<>(new NullPointerException());
7977
Predicate<RFuture> predicate2 = Objects::nonNull;
8078
return Stream.of(
81-
arguments(mocker1, futureCallable, predicate2),
82-
arguments(mocker2, futureCallable, predicate2),
83-
arguments(mocker2, futureCallable1, predicate2),
84-
arguments(mocker2, futureCallable2, predicate1)
79+
arguments(mocker1, futureSupplier, predicate2),
80+
arguments(mocker2, futureSupplier, predicate2),
81+
arguments(mocker2, futureSupplier1, predicate2)
8582
);
8683
}
87-
}
84+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<parent>
6+
<artifactId>arex-instrumentation-parent</artifactId>
7+
<groupId>io.arex</groupId>
8+
<version>${revision}</version>
9+
<relativePath>../../pom.xml</relativePath>
10+
</parent>
11+
<modelVersion>4.0.0</modelVersion>
12+
13+
<artifactId>arex-spring-data-redis</artifactId>
14+
15+
<dependencies>
16+
<dependency>
17+
<groupId>io.arex</groupId>
18+
<artifactId>arex-redis-common</artifactId>
19+
<version>${project.version}</version>
20+
<scope>compile</scope>
21+
</dependency>
22+
<dependency>
23+
<groupId>org.springframework.data</groupId>
24+
<artifactId>spring-data-redis</artifactId>
25+
<version>2.2.4.RELEASE</version>
26+
<scope>provided</scope>
27+
</dependency>
28+
</dependencies>
29+
</project>

0 commit comments

Comments
 (0)