Futur De RamSQL
RamSQL est un moteur SQL léger, en RAM, qui a pour objet d’aider à
- vérifier la validité des schémas SQL
- vérifier facilement la validité des queries SQL
Ce projet a 8 ans maintenant. Désormais de nombreux “vrai” SQL engines propose un mode “in memory”
ou encore faire tourner un container dans la CI pour les tests.
Bref, la première question à se poser concernant le futur de RamSQL c’est de savoir s’il faut archiver le projet et pointer vers d’autres solution.
Archiver le projet ?
Je veux essayer de lister dans cette section des arguments en faveur de RamSQL, qui justifieraient de poursuivre le développement. Mais commençons par les arguments en faveur d’un archivage.
Grammaire SQL incomplète
La grammaire gérée par RamSQL n’est pas complète, et ne sera jamais aussi complète que celle de SQLite ou MySQL. Le travail à fournir est titanesque et je suis loin de gérer l’ensemble des corners cases.
Pas d’Index
Les index ne sont pas implémenté, ce qui empêchent tout tests de query lié à un index spécifique.
Aujourd’hui le CREATE INDEX
n’est même pas parsé, ce qui empêche même la validation de la plupart des fichiers de schémas SQL.
CREATE TABLE some_table (id BIGSERIAL AUTOINCREMENT, name TEXT, content TEXT);
CREATE INDEX some_table_index ON some_table (name, content);
$ ramsql < index.sql
ramsql> Query OK. 1 rows affected
ramsql> ERROR : cannot execute : Parsing failed, unknown token index
ramsql> exit
Pas de Foreign Key
Encore une fois, le principe même de RamSQL étant de tester la validité des queries avec des tests unitaires, si les contraintes de foreign key ne sont pas respecté, l’intérêt est limité.
Pas de Returing
Composant assez classique d’une query d’insert, le RETURING ne fonctionne pas vraiment, l’implémentation est bancale
Plusieurs deadlocks
Le code comporte pas mal de deadlock qui sont difficilement resolvable vu la qualité du code.
Pas de release sur Github, ni de tag v1.
Les utilisateurs n’ont aucune idée de ce à quoi s’attendre avec RamSQL en arrivant sur la page du projet. Le code n’est pas tagué, il n’y a pas de release note, et aucune matrice de feature set n’est présente dans le README. Personnellement, je n’aurais pas confiance.
Continuer le projet ?
Oui mais…RamSQL a peut-être encore une place dans l’écosystème des imdb, spécifiquement dans l’écosystème du testing.
Rapidité d’exécution
Écrire un test avec RamSQL c’est avoir la rapidité de son coté. Les gens développent en Go en partie parce que la compilation est très rapide, on veut aussi des tests rapide. Impossible de faire du TDD s’il faut plus de 30s pour executer la test suite entière.
Et là ben…RamSQL est devant. C’est un package Go, le code tourne dans le même process que les tests. Pas d’histoire de docker, pas de setup externe. Le setup/teardown d’un test utilisant RamSQL est de 5ms.
$ time go test -count=1 -v ./... | grep PASS | wc -l
121
real 0m0.851s
user 0m1.125s
sys 0m1.547s
Portabilité
Encore une fois, c’est une lib Go. RamSQL a le même niveau de compatibilité que Go: pas de bindings C/pas d’installation de docker.
Dead simple
Less is more, toussa.
Cependant, la facilité d’utilisation de RamSQL est toujours très agréable, à chaque fois que j’en ai eu besoin. Il suffit d’importer le driver et c’est parti.
import (
"testing"
_ "github.com/proullon/ramsql"
)
func TestCRUD(t *testing.T) {
db, err := sql.Open("ramsql", "TestCRUD")
db.Exec(`CREATE TABLE my_stuff (...)`)
id, err = InsertStuff(db, stuff)
stuff, err := GetStuff(db, id)
err = DeleteStuff(db, if)
}
Done.
C’est utilisé
Malgré l’ensemble des limitations et des bugs, RamSQL est utilisé. J’ai envie de faire en sorte que ces gens aient au moins une version clean.
D’après Github, le traffic journalier sur RamSQL est d’une centaine de visite unique et le double pour les clones.
Ce qui nous amène à…
RamSQL v1.0
Objectif v1.0 pour RamSQL. Je ne sais pas si j’aurais envie de continuer le développement ensuite, mais au moins le projet sera propre, et la documentation également.
Je veux que d’un coup d’oeil au README, on puisse savoir si RamSQL convient.
Je veux que le projet soit bugfree dans le scope défini.
Je veux que les avantages et inconvénient soient clairement documentés.
Features SQL
Features dédiées au testing
Query history
RamSQL devrait sauvegardé les queries exécutées pour permettre un debug plus facile, j’ai utilisé RamSQL récemment pour un test technique et je me suis surpris à vouloir cette feature.
CLI breakpoint
Je veux qu’il soit possible au milieu d’un test d’intégration de stopper l’application et d’ouvrir la CLI de RamSQL. Cette feature permettrait de servir de breakpoint pour inspecter le contenu de la db avec un lock complet, ce qui mettrait de facto en pause le programme à debug.
Encore une fois, j’aurais aimé avoir cette feature au moment de debug une valeur étrange inséré au fin fond d’une goroutine lors d’un test technique.
Better CLI
Les deux derniers points implique également d’améliorer la CLI pour intégrer l’historique, up, down, etc.
Autogeneration
Taille maximale d’une table ou de la database
Il y a une issue ouverte pour cette feature request, je n’y avais pas pensé mais ça peut être intéressant pour faire un peu de chaos engineering.
Features dédiées au LFRU caching
J’ai eu plusieurs fois le cas d’usage d’un LFRU en cache directement dans l’application, que ce soit une grosse table avec une petite partie chaude, soit simplement une petite table. J’avais une grosse contrainte réseau par contre, donc cacher facilement dans l’application directement au lieu de tabasser un redis a fait gagner des perfs énormes, pour quelques Gb de RAM.
Il “suffit” que quelques éléments soient présents.
Peut-être que RamSQL peut fournir le nécessaire:
- Indexing (facile si c’est fait de toute façon)
- RAM limit (facile si c’est fait de toute façon)
- Algorithme LFRU activable sur une table
Reste le cache invalidation à plug quelque part.
Architecture technique
Réecriture
Le projet entier a besoin d’être réécrit. J’étais parti à l’époque avec l’idée de communiquer localement via channel entre le driver et l’engine, mais avec l’objectif de feature set actuel ce n’est pas nécessaire.
L’engine doit être réécrit avec transactions from scratch, pour permettre l’implémentation des transactions et auto-commit.
Les tests doivent être triés et regroupés, pour faciliter le travail des contributeurs.
Le binaire CLI doit être bougé dans cmd/ramsql
, pour permettre d’importer github.com/proullon/ramsql
qui contiendrait les features de tests et debug.
Documentation
Le projet doit être documenté avec:
- Matrice croisée de features avec les catégories
planned
parsed
implemented
- Objectif final de cas d’usage
- Code d’exemple pour du test et du LFRU caching
Roadmap
- Transaction object
- Relation rewrite
- transaction safe
- size counting
- map[int]int indexes
- Engine rewrite
- query history
- transaction safe
- ramsql.CLI()
- ramsql.Generate()
- ramsql.History()
- Parser generation with BnF grammar
- Size limits
- Indexes
- LFRU