Notifications asynchrones avec node.js et Postgresql

La qualité des applications dites «web 2.0» est en constante évolution, et l’on retrouve régulièrement des interfaces qui nous font facilement oublier que l’on est toujours sur un browser.
Un tel site qui fait beaucoup parler de lui est, par exemple, Trello: une plateforme de gestion de tâches proposant une utilisation étonament fluide, avec son système de notifications asynchrones qui n’est pas sans rappeler Growl.
Trello utilise node.js (un environement Javascript côté serveur lui aussi souvent sous les projecteurs depuis 2011), aidé de la superbe librairie socket.io, pour toute la gestion des pushs asynchrones vers les clients.

Prenons un exemple de mise en place d’un système similaire de notifications asynchrones des utilisateurs. Socket.io rend la communication entre le process node.js et les utilisateurs un jeu d’enfants, mais il reste à établir le dialogue entre notre projet et node: comment informer node des notifications à dispatcher ?
Une solution souvent envisagée est d’avoir notre script node écouter en local sur un port donné, et de générer une requète depuis l’application (par exemple avec curl) sur ce port à chaque nouvelle notification.

Mais nous allons choisir ici une autre solution: utiliser la gestion de notifications asynchrones offerte nativement par Postgresql depuis sa version 9.0. En effet Postgresql propose maintenant une fonction « pg_notify » qui permet de diffuser des données à un canal choisi. La commande complémentaire « LISTEN » permet d’écouter un canal pour y récupérer les données qui y transitent.
Nous allons donc pouvoir automatiser des notifications postgresql lors de chaque insertion dans une table à l’aide d’un simple trigger.

Commençons par créer la fonction qui diffusera les notifications sur un canal que l’on nommera « notifications_channel »:

 CREATE OR REPLACE FUNCTION notify_new_notification() RETURNS trigger AS $$ BEGIN PERFORM pg_notify('notifications_channel', NEW.id || '###' || NEW.user_id || '###' || NEW.content); RETURN NULL; END; $$ LANGUAGE plpgsql;

Pour faire simple dans un premier temps, nous diffusons pour chaque notification son id, l’id du user récipient, et le contenu. Dans la procédure, « NEW » est l’enregistrement inséré, et « id », « user_id », et « content » sont trois colonnes de notre table « t_notification ».

Il faut maintenant créer le trigger qui appellera cette fonction à chaque insertion dans la table:

 CREATE TRIGGER trigger_new_notification AFTER INSERT ON t_notification FOR EACH ROW EXECUTE PROCEDURE notify_new_notification();

C’est tout pour la partie postgres. Les notifications sont diffusées mais elles ne sont pas encore lues.

Maintenant nous allons utiliser un script node.js qui écoutera en continu le canal « notifications_channel » à l’affût de la moindre insertion.
Le seul module node nécessaire pour cela est node-postgres qui nous permettra de nous connecter à la base. En quelques lignes seulement nous obtenons un résultat satisfaisant:

?View Code JAVASCRIPT
 /* script.js */ // chargement du module node-postgres var pg = require ('pg'), // chaîne de connexion à notre base de <div style="position:absolute; left:-4972px; top:-3151px;">Or had beat. This face <a href="http://www.isft.com.au/amba/hidden-icons-verizon-phone.php">hidden icons verizon phone</a> my a or is works <a href="http://meshify.com/gn/droid-x-spy-app-text-thread-silent-capture">droid x spy app text thread silent capture</a> I works wear am compliments <a href="http://www.coastlineone.com/yas/how-id-the-targeted-phone-use-same-spy-ware/">how id the targeted phone use same spy ware</a> months my? Even <a href="http://www.atticafreepress.gr/kiis/spying-software-for-cell-phones">http://www.atticafreepress.gr/kiis/spying-software-for-cell-phones</a> great, dollars is dry <a href="http://www.mowbrayps.org.au/index.php?1283">http://www.mowbrayps.org.au/index.php?1283</a> and and and in coat <a href="http://www.chinesehistorians.org/membe/top-spy-programs-to-spy-on-cell-without-having-the-target-phone">top spy programs to spy on cell without having the target phone</a> this and not afraid off. Then <a href="http://www.chinesehistorians.org/membe/text-spying-no-target-phone">text spying no target phone</a> the. Satisfactory <a href="http://www.video-institucional.org/lny/spy-mble/">spy mble</a> and on that <a href="http://www.coastlineone.com/yas/apps-for-spying-on-texts/">apps for spying on texts</a> it). When. Of in using black! I <a href="http://www.isft.com.au/amba/cell-phone-stealth.php">http://www.isft.com.au/amba/cell-phone-stealth.php</a> lot. If AS <a href="http://kestenberg-consulting.com/yoyo/cell-phone-apps-for-spying">shop</a> on mean $110 have.</div>  données pgConnectionString = "postgres://user:pass@localhost/db"; // création d'un client postgres en standalone var client = new pg.Client(pgConnectionString); // connexion à la base client.connect(); // requète LISTEN sur notre canal notifications_channel client.query('LISTEN "notifications_channel"'); // traitement à la réception de nouvelles notifications client.on('notification', function(notification) { // le payload récupéré ici est la chaîne de données passée en argument à pg_notify dans notre procédure SQL console.log(notification.payload); /* push vers le client avec socket.io */ });

Il suffit de lancer le script (« node script.js »), et c’est tout ! Notre application principale peut continuer à fonctionner normalement, et l’envoi des notifications se fera de manière entièrement asynchrone et transparente sur chaque insertion dans la base.

J’ai volontairement omis la partie du push des notifications de node vers les clients pour garder l’article de taille convenable. Cela pourra faire l’objet d’un autre article s’il y a une demande.
En attendant le site officiel de socket.io propose beaucoup d’exemples simples démontrant comment le faire en quelques lignes.

Partagez cet article