Anuncios

Bienvenidos sean a este post, hoy veremos otra forma de almacenar nuestras notas.

Anuncios
Anuncios

En el post anterior vimos la primer alternativa para poder almacenar nuestras notas, en ese caso fue en el PC mediante un archivo de JSON, pero hoy nos centraremos en verlo en una «base de datos» aunque no es como tal, esta es LevelDB y es muy utilizada en los navegadores para almacenar informacion internamente, cuando nos referimos a que no es una base de datos como tal es por el hecho de que no tiene indices, no es SQL y tampoco nos permite algunas operaciones tipicas de base de datos pero como dijimos nos permite almacenar datos en nuestros navegadores y como node.js posee un modulo que nos permite manejarlo perfectamente vamos a agregarlo a nuestra aplicacion, para ello debemos usar el codigo que trabajamos en el post anterior, en caso de no poseerlo les dejo un link para descargarlo:

Anuncios

Una vez descargado simplemente extraen el directorio en el PC y ya tenemos nuestra aplicacion lista para ser utilizada, lo primero que deben hacer es ingresar al directorio notas y desde ahi ejecuten el siguiente comando:

$ npm install level@6.x --save
Anuncios
Anuncios

Este instalara el modulo que nos permitira trabajar con este engine, ahora podemos comenzar a trabajar con ella si no pasaron por el post anterior les hare un breve resumen. En ese post vimos como crear una fabrica (factory) para los distintos tipos de almacenamiento donde mediante una simple variable intercambiara cual es el encargado de manejar la informacion, y en caso de no informar alguno lo almacenara en memoria, la cual era la forma original al momento de crear la aplicacion, por esto nuestro siguiente paso sera crear un nuevo archivo en el directorio models con el nombre de notas-level.mjs y le agregaremos el siguiente codigo:

models/notas-level.mjs

import util from 'util';
import { Nota, AlmacenNotasAbs } from './Notas.mjs';
import level from 'level';
import { default as DBG } from 'debug';
const debug = DBG('notas:notas-level');
const error = DBG('notas:error-level');

let db;

async function conectarDB() {
if (typeof db !== 'undefined' || db) return db;
db = await level(
process.env.LEVELDB_LOCATION || 'notas.level', {
createIfMissing: true,
valueEncoding: "json"
});
return db;
}
Anuncios
Anuncios

Aqui importaremos todo lo necesario, la herramienta util, asi como nuestras clases para las notas, y el modulo level para nuestra base de datos, y el bloque encargado de la depuracion mediante debug, un objeto para la base de datos, solamente declarado, nuestra primera funcion sera para conectarse a la base de datos, el primer condicional sera para verificar si el tipo del objeto db es distinto de undefined o si ya esta creado por lo tanto ya esta conectado y devolvemos este objeto en caso contrario procede a crear el objeto de level, que en este caso es lo mismo que conectarse, en este primero verificamos si tenemos un valor mediante la variable de entorno LEVELDB_LOCATION sino utilizaremos el otro valor de manera predeterminada, sea cual sea el caso estableceremos dos propiedades de la conexion, por ultimo devolvemos el objeto creado, nuestro siguiente paso sera agregar el siguiente segmento de codigo:

export default class AlmacenNotasLevel extends AlmacenNotasAbs {
async cerrar() {
const _db = db;
db = undefined;
return _db ? _db.close() : undefined;
}

async update(clave, titulo, cuerpo) {
return crupdate(clave, titulo, cuerpo);
}

async create(clave, titulo, cuerpo) {
return crupdate(clave, titulo, cuerpo);
}

async read(clave) {
const db = await conectarDB();
const nota = Nota.desdeJSON(await db.get(clave)));
return nota;
}

async delete(clave) {
const db=await conectarDB();
await db.del(clave);
}

async listarClaves() {
const db = await conectarDB();
const clavez = [];
await new Promise((resolve, reject) => {
db.createKeyStream()
.on('data', data => clavez.push(data))
.on('error', err => reject(err))
.on('end', () => resolve(clavez));
});
return clavez;
}

async contar() {
const db = await conectarDB();
var total = 0;
await new Promise((resolve, reject) => {
db.createKeyStream()
.on('data', data => total++)
.on('error', err => reject(err))
.on('end', () => resolve(total));
});
return total;
}
}

async function crupdate(clave, titulo, cuerpo) {
const db = await conectarDB();
const nota = new Nota(clave, titulo, cuerpo);
await db.put(clave, nota.JSON);
return nota;
}
Anuncios
Anuncios

Ahora agregamos basicamente la clase que se encarga de las notas en Level, el default es para que pueda ser obtenido en la fabrica creada en el archivo notas-almacen.mjs, este sera heredero de la clase AlmacenNotasAbs y aqui definiremos las distintas funciones que heredamos, si vienen de los posts anteriores en los dos almacenamientos anteriores no habiamos definido a la funcion cerrar pero en este caso si debemos hacerlo porque sera la encargada de cerrar la conexion a la base de datos cuando hayamos terminado, para ello define como undefined al objeto db y cierra la copia que hicimos internamente, despues definimos update y create y para ambos casos pasaremos los datos a la funcion crupdate de la cual hablaremos en un momento, despues tenemos la funcion read la cual sera la encargada de leer la nota y para ello recibe la clave de la nota a buscar, se conecta a la base, crea un objeto llamado nota donde obtendremos la nota relacionado a la clave y por ultimo la devolveremos.

Anuncios
Anuncios

Lo siguiente sera la funcion delete y la usaremos para eliminar la clave informada, tambuen se conecta con la base y despues mediante del la eliminaremos en base a la clave informada, la siguiente funcion sera la encargada de listar las claves, de nuevo nos conectamos a la base, definimos un array vacio llamado clavez que usaremos para almacenar todas las claves de la base, para despues mediante una promesa obtendremos este dato y para ello tendremos dos variables que almacenaran los valores resueltos y rechazados respectivamente, dentro de este bloque crearemos un «key stream», es decir un stream que solo contendra las claves de la base, en este interceptaremos tres eventos, el primero sera para los datos, en este caso pasaremos el valor de data al array clavez, el siguiente sera para el caso de algun error y lo pasaremos a reject con el error pertinente y por ultimo tenemos a end donde pasaremos a resolve el valor final de clavez, por ultimo devolveremos este objeto, la siguiente funcion es para contar el total de notas, es muy similar a la anterior pero en lugar de obtener claves solamente incrementamos una variable por cada valor encontrado y por ultimo lo devolveremos.

Anuncios
Anuncios

Por fuera de la clase tenemos la funcion llamada crupdate que como comentamos anteriormente se encargara de crear y modificar las notas, de vuelta nos conectamos a la base, luego crearemos un objeto que sera la nota con los tres valores, para luego mediante put agregaremos la nota anterior a la base de datos, observen que usamos la funcion JSON para pasar los datos correctamente y para finalmente devolver el objeto nota, con esto ya tenemos todo casi cocinado pero vamos a hacer un par de modificaciones mas antes de finalizar, la primera modificacion sera agregar la siguiente linea en la seccion de scripts en el archivo package.json:

"lvl-start": "cross-env DEBUG=notas:* PORT=3000 MODELO_NOTAS=level node ./app.mjs"
Anuncios

Esta es para iniciar a nuestra aplicacion pero con la nueva configuracion, es muy similar a lo visto en otras oportunidades donde definimos el PORT, el tipo de notas (MODELO_NOTAS) y llamamos a la aplicacion en si, con esto podriamos probarlo pero antes vamos a realizar una ultima modificacion, para ello debemos ir al archivo appsupport.mjs y entre los modulos importados agregaremos la siguiente linea:

import { AlmacenNotas } from './models/notas-almacen.mjs';
Anuncios

Esto nos importara este elemento de nuestra fabrica de notas, nuestro siguiente paso sera agregar una funcion en conjunto con las otras funciones:

async function captarMuerteProc() {
debug('Ouuchh...');
await AlmacenNotas.cerrar();
await server.close();
process.exit(0);
}
Anuncios

Esta funcion sera la que usaremos cuando se finalice el proceso, en cualquier caso mostrara un mensaje indicando esto, luego cerraremos primero al objeto de la notas asi como tambien al servidor y por ultimo saldremos del proceso con una salida de 0, nuestra ultima modificacion sera agregar el siguiente segmento de codigo al final del archivo:

process.on('SIGTERM', captarMuerteProc);
process.on('SIGINT', captarMuerteProc);
process.on('SIGHUP', captarMuerteProc);
process.on('exit', () => { debug('saliendo...'); });
Anuncios

Observen que vamos a escuchar varios eventos de interrupcion del proceso, sea cual sea llamara a la funcion anterior para cerrar todo antes de salir y en el ultimo cuando encuentre el evento exit nos mostrara una notificacion de que esta saliendo, ahora con todo esto podemos probar como trabaja ahora nuestra aplicacion mediante el siguiente video

Anuncios

En el video podemos ver varias cosas, entre ellas que seguimos sin perder las notas mas alla de reiniciado el servidor sino que tambien tenemos notificaciones cada vez que lo cerramos, el resto sigue funcional y pueden probar para ver como trabaja, antes de finalizar les dejo un link con todos los archivos del proyectos y los codigos modificados en este post:

Anuncios

En resumen,, hoy hemos visto como almacenar datos en LevelDB, hemos visto sus practicidades a pesar de no ser una verdadera base de datos, la hemos agregado al listado de posibilidad de modelo de notas, tambien hemos visto como agregar una mejor salida de nuestra aplicacion al finalizarla, espero les haya resultado de utilidad sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.

Anuncios
pp258

Donación

Es para mantenimento del sitio, gracias!

$1.50