Home »

MammutDB: Functional ΠWEEK

Durante la última ΠWEEK nos juntamos el equipo triple-A (Andrey, Alejandro y Alonso) para petarlo. Dijimos, las web ya están muy vistas así que vamos a hacer algo distinto… por ejemplo, una Base de Datos.

Nos han preguntado muchas veces ¿Qué aporta MammutDB?

Existe en la comunidad un poco de “rant” debido a que el modelo relacional de base de datos no ha evolucionado desde los 70 cuando se creó. Además, en muchos casos, no ha avanzado pese a que tenemos un hardware 100 veces superior al de aquella época.

MammutDB nace inspirándose en ideas de otras bases de datos similares como CouchDB y, en menor medida, a Datomic.

Base de datos inmutable

Se trata de una BBDD orientada a documentos JSON (aunque con vistas a soportar otros tipos) y cuya principal característica es que es inmutable.

¿Qué significa esto? Una vez creado el documento no lo actualizamos “in-place” sino que añadimos una nueva revisión a su histórico. De esta forma podemos recuperar cualquier revisión del documento en el que haya estado. Esto implica también que los datos que ha habido no “desaparecen” ya que podemos acceder a alguna de sus revisiones.

Esto, que puede parecer una locura, lo estamos haciendo todos los días con nuestros sistemas de control de versiones y sabemos los beneficios que aporta. ¿Por qué no hacerlo con nuestras datos? ¿no sería la analítica trivial? ¿no es cierto que podríamos revertir una versión de un documento “corrupta” a una que sabemos que es correcta?

OCC (Optimistic Concurrency Control)

Otra característica que queríamos incorporar es el soporte a OCC. Esto significa que si alguien intenta actualizar un documento desde una versión antigua va a fallar a no ser que primero recupere la versión más reciente.

Esto normalmente está implementado a nivel de aplicación pero que es fundamental en ciertos contextos (por ejemplo al editar las páginas de una wiki… ) y merece ser llevado a nivel de BBDD.

Esta característica se puede activar o desactivar a nivel de creación de colecciones según nos interese.

OCC error

API HTTP

Soporte nativo a HTTP mediante un API REST permite la fácil interoperabilidad con las aplicaciones o entre varias instancias de cara a futuro. Además reduce radicalmente la barrera de entrada a quien quiera usar MammutDB.

Nos dio tiempo a implementar un motor de queries que también se puede acceder por HTTP y que tiene un “toque” funcional, en vez de página y offset usamos take y drop 🙂

Storage: PostgreSQL 9.4

Al ser un proyecto que tiene que ser desarrollado en una semana no nos podíamos complicar la vida con las “tripas” por lo que utilizamos PostgresSQL 9.4beta1 como almacenamiento y su soporte de JSONB para almacenar los documentos.

La idea era no tener que resolver el problema del almacenamiento a corto plazo pero tener un storage robusto desde principio con la premisa de que podría ser el storage definitivo que acabaríamos usando. De ahí la elección de PostgreSQL.

También está en consideración la posibilidad de hacer el storage plugable (con todos los posibles problemas adicionales que resolver como transaccionalidad, sistema de consultas, indexado …), pero aún es pronto para saber donde queremos centrar nuestros esfuerzos.

Es posible que sea más interesante centrarse en otros muchos temas igual de complejos que aún no están resueltos.

Cliente WEB

De cara a la demo y para demostrar que la base de datos era práctica decidimos hacer una interfaz que accediera al backend a través de su API. Este cliente (como no) se desarrolló en Clojurescript usando la biblioteca Om.

Om es un wrapper sobre ReactJS en Clojurescript. ReactJS es una herramienta que mantiene un DOM virtual con el que va actualizando el DOM real según va cambiando lo que tiene en memoria. Esta aproximación encaja muy bien con paradigma funcional de Clojurescript y es un “match” perfecto cuando lo usas con Om.

Acostumbrado a otras bibliotecas clientes de Javascript puedo decir que la velocidad de ReactJS es asombrosa y se nota la aplicación mucho más rápida que con otras bibliotecas como AngularJS. La pega es que no te da el resto de facilidades que esta última a la hora de organizar el código en diferentes partes.

Lo bueno es que al estar usando Clojurescript pudimos usar la magnífica biblioteca “core.async” con lo que obtuvimos un código mucho más limpio teniendo sus diferentes componentes comunicándose independientemente a través de canales y suscripciones.

Insert a document

PRE-ΠWEEK

CATS

Inspirados un poco por Haskell y su biblioteca estándar Alejandro y Andrey empezaron a trabajar en una biblioteca para llevar estos conceptos a Clojure: cats. La ventaja de usar algunas de las abstracciones que provee cats (como la mónada Either) es que nos permite separar la gestión de errores de la lógica de negocio en vez de entremezclarlas como se hace habitualmente.

Definición de tareas y arquitectura

Un proyecto tan grande era difícil de coordinar para 3 personas en una única semana por lo que Andrey le dio cera antes de empezar. Desarrolló tanto una versión de la arquitectura general como una estructura que resultó muy buena base para el trabajo posterior, además de una clara definición de las tareas a realizar.

Full-stack Clojure

Otra de las características de MammutDB es que es 100% clojure, tanto la base de datos propiamente dicha como el cliente de administración que hicimos de ejemplo. Esto no fue accidental 😛 uno de nuestros objetivos personales para este proyecto era usar Clojure/Clojurescript en un proyecto más complejo que el típico “pet project” del tiempo libre.

La experiencia ha sido más que satisfactoria, creemos que Clojure es un lenguaje que está maduro y muy bien preparado para solucionar los problemas de hoy en día, es sobre todo un lenguaje práctico.

Además las herramientas que dispone como el REPL, leiningen y la integración con las máquinas virtuales de JVM y Javascript

hace que sea mucho más sencillo la incorporación a otros proyectos.

Conclusiones

Sobre Clojure

Tanto Clojure como Clojurescript son herramientas muy maduras y están listas para el “spotlight”. Creemos firmemente que van a empezar a proliferar aplicaciones usando estas tecnologías.

Paradigma funcional

Clojure es un lenguaje de programación funcional, con estructuras de datos inmutables y una clara separación de estado e identidad que en algún modo ha influido el diseño de MammutDB. La aproximación funcional a la implementación de MammutDB ha hecho que tengamos código fácilmente extensible y nos ha permitido desacoplar la lógica de negocio y de gestión de errores.

Toolkit pulido

Las herramientas de desarrollo de Clojure(Script) hacen posible un la programación interactiva, con un feedback muy rápido y continuo. El REPL permite la inspección directa del sistema que estamos desarrollando, y podemos ejecutar los tests o recargar el código desde el mismo. Leiningen permite la compilación, ejecución y distribución de código de forma muy simple. Nos ha sorprendido la madurez y capacidad de las herramientas aunque es cierto que nos hemos encontrado algún “breakage”, especialmente en ClojureScript.

Sobre OM/ReactJS

Para mi ha sido la gran sorpresa del proyecto. ReactJS tiene una velocidad de desarrollo y de renderizado que nos ha sorprendido. Por otro lado la integración con Om y la afinidad que tiene con el paradigma funcional la convierten en una gran opción en el cliente para futuros proyectos.

Visión a futuro

Este no es un proyecto pensado para “cerrarlo” en una ΠWEEK. Es un prototipo y ha servido para poder investigar sobre un tema que creemos que tiene mucho potencial. A largo plazo la aplicación tiene que evolucionar mucho aún para estar “production-ready” y nos parece un proyecto de investigación muy interesante.