27.6. Notification asynchrone

PostgreSQL propose des notifications asynchrone via les commandes LISTEN and NOTIFY. Une session cliente enregistre son intérêt pour une notification particulière avec la commande LISTEN (et peut arrêter son écoute avec la commande UNLISTEN). Toutes les sessions écoutant une condition particulière sont notifiées de façon asynchrone lorsqu'une commande NOTIFY avec ce nom de condition est exécutée par une session. Aucune autre information n'est passée du notifieur au notifié. Du coup, souvent, toute donnée qui a besoin d'être communiquée est transférée via une table de la base. D'habitude, le nom de la condition est identique à la table associée mais il n'est pas nécessaire d'avoir une table associée.

Les applications libpq soumettent les commandes LISTEN et UNLISTEN comme des commandes SQL ordinaires. L'arrivée des messages NOTIFY peut être détectée ensuite en appelant PQnotifies.

La fonction PQnotifies renvoie la prochaine notification à partir d'une liste de messages de notification encore non gérés reçus à du serveur. Elle renvoie un pointeur nul s'il n'existe pas de notifications en attente. Une fois qu'une notification est renvoyée par PQnotifies, elle est considérée comme traitée et est supprimée de la liste des notifications.

PGnotify* PQnotifies(PGconn *conn);

typedef struct pgNotify {
    char *relname;              /* nom de la condition de la notification */
    int  be_pid;                /* ID du processus serveur */
    char *extra;                /* paramètre de notification */
} PGnotify;

Après avoir traité un objet PGnotify renvoyé par PQnotifies, assurez-vous de le libérer avec PQfreemem. Il est suffisant de libérer le pointeur PGnotify ; les champs relname et extra ne représentent pas des allocations séparées. (Actuellement, le champ extra est inutilisé et pointe toujours vers une chaîne vide.)

Note : Avec PostgreSQL 6.4 et ultérieur, le champ be_pid est celui du processus serveur ayant lancé la notification alors que, pour les versions précédentes il s'agissait toujours du PID de votre propre processus serveur.

Exemple 27-2 donne un programme d'exemple illustrant l'utilisation d'une notification asynchrone.

PQnotifies ne lit pas réellement les données à partir du serveur ; il renvoie simplement les messages précédemment absorbés par une autre fonction de libpq. Dans les précédentes versions de libpq, la seule façon de s'assurer d'une réception à temps des messages NOTIFY consistait à soumettre constamment des commandes, même vides, puis de vérifier PQnotifies après chaque PQexec. Cette méthode fonctionne toujours, mais elle est dépréciée à cause de sa consommation inutile de puissance de calcul.

Une meilleure façon de vérifier les messages NOTIFY lorsque vous n'avez pas de commandes utiles à exécuter est d'appeler PQconsumeInput puis de vérifier PQnotifies. Vous pouvez utiliser select() pour attendre l'arrivée des données à partir du serveur, ce qui ne consomme aucune puissance du CPU sauf lorsqu'il y a quelque chose à faire. (Voir PQsocket pour obtenir le numéro du descripteur de fichiers à utiliser avec select().) Notez que ceci fonctionne bien, que vous soumettiez les commandes avec PQsendQuery/PQgetResult ou que vous utilisiez simplement PQexec. Néanmoins, vous devez vous rappeler de vérifier PQnotifies après chaque PQgetResult ou PQexec, pour savoir si des notifications sont arrivées lors du traitement de la commande.