tarantool: Biblioteca para trabalhar com tarantool a partir do nginx com o módulo Lua embutido ou com nginx-module-lua
Instalação
Se você ainda não configurou a assinatura do repositório RPM, inscreva-se. Então você pode prosseguir com os seguintes passos.
CentOS/RHEL 7 ou Amazon Linux 2
yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install lua-resty-tarantool
CentOS/RHEL 8+, Fedora Linux, Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install lua5.1-resty-tarantool
Para usar esta biblioteca Lua com o NGINX, certifique-se de que o nginx-module-lua esteja instalado.
Este documento descreve lua-resty-tarantool v0.3 lançado em 21 de outubro de 2015.
Introdução
Esta é uma biblioteca para conectar ao banco de dados NoSQL tarantool. Este banco de dados possui características muito interessantes que o tornam uma espécie de ponte entre um banco de dados tradicional baseado em SQL e armazenamentos orientados a documentos como o CouchDB.
É um fork de outro projeto com o qual eu não estava satisfeito. É amplamente documentado e está atualizado em relação à API do tarantool. Notavelmente com suporte para o comando upsert.
Outra coisa a ter em mente é que a biblioteca tenta ser consistente entre a forma como os comandos update e upsert são emitidos no console usando Lua e a forma como a API funciona. Notavelmente os números dos campos. No console, um número de campo leva em conta a existência de um índice primário como o primeiro campo. Portanto, qualquer campo que venha depois terá uma posição que considera isso. Especificamente ao especificar os operadores a serem usados para as operações update ou upsert.
Uso
Criando uma conexão
local tar = require 'resty.tarantool'
local tar, err = tnt:new({
host = '127.0.0.1',
port = 3301,
user = 'luser',
password = 'some password',
socket_timeout = 2000,
})
luser com a senha some password. Veja o manual do Tarantool sobre autenticação para detalhes sobre como configurar usuários e atribuir privilégios a eles.
O tempo limite do socket (receber e enviar) é de 2 segundos (2000 ms).
set_timeout
settimeout(<objeto de conexão>, <tempo limite em ms>)
Define tanto os tempos limites de envio quanto de recebimento em milissegundos para um dado socket.
tnt:set_timeout(5000) -- tempo limite de 5s para operações de envio/recebimento
A função retorna verdadeiro se a configuração for bem-sucedida, nil se não. Note que para o tempo limite ter efeito, esta função precisa ser invocada antes da conexão ser estabelecida, ou seja, antes de invocar a função connect. Alternativamente, o tempo limite pode ser especificado ao criar o objeto de conexão (cosocket).
connect
connect(<objeto de conexão>)
Conecta o socket criado acima à porta e ao endereço especificados ao criar o objeto de conexão.
tar:connect()
nil se não.
set_keepalive
set_keepalive(<objeto de conexão>)
Faz com que a conexão criada seja enviada para um pool de conexões, de modo que a conexão seja mantida ativa em várias solicitações.
tar:set_keepalive()
A função retorna verdadeiro se o socket for enviado com sucesso para o pool de conexões (manter viva). nil se não.
disconnect
disconnect(<objeto de conexão>)
Fecha uma conexão com um determinado servidor tarantool rodando em um determinado endereço e porta.
tar:disconnect()
A função retorna verdadeiro se a conexão for fechada com sucesso. nil se não.
ping
O comando ping é útil para monitorar o servidor tarantool para ver se ele está disponível. Se estiver disponível para consultas, retorna a string PONG.
tar:ping()
-- retorna PONG
select
A operação select consulta um determinado banco de dados (espaço) para recuperar registros.
select(<objeto de conexão>, <nome do espaço>, <índice>, <chave>, <opções>)
onde <opções> é um argumento opcional que pode consistir em uma tabela que pode ter as seguintes chaves:
offset: número de registros a serem ignorados ao fazer a consulta.limit: o número máximo de registros a serem retornados.iterator: um número especificando o iterador a ser usado. Especificado pela tabela:
local iterator_keys = {
EQ = 0, -- igualdade
REQ = 1, -- igualdade reversa
ALL = 2, -- todas as tuplas em um índice
LT = 3, -- menor que
LE = 4, -- menor ou igual
GE = 5, -- maior ou igual
GT = 6, -- maior que
BITSET_ALL_SET = 7, -- bits na máscara de bits todos definidos
BITSET_ANY_SET = 8, -- qualquer um dos bits na máscara de bits está definido
BITSET_ALL_NOT_SET = 9, -- nenhum dos bits na máscara de bits está definido
}
exemplos de select
Consultar o espaço _space (DB) para obter o id do espaço _index.
local res, err = tar:select('_space', 'name', '_index')
-- resposta:
[2881,"_index","memtx",0,"",
[{"name":"id","type":"num"},
{"name":"iid","type":"num"},
{"name":"name","type":"str"},
{"name":"type","type":"str"},
{"name":"opts","type":"array"},
{"name":"parts","type":"array"}]]]
box.space._space.index.name:select{ '_index' }
Consultar o espaço 'activities' para as atividades com um price menor que 300
-- N.B. price é um índice do espaço activities.
local res, err = tar:select('activities', 'price', 300, { iterator = 'LT' })
box.space.activities.index.price:select({ 300 }, { iterator = 'LT' })
insert
insert(<objeto de conexão>, <nome do espaço>, <tupla>)
onde <tupla> é a tupla a ser inserida no <espaço> enquanto define o índice primário, que é único, para o valor especificado na tupla.
A função retorna o registro inserido se a operação for bem-sucedida.
exemplos de insert
local res, err = tar:insert('activities', { 16, 120, { activity = 'surf', price = 121 } })
-- resposta:
[[16,120,{"activity":"surf","price":121}]]
box.space.activities:insert({16, 120, { activity = 'surf', price = 121 }})
replace
replace(<objeto de conexão>, <nome do espaço>, <tupla>)
O comando replace é semelhante na invocação e assinatura ao comando insert. Mas agora estamos procurando substituir um registro que já existe em vez de inserir um novo. Precisamos novamente do valor de um índice primário único. Mas agora o valor deve existir para que a operação seja bem-sucedida. Se a operação for bem-sucedida, o registro com os valores substituídos é retornado.
exemplos de replace
local res, err = tar:replace('activities', { 16, 120, { activity = 'surf', price = 120 } })
-- resposta:
[[16,120,{"activity":"surf","price":120}]]
A solicitação acima é equivalente à solicitação do console:
box.space.activities:update({ 16, 120, { activity = 'surf', price = 120 }})
update
update(<objeto de conexão>, <nome do espaço>, <índice>, <chave>, <lista de operadores>)
onde <lista de operadores> é a lista de operadores conforme especificado no manual do tarantool. O par (<índice>, <chave> é um valor do índice primário (único) <índice>.
<lista de operadores> é uma tabela da forma:
{ <operador>, <posição do campo>, <valor> }
+para adicionar a um campo numérico.-para subtrair de um campo numérico.¶ operação AND bit a bit entre dois inteiros sem sinal.|para operação OR bit a bit entre dois inteiros sem sinal.^para operação XOR bit a bit entre dois inteiros sem sinal.:para concatenação de strings.!para inserção de campo.#para exclusão de campo.=para atribuir um valor dado a um campo.
retorna o registro atualizado se a operação for bem-sucedida.
exemplos de update
local res, err = tar:update('activities', 'primary', 16, { { '=', 2, 341 }, { '=', 3, { activity = 'kitesurfing', price = 341 }} } )
-- resposta:
[16,341,{"activity":"kitesurfing","price":341}]]
primary 16 que inserimos acima foi atualizado.
A solicitação acima é equivalente à solicitação do console:
box.space.activities.index.primary({ 16 }, { { '=', 2, 341 }, { '=', 3, { activity = 'kitesurfing', price = 341 }}})
upsert
upsert(<objeto de conexão>, <nome do espaço>, <chave>, <lista de operadores>, <nova tupla>)
além do argumento <nova tupla>, a assinatura da função é semelhante à de update. Na verdade, upsert é dois comandos em um. update se o registro especificado pelo par (<índice>, <nova tupla> é a tupla a ser inserida se o valor da <chave> não existir no <índice>. Retorna uma tabela vazia {} se a operação for bem-sucedida. Se a operação não for bem-sucedida, retorna nil.
exemplos de upsert
Um insert.
local res, err = tar:upsert('activities', 17, { { '=', 2, 450 }, { '=', 3, { activity = 'submarine tour 8', price = 450 }}}, { 17, 450, { activity = 'waterski', price = 365 }})
-- resposta:
{}
{ 18, 450, { activity = 'waterski', price = 365 }}
box.space.activities:upsert({ 17 }, { { '=', 2, 450 }, { '=', 3, { activity = 'submarine tour 8', price = 450 }}}, { 17, 450, { activity = 'waterski', price = 365 }})
local res, err = tar:upsert('activities', 17, { { '=', 2, 450 }, { '=', 3, { activity = 'submarine tour 8', price = 450 }}}, { 18, 285, { activity = 'kitesurfing', price = 285 }})
-- resposta:
{}
primary (único).
delete
delete(<objeto de conexão>, <espaço>, <chave>)
deleta o registro especificado de forma única pela <chave> do <espaço>. Note que <chave> deve pertencer a um índice primário (único). Retorna o registro deletado se a operação for bem-sucedida.
exemplos de delete
local response, err = tar:delete('activities', 17)
-- resposta:
[17,450,{"activity":"waterski","price":365}]]
A solicitação acima é equivalente à solicitação do console:
box.space.activities:delete({ 17 })
call
call(<objeto de conexão>, <proc>, <args>)
Invoca uma procedimento armazenado (função Lua) no servidor tarantool ao qual estamos conectados. Retorna os resultados da invocação.
exemplos de call
Como o console do tarantool é um REPL Lua, qualquer função pode ser invocada desde que esteja disponível no ambiente.
local res, err = tar:call('table.concat', { {'hello', ' ', 'world' } })
-- resposta:
[["hello world"]]
table.concat da biblioteca table para concatenar a tabela:
{'hello', ' ', 'world' }
table.concat({'hello', ' ', 'world' })
Para muitos exemplos de procedimentos armazenados do tarantool, veja o repositório; https://github.com/mailru/tarlua
hide_version_header
hide_version_header(<objeto de conexão>)
Por padrão, cada resposta envia um cabeçalho HTTP personalizado X-Tarantool-Version com a versão do servidor tarantool.
X-Tarantool-Version: 1.6.6-191-g82d1bc3
Invocar hide_version_header remove o cabeçalho.
tar:hide_version_header()
Não retorna valores.
GitHub
Você pode encontrar dicas adicionais de configuração e documentação para este módulo no repositório GitHub do nginx-module-tarantool.