redis 127.0.0.1:6379> RPUSH filaDeDragoes Saphira
(integer) 1
redis 127.0.0.1:6379> RPUSH filaDeDragoes Glaedr
(integer) 2
redis 127.0.0.1:6379> RPUSH filaDeDragoes Thorn
(integer) 3
redis 127.0.0.1:6379> LPOP filaDeDragoes
"Saphira"
redis 127.0.0.1:6379> LPOP filaDeDragoes
"Glaedr"
redis 127.0.0.1:6379> LPOP filaDeDragoes
"Thorn"
redis 127.0.0.1:6379> LPOP filaDeDragoes
(nil)
58
Casa do Código
Capítulo 5. Redis no mundo real Parte 3
Repare que iniciamos populando uma lista chamada filaDeDragoes com
três itens utilizando o comando RPUSH. Logo em seguida, usamos o comando
LPOP para remover o item do topo da lista, e ao executá-lo após todos os itens já terem sido removidos da lista, o Redis retornou o valor (nil) indicando que a chave filaDeDragoes não existia mais.
Agora que entendemos o LPOP, vamos conhecer o segundo comando
citado anteriormente, que é o BLPOP. Ele realiza a mesma tarefa que o LPOP, ou seja, remove e retorna o item no topo da lista, mas a letra B do BLPOP
significa bloqueio ou comando bloqueante (blocking), e esse comportamento
bloqueante é o que torna o BLPOP confiável para usarmos uma lista do Redis
como uma fila de mensagens.
Esse comportamento de bloqueio significa que a conexão fica bloqueada
pelo comando ( BLPOP no nosso caso) até que ele retorne seu resultado. É
claro que, se a lista contém itens armazenados, o resultado será obtido de
forma instantânea e, consequentemente, a conexão já será liberada. Uma
outra característica dos comandos bloqueantes é que em geral eles recebem
como parâmetro um valor (número inteiro) que define o tempo em segun-
dos (timeout) para que o comando aguarde um resposta. Se após esse tempo
o comando não obtiver uma resposta, a conexão é liberada. Vamos realizar
alguns testes pelo CLI para entender de forma prática seu uso.
redis 127.0.0.1:6379> RPUSH filaDeDragoes Saphira
(integer) 1
redis 127.0.0.1:6379> RPUSH filaDeDragoes Glaedr
(integer) 2
redis 127.0.0.1:6379> BLPOP filaDeDragoes 1
1) "filaDeDragoes"
2) "Saphira"
redis 127.0.0.1:6379> BLPOP filaDeDragoes 1
1) "filaDeDragoes"
2) "Glaedr"
redis 127.0.0.1:6379> BLPOP filaDeDragoes 1
(nil)
59
5.2. Criando uma fila de mensagens
Casa do Código
(1.06s)
Repare nos comandos executados anteriormente. Primeiro, adicionamos
dois itens à nossa lista chamada filaDeDragoes, em seguida, executamos
o comando BLPOP passando como parâmetro o nome da lista e o timeout
de 1 segundo. Nas duas primeiras vezes que o comando foi executado, a res-
posta (o item do topo da lista) foi retornada de imediado, mas na terceira vez, ele aguardou durante 1 segundo
ou 1.06 segundo para ser mais preciso
para que um novo item fosse inserido na lista. Como isso não aconteceu, o
comando retornou o valor (nil) e liberou a conexão. É possível bloquear a
conexão indefinidamente e ficar aguardando por um novo item na lista, para
isso basta definir o valor do timeout como 0.
Voltando agora ao nosso exemplo em Java, vamos criar uma outra apli-
cação que irá consumir os itens da nossa lista fila:confirmar-usuario.
Essa aplicação precisa ficar monitorando a nossa lista constantemente ou a
cada intervalo de tempo. No nosso caso, para simplificar o código Java vamos utilizar um simples laço (loop) infinito. Veja a aplicação:
public class ConsumirItemDaFila {
class Mensagem {
private String nome;
private String email;
public String getNome() { return nome; }
public void setNome(String nome) { this.nome = nome; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email;}
};
public void enviarEmailAtivacaoUsuario() {
int timeout = 2;
String chave = "fila:confirmar-usuario";
Jedis jedis = new Jedis("localhost");
List<String> mensagens = jedis.blpop(timeout, chave);
60
Casa do Código
Capítulo 5. Redis no mundo real Parte 3
if (mensagens == null) {
System.out.println(String.format(
"A fila %s está vazia.", chave));
}
else {
String json = mensagens.get(1);
Mensagem mensagem =
new Gson().fromJson(json, Mensagem.class);
System.out.println(
String.format(
"Enviando e-mail para %s (%s)",
mensagem.getEmail(),
mensagem.getNome()
)
);
}
}
public static void main(String[] args) {
ConsumirItemDaFila fila = new ConsumirItemDaFila();
while (true) {
fila.enviarEmailAtivacaoUsuario();
}
}
}
Vamos verificar o seu resultado quando executado:
Enviando e-mail para daenerys@targaryen.com (Daenerys Targaryen)
Enviando e-mail para jon@snow.com (Jon Snow)
Enviando e-mail para tyrion@lannister.com (Tyrion Lannister)
A fila fila:confirmar-usuario está vazia.
A fila fila:confirmar-usuario está vazia.
Quando o exemplo foi executado, o comando BLPOP recuperou os três
itens da lista que já tínhamos inseridos anteriormente e executou nossa falsa rotina de envio de e-mail que apenas imprime uma mensagem com o nome
61
5.2. Criando uma fila de mensagens
Casa do Código
e e-mail a ser enviado. Como esse exemplo ficou rodando continuamente até