7

Creando una API Realtime con PostgreSQL

2065Puntos

hace 9 años

PostgreSQL es la base de datos que nos permite llevar a cabo funciones que normalmente no serían posibles con SQL. Una de ellas es obtener notificaciones en tiempo real.

Hoy vamos a retomar el ejemplo del artículo Cómo crear un API JSON en PostgreSQL con NodeJS y le vamos a agregar esta funcionalidad. De esta manera, cuando se agregue un nuevo elemento a la lista, todos los clientes conectados sabrán que hubo un cambio y actualizarán sus datos automáticamente.

Para crear una aplicación en tiempo real con PostgreSQL, lo que hacemos es enviar una notificación a todos los clientes cada vez que se realiza algún cambio usando el comando NOTIFY. Al hacerlo, debemos indicar qué canal deseamos usar y, de manera opcional, también podemos enviar un paquete de datos. Del mismo modo, para mantener nuestros datos actualizados en tiempo real tenemos dos opciones:

  • La primera es sólo enviar una notificación desde NodeJS a un canal cada que hagamos cambios. Esto le indica a los clientes que deben actualizar los datos que se relacionen con ese canal; ya sea agregando los cambios que deben aplicar directamente en la notificación, o enviarla sin datos y que los clientes descarguen los datos necesarios.
  • La segunda opción es usar la consola de PostgreSQL para crear una función en nuestra base de datos que envíe una notificación y después crear un trigger que llame esta función cuando se detecte un insert-query. Esto debe hacerse por cada tabla que deseamos observar. Este último método es difícil de ejecutar y propenso a error humano. Además, tiene más sentido hacer esta clase de cambios desde el controlador (NodeJS) que desde el modelo (PostgreSQL). Así que para este ejemplo, usaremos la primera opción.

En el Backend

Para las notificaciones usaremos la librería node-postgres para comunicar NodeJS con la base de datos; y Socket.IO para comunicarnos con los clientes via Web Sockets. Empecemos por agregar estas dependencias: server.js

// Socket Server var server = require('http').Server(app); 
// Socket.IO var io = require('socket.io')(server); 
// PostgreSQL var massive = require("massive"); var pg = require ("pg");`

Para que nuestro servidor de Web Sockets funcione correctamente, debemos iniciar Express usando el servidor HTTP. server.js

var startExpress = function(){ server.listen(config.express.port); db = app.get('db'); }

Ahora debemos conectar node-postgres con nuestra base de datos y ejecutar el comando LISTEN agregando el nombre del canal que deseamos escuchar. Esto para poder segmentar las notificaciones de nuestra aplicación.

Para nuestro ejemplo usaremos un canal al que llamaremos changes. Cuando recibamos una notificación de PostgreSQL, emitiremos un mensaje por Web Sockets a nuestros clientes con el dato change. Si tenemos más de un canal, podremos saber qué canal envió la notificación si revisamos el valor de data.channel. Podemos pasar esta información a un switch case para emitir el mensaje correcto, o bien, emitir directamente el nombre del canal por Web Sockets. server.js

var connectionString = "postgres://"+config.postgres.user+":"+config.postgres.password+"@"+config.postgres.host+"/"+config.postgres.db; 
var pgClient = new pg.Client(connectionString); 
pgClient.connect(); 
pgClient.query('LISTEN "changes"'); 
pgClient.on('notification', function(data) { io.emit("change"); });

Enviar una notificación por PostgreSQL es muy fácil. Basta con ejecutar:
_pgClient.query('NOTIFY_ "<nombre_del_canal>"')</nombre_del_canal> cuando guardemos información en la base de datos.

server.js

var update = function(request, res, next) { var newDoc = request.body.data;
 db.steps.saveDoc({id:1,data:newDoc}, function(err,response){ if (err) { handleError(err) }; 
res.json({ data: response }); 
pgClient.query('NOTIFY "change"'); }); } 

En el Frontend

Ahora que ya tenemos los ajustes en el backend, es hora de hacer unos pequeños ajustes en el cliente de ReactJS. Lo primero que debemos hacer es crear un método para establecer la conexión por Web Sockets y un objeto en el que vamos a guardar dicha conexión. reactApp.jsx

var socket; 
var startSocket = function() { socket = io(window.location.hostname); }

Ahora debemos agregar el código adicional a nuestra aplicación de ReactJS, este debe ir en nuestro componente de mayor jerarquía y colocarse en en el evento componentDidMount. Lo primero que debemos hacer es llamar startSocket() para iniciar nuestra conexión. Después, debemos crear un evento que mande llamar downloadData() cuando recibamos una notificación. En este caso change, para que cada que se reciba la notificación de que hubo un cambio, ReactJS se encargue de descargar los datos y realizar los ajustes necesarios en el DOM para actualizar la vista.

reactApp.jsx

componentDidMount: function() { instance = this; 
downloadData(); 
startSocket(); 
socket.on('change', function (data) { downloadData(); }); } 

No olvides ejecutar el comando jsx -x jsx -w jsx/ js/ desde tu consola para que se actualicen los cambios que realizaste en tu aplicación de ReactJS. Ahora sólo necesitamos descargar la librería de Socket.io en nuestro cliente. Esta se agrega de forma automática a nuestro servidor por defecto; por lo que sólo necesitamos agregar la ruta socket.io/socket.io.jsindex.html

Listo, ahora tenemos una aplicación que funciona en tiempo real con PostgreSQL.

Te invito a que hagasfork al repositorio en Github y nos compartas tus ideas, mejoras y creaciones con lo que hoy aprendimos. Y si deseas aprender más sobre este y otros secretos de las bases de datos y aplicaciones en tiempo real, tenemos cursos de PostgreSQLReactJS y de Node.js en Platzi. Si te interesa algún tema en específico, no dudes en dejarlo en los comentarios.

Cesar
Cesar
reicek

2065Puntos

hace 9 años

Todas sus entradas
Escribe tu comentario
+ 2