Skip to content

v0.8.0 Release Notes¶

Release Date: February 2026

This release introduces the Data Layer features, providing first-class database and Redis integration with connection pooling, transaction management, and async support.

Highlights¶

  • Enhanced Database Pooling - Async connection pool with health monitoring & automatic reconnection
  • Redis Integration - Async Redis client with pool management, Pub/Sub, and cluster mode
  • Transaction Support - Automatic transaction management with @transactional decorator

New Features¶

Enhanced Database Connection Pooling¶

Database connection pooling with health monitoring and automatic reconnection:

from cello import App, DatabaseConfig

app = App()

app.enable_database(DatabaseConfig(
    url="postgresql://user:pass@localhost/mydb",
    pool_size=20,
    min_idle=5,
    max_lifetime_secs=1800,
    idle_timeout_secs=300,
    connect_timeout_secs=5,
))

Features:

  • Configurable pool size with min idle connections
  • Connection health checks and automatic reconnection
  • Connection lifetime management to prevent stale connections
  • Pool metrics exposed via Prometheus (/metrics)
  • Support for PostgreSQL, MySQL, and SQLite connection strings

Redis Integration¶

Full-featured async Redis client with connection pooling:

from cello import App, RedisConfig

app = App()

app.enable_redis(RedisConfig(
    url="redis://localhost:6379",
    pool_size=10,
    default_ttl=3600,
    key_prefix="myapp:",
))

# Or use convenience constructors
app.enable_redis(RedisConfig.local())           # localhost defaults
app.enable_redis(RedisConfig.cluster(           # cluster mode
    url="redis://cluster:7000",
    pool_size=20,
))

Features:

  • Async connection pool with configurable size
  • All Redis data types: strings, hashes, lists, sets
  • Key expiration and TTL management
  • Pub/Sub messaging support
  • Redis Cluster mode
  • TLS support for secure connections
  • Key prefix namespacing
  • Pool metrics via Prometheus

Supported Operations:

from cello.database import Redis

redis = await Redis.connect(config)

# String operations
await redis.set("key", "value", ttl=3600)
value = await redis.get("key")
await redis.delete("key")
count = await redis.incr("counter")

# Hash operations
await redis.hset("user:1", "name", "Alice")
name = await redis.hget("user:1", "name")
data = await redis.hgetall("user:1")

# List operations
await redis.lpush("queue", "task1", "task2")
task = await redis.lpop("queue")
items = await redis.lrange("queue", 0, -1)

# Pub/Sub
await redis.publish("events", '{"type": "update"}')

Transaction Support¶

Automatic transaction management with the @transactional decorator:

from cello import App
from cello.database import transactional

app = App()

@app.post("/transfer")
@transactional
async def transfer(request):
    data = request.json()
    # All database operations here run in a single transaction
    await db.execute(
        "UPDATE accounts SET balance = balance - $1 WHERE id = $2",
        data["amount"], data["from_id"]
    )
    await db.execute(
        "UPDATE accounts SET balance = balance + $1 WHERE id = $2",
        data["amount"], data["to_id"]
    )
    return {"success": True}
    # Transaction auto-commits on success
    # Transaction auto-rollbacks on exception

Features:

  • Decorator-based transaction boundaries
  • Automatic commit on success
  • Automatic rollback on exception
  • Works with both sync and async handlers
  • Transaction context available via dependency injection
  • Nested transaction support (savepoints)

Improvements¶

Performance¶

  • Connection pool warming - Pre-establish minimum idle connections on startup
  • Redis pipelining - Batch multiple Redis commands for reduced round trips
  • Lazy connection creation - Connections created on demand, not at startup

Observability¶

  • Pool metrics - Active connections, idle connections, wait time, and error counts exposed via Prometheus
  • Redis metrics - Command count, latency, cache hit/miss ratio at /metrics
  • Health check integration - Database and Redis connectivity included in /health endpoint

Developer Experience¶

  • Convenience constructors - RedisConfig.local() and RedisConfig.cluster() for common setups
  • Pythonic API - Database and Redis wrapper classes with intuitive async methods
  • Type hints - Full type annotations on all public APIs

Bug Fixes¶

  • Fixed loogs parameter typo in App.run() method (renamed to logs)
  • Fixed Response.error() usage in circuit breaker example (method does not exist)
  • Fixed CORS middleware ignoring custom origins configuration
  • Fixed connection leak when handler raises exception during response building
  • Improved error messages for invalid configuration values

Example¶

See the complete database demo example for a working application demonstrating all Data Layer features.

from cello import App, Response, DatabaseConfig, RedisConfig
from cello.database import transactional

app = App()

# Enable database and Redis
app.enable_database(DatabaseConfig(
    url="postgresql://user:pass@localhost/mydb",
    pool_size=20,
    max_lifetime_secs=1800,
))

app.enable_redis(RedisConfig(
    url="redis://localhost:6379",
    pool_size=10,
))

@app.get("/")
def home(request):
    return {"status": "ok", "version": "0.8.0"}

@app.post("/transfer")
@transactional
async def transfer(request):
    # Automatic transaction management
    return {"success": True}

app.run()

Migration Guide¶

See the Migration Guide for detailed upgrade instructions.

Quick Migration¶

  1. Update your dependency:

    pip install --upgrade cello-framework
    

  2. Import new Data Layer classes:

    from cello import DatabaseConfig, RedisConfig
    from cello.database import transactional
    

  3. Configure database and Redis (optional - only if you need these features):

    app.enable_database(DatabaseConfig(url="..."))
    app.enable_redis(RedisConfig(url="..."))
    

  4. No breaking changes from v0.7.0 - all existing code continues to work.


Contributors¶

Thanks to all contributors who made this release possible!


Full Changelog¶

See the complete changelog for all changes.