Skip to main content

resonate-pg

Postgres connector for Resonate. The server is the database.

PostgresConnection is both a Network (request/reply) and a Source (execute / unblock messages), so it can serve as a Resonate client's only connection -- passed as network, it doubles as the source.

from resonate.resonate import Resonate
from resonate_pg import PostgresConnection

conn = PostgresConnection(
    "postgresql://user:pass@localhost:5432/app",
    group="workers",
)
resonate = Resonate(network=conn, group="workers")

Name the same group on both. The connection uses it to build the addresses it drains; Resonate uses it as the routing target a run/rpc defaults to. Told two different groups, a worker would dispatch its own work to an address it is not draining.

The server

Apply resonate.sql to Postgres 16+ once:

psql -d yourdb -f resonate.sql

Every protocol action is then a stored procedure, and this connector runs each request as SELECT resonate.resonate_rpc($1::jsonb).

Addressing

Addresses are poll:// URLs, the same shapes the SDK's SSE source mints:

Address Drained with
unicast poll://uni@{group}/{pid} dequeue_execute + dequeue_unblock
anycast poll://any@{group} dequeue_execute, which deletes FOR UPDATE SKIP LOCKED -- so exactly one group member wins each row

These are required, not chosen. resonate.promise_register_listener rejects any address that is not http(s):// or poll://…@…, and dequeue_execute matches an address byte-for-byte against the resonate:target a peer stamped.

Delivery

A background pump drains this node's outbox rows and hands them to the SDK. It wakes on NOTIFY -- resonate-pg signals resonate_q_{md5(address)} for every row it enqueues -- and, failing that, on a 250 ms tick, so a notification lost to a dropped connection costs latency and nothing else. Messages are delivered only after the claiming transaction commits.

Delivery is at-least-once. A crash between the commit and the callback is recovered by the task's own retry timeout, which is the guarantee the SDK is built on anyway.

Timers

resonate-pg's timers -- durable sleeps, task retries, promise timeouts -- are driven by resonate.process_timeouts(), which pg_cron normally runs every 5s. The pump also calls it on every wake, so a database without pg_cron still works.

resonate.sql does not grant process_timeouts to the resonate_worker role. A worker on that role is refused, logs once, and leaves timers to pg_cron. Pass drive_timers=False to skip the call entirely.

Connections

Pass a connection string and the connector owns its connections: a pooled one per query, plus one autocommit connection holding LISTEN open. To own them yourself -- a shared pool, custom TLS, a proxy -- pass anything satisfying PgSessions:

from resonate_pg import PostgresConnection, PsycopgSessions

sessions = PsycopgSessions("postgresql:///app", max_size=64)
conn = PostgresConnection(sessions=sessions, group="workers")

Errors

Transport failures surface as ConnectorError, so application code can handle any transport giving up without importing this package or knowing which connector is in use:

from resonate_base import ConnectorError

try:
    await resonate.run("greet", ...)
except ConnectorError as exc:
    ...

Operations

Completed workflows stay in the database. Delete old ones on a schedule:

select cron.schedule('resonate-gc', '0 3 * * *',
  $$select resonate.gc((extract(epoch from now())*1000 - 7*86400000)::bigint)$$);

Install

pip install resonate-pg

Deliberately not an extra of resonate-sdk: an extra would put this package in the SDK's published dependency metadata, pointing the arrow back down the stack. resonate-pg depends only on resonate-base and psycopg, never on resonate-sdk.

Release files for resonate-pg 0.8.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for resonate-pg 0.8.0
File Size Uploaded
resonate_pg-0.8.0.tar.gz 10.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for resonate-pg 0.8.0
File Interpreter ABI Platform
resonate_pg-0.8.0-py3-none-any.whl Python 3 none any Details

Total release size: 23.4 kB

Release files / resonate_pg-0.8.0.tar.gz

Download URL resonate_pg-0.8.0.tar.gz
Size 10.5 kB
Tags Source
SHA-256 checksum
How to use checksums
a70145dec88d950a786b86e4b81eafd4e6aa37cfff069e547007313e256e77fd
BLAKE2b-256 checksum
How to use checksums
bd9a5e236ec654778cea0a10d70cd2736d21df84200d70d1ac842ab7865fc712
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / resonate_pg-0.8.0-py3-none-any.whl

Download URL resonate_pg-0.8.0-py3-none-any.whl
Size 12.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
77e0ea15f74b6873285e532501497deaf293d5f48b51f349d9934227a4fb4f6e
BLAKE2b-256 checksum
How to use checksums
5f110ce8dfb868eb48b3771a1039955bedc12a5120108438cdbde5472add788f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

0.8.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page