编写简单节点redis循环(使用ioredis)的更好方法?

时间:2021-06-26 12:37:03

So, I'm stilling learning the JS/Node way from a long time in other languages.

因此,我仍然在用其他语言长期学习JS/Node。

I have a tiny micro-service that reads from a redis channel, temp stores it in a working channel, does the work, removes it, and moves on. If there is more in the channel it re-runs immediately. If not, it sets a timeout and checks again in 1 second.

我有一个小的微服务,从redis通道读取数据,temp将其存储在一个工作通道中,完成工作,删除它,然后继续。如果有更多的频道,它会立即重新运行。如果不是,则设置一个超时,并在1秒内再次检查。

It works fine...but timeout polling doesn't seem to be the "correct" way to approach this. And I haven't found much about using BRPOPLPUSH to try to block (vs. RPOPLPUSH) and wait in Node....or other options like that. (Pub/Sub isn't an option here...this is the only listener, and it may not always be listening.)

它工作正常…但是超时轮询似乎并不是解决这个问题的“正确”方法。我还没有找到关于使用BRPOPLPUSH试图阻止(vs RPOPLPUSH)等节点....或者其他类似的选择。(这里没有酒吧/潜水艇……)这是唯一的倾听者,它可能并不总是在倾听。

Here's the short essence of what I'm doing:

以下是我所做的简短的要点:

var Redis = require('ioredis');
var redis = new Redis();

var redisLoop = function () {
    redis.rpoplpush('channel', 'channel-working').then(function (result) {
        if (result) {
            processJob(result); //do stuff

            //delete the item from the working channel, and check for another item
            redis.lrem('channel-working', 1, result).then(function (result) { });
            redisLoop();
        } else {
            //no items, wait 1 second and try again
            setTimeout(redisLoop, 1000);
        }
    });
};

redisLoop();

I feel like I'm missing something really obvious. Thanks!

我觉得我错过了一些很明显的东西。谢谢!

1 个解决方案

#1


2  

BRPOPLPUSH doesn't block in Node, it blocks in the client. In this instance I think it's exactly what you need to get rid of the polling.

BRPOPLPUSH不会在节点中阻塞,它会在客户机中阻塞。在这种情况下,我认为这正是您需要摆脱轮询的地方。

var Redis = require('ioredis');
var redis = new Redis();

var redisLoop = function () {
    redis.brpoplpush('channel', 'channel-working', 0).then(function (result) {
        // because we are using BRPOPLPUSH, the client promise will not resolve
        // until a 'result' becomes available
        processJob(result);

        // delete the item from the working channel, and check for another item
        redis.lrem('channel-working', 1, result).then(redisLoop);
    });
};

redisLoop();

Note that redis.lrem is asynchronous, so you should use lrem(...).then(redisLoop) to ensure that your next tick executes only after the item is successfully removed from channel-working.

注意,复述。lrem是异步的,所以您应该使用lrem(…)然后(redisLoop)来确保您的下一个tick只在成功地从通道工作中删除后才执行。

#1


2  

BRPOPLPUSH doesn't block in Node, it blocks in the client. In this instance I think it's exactly what you need to get rid of the polling.

BRPOPLPUSH不会在节点中阻塞,它会在客户机中阻塞。在这种情况下,我认为这正是您需要摆脱轮询的地方。

var Redis = require('ioredis');
var redis = new Redis();

var redisLoop = function () {
    redis.brpoplpush('channel', 'channel-working', 0).then(function (result) {
        // because we are using BRPOPLPUSH, the client promise will not resolve
        // until a 'result' becomes available
        processJob(result);

        // delete the item from the working channel, and check for another item
        redis.lrem('channel-working', 1, result).then(redisLoop);
    });
};

redisLoop();

Note that redis.lrem is asynchronous, so you should use lrem(...).then(redisLoop) to ensure that your next tick executes only after the item is successfully removed from channel-working.

注意,复述。lrem是异步的,所以您应该使用lrem(…)然后(redisLoop)来确保您的下一个tick只在成功地从通道工作中删除后才执行。