How to receive Redis expire events with node?
Asked Answered
M

4

15

I want to listen the expire events from Redis. I've configured on my redis.conf the notify-keyspace-events "AKE" and this is my code on node:

const redis = require('redis');
const client = redis.createClient();
const subscriber = redis.createClient();
const KEY_EXPIRING_TIME = 10; // seconds

client.setex('myKey', KEY_EXPIRING_TIME, 'myValue');

subscriber.on('message', function(channel, msg) {
  console.log( `On ${channel} received ${msg} event`);
});

subscriber.subscribe('myKey', function (err) {
  console.log('subscribed!');
});

What I hope is to see in 10 seconds that the event is triggered. The setex command works correctly, in 10 seconds the key is not in the database, I have the problem when I try to capture the event.

What am I doing wrong?

Motorize answered 3/2, 2017 at 15:45 Comment(1)
Check my answer for a solution without additional modules/libraries & no need for sloppy timeouts/intervals. ;)Sunderland
I
7

no need for setInterval / setTimeout or additional libraries

you can get every expired key from below the code.

import { createClient } from "redis";

const pub=createClient({ url: process.env.REDIS_URL });
pub.connect();
pub.configSet("notify-keyspace-events", "Ex");

const sub=pub.duplicate();
sub.connect();

sub.subscribe("__keyevent@0__:expired", (key) => {
    console.log("key=> ", key)
})

Note: this code is tested with [email protected]

Insuperable answered 3/12, 2021 at 12:19 Comment(2)
How can you listen to a particular key pattern expired event?Keneth
Also, why do we need to duplicate the Redis client in order to use it as a subscriber?Keneth
S
29

It is in fact possible to listen to the "expired" type keyevent notification using a subscribed client to the specific channel ('__keyevent@db__:expired') and listening to its message event.

no need for setInterval / setTimeout or additional libraries

Proof-of-concept (working : tested with NodeJS v.9.4.0)

const redis = require('redis')
const CONF = {db:3}
var pub, sub
//.: Activate "notify-keyspace-events" for expired type events
pub = redis.createClient(CONF)
pub.send_command('config', ['set','notify-keyspace-events','Ex'], SubscribeExpired)
//.: Subscribe to the "notify-keyspace-events" channel used for expired type events
function SubscribeExpired(e,r){
 sub = redis.createClient(CONF)
 const expired_subKey = '__keyevent@'+CONF.db+'__:expired'
 sub.subscribe(expired_subKey,function(){
  console.log(' [i] Subscribed to "'+expired_subKey+'" event channel : '+r)
  sub.on('message',function (chan,msg){console.log('[expired]',msg)})
  TestKey()
 })
}
//.: For example (create a key & set to expire in 10 seconds)
function TestKey(){
 pub.set('testing','redis notify-keyspace-events : expired')
 pub.expire('testing',10)
}
Sunderland answered 17/1, 2018 at 3:31 Comment(1)
Can I listen on particular key pattern expired event?.Ghat
T
7

Approach 1:-

The setInterval function has to be used to check whether the value is expired periodically. I am aware that this is not equal to listening to events. However, it serves the purpose indirectly.

The below code checks the value for every 5 seconds.

const redis = require('redis');
const client = redis.createClient();
const subscriber = redis.createClient();
const KEY_EXPIRING_TIME = 10; // seconds

var args = ['myKey', KEY_EXPIRING_TIME,  'myValue'];


client.setex('myKey', KEY_EXPIRING_TIME, 'myValue');

subscriber.on('message', function(channel, msg) {
  console.log( `On ${channel} received ${msg} event`);
});

subscriber.subscribe('myKey', function (err) {
  console.log('subscribed!');
});

setInterval(function() {  
  client.get('myKey', function(err, value) {
    if (err) {
      throw err;
    }
    if (value) {
      console.log('value:', value);
    }
    else {
      console.log('value is gone');
      process.exit();
    }
  });
}, 5e3);

Approach 2:-

The redis-notifier can be used to listen to the events. However, it requires Python >= v2.5.0 & < 3.0.0 in order to install this package.

redis-notifier

var RedisNotifier = require('redis-notifier');

var eventNotifier = new RedisNotifier(redis, {
  redis : { host : '127.0.0.1', port : 6379 },
  expired : true,
  evicted : true,
  logLevel : 'DEBUG' //Defaults To INFO 
});

//Listen for event emission 
eventNotifier.on('message', function(pattern, channelPattern, emittedKey) {
  var channel = this.parseMessageChannel(channelPattern);
  switch(channel.key) {
    case 'expired':
        this._handleExpired(emittedKey);
      break;
    case "evicted":
      this._handleEvicted(emittedKey);
      break;
    default:
      logger.debug("Unrecognized Channel Type:" + channel.type);
  }
});
Testamentary answered 3/2, 2017 at 17:46 Comment(0)
I
7

no need for setInterval / setTimeout or additional libraries

you can get every expired key from below the code.

import { createClient } from "redis";

const pub=createClient({ url: process.env.REDIS_URL });
pub.connect();
pub.configSet("notify-keyspace-events", "Ex");

const sub=pub.duplicate();
sub.connect();

sub.subscribe("__keyevent@0__:expired", (key) => {
    console.log("key=> ", key)
})

Note: this code is tested with [email protected]

Insuperable answered 3/12, 2021 at 12:19 Comment(2)
How can you listen to a particular key pattern expired event?Keneth
Also, why do we need to duplicate the Redis client in order to use it as a subscriber?Keneth
O
0
REDIS_CLIENT.sendCommand(['config', 'set', 'notify-keyspace-events', 'Ex']);


REDIS_CLIENT.subscribe("__keyevent@0__:expired", (err) => {         
    if (err) {
        console.error(err);
    } else {
        console.log('Subscribed to mychannel');
    }
 });

Use this code segment and Grant all the necessary permissions and your code will work.

Osseous answered 24/4, 2023 at 7:47 Comment(1)
How can you listen to a particular key pattern expired event?Keneth

© 2022 - 2024 — McMap. All rights reserved.