Archive for the 'SimpleDatabase' Category

SimpleDatabase, implementando RethinkDB en NodeJS (1)

Monday, January 4th, 2016

Hace ya unos años entró en mi radar el proyecto:

http://www.rethinkdb.com

y si bien no tuve que usarlo en ninguno de mis trabajos profesionales, me interesó la idea que expresa en su API. Esto me llevó a comenzar a implementarlo, en memoria, con JavaScript/NodeJS, y con métodos sincrónicos (otro que nació hace tiempo ya es el OStore, que ya emula bastante de MongoDB, directamente en memoria). Y por supuesto, como una excusa más para practicar TDD.

Pueden leer más de la API original del proyecto en:

http://www.rethinkdb.com/api/

Mi implementación inicialmente tenía métodos como:

sdb.dbCreate('purchases').run();

Vean que el .run() era el que lanzaba la ejecución de todo lo que se expresaba antes (algo así también implementé en SimpleAsync, y en estos días saqué la necesidad de poner .run(), simplemente se ejecuta). Pero el run() de RethinkDB es algo más interesante. Mientras que la fluent API va expresando lo que se va a ejecutar, el run lo lanza y ejecuta contra una connection.

Entonces. en estos días festivos, refactoricé mi código a soportar cosas como en este test::

exports['create database'] = function (test) {
    test.async();
    
    sdb.dbCreate('purchases').run(connection, function (err, data) {
        test.ok(!err);
        test.ok(data);
        test.done();
    });
};

La connection por ahora es local, y se obtiene con código como:

exports['get connection'] = function (test) {
    test.async();
    
    sdb.connection(function (err, data) {
        test.ok(!err);
        test.ok(data);
        connection = data;
        test.done();
    });
};

En la API original de RethingDB, al pedir una connection se especifica en que servidor y puerto está escuchando.

Por eso, estoy pensando en luego refactorizar para tener una connection que establezca una comunicación con un servidor remoto. No parece complicado, luego del trabajo que realicé de llamar a objetos remotos (ver SimpleRemote).

Lo interesante es que toda la fluent API que precede al run, va armando internamente lo que tiene que ejecutar, y luego lo lanza contra la connection que se le provee al final. Cuando la connection sea remota, tengo pensado serializar a JSON el comando armado y enviarlo a ejecutar en el servidor remoto (una estrategia parecida a la que ví en la implementacion de Linq en .NET)

La API original es bastante larga, y me falta implementar decenas de métodos. Pero hay algunos interesantes, que ya van tomando forma, como la inserción de registros:

sdb.db('test')
.table('users')
.insert([
    { name: 'Adam', age: 800 },
    { name: 'Eve', age: 700 }
])
.run(connection, function (err, data) {
    // callback code
});

y el armado de funciones a aplicar en un update o en un filter:

sdb
.db('company')
.table('persons')
.get(adamId)
.update({ age: sdb.row('age').add(100) })
.run(connection, next);

Para los tests, estuve haciendo “dog fooding” de mi proyecto SimpleAsync, que permite encadenar callbacks, ejemplo:

exports['insert document'] = function (test) {
    test.async();
    
    var doc = { name: 'Adam' };
    
    async()
    .exec(function (next) {
        sdb
        .db('test')
        .table('persons')
        .insert(doc)
        .run(connection, next);
    })
    .then(function (result, next) {
        test.ok(result);
        test.equal(result.inserted, 1);
        test.equal(result.errors, 0);
        test.ok(result.generated_keys);
        test.equal(result.generated_keys.length, 1);
        test.equal(result.generated_keys[0], 1);

        test.done();
    })
};

Espero seguir descriendo la implementación en próximos posts. TDD (Test-Driven Development) me ha servido en la semana pasada para encarar el refactor quirúrgico de reimplementar todo a usar una connection y método run asincrónico. No ha sido fácil, pero tampoco fue algo muy difícil: una vez establecida firmemente la implementación de una connection local, cimentada con el flujo de trabajo de TDD, luego pude refactorizar el API pública para que aceptara ser asincrónica en el run.

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez