postgres-notify
A resilient PostgreSQL client wrapper for tokio_postgres with automatic reconnection, query timeouts, and NOTIFY/LISTEN support.
- Automatic reconnection with exponential backoff and jitter
- Query timeouts with server-side cancellation
- PostgreSQL NOTIFY/LISTEN pub/sub notifications
- RAISE message capture for execution logging
Installation
Add to your Cargo.toml:
[]
= "0.3"
= { = "1", = ["rt", "time"] }
= "0.7"
Feature Flags
| Feature | Default | Description |
|---|---|---|
chrono |
Yes | Use DateTime<Utc> for timestamps instead of SystemTime |
serde |
Yes | Enable serialization for message types |
tracing |
Yes | Structured logging via the tracing crate |
To disable default features:
[]
= { = "0.3", = false }
Quick Start
use ;
use NoTls;
use Duration;
async
Features
LISTEN/NOTIFY
PostgreSQL supports asynchronous notifications via LISTEN/NOTIFY commands. This allows the database to push messages to clients without polling.
use ;
use NoTls;
use Duration;
async
RAISE/Logs
Capture PostgreSQL RAISE messages during query execution. Useful for debugging stored procedures and functions.
use ;
use NoTls;
use Duration;
async
Log Levels: DEBUG, LOG, INFO, NOTICE, WARNING, ERROR, FATAL, PANIC
Automatic Reconnection
If the connection is lost, the client automatically reconnects with exponential backoff:
- Initial delay: 500ms
- Doubles after each attempt (with jitter)
- Maximum delay: 1 hour
- Default max attempts: 10
On reconnection:
- Connect script is re-executed
- Channel subscriptions are restored
let config = new
.max_reconnect_attempts // Limit retry attempts
.callback;
Query Timeouts
All query methods accept an optional timeout. If exceeded, the query is cancelled server-side.
use Duration;
// With explicit timeout
let rows = client.query.await;
// Returns Err(PGError::Timeout(..))
// Use default timeout (1 hour)
let rows = client.query.await?;
// Configure default timeout
let config = new
.default_timeout;
// Manual cancellation
client.cancel_query.await?;
Configuration
Builder Pattern
use ;
use NoTls;
use Duration;
let config = new
// Event callback (required for NOTIFY/RAISE)
.callback
// Reconnection settings
.max_reconnect_attempts
// Default query timeout
.default_timeout
// SQL executed on each connection
.connect_script
// PostgreSQL application name
.application_name
// Pre-configure LISTEN channels
.subscriptions;
API Overview
Main Types
| Type | Description |
|---|---|
PGRobustClient<TLS> |
Main client with resilience features |
PGRobustClientConfig<TLS> |
Builder for client configuration |
PGMessage |
Event enum delivered to callbacks |
PGError |
Error type with timeout/reconnect variants |
PGResult<T> |
Alias for Result<T, PGError> |
Query Methods
All methods mirror tokio_postgres::Client with an additional timeout parameter:
| Method | Description |
|---|---|
query |
Execute query, return all rows |
query_one |
Execute query, return exactly one row |
query_opt |
Execute query, return zero or one row |
query_raw |
Execute query with streaming results |
execute_raw |
Execute statement, return affected row count |
prepare |
Prepare a statement |
transaction |
Begin a transaction |
simple_query |
Execute simple (non-parameterized) query |
batch_execute |
Execute multiple statements |
Message Types
Error Handling
use ;
async
Best Practices
Callback Safety
The callback runs in a background tokio task. If it panics:
- The internal message log becomes inaccessible
- The connection polling task terminates
Recommendation: Never panic in callbacks. Use std::panic::catch_unwind if calling untrusted code.
Security
The connect_script and application_name values are interpolated directly into SQL. Do not pass untrusted user input to these methods.
Performance
- This is a single-connection client, not a connection pool
query,query_one, andquery_optclone parameters internally- For bulk operations, consider
query_raworexecute_raw
TLS Configuration
For production use, configure TLS:
// Without TLS (development only)
use NoTls;
let config = new;
// With rustls
// Add: tokio-postgres-rustls = "0.12"
use MakeRustlsConnect;
let tls = new;
let config = new;
// With native-tls
// Add: postgres-native-tls = "0.5"
use MakeTlsConnector;
let tls = new;
let config = new;
Requirements
- Rust 1.85+ (Edition 2024)
- Tokio runtime with
rtandtimefeatures - PostgreSQL 9.0+ (LISTEN/NOTIFY support)
Changelog
See CHANGELOG.md for a detailed history of changes.
License
MIT License - see LICENSE for details.