Redis
 sql >> Base de données >  >> NoSQL >> Redis

Comment puis-je lire depuis Redis dans un bloc MULTI dans Ruby ?

Vous ne pouvez pas, car toutes les commandes (y compris get) sont en fait exécutées au moment de l'exécution. Dans cette situation, la commande get ne renvoie qu'un objet futur, pas la valeur réelle.

Il existe deux façons d'implémenter une telle transaction.

Utiliser une clause WATCH

La clause watch est utilisée pour se protéger contre les mises à jour simultanées. Si la valeur de la variable est mise à jour entre les clauses watch et multi, les commandes du bloc multi ne sont pas appliquées. Il appartient au client de retenter la transaction une autre fois.

loop do
    $redis.watch "foo" 
    val = $redis.get("foo")
    if val == "bar" then
        res = $redis.multi do |r|
            r.set("foo", "baz") 
        end
        break if res
    else
        $redis.unwatch "foo"
        break
    end
end

Ici le script est un peu complexe car le contenu du bloc peut être vide, il n'y a donc pas de moyen simple de savoir si la transaction a été annulée, ou si elle n'a pas eu lieu du tout. C'est généralement plus facile lorsque le multibloc renvoie des résultats dans tous les cas sauf si la transaction est annulée.

Utilisation des scripts côté serveur Lua

Avec Redis 2.6 ou supérieur, les scripts Lua peuvent être exécutés sur le serveur. L'exécution de l'ensemble du script est atomique. Il peut être facilement implémenté en Ruby :

cmd = <<EOF
    if redis.call('get',KEYS[1]) == ARGV[1] then
       redis.call('set',KEYS[1],ARGV[2] )
    end
EOF
$redis.eval cmd, 1, "foo", "bar", "baz"

C'est généralement beaucoup plus simple que d'utiliser des clauses WATCH.