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.