<!-- JSON-LD markup generated by Google Structured Data Markup Helper. --><script type="application/ld+json">{  "@context" : "http://schema.org",  "@type" : "Article",  "name" : "Using Redis keyspace notifications for discard task after the timeout",  "author" : {    "@type" : "Person",    "name" : "Subham Majavadiya"  },  "image" : "https://global-uploads.webflow.com/5ef788f07804fb7d78a4127a/5f3272076e05504936ddad24_Using%20Redis%20keyspace%20notifications%20for%20discard%20task%20after%20the%20timeout.png",  "articleSection" : "how to implement some sort of timeout mechanism to discard any task if that task surpassed the maximum wait time",  "articleBody" : [ "Enable keyspace notifications for Expired key Only", "Enable Using Redis-CLI", "Enable Using Redis.conf", "Create Task timeout listener" ],  "url" : "https://www.engati.com/blog/using-redis-keyspace-notifications-for-discard-task-after-the-timeout",  "publisher" : {    "@type" : "Organization",    "name" : "Engati"  }}</script>

How to use Redis keyspace notifications to discard tasks after timeouts

Subham Majavadiya
|
2
min read
How to use Redis keyspace notifications to discard tasks after timeouts

I was trying to figuring out how to implement some sort of timeout mechanism to discard any task if that task surpassed the maximum wait time, and the wait time can be configurable in seconds, minutes, hours, and may vary customer to customer.
Then I came across notifications events in Redis. In this article, I will give you an overview of how I have used Redis keyspace notifications events with spring boot application to achieve the functionality.

Basically the idea here is whenever a new task came in, set a key in Redis with some prefix along with task metadata and expiry as the configured max wait time and then by using Redis Keyspace Notifications for Expired Keys listen the key expiry event, and based on that discard the task.

Enable keyspace notifications for Expired key Only:

IMPORTANT Keyspace notifications feature is available in Redis server version 2.8.0 or higher.

By default keyspace, notifications are disabled in Redis to avoid unnecessary CPU utilization, There are two ways we can enable this either using redis-cli or redis.conf file.

Enable Using Redis-CLI:

Subhams-MBP-2:~ subhammajavadiya$ redis-cli
127.0.0.1:6379> config set notify-keyspace-events Ex
OK

Enable Using Redis.conf:

By adding the below line in redis.conf and restarting the redis-server.

notify-keyspace-events Ex

would recommend enabling from redis.conf file in the production environment, to avoid the config reset if redis-server get restarted.

Create Task timeout listener

  • To listen to the key expire event in spring boot application I have added spring.data.redis dependency in the build.gradleand implemented TaskTimeOutListener as MessageListener bean.

@Slf4j
@Component
public class TaskTimeOutListener implements MessageListener {  @Override
 public void onMessage(Message message, byte[] pattern) {
   String body = new String(message.getBody());
   String channel = new String(message.getChannel());log.info("Received task timeout event: {} for key: {}", body, channel);

   String expiredKey = channel.split(":")[1];
   //implemented logic to discard task
 }}

  • Register TaskTimeOutListener, MessageListener bean with RedisMessageListenerContainer to listen the key expiry event with a specific pattern i.e task_with_max_wait_time__*

@Slf4j
@Configuration
public class RedisConfiguration {  @Bean
 public RedisMessageListenerContainer redisMessageListenerContainer(
     RedisConnectionFactory connectionFactory,
     TaskTimeOutListener taskTimeoutListener) {
   RedisMessageListenerContainer listenerContainer = new RedisMessageListenerContainer();
   listenerContainer.setConnectionFactory(connectionFactory);
   listenerContainer.addMessageListener(maxWaitTimeExpiryListener,
       new PatternTopic("__key*__:task_with_max_wait_time__*"));
   listenerContainer.setErrorHandler(
       e ->log.error("Error in redisMessageListenerContainer", e));
   return listenerContainer;
 }
}

  • Let’s start the spring boot application and from redis-cli set a task with expiry time as 10 sec with key task_with_max_wait_time__1.

Subhams-MBP-2:~ subhammajavadiya$ redis-cli
127.0.0.1:6379> SETEX  task_with_max_wait_time__1  10  "test task"
OK

  • After 10 seconds

{"@timestamp":"2020-06-12T19:28:48.063+00:00","@version":1,"message":"Received task timeout event: expired, for key :task_with_max_wait_time__1","logger_name":"com.test.redislistener.TaskTimeOutListener",

"thread_name":"redisMessageListenerContainer-2","level":"INFO","level_value":20000,"app_name":"test-app","log_type":"app"}

And, it's up and running. Hope this helps you.

Tags
No items found.
About Engati

Engati powers 45,000+ chatbot & live chat solutions in 50+ languages across the world.

We aim to empower you to create the best customer experiences you could imagine. 

So, are you ready to create unbelievably smooth experiences?

Check us out!