Aller au contenu

tarantool: Bibliothèque pour travailler avec tarantool depuis nginx avec le module Lua intégré ou avec nginx-module-lua

Installation

Si vous n'avez pas configuré l'abonnement au dépôt RPM, inscrivez-vous. Ensuite, vous pouvez procéder avec les étapes suivantes.

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

Pour utiliser cette bibliothèque Lua avec NGINX, assurez-vous que nginx-module-lua est installé.

Ce document décrit lua-resty-tarantool v0.3 publié le 21 octobre 2015.


Introduction

Ceci est une bibliothèque pour se connecter à la base de données NoSQL tarantool. Cette base de données possède des fonctionnalités très intéressantes qui en font une sorte de pont entre une base de données traditionnelle basée sur SQL et des stockages orientés documents comme CouchDB.

C'est un fork d'un autre projet qui ne me satisfaisait pas. Il est abondamment documenté et est à jour concernant l'API de tarantool. Notamment avec le support de la commande upsert.

Une autre chose à garder à l'esprit est que la bibliothèque essaie d'être cohérente entre la manière dont les commandes update et upsert sont émises dans la console en utilisant Lua et la manière dont l'API fonctionne. Notamment les numéros de champ. Dans la console, un numéro de champ prend en compte l'existence d'un index primaire comme premier champ. Ainsi, tout champ qui vient après aura une position qui en tient compte. Spécifiquement lors de la spécification des opérateurs à utiliser pour les opérations update ou upsert.

Utilisation

Création d'une connexion

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,
})
Ce qui précède crée un objet de connexion qui se connecte à une instance de serveur tarantool fonctionnant sur la boucle locale au port 3301, pour l'utilisateur luser avec le mot de passe some password. Consultez le manuel Tarantool sur l'authentification pour des détails sur la façon de configurer les utilisateurs et d'attribuer des privilèges.

Le délai d'attente du socket (réception et envoi) est de 2 secondes (2000 ms).

set_timeout

settimeout(<objet de connexion>, <délai en ms>)

Définit à la fois les délais d'envoi et de réception en millisecondes pour un socket donné.

tnt:set_timeout(5000) -- délai de 5s pour les opérations d'envoi/réception

La fonction retourne true si le paramètre réussit, nil sinon. Notez que pour que le délai d'attente prenne effet, cette fonction doit être invoquée avant que la connexion soit établie, c'est-à-dire avant d'invoquer la fonction connect. Alternativement, le délai d'attente peut être spécifié lors de la création de l'objet de connexion (cosocket).

connect

connect(<objet de connexion>)

Connecte le socket créé ci-dessus au port et à l'adresse spécifiés lors de la création de l'objet de connexion.

tar:connect()
La fonction retourne true si la connexion réussit, nil sinon.

set_keepalive

set_keepalive(<objet de connexion>)

Fait en sorte que la connexion créée soit poussée vers un pool de connexions afin que la connexion soit maintenue active à travers plusieurs requêtes.

tar:set_keepalive()

La fonction retourne true si le socket est poussé avec succès vers le pool de connexions (définir keepalive). nil sinon.

disconnect

disconnect(<objet de connexion>)

Ferme une connexion à un serveur tarantool donné fonctionnant à une adresse et un port donnés.

tar:disconnect()

La fonction retourne true si la connexion est fermée avec succès. nil sinon.

ping

La commande ping est utile pour surveiller le serveur tarantool afin de voir s'il est disponible. S'il est disponible pour les requêtes, il retourne la chaîne PONG.

tar:ping()
-- retourne PONG

select

L'opération select interroge une base de données donnée (espace) pour récupérer des enregistrements.

select(<objet de connexion>, <nom de l'espace>, <index>, <clé>, <options>)

<options> est un argument optionnel qui peut consister en une table ayant les clés suivantes :

  • offset: nombre d'enregistrements à ignorer lors de la requête.
  • limit: le nombre maximum d'enregistrements à retourner.
  • iterator: un nombre spécifiant l'itérateur à utiliser. Spécifié par la table :

local iterator_keys = {
  EQ = 0, -- égalité
  REQ = 1, -- égalité inverse
  ALL = 2, -- tous les tuples dans un index
  LT = 3, -- moins que
  LE = 4, -- moins que ou égal
  GE = 5, -- plus que ou égal
  GT = 6, -- plus que
  BITSET_ALL_SET = 7, -- bits dans le masque de bits tous définis
  BITSET_ANY_SET = 8, -- n'importe quel des bits dans le masque de bits est défini
  BITSET_ALL_NOT_SET = 9, -- aucun des bits dans le masque de bits n'est défini
}
Plus de détails sur les itérateurs dans le manuel tarantool.

exemples de select

Interroger l'espace _space (DB) pour obtenir l'identifiant de l'espace _index.

local res, err = tar:select('_space', 'name', '_index')

-- réponse :
[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"}]]]
La requête ci-dessus est équivalente à la requête de la console :

box.space._space.index.name:select{ '_index' }

Interroger l'espace 'activities' pour les activités avec un price inférieur à 300

-- N.B. price est un index de l'espace activities.
local res, err = tar:select('activities', 'price', 300, { iterator = 'LT' })
La requête ci-dessus est équivalente à la requête de la console :

box.space.activities.index.price:select({ 300 }, { iterator = 'LT' }) 

insert

insert(<objet de connexion>, <nom de l'espace>, <tuple>)

<tuple> est le tuple à insérer dans <space> tout en définissant l'index primaire, qui est unique, à la valeur spécifiée dans le tuple.

La fonction retourne l'enregistrement inséré si l'opération réussit.

exemples d'insertion

local res, err = tar:insert('activities', { 16, 120, { activity = 'surf', price = 121 } })

-- réponse : 
[[16,120,{"activity":"surf","price":121}]]
La requête ci-dessus est équivalente à la requête de la console :

box.space.activities:insert({16, 120, { activity = 'surf', price = 121 }})
16 est la valeur de l'index primaire ici. Cela signifie que pour un index de type entier, ce sera l'enregistrement avec l'index primaire 16.

replace

replace(<objet de connexion>, <nom de l'espace>, <tuple>)

La commande replace est similaire dans l'invocation et la signature à la commande insert. Mais maintenant, nous cherchons à remplacer un enregistrement qui existe déjà au lieu d'insérer un nouveau. Nous avons encore besoin de la valeur d'un index primaire unique. Mais maintenant, la valeur doit exister pour que l'opération réussisse. Si l'opération réussit, l'enregistrement avec les valeurs remplacées est retourné.

exemples de remplacement

local res, err = tar:replace('activities', { 16, 120, { activity = 'surf', price = 120 } })
-- réponse :
[[16,120,{"activity":"surf","price":120}]]
Ici, nous remplaçons l'ancien prix de 121 par 120. La valeur de l'index primaire, 16, correspond à l'enregistrement que nous avons inséré ci-dessus.

La requête ci-dessus est équivalente à la requête de la console :

box.space.activities:update({ 16, 120, { activity = 'surf', price = 120 }})

update

update(<objet de connexion>, <nom de l'espace>, <index>, <clé>, <liste d'opérateurs>)

<liste d'opérateurs> est la liste des opérateurs comme spécifié dans le manuel tarantool. La paire (, ) identifie de manière unique un enregistrement, c'est-à-dire que la <clé> est une valeur de l'index primaire (unique) <index>.

<liste d'opérateurs> est une table de la forme :

{ <opérateur>, <position du champ>, <valeur> }
les opérateurs sont :

  • + pour ajouter à un champ numérique.
  • - pour soustraire à un champ numérique.
  • & pour l'opération AND bit à bit entre deux entiers non signés.
  • | pour l'opération OR bit à bit entre deux entiers non signés.
  • ^ pour l'opération XOR bit à bit entre deux entiers non signés.
  • : pour la concaténation de chaînes.
  • ! pour l'insertion de champ.
  • # pour la suppression de champ.
  • = pour attribuer une valeur donnée à un champ.

il retourne l'enregistrement mis à jour si l'opération est réussie.

exemples de mise à jour

local res, err = tar:update('activities', 'primary', 16, { { '=', 2, 341 }, { '=', 3,  { activity = 'kitesurfing', price = 341 }}} )
-- réponse :
[16,341,{"activity":"kitesurfing","price":341}]]
L'enregistrement avec l'index primary 16 que nous avons inséré ci-dessus a été mis à jour.

La requête ci-dessus est équivalente à la requête de la console :

box.space.activities.index.primary({ 16 }, { { '=', 2, 341 }, { '=', 3,  { activity = 'kitesurfing', price = 341 }}})

upsert

upsert(<objet de connexion>, <nom de l'espace>, <clé>, <liste d'opérateurs>, <nouveau tuple>)

à part l'argument <nouveau tuple>, la signature de la fonction est similaire à update. En fait, upsert est deux commandes en une. update si l'enregistrement spécifié par la paire (, ) existe et insérer si ce n'est pas le cas. La clé est une valeur d'un index primaire, c'est-à-dire qu'elle est unique. Le <nouveau tuple> est le tuple à insérer si la valeur <clé> n'existe pas dans l'<index>. Il retourne une table vide {} si l'opération réussit. Si l'opération échoue, elle retourne nil.

exemples d'upsert

Un insert.

local res, err = tar:upsert('activities', 17, { { '=', 2, 450 }, { '=', 3,  { activity = 'submarine tour 8', price = 450 }}}, { 17, 450, { activity = 'waterski', price = 365 }})
-- réponse :
{}
Nous avons inséré un nouvel enregistrement avec la clé 17 pour l'index primaire à partir du tuple :

{ 18, 450, { activity = 'waterski', price = 365 }}
La requête ci-dessus est équivalente à la requête de la console :

box.space.activities:upsert({ 17 }, { { '=', 2, 450 }, { '=', 3,  { activity = 'submarine tour 8', price = 450 }}}, { 17, 450, { activity = 'waterski', price = 365 }})
Une mise à jour.

local res, err = tar:upsert('activities', 17, { { '=', 2, 450 }, { '=', 3,  { activity = 'submarine tour 8', price = 450 }}}, { 18, 285, { activity = 'kitesurfing', price = 285 }})
-- réponse :
{}
Maintenant, nous effectuons une mise à jour de l'enregistrement identifié par la clé 17 dans l'index primary (unique).

delete

delete(<objet de connexion>, <espace>, <clé>)

supprime l'enregistrement spécifié de manière unique par <clé> de <espace>. Notez que <clé> doit appartenir à un index primaire (unique). Il retourne l'enregistrement supprimé si l'opération réussit.

exemples de suppression

local response, err = tar:delete('activities', 17)
-- réponse :
[17,450,{"activity":"waterski","price":365}]]
Nous avons supprimé l'enregistrement identifié de manière unique par la clé 17 dans l'index primaire de l'espace activities.

La requête ci-dessus est équivalente à la requête de la console :

box.space.activities:delete({ 17 })

call

call(<objet de connexion>, <proc>, <args>)

Invoque une procédure stockée (fonction Lua) dans le serveur tarantool auquel nous sommes connectés. Elle retourne les résultats de l'invocation.

exemples d'appel

Puisque la console tarantool est un REPL Lua, toute fonction peut être invoquée tant qu'elle est disponible dans l'environnement.

local res, err = tar:call('table.concat', { {'hello', ' ', 'world' } })
-- réponse :
[["hello world"]]
Nous avons appelé la fonction table.concat de la bibliothèque table pour concaténer la table :

{'hello', ' ', 'world' }
La requête ci-dessus est équivalente à la requête de la console :

table.concat({'hello', ' ', 'world' })

Pour de nombreux exemples de procédures stockées tarantool, consultez le dépôt ; https://github.com/mailru/tarlua

hide_version_header

hide_version_header(<objet de connexion>)

Par défaut, chaque réponse envoie un en-tête HTTP personnalisé X-Tarantool-Version avec la version du serveur tarantool.

X-Tarantool-Version: 1.6.6-191-g82d1bc3

L'invocation de hide_version_header supprime l'en-tête.

tar:hide_version_header()

Elle ne retourne aucune valeur.

GitHub

Vous pouvez trouver des conseils de configuration supplémentaires et de la documentation pour ce module dans le dépôt GitHub pour nginx-module-tarantool.