Postgres Connection¶
The database module provides asynchronous database clients with connection pooling and transaction management for various database systems.
Environment Variables¶
The PostgreSQL client can be configured using either a connection string or individual environment variables: The PostgreSQL client can be configured using the following environment variables:
DB_HOST
: Database host (default: localhost)DB_PORT
: Database port (default: 5432)DB_NAME
: Database name (default: postgres)DB_USER
: Database user (required)DB_PASSWORD
: Database password (required)DB_SSLMODE
: SSL mode (default: disable)
Example .env
file:
# Database configuration
DB_HOST=localhost
DB_PORT=5432
DB_NAME=mydb
DB_USER=myuser
DB_PASSWORD=mypassword
DB_SSLMODE=disable
API Reference¶
- class prs_commons.db.PostgresConnection(*args: Any, **kwargs: Any)[source]¶
PostgreSQL database connection manager with connection pooling.
This class implements the DatabaseConnection interface and provides connection pooling and transaction management. It uses a singleton pattern to ensure a single connection pool is used per process.
The connection pool is automatically managed and will be created on first use. Connections are automatically returned to the pool when their transaction context is exited.
The
PostgresConnection
manages the actual database connections and connection pooling. It’s typically not used directly but rather through the higher-levelPostgresClient
.- __init__(dsn=None, min_size=1, max_size=50, **kwargs)[source]
Initialize the PostgreSQL client.
Note: This will only initialize the instance once due to the singleton pattern. Subsequent calls with different parameters will be ignored.
- __init__(dsn: str | None = None, min_size: int = 1, max_size: int = 50, **kwargs: Any) None [source]¶
Initialize the PostgreSQL client.
Note: This will only initialize the instance once due to the singleton pattern. Subsequent calls with different parameters will be ignored.
- async connect() None [source]¶
Initialize the database connection pool.
Creates a connection pool with the configured parameters. This method is called automatically when the first connection is requested.
The connection pool parameters are: - min_size: Minimum number of connections to keep open - max_size: Maximum number of connections to allow - Other parameters passed during client initialization
Note
This method is idempotent - calling it multiple times will only create the pool once.
- async disconnect() None [source]¶
Close all connections in the connection pool.
This method should be called when the database client is no longer needed to ensure proper cleanup of resources. After calling this method, the client can be reused by calling connect() again.
Note
It’s good practice to call this when your application shuts down.
- get_connection() AsyncIterator[Connection] [source]¶
Get a managed database connection with transaction support.
This context manager provides a connection from the pool with automatic transaction management. The connection is automatically returned to the pool when the context exits.
The following operations are performed automatically:
Starts a new transaction when entering the context
Commits the transaction if the block completes successfully
Rolls back the transaction if an exception occurs
Returns the connection to the pool when done
Example
async with db.get_connection() as conn: # Execute queries within a transaction result = await conn.fetch("SELECT * FROM users") # Transaction will be committed if no exceptions occur
- Yields:
asyncpg.Connection – A database connection from the pool.
Note
The connection and its transaction are managed automatically. Do not manually commit or rollback the transaction within the context.
Note
Nested transactions are supported using savepoints. For example:
async with db.get_connection() as conn: # Outer transaction starts automatically await conn.execute("INSERT INTO users (name) VALUES ('user1')") try: # Start a nested transaction (savepoint) async with conn.transaction(): await conn.execute("INSERT INTO accounts (user_id, balance) VALUES (1, 100)") # This savepoint can be rolled back independently raise Exception("Something went wrong") except Exception as e: # Only the inner transaction is rolled back print(f"Caught error: {e}") # The outer transaction continues and will be committed await conn.execute("UPDATE users SET status = 'active' WHERE name = 'user1'") # The outer transaction is committed here if no exceptions
Important
If an exception occurs in the outer transaction after an inner transaction has committed, the entire transaction (including the committed savepoint) will be rolled back. This ensures transaction atomicity - either all changes complete successfully, or none of them do.
If you need the inner transaction to persist regardless of the outer transaction’s outcome, use separate database connections/transactions instead of nested transactions.
- async __aenter__() PostgresConnection [source]¶
Async context manager entry.
- async __aexit__(exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: Any | None) None [source]¶
Async context manager exit.
Error Handling¶
The PostgresConnection
raises the following exceptions:
ValueError
: If required environment variables are missingasyncpg.PostgresError
: For database-related errorsRuntimeError
: For connection pool errorsException
: For other unexpected errors