Navigation

Related Articles

Back to Latest Articles

Notifications asynchrones avec node.js et Postgresql


laurent
Notifications asynchrones avec node.js et...

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.

Show Comments (2)

Comments

  • Grégoire Hubert

    Merci pour ce très bon article. Ça fait plaisir de voir une web agency qui blogue sur du Pg. Pour élargir un peu le sujet, à regarder également le plugin pg_amqp qui, vous l’aurez compris, permet de dialoguer avec des files de messages et faire du pub/sub, ce qui est également possible via Nodejs avec hook.io.

    Pour info, ça aurait pu également être intéressant de coupler le système de notification de Postrgresql sur l’event dispatcher de Symfony… c’était sans compter que PDO n’a jamais implémenté les fonctions LISTEN / NOTIFY de postgres (encore un grand pas en avant).

    • Article Author
  • Eric Mas

    Merci pour ce bel article qui montre bien toute la puissance que peut avoir un mécanisme de publish/subscribe couplé avec socket.io.

    J’ai réalisé le même exemple, tout marche bien à une exception près : lorsque le champs « content » de la ligne mise à jour en base est à null, aucun argument n’est reçu (pas même id et user_id qui pourtant ont bien une valeur) par le client instancié dans le script nodejs. Avez vous également constaté ce problème ?

    • Article Author

Recevez nos articles