NOTIFY — engendrer une notification
NOTIFYcanal
[ ,charge
]
La commande NOTIFY
envoie une notification avec une
chaîne de « charge » supplémentaire
à chaque application cliente qui a exécuté précédemment la commande
LISTEN
dans la base de données courante pour le nom du canal indiqué.
Les notifications sont visibles par tous les utilisateurs.
canal
NOTIFY
fournit un mécanisme simple
de communication interprocessus pour tout ensemble de processus accédant à
la même base de données PostgreSQL.
Une chaîne de charge peut être envoyée avec la notification, et des
mécanismes de plus haut niveau permettant de passer des données structurées
peuvent être construits en utilisant les tables de la base de données.
L'information passée au client pour une notification inclut le nom de la notification et le PID du processus serveur de la session le notifiant.
C'est au concepteur de la base de données de définir les noms
de notification utilisés dans une base de données précise et la
signification de chacun.
Habituellement, le nom du canal correspond au nom d'une table
dans la base de données. L'événement notify signifie
essentiellement « J'ai modifié cette table, jetez-y un œil pour
vérifier ce qu'il y a de nouveau ». Mais cette association n'est
pas contrôlée par les commandes NOTIFY
et
LISTEN
. Un concepteur de bases de données
peut, par exemple, utiliser plusieurs noms de canal différents pour signaler
différentes sortes de modifications au sein d'une même table. Sinon, la
chaîne de charge peut être utilisée pour différencier plusieurs cas.
Lorsque NOTIFY
est utilisé pour signaler des
modifications sur une table particulière, une technique de programmation
utile est de placer le NOTIFY
dans un trigger sur instruction
déclenchée par les mises à jour de la table. De cette façon, la notification
est automatique lors d'une modification de la table et le programmeur
de l'application ne peut accidentellement oublier de le faire.
NOTIFY
interagit fortement avec les transactions SQL.
Primo, si un NOTIFY
est exécuté
à l'intérieur d'une transaction, les événements notify ne sont pas délivrés
avant que la transaction ne soit validée, et à cette condition uniquement.
En effet, si la transaction est annulée, les commandes qu'elle
contient n'ont aucun effet, y compris NOTIFY
.
Cela peut toutefois s'avérer déconcertant pour quiconque s'attend à une
délivrance immédiate des notifications.
Secondo, si une session à l'écoute reçoit un signal de notification alors
qu'une transaction y est active, la notification n'est pas délivrée au client
connecté avant la fin de cette transaction (par validation ou annulation).
Là encore, si une notification est délivrée à l'intérieur d'une transaction
finalement annulée, on pourrait espérer annuler cette notification par
quelque moyen --
mais le serveur ne peut pas « reprendre » une notification déjà
envoyée au client. C'est pourquoi les notifications ne sont
délivrés qu'entre les transactions. Il est, de ce fait, important que les
applications qui utilisent NOTIFY
pour l'envoi de signaux
en temps réel conservent des transactions courtes.
Si le même nom de canal est signalé plusieurs fois à partir de la même
transaction avec des chaînes de charge identiques, le serveur de bases
de données peut décider de délivrer une seule notification. Par contre, les
notifications avec des chaînes de charges distinctes seront toujours
délivrées par des notifications distinctes. De façon similaire, les
notifications provenant de différentes transactions ne seront jamais
regroupées en une seule notification. Sauf pour supprimer des instances
ultérieures de notifications dupliquées, la commande
NOTIFY
garantie que les notifications de la même
transaction seront délivrées dans l'ordre où elles ont été envoyées. Il
est aussi garantie que les messages de transactions différentes seront
délivrées dans l'ordre dans lequel les transactions ont été validées.
Il est courant qu'un client qui exécute NOTIFY
écoute lui-même des notifications de même canal. Dans ce cas, il récupère une
notification, comme toutes les autres sessions en écoute.
Suivant la logique de l'application, cela peut engendre un travail
inutile, par exemple lire une table de la base de données pour trouver les
mises à jour que cette session a elle-même écrites. Il est possible d'éviter
ce travail supplémentaire en vérifiant si le PID du processus
serveur de la session notifiante (fourni dans le message d'événement de la
notification) est le même que le PID de la session
courante (disponible à partir de libpq).
S'ils sont identiques, la notification est le retour du travail actuel et
peut être ignorée.
canal
Nom du canal à signaler (identifiant quelconque).
charge
La chaîne de « charge » à communiquer avec la notification. Elle doit être spécifiée comme une chaîne litérale. Dans la configuration par défaut, elle doit avoir une taille inférieure à 8000 octets. (Si des données binaires ou de tailles plus importantes doivent être communiquées, il est mieux de les placer dans une table de la base et d'envoyer la clé correspondant à l'enregistrement.)
Il existe une queue qui récupère les notifications qui ont été envoyées
mais pas encore traitées par les sessions en écoute. Si la queue est
remplie, les transactions appelant NOTIFY
échoueront à
la validation. La queue est assez large (8 Go dans une installation
standard) et devrait être suffisamment bien taillée dans la majorité des
cas. Néanmoins, aucun nettoyage ne peut se faire si une session exécute
LISTEN
puis entre en transaction pendant une longue
période. Une fois qu'une queue est à moitié pleine, des messages
d'avertissements seront envoyés dans les traces indiquant la session qui
empêche le nettoyage. Dans ce cas, il faut s'assurer que la session termine
sa transaction en cours pour que le nettoyage puisse se faire.
La fonction pg_notification_queue_usage
renvoie la
fraction de queue actuellement occupée par des notifications en attente.
Voir Section 9.25 pour plus d'informations.
Une transaction qui a exécuté NOTIFY
ne peut pas être
préparée pour une validation en deux phases.
Pour envoyer une notification, vous pouvez aussi utiliser la fonction
. La fonction prend en premier argument le
nom du canal et en second la charge. La fonction est bien plus simple à
utiliser que la commande pg_notify
(text
,
text
)NOTIFY
si vous avez besoin de
travailler avec des noms de canaux et des charges non constants.
Configurer et exécuter une séquence listen/notify à partir de psql :
LISTEN virtual; NOTIFY virtual; Asynchronous notification "virtual" received from server process with PID 8448. NOTIFY virtual, 'This is the payload'; Asynchronous notification "virtual" with payload "This is the payload" received from server process with PID 8448. LISTEN foo; SELECT pg_notify('fo' || 'o', 'pay' || 'load'); Asynchronous notification "foo" with payload "payload" received from server process with PID 14728.
Il n'y a pas d'instruction NOTIFY
dans le standard SQL.