Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
afec947
build: add jandex dependency
liqi19950722 Mar 17, 2024
8fec691
feat: get method info from RedisCommand class
liqi19950722 Mar 17, 2024
3222193
build(redis-spring-test): add mockito in test
liqi19950722 Mar 17, 2024
ca4a1f8
feat: MethodInfoList to MethodHandleMap
liqi19950722 Mar 17, 2024
85d3256
feat: change generateMethodHandle method Signature
liqi19950722 Mar 17, 2024
fd6d8d7
feat: implement findMethodHande
liqi19950722 Mar 17, 2024
16b7b28
build: add jupiter
liqi19950722 Mar 17, 2024
6ce07bb
feat: getClassBy Method
liqi19950722 Mar 17, 2024
07c3f4c
feat: complete getClassBy Method
liqi19950722 Mar 17, 2024
16ad659
doc: modify comment
liqi19950722 Mar 17, 2024
52891e5
feat: complete getClassBy Method
liqi19950722 Mar 17, 2024
76929c7
feat: complete findMethodHandle
liqi19950722 Mar 17, 2024
89b81ed
refactor: simplify the code
liqi19950722 Mar 17, 2024
c8fa4e0
feat: find MethodHandle From Map
liqi19950722 Mar 17, 2024
b9ad5bf
build: add testcontainers Dependency
liqi19950722 Mar 17, 2024
1f940ee
feat: exception message show methodSignature
liqi19950722 Mar 17, 2024
ec8205b
build: transfer jandex to dependent model
liqi19950722 Mar 17, 2024
563db9b
test: write event handle test case
liqi19950722 Mar 17, 2024
f4ed19c
refactor: extract event handle interface
liqi19950722 Mar 17, 2024
4b0db5e
feat: transferMethodToMethodSignature
liqi19950722 Mar 17, 2024
f24a3a0
test: MethodHandleRedisCommandReplicatedEventHandler
liqi19950722 Mar 17, 2024
431b3ff
feat: implement transferMethodToMethodSignature
liqi19950722 Mar 24, 2024
d5a67e7
test: remove mock
liqi19950722 Mar 24, 2024
757f24b
refactor: refactor RedisCommandsMethodHandles
liqi19950722 Mar 24, 2024
29762dc
refactor: reimport HandleRedisCommandReplicatedEventTest
liqi19950722 Mar 24, 2024
c08af07
build: jandex
liqi19950722 Mar 24, 2024
34f05b4
test: remove unnecessary
liqi19950722 Mar 24, 2024
3719ab4
refactor: writeCommandMethodHandlesCache
liqi19950722 Mar 25, 2024
9da4aef
test: test RedisCommandReplicatedEventHandler
liqi19950722 Mar 25, 2024
2457897
Merge branch 'main' into RedisCommandReplicatedEvent-MethodHandleInvoke
liqi19950722 Mar 28, 2024
d99bdc9
build: remove unnecessary
liqi19950722 Mar 29, 2024
c5b5682
Merge branch 'dev-pr' into RedisCommandReplicatedEvent-MethodHandleIn…
liqi19950722 Nov 26, 2025
97fcf62
build: build project
liqi19950722 Nov 26, 2025
16074b2
test: benchmark RedisCommandReplicatedEventHandler
liqi19950722 Nov 26, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion microsphere-redis-parent/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@
<description>Microsphere Redis Parent</description>

<properties>
<microsphere-spring-cloud.version>${revision}</microsphere-spring-cloud.version>
<microsphere-spring-cloud.version>0.0.1</microsphere-spring-cloud.version>
<jandex.version>3.1.7</jandex.version>
<testcontainers.version>1.19.5</testcontainers.version>
<jmh.version>1.37</jmh.version>
</properties>

<dependencyManagement>
Expand All @@ -34,6 +37,31 @@
<scope>import</scope>
</dependency>

<!-- jandex Dependencies -->
<dependency>
<groupId>io.smallrye</groupId>
<artifactId>jandex</artifactId>
<version>${jandex.version}</version>
</dependency>

<!-- testcontainers Dependencies -->
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers-bom</artifactId>
<version>${testcontainers.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>${jmh.version}</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>${jmh.version}</version>
</dependency>
</dependencies>
</dependencyManagement>

Expand Down
57 changes: 54 additions & 3 deletions microsphere-redis-replicator-spring/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
<dependency>
<groupId>io.github.microsphere-projects</groupId>
<artifactId>microsphere-spring-context</artifactId>
<version>${revision}</version>
<version>0.0.1</version>
</dependency>

<!-- Microsphere Spring Redis -->
Expand Down Expand Up @@ -76,7 +76,7 @@
<dependency>
<groupId>io.github.microsphere-projects</groupId>
<artifactId>microsphere-spring-test</artifactId>
<version>${revision}</version>
<version>0.0.1</version>
<scope>test</scope>
</dependency>

Expand All @@ -92,6 +92,57 @@
<scope>test</scope>
</dependency>

</dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<finalName>benchmarks</finalName>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>org.openjdk.jmh.Main</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
package io.microsphere.redis.replicator.spring;

import io.microsphere.redis.spring.event.RedisCommandEvent;
import io.microsphere.redis.replicator.spring.event.RedisCommandReplicatedEvent;
import io.microsphere.redis.replicator.spring.event.handler.RedisCommandReplicatedEventHandler;
import io.microsphere.redis.spring.event.RedisCommandEvent;
import io.microsphere.spring.util.SpringFactoriesLoaderUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationListener;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Method;
import java.util.function.Function;

import static io.microsphere.redis.replicator.spring.config.RedisReplicatorConfiguration.CONSUMER_EVENT_HANDLE_PROPERTY_NAME;
import static io.microsphere.redis.replicator.spring.event.handler.RedisCommandReplicatedEventHandler.EventHandleName.REFLECT;
import static io.microsphere.redis.spring.beans.Wrapper.tryUnwrap;
import static io.microsphere.redis.spring.metadata.RedisMetadataRepository.findWriteCommandMethod;
import static io.microsphere.redis.spring.metadata.RedisMetadataRepository.getRedisCommandBindingFunction;
Expand All @@ -23,7 +29,8 @@
* @author <a href="mailto:mercyblitz@gmail.com">Mercy<a/>
* @since 1.0.0
*/
public class RedisCommandReplicator implements ApplicationListener<RedisCommandReplicatedEvent> {
public class RedisCommandReplicator implements ApplicationListener<RedisCommandReplicatedEvent>,
ApplicationContextAware {

private static final Logger logger = LoggerFactory.getLogger(RedisCommandReplicator.class);

Expand All @@ -35,6 +42,7 @@
this.redisConnectionFactory = tryUnwrap(redisConnectionFactory, RedisConnectionFactory.class);
}


@Override
public void onApplicationEvent(RedisCommandReplicatedEvent event) {
try {
Expand All @@ -53,12 +61,26 @@
Object[] args = redisCommandEvent.getArgs();
Function<RedisConnection, Object> bindingFunction = getRedisCommandBindingFunction(interfaceNme);
Object redisCommandObject = bindingFunction.apply(redisConnection);
// TODO: Native method implementation
ReflectionUtils.invokeMethod(method, redisCommandObject, args);
// Native method implementation
// ReflectionUtils.invokeMethod(method, redisCommandObject, args);

Check warning on line 65 in microsphere-redis-replicator-spring/src/main/java/io/microsphere/redis/replicator/spring/RedisCommandReplicator.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

This block of commented-out lines of code should be removed.

See more on https://sonarcloud.io/project/issues?id=microsphere-projects_microsphere-redis&issues=AZZwwdG2SVP_ekrR4c_A&open=AZZwwdG2SVP_ekrR4c_A&pullRequest=3
eventHandler.handleEvent(method, redisCommandObject, args);
}
}

private RedisConnection getRedisConnection() {
return redisConnectionFactory.getConnection();
}

RedisCommandReplicatedEventHandler eventHandler;

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
String eventHandleType = applicationContext.getEnvironment()
.getProperty(CONSUMER_EVENT_HANDLE_PROPERTY_NAME, String.class, REFLECT.name());
eventHandler = SpringFactoriesLoaderUtils.loadFactories(applicationContext, RedisCommandReplicatedEventHandler.class)
.stream()
.filter(eventHandle -> eventHandle.name().equals(eventHandleType))
.findFirst()
.orElseThrow(() -> new IllegalStateException("No eventHandle found"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,11 @@ public class RedisReplicatorConfiguration implements ApplicationListener<RedisCo

public static final String CONSUMER_ENABLED_PROPERTY_NAME = CONSUMER_PROPERTY_NAME_PREFIX + "enabled";

public static final String CONSUMER_EVENT_HANDLE_PROPERTY_NAME = CONSUMER_PROPERTY_NAME_PREFIX + "event.handler";

public static final boolean DEFAULT_ENABLED = true;

public static final boolean DEFAULT_CONSUMER_ENABLED = Boolean.getBoolean(CONSUMER_ENABLED_PROPERTY_NAME);

/**
* Business Domains
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package io.microsphere.redis.replicator.spring.event.handler;

import java.lang.reflect.Method;

import static io.microsphere.redis.spring.metadata.RedisMetadataRepository.getWriteCommandMethodHandle;

public class MethodHandleRedisCommandReplicatedEventHandler implements RedisCommandReplicatedEventHandler {

@Override
public void handleEvent(Method method, Object redisCommandObject, Object... args) throws Throwable {
int length = args.length;
Object[] arguments = new Object[1 + args.length];
arguments[0] = redisCommandObject;
System.arraycopy(args, 0, arguments, 1, length);
getWriteCommandMethodHandle(method).invokeWithArguments(arguments);
}

@Override
public String name() {
return EventHandleName.METHOD_HANDLE.name();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package io.microsphere.redis.replicator.spring.event.handler;

import java.lang.reflect.Method;

public interface RedisCommandReplicatedEventHandler {
void handleEvent(Method method, Object redisCommandObject, Object... args) throws Throwable;

Check warning on line 6 in microsphere-redis-replicator-spring/src/main/java/io/microsphere/redis/replicator/spring/event/handler/RedisCommandReplicatedEventHandler.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace generic exceptions with specific library exceptions or a custom exception.

See more on https://sonarcloud.io/project/issues?id=microsphere-projects_microsphere-redis&issues=AZZwwdGoSVP_ekrR4c-_&open=AZZwwdGoSVP_ekrR4c-_&pullRequest=3

String name();

enum EventHandleName{
REFLECT,
METHOD_HANDLE;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package io.microsphere.redis.replicator.spring.event.handler;

import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Method;

import static io.microsphere.redis.replicator.spring.event.handler.RedisCommandReplicatedEventHandler.EventHandleName.REFLECT;

public class ReflectRedisCommandReplicatedEventHandler implements RedisCommandReplicatedEventHandler {

@Override
public void handleEvent(Method method, Object redisCommandObject, Object... args) throws Throwable {

ReflectionUtils.invokeMethod(method, redisCommandObject, args);
}

@Override
public String name() {
return REFLECT.name();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,8 @@ io.microsphere.redis.spring.context.RedisModuleInitializer=\
io.microsphere.redis.replicator.spring.RedisReplicatorInitializer

io.microsphere.redis.replicator.spring.RedisReplicatorModuleInitializer=\
io.microsphere.redis.replicator.spring.kafka.KafkaRedisReplicatorModuleInitializer
io.microsphere.redis.replicator.spring.kafka.KafkaRedisReplicatorModuleInitializer

io.microsphere.redis.replicator.spring.event.handler.RedisCommandReplicatedEventHandler=\
io.microsphere.redis.replicator.spring.event.handler.ReflectRedisCommandReplicatedEventHandler,\
io.microsphere.redis.replicator.spring.event.handler.MethodHandleRedisCommandReplicatedEventHandler
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package io.microsphere.redis.benchmark;

import io.microsphere.redis.replicator.spring.event.handler.MethodHandleRedisCommandReplicatedEventHandler;
import io.microsphere.redis.replicator.spring.event.handler.RedisCommandReplicatedEventHandler;
import io.microsphere.redis.replicator.spring.event.handler.ReflectRedisCommandReplicatedEventHandler;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Level;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;
import org.openjdk.jmh.annotations.Warmup;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.RedisStringCommands;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.testcontainers.containers.GenericContainer;

import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;

import static io.microsphere.redis.spring.metadata.RedisMetadataRepository.findWriteCommandMethod;
import static org.testcontainers.utility.DockerImageName.parse;

@State(Scope.Thread)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 5, time = 1)
@Measurement(iterations = 20, time = 1)
@Fork(3)
public class RedisCommandReplicatedEventHandlerBenchmark {
static GenericContainer<?> redisContainer;
RedisStringCommands redisStringCommands;
Method method;
RedisCommandReplicatedEventHandler methodHandleHandler;
RedisCommandReplicatedEventHandler reflectHandler;

byte[] key;
byte[] value;

@Setup(Level.Trial)
public void setup() throws Exception {
// 启动 PostgreSQL 容器
redisContainer = new GenericContainer<>(parse("redis:latest")).withExposedPorts(6379);
redisContainer.start();

String interfaceName = "org.springframework.data.redis.connection.RedisStringCommands";
String methodName = "set";
String[] parameterTypes = new String[]{"[B", "[B"};
method = findWriteCommandMethod(interfaceName, methodName, parameterTypes);

LettuceConnectionFactory redisConnectionFactory = new LettuceConnectionFactory(new RedisStandaloneConfiguration(redisContainer.getHost(), redisContainer.getFirstMappedPort()));
redisConnectionFactory.afterPropertiesSet();
RedisConnection connection = redisConnectionFactory.getConnection();
redisStringCommands = connection.stringCommands();

methodHandleHandler = new MethodHandleRedisCommandReplicatedEventHandler();
reflectHandler = new ReflectRedisCommandReplicatedEventHandler();
key = "key".getBytes(StandardCharsets.UTF_8);
value = "value".getBytes(StandardCharsets.UTF_8);
}

@Benchmark
public void benchmarkDirect() throws Throwable {
redisStringCommands.set(key, value);
}

@Benchmark
public void benchmarkMethodHandleRedisCommandReplicatedEventHandler() throws Throwable {
methodHandleHandler.handleEvent(method, redisStringCommands, key, value);
}

@Benchmark
public void benchmarkReflectRedisCommandReplicatedEventHandler() throws Throwable {
reflectHandler.handleEvent(method, redisStringCommands, key, value);
}

@TearDown(Level.Trial)
public void tearDown() throws Exception {

Check warning on line 85 in microsphere-redis-replicator-spring/src/test/java/io/microsphere/redis/benchmark/RedisCommandReplicatedEventHandlerBenchmark.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove the declaration of thrown exception 'java.lang.Exception', as it cannot be thrown from method's body.

See more on https://sonarcloud.io/project/issues?id=microsphere-projects_microsphere-redis&issues=AZrAbJiYZ7BP27FR4e6x&open=AZrAbJiYZ7BP27FR4e6x&pullRequest=3
if (redisContainer != null) {
redisContainer.stop();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package io.microsphere.redis.benchmark.runner;

import io.microsphere.redis.benchmark.RedisCommandReplicatedEventHandlerBenchmark;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

public class BenchmarkRunner {
public static void main(String[] args) throws RunnerException {
Options options = new OptionsBuilder()
.include(RedisCommandReplicatedEventHandlerBenchmark.class.getSimpleName())
.warmupIterations(3)
.measurementIterations(5)
.forks(1)
.build();

new Runner(options).run();
}
}
Loading