#logging #postgresql #notifications #notfiy

postgres-notify

Library that makes it easy to subscribe to PostgreSQL notifications

1 unstable release

Uses new Rust 2024

new 0.2.1 May 21, 2025

#1073 in Database interfaces

MIT license

24KB
324 lines

Maintenance

postgres-notify

PGNotifier makes it easy to subscribe to PostgreSQL notifications.

There are few examples in Rust that show how to capture these notifications mostly because tokio_postgres examples spawn off the connection half such that you can't listen for notifications anymore. PGNotifier also spawns a task for the connection, but it also listens for notifications.

PGNotifier maintains a two list of callback functions, which are called every time the it receives a notification. These two lists match the types of notifications sent by Postgres: NOTIFY and RAISE.

LISTEN/NOTIFY

For a very long time (at least since version 7.1) postgres has supported asynchronous notifications based on LISTEN/NOTIFY commands. This allows the database to send notifications to the client in an "out-of-band" channel.

Once the client has issued a LISTEN <channel> command, the database will send notifications to the client whenever a NOTIFY <channel> <payload> is issued on the database regardless of which session has issued it. This can act as a cheap alternative to a pubsub system.

When calling subscribe_notify with a channel name, PGNotifier will call the supplied closure upon receiving a NOTIFY message but only if it matches the requested channel name.

use postgres_notify::PGNotifier;

let mut notifier = PGNotifier::spawn(client, conn);

notifier.subscribe_notify("test-channel", |notify| {
    println!("[{}]: {}", &notify.channel, &notify.payload);
});

RAISE/LOGS

Logs in PostgreSQL are created by issuing RAISE <level> <message> commands within your functions, stored procedures and scripts. When such a command is issued, PGNotify receives a notification even if the call is in progress, which allows a user to capture the execution log in realtime.

PGNotify simplifies log collection in two ways: first it provides the subscribe_raise function, which registers a callback. Second, it also provides the capture_log and with_captured_log functions.

use postgres_notify::PGNotifier;

let mut notifier = PGNotifier::spawn(client, conn);

notifier.subscribe_raise(|notice| {
    // Will print the below message to stdout
    println!("{}", &notice);
});

// Will capture the notices in a Vec
let (_, log) = notifier.with_captured_log(async |client| {
    client.batch_execute(r#"
       do $$
       begin
           raise debug 'this is a DEBUG notification';
           raise log 'this is a LOG notification';
           raise info 'this is a INFO notification';
           raise notice 'this is a NOTICE notification';
           raise warning 'this is a WARNING notification';
       end;
       $$
    "#).await;
    Ok(())
}).await?

println!("{:#?}", &log);

You can look at the unit tests for a more in-depth example.

Dependencies

~9–18MB
~259K SLoC