My Environment
- Mac Ventura 13.6.3
- Temurin 17
- SpringBoot 3.2.1
- org.springframework.boot:spring-boot-starter-data-redis
- redis cluster running on local machine. (localhost: 7001, localhost: 7002, localhost: 7003
What I want to do
I want to receive expire event from redis cluster with spring.
What I did
I connected to cluster, and expired a key
CONFIG SET notify-keyspace-events Ex
SET hi 123
EXPIRE hi 3
My (java) code
Configuration
package kr.co.yogiyo.payo.infrastructure.temporal;
import io.lettuce.core.ReadFrom;
import kr.co.yogiyo.payo.infrastructure.temporal.service.RedisExpireEventService;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.autoconfigure.data.redis.RedisConnectionDetails;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisNode;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
@RequiredArgsConstructor
@Configuration
public class RedisConfig {
private final RedisConnectionDetails redisConnectionDetails;
@Bean
public RedisConnectionFactory redisConnectionFactory() {
RedisConnectionDetails.Cluster cluster = redisConnectionDetails.getCluster();
RedisClusterConfiguration clusterConfiguration = new RedisClusterConfiguration();
for (RedisConnectionDetails.Node node : cluster.getNodes()) {
clusterConfiguration.addClusterNode(new RedisNode(node.host(), node.port()));
}
LettuceClientConfiguration clientConfig =
LettuceClientConfiguration.builder().readFrom(ReadFrom.REPLICA_PREFERRED).build();
return new LettuceConnectionFactory(clusterConfiguration, clientConfig);
}
@Bean
RedisMessageListenerContainer keyExpirationListenerContainer(
RedisConnectionFactory connectionFactory, RedisExpireEventService redisExpireEventService) {
RedisMessageListenerContainer listenerContainer = new RedisMessageListenerContainer();
listenerContainer.setConnectionFactory(connectionFactory);
listenerContainer.addMessageListener(
redisExpireEventService, new PatternTopic("__keyevent@*__:expired"));
return listenerContainer;
}
}
the service
package kr.co.yogiyo.payo.infrastructure.temporal.service;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class RedisExpireEventService implements MessageListener {
@Override
public void onMessage(Message message, byte[] pattern) {
System.out.println("Message received: " + message.toString());
}
}
application.yml
spring:
main:
banner-mode: off
allow-bean-definition-overriding: true
jackson:
property-naming-strategy: SNAKE_CASE
data:
redis:
host: ${PAYO_REDIS_MASTER_HOST:localhost}
port: ${PAYO_REDIS_MASTER_PORT:7002}
cluster:
nodes: ${PAYO_REDIS_REPLICATION_NODES:localhost:7001,localhost:7002,localhost:7003}
spring runs well, but nothing happens when key expired. (I set breakpoint and ran with debug mode, still nothing happens)
Working python code
I tried with python, it worked like charm... I want to subscribe the event with spring.
import redis
def main():
# Connect to Redis
r = redis.Redis(host='localhost', port=7002, db=0)
# Subscribe to the '__keyevent@0__:expired' channel
pubsub = r.pubsub()
pubsub.psubscribe('__keyevent@*__:expired')
# Start listening for messages
for message in pubsub.listen():
print("something expired! ", message)
if __name__ == "__main__":
main()
something expired! {'type': 'psubscribe', 'pattern': None, 'channel': b'__keyevent@*__:expired', 'data': 1}
something expired! {'type': 'pmessage', 'pattern': b'__keyevent@*__:expired', 'channel': b'__keyevent@0__:expired', 'data': b'hi'}
could you guys let me know what am I missing in my java code?