Redis
 sql >> Base de Dados >  >> NoSQL >> Redis

Como posso ler do Redis dentro de um bloco MULTI em Ruby?


Você não pode, pois todos os comandos (incluindo get) são realmente executados em tempo de execução. Nessa situação, o comando get retorna apenas um objeto futuro, não o valor real.

Existem duas maneiras de implementar tal transação.

Usando uma cláusula WATCH

A cláusula watch é usada para proteger contra atualizações simultâneas. Se o valor da variável for atualizado entre a cláusula watch e multi, os comandos no bloco multi não serão aplicados. Cabe ao cliente tentar a transação outra vez.
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

Aqui o script é um pouco complexo porque o conteúdo do bloco pode estar vazio, então não há uma maneira fácil de saber se a transação foi cancelada ou se não ocorreu. Geralmente é mais fácil quando o multiblock retorna resultados em todos os casos, exceto se a transação for cancelada.

Usando scripts do lado do servidor Lua

Com o Redis 2.6 ou superior, os scripts Lua podem ser executados no servidor. A execução de todo o script é atômica. Ele pode ser facilmente implementado em 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"

Isso geralmente é muito mais simples do que usar cláusulas WATCH.