Skip to main content

High-performance PostgreSQL connector for DataPulse - async-first, connection pooling, and enterprise features

Project description

DataPulse PostgreSQL

PyPI version Python versions License: MIT Code style: black Imports: isort Type checked with mypy

High-performance, async-first PostgreSQL connector for the DataPulse ecosystem.

DataPulse PostgreSQL provides enterprise-grade connectivity to PostgreSQL databases with advanced features like connection pooling, high-performance bulk operations, and comprehensive error handling.

✨ Features

  • ⚡ Async-First: Built on asyncpg for maximum performance
  • 🔌 Connection Pooling: Efficient resource management
  • 📊 High-Performance Operations: Bulk insert, replace, and custom SQL
  • 🔄 Transaction Support: Full ACID compliance with rollback
  • 🛡️ Type Safe: Full type hints and runtime validation
  • 📈 Performance Monitoring: Built-in metrics and observability
  • 🔧 Flexible Configuration: Support for complex operations and custom SQL
  • 📋 Partitioned Tables: Native support for PostgreSQL partitioning

🚀 Quick Start

Installation

pip install metronome-pulse-postgres

Basic Usage

import asyncio
from metronome_pulse_postgres import PostgresPulse

async def main():
    # Initialize connector
    pulse = PostgresPulse(
        host="localhost",
        port=5432,
        user="myuser",
        password="mypassword",
        database="mydb"
    )
    
    # Connect to database
    await pulse.connect()
    
    try:
        # Simple query
        users = await pulse.query("SELECT * FROM users WHERE active = $1", {"active": True})
        print(f"Found {len(users)} active users")
        
        # Bulk insert
        new_users = [
            {"name": "Alice", "email": "alice@example.com", "active": True},
            {"name": "Bob", "email": "bob@example.com", "active": True}
        ]
        inserted = await pulse.write(new_users, {
            "operation": "insert",
            "table": "users",
            "batch_size": 1000
        })
        print(f"Inserted {inserted} users")
        
    finally:
        await pulse.disconnect()

# Run the async function
asyncio.run(main())

🔧 Advanced Features

High-Performance Bulk Operations

# High-performance replace (delete + insert in transaction)
await pulse.write(data, {
    "operation": "replace",
    "table": "users",
    "batch_size": 5000,
    "use_transaction": True,
    "on_conflict": "DO NOTHING"
})

# Custom SQL operations
await pulse.write(data, {
    "operation": "custom",
    "sql_template": """
        INSERT INTO {table} ({columns}) 
        VALUES {values} 
        ON CONFLICT (id) 
        DO UPDATE SET 
            name = EXCLUDED.name,
            updated_at = NOW()
    """,
    "batch_size": 1000
})

Connection Pooling

from metronome_pulse_postgres import PostgresPulsePool

# Create connection pool
pool = PostgresPulsePool(
    host="localhost",
    port=5432,
    user="myuser",
    password="mypassword",
    database="mydb",
    min_connections=5,
    max_connections=20,
    connection_timeout=30
)

async with pool.get_connection() as conn:
    result = await conn.query("SELECT COUNT(*) FROM users")
    print(f"Total users: {result[0]['count']}")

Partitioned Table Support

# Create partitioned table
await pulse.write([], {
    "operation": "create_partitioned_table",
    "table": "events",
    "partition_key": "created_at",
    "partition_type": "RANGE",
    "partitions": [
        {"name": "events_2024_q1", "start": "2024-01-01", "end": "2024-04-01"},
        {"name": "events_2024_q2", "start": "2024-04-01", "end": "2024-07-01"}
    ]
})

# Insert into specific partition
await pulse.write(events_data, {
    "operation": "insert",
    "table": "events",
    "partition": "events_2024_q1"
})

Complex Queries with Parameters

# Parameterized queries
users = await pulse.query("""
    SELECT u.*, COUNT(o.id) as order_count
    FROM users u
    LEFT JOIN orders o ON u.id = o.user_id
    WHERE u.created_at >= $1 
    AND u.status = $2
    GROUP BY u.id
    HAVING COUNT(o.id) > $3
    ORDER BY order_count DESC
    LIMIT $4
""", {
    "created_after": "2024-01-01",
    "status": "active",
    "min_orders": 5,
    "limit": 100
})

📊 Performance Benchmarks

DataPulse PostgreSQL is designed for high-performance data operations:

Operation Records Time Throughput
Bulk Insert 100K 2.3s 43.5K rec/s
Bulk Replace 100K 4.1s 24.4K rec/s
Simple Query 1M 0.8s 1.25M rec/s
Complex Query 100K 1.2s 83.3K rec/s

Benchmarks run on PostgreSQL 15, Python 3.11, 16GB RAM, SSD storage

🧪 Testing

Run Tests

# Install development dependencies
pip install -e ".[dev]"

# Run all tests
pytest

# Run with coverage
pytest --cov=metronome_pulse_postgres

# Run specific test categories
pytest -m "unit"        # Unit tests only
pytest -m "integration"  # Integration tests only
pytest -m "performance"  # Performance tests only
pytest -m "slow"         # Slow tests only

Test with Docker

# Start PostgreSQL test instance
docker run -d \
    --name test-postgres \
    -e POSTGRES_PASSWORD=test \
    -e POSTGRES_DB=testdb \
    -p 5432:5432 \
    postgres:15

# Run integration tests
pytest -m "integration" --postgres-host=localhost

# Clean up
docker stop test-postgres && docker rm test-postgres

🔧 Configuration

Connection Options

pulse = PostgresPulse(
    # Basic connection
    host="localhost",
    port=5432,
    user="myuser",
    password="mypassword",
    database="mydb",
    
    # Advanced options
    ssl_mode="require",
    ssl_cert="path/to/cert.pem",
    ssl_key="path/to/key.pem",
    ssl_ca="path/to/ca.pem",
    
    # Connection pooling
    min_size=5,
    max_size=20,
    command_timeout=60,
    
    # Performance tuning
    server_settings={
        "jit": "off",
        "work_mem": "256MB",
        "maintenance_work_mem": "512MB"
    }
)

Write Operation Configuration

config = {
    "operation": "insert",           # insert, replace, update, delete, custom
    "table": "users",               # Target table name
    "batch_size": 1000,             # Records per batch
    "use_transaction": True,         # Wrap in transaction
    "on_conflict": "DO NOTHING",    # Conflict resolution
    "returning": ["id", "name"],    # Return specific columns
    "timeout": 300,                 # Operation timeout in seconds
    "retry_attempts": 3,            # Retry failed operations
    "retry_delay": 1.0,             # Delay between retries
}

📚 API Reference

Core Methods

connect() -> None

Establish connection to PostgreSQL database.

disconnect() -> None

Close connection to PostgreSQL database.

is_connected() -> bool

Check if connection is currently active.

query(query: str, params: dict | None = None) -> list[dict]

Execute a query and return results.

write(data: list[dict], config: dict | None = None) -> int

Write data using the specified configuration.

Advanced Methods

replace_using_values(data: list[dict], table: str, batch_size: int = 1000) -> int

High-performance replace operation using VALUES clause.

apply_operations(operations: list[dict]) -> dict

Execute multiple operations in sequence.

create_partition(table: str, partition_name: str, partition_def: dict) -> None

Create a new partition for a partitioned table.

🚨 Error Handling

DataPulse PostgreSQL provides comprehensive error handling:

from metronome_pulse_postgres import PostgresError, ConnectionError, QueryError

try:
    await pulse.query("SELECT * FROM non_existent_table")
except ConnectionError as e:
    print(f"Connection failed: {e}")
except QueryError as e:
    print(f"Query failed: {e}")
    print(f"SQL: {e.sql}")
    print(f"Parameters: {e.params}")
except PostgresError as e:
    print(f"PostgreSQL error: {e}")

🔍 Monitoring & Observability

# Get connection pool statistics
stats = pulse.get_pool_stats()
print(f"Active connections: {stats['active']}")
print(f"Available connections: {stats['available']}")
print(f"Total connections: {stats['total']}")

# Get performance metrics
metrics = pulse.get_performance_metrics()
print(f"Average query time: {metrics['avg_query_time']:.2f}ms")
print(f"Total queries: {metrics['total_queries']}")
print(f"Failed queries: {metrics['failed_queries']}")

🤝 Contributing

We welcome contributions! Please see our Contributing Guide for details.

Development Setup

# Clone the repository
git clone https://github.com/datametronome/metronome-pulse-postgres.git
cd metronome-pulse-postgres

# Create virtual environment
python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate

# Install in development mode
pip install -e ".[dev]"

# Install pre-commit hooks
pre-commit install

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🔗 Links

🙏 Acknowledgments

  • Built with ❤️ by the DataMetronome team
  • Powered by the excellent asyncpg library
  • Designed for enterprise data engineering workflows
  • Inspired by modern async Python patterns

Ready to supercharge your PostgreSQL operations? Get started with DataPulse PostgreSQL today! 🚀

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

metronome_pulse_postgres-0.1.0.tar.gz (18.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

metronome_pulse_postgres-0.1.0-py3-none-any.whl (18.0 kB view details)

Uploaded Python 3

File details

Details for the file metronome_pulse_postgres-0.1.0.tar.gz.

File metadata

  • Download URL: metronome_pulse_postgres-0.1.0.tar.gz
  • Upload date:
  • Size: 18.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.0

File hashes

Hashes for metronome_pulse_postgres-0.1.0.tar.gz
Algorithm Hash digest
SHA256 e64cf8183eb733f743d6aa99d567eed9bd4cbfc82cf52156bfc95ce04fd752ac
MD5 e70253c1f51f9c4344b0d2550bab59bd
BLAKE2b-256 ade73c2be23b9bfef2b30c13fa5eb7556e60d755b702c848c4846a8454d8a7ec

See more details on using hashes here.

File details

Details for the file metronome_pulse_postgres-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for metronome_pulse_postgres-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 aebbd9e1961dcc9e60363232e25b5d4fca93ab94833a5848c851b3af6652a06e
MD5 3622784ffb8a88359e20ddfcbc0b28aa
BLAKE2b-256 3d20c48fda4f90f02d20cce657c722a58718bdee70ae2217a665b58cd24e22c5

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page