Skip to content

Postgres

PostgresProvider ships all factory methods: .lock(), .leaderelection(), .cache(), .outbox(), .ratelimiter(), .circuitbreaker(), and .schedule(). The provider wraps an asyncpg.Pool and opens it lazily on __aenter__.

from grelmicro import Grelmicro
from grelmicro.coordination import Coordination
from grelmicro.providers.postgres import PostgresProvider

postgres = PostgresProvider("postgresql://localhost/app")

micro = Grelmicro(uses=[
    Coordination(postgres),
])

Install the postgres extra first: pip install "grelmicro[postgres]".

A SQLAlchemy-style URL works as it is. The provider drops the driver suffix, so an app already holding postgresql+asyncpg://localhost/app passes it straight through with no string surgery:

postgres = PostgresProvider("postgresql+asyncpg://localhost/app")

The suffix names the client library that app uses, not the wire protocol, and this provider always connects with asyncpg.

Environment variables

Set POSTGRES_URL (or POSTGRES_HOST + POSTGRES_PORT + POSTGRES_DB + POSTGRES_USER + POSTGRES_PASSWORD) for env-driven construction. The database name also reads from POSTGRES_DATABASE when POSTGRES_DB is unset, so both the postgres Docker image convention and the longer spelling work.

Bounding a hung server

Pass command_timeout (or set POSTGRES_COMMAND_TIMEOUT) to bound every operation. A query that hangs on a frozen or unreachable server then raises TimeoutError after that many seconds, instead of blocking until the OS TCP timeout. It defaults to None (no timeout).

postgres = PostgresProvider("postgresql://localhost/app", command_timeout=5)

This matters most for the outbox, where publish runs inside your business transaction.

Two pools

For a writer and a reader, split by env prefix:

write = PostgresProvider(env_prefix="WRITE_POSTGRES_")
read = PostgresProvider(env_prefix="READ_POSTGRES_")

micro = Grelmicro(uses=[
    write,
    read,
    Coordination(write),
    Coordination(read, name="read"),
])

Construction forms

PostgresProvider("postgresql://localhost/app")  # positional URL
PostgresProvider(url="postgresql://...")        # keyword URL
PostgresProvider(host="db", port=5432, database="app", user="u", password="pw")
PostgresProvider()                              # env-driven (POSTGRES_*)
PostgresProvider(env_prefix="WRITE_POSTGRES_")  # custom env prefix
PostgresProvider(env_load=False)                # kwargs only, no env
PostgresProvider.from_config(PostgresConfig(...))
PostgresProvider.from_client(pool)              # bring-your-own pool