Desde la versión 8 de este magnífico ORDBMS, existe un mecanismo que permite enviar y recibir notificaciones de manera muy simple.
LISTEN
test=# NOTIFY foo;
NOTIFY
Notificación asíncrona «foo» recibida del proceso de servidor con PID 8872.
test=#
Esta característica -como menciona la documentación- es especialmente útil cuando existen procesos que deben estar englobados por una transacción, ejm. enviar un mail luego de la ejecución satisfactoria de un conjunto de procesos críticos.
A continuación un pequeño ejemplo realizado con el proveedor Npgsql, que implementa la caracterísca mencionada.
using System;
using Npgsql;
using System.Net.Mail;
using System.Net;
namespace listener
{
class Program
{
static void Main(string[] args)
{
NpgsqlConnection connection =
new NpgsqlConnection("uid=alex;pwd=***;server=localhost;encoding=unicode;SyncNotification=true;database=test;");
connection.Notification += new NotificationEventHandler(connection_Notification);
// Escuchar las notificaciones con el nombre 'proceso_largo'
using (NpgsqlCommand command =new NpgsqlCommand("LISTEN proceso_largo;", connection))
{
connection.Open();
command.ExecuteNonQuery();
}
Console.WriteLine("Esperando notificaciones...");
}
static void connection_Notification(object sender, NpgsqlNotificationEventArgs e)
{
Console.WriteLine("Notificación Recibida: {0}\t{1}", e.Condition, e.PID);
// Hacer algo útil
SmtpClient client =new SmtpClient("smtp.empresa.com");
client.Credentials =new NetworkCredential("usuario@empresa.com", "password");
client.Send(
"aplicacion_x@empresa.com",
"logs@empresa.com",
"Notificación aplicación_x",
"Notificación: " + e.Condition + "\tPID : " + e.PID // ...
);
}
}
}
Un cliente cualquiera:
using Npgsql;
using System.Threading;
namespace app
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Iniciar Aplicación - Presione una tecla...");
Console.Read();
using (NpgsqlConnection connection =
new NpgsqlConnection("uid=alex;pwd=***;server=localhost;encoding=unicode;database=test;"))
{
NpgsqlTransaction transaction = null;
try
{
connection.Open();
transaction = connection.BeginTransaction();
NpgsqlCommand command =new NpgsqlCommand("select current_date;", connection, transaction);
Console.WriteLine("Recuperando la fecha");
command.ExecuteScalar(); // hacer algo
Console.WriteLine("Enviando notificación - Transacción NO 'comprometida'.");
command.CommandText = "NOTIFY proceso_largo;";
command.ExecuteNonQuery(); // No ejecuta la notificación
// Continúa la transacción
Thread.Sleep(2000);
transaction.Commit();
Console.WriteLine("Transacción 'comprometida', recien se envía la notificación 'proceso_largo'");
}
catch (NpgsqlException)
{
if (transaction != null)
transaction.Rollback();
throw;
}
}
Console.Read();
}
}
}
Además de las cosas mencionadas sobre esta característica de PostgreSQL, también podría servir como un mecanismo para que el Cache tenga datos coherentes.
Nota: Disculpen si encuentran malas prácticas de programación :-).