2016-09-12 3 views
0

J'ai 7 ensembles et je dois vérifier si la valeur existe (sismember) au moins dans un ensemble et retourner vrai ou faux.Node.js vérifier la valeur dans quelques ensembles redis et retourner de manière synchrone

Je dois obtenir cette valeur de manière synchrone, comme ceci:

const isExist = !!(_.max(_.range(7).map((day) => { 
    redis.sismember(`blacklist${day}`, hashToken, function (err, res) { 
     return res; 
    }); 
}))); 
+1

Vous pouvez exécuter la requête redis-side avec des scripts lua? –

+0

@ChrisTanner Non, désolé, je ne peux pas. Je dois le faire sur le serveur node.js. –

+0

Au lieu de faire 7 roundtrips à redis, pensez à utiliser le script lua qui peut effectuer cette opération atomiquement. De cette façon, vous êtes sûr que votre opération de vérification n'est pas interrompue par un autre code client. –

Répondre

2

Vous ne voulez jamais code synchrone quand vous pouvez l'éviter.

Dans ce cas, je recommande d'utiliser Promises afin de gérer les sept demandes de redis.

Le Bluebird promise library peut rendre la plupart des API promesses-compatibles dans une ligne de code (lire environ promisification), l'API de redis ne fait pas exception. (La documentation de Bluebird même uses redis as an example, et ainsi fait la node-redis documentation, il est encore « officiellement pris en charge », si vous tenez à ce genre de chose.)

Donc ce que vous semblez vouloir est une fonction qui vérifie jusqu'à sept appels asynchrones à sismember et résout à un résultat positif global dès que le premier d'entre eux a un résultat positif - Promise#any() peut le faire.

var Promise = require('bluebird'); 
var _ = require('lodash'); 
var redis = require('redis'); 

Promise.promisifyAll(redis); 

function checkBlacklist(hashToken) { 
    var blacklistChecks = _.range(7).map((day) => { 
     return redis.sismemberAsync(`blacklist${day}`, hashToken); 
    }); 
    return Promise.any(blacklistChecks); 
} 

utilisation

checkBlacklist('some_token').then((result) => { 
    // do something with the result 
}).catch((err) => { 
    // an error has occurred - handle it or rethrow it 
}); 
0

Si plusieurs opérations de redis sont impliqués, en général, je préfère écrire script lua puis l'appeler par mon programme nodejs. Ceci est un exemple sans rapport, mais il montre comment vous pouvez utiliser lua via nodejs.

exemple: get_state.lua

local jobId = KEYS[1] 
local jobExists = redis.pcall('exists', jobId) 
if jobExists == 0 or jobExists == nil then 
    return 404 -- not found. 
end 

-- check the job state 
local st = tonumber(redis.pcall('hmget', jobId, 'ctlState')[1]) 
if st == nil then 
    st = 12002 -- job running, unless explicitly stated otherwise 
end 
return st 

code NodeJS qui utilise Lua: dire index.js

... 
// List of script files 
var scriptMap = { 
    getState: {file:'./scripts/get_state.lua'} 
}; 


... 

// A function to load the script file to Redis and cache the sha. 
function loadScript(script) { 
    logger.trace("loadScript(): executing..."); 
    if (scriptMap[script]['hash']) { 
    logger.trace("Sript already loaded. Returning without loading again..."); 
    return Promise.resolve(scriptMap[script]['hash']); 
    } 

    //load from file and send to redis 
    logger.trace("Loading script from file %s...", scriptMap[script].file); 
    return fs.readFileAsync(scriptMap[script].file).then(function(data) { 
    return getConnection().then(function(conn) { 
     logger.trace("Loading script to Redis..."); 
     return conn.scriptAsync('load', data) 
    }) 
    }) 
} 

Et, enfin, une fonction qui utilise le cache sha digérer pour exécuter le script:

getJobState: function(jobId) { 
    return loadScript('getState').then(function(hash) { 
     return getConnection().then(function (conn) { 
     return conn.evalshaAsync(hash, 1, jobId) 
     }) 
    }) 
    },