/PostgresPubSub

Primary LanguageC#MIT LicenseMIT

Postgres Pub/Sub

Code sample to use Postgresql Notify and Listen commands as a Pub/Sub server, with C# and Npgsql.

Try it

You can start a Postgresql server with the following docker command :

docker run -d -p 5432:5432 --name pubsub-postgres -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=pwd1234 postgres:latest

You can now start the two console apps. One will send a message, the second will display the message received.

How it works : send a notification

You can send a notification to a specific channel with either of the following command :

NOTIFY channel, 'message';
SELECT pg_notify('channel', 'message');

In a C# app with Npgsql, you can do it like that :

await using var dataSource = NpgsqlDataSource.Create(connectionString);
await using (var cmd = dataSource.CreateCommand($"SELECT pg_notify('message',  @message)"))
{
    cmd.Parameters.AddWithValue("message", msg);
    await cmd.ExecuteNonQueryAsync();
}

How it works : listen to a channel

You can listen to a channel with this command :

LISTEN channel

In a C# app, you can do it like that :

First, you open the connection, and you register the Notification event :

await connection.OpenAsync();
connection.Notification += (sender, args) =>
{
    logger.LogInformation("Notification received. Channel: {Channel}; Payload: {Payload}", args.Channel, args.Payload);
};

Now you can start listening the channel :

var cmd = dataSource.CreateCommand("LISTEN channel", connection);	
await cmd.ExecuteNonQueryAsync();

The Notification event isn't raised in real time , see docs) :
"Since asynchronous notifications are rarely used and processing can be complex, Npgsql only processes notification messages as part of regular (synchronous) query interaction"

Here I want real time notifications, so I used the WaitAsync method to be sure the event is raised as soon as the message is sent to a channel :

while (true)
{
    await connection.WaitAsync();
}