Releases: Mayuradlak123/pgmesh
Release list
release-v0.2.0.md
With it on, every statement's plan is logged to the pgmesh logger at INFO before the statement runs — on the same connection, so the plan describes the same session.
Three deliberate choices here:
Plain EXPLAIN, not EXPLAIN ANALYZE. ANALYZE executes the statement it measures, so using it for automatic capture would double-apply every write. The flag plans without executing; your INSERT reaches the server exactly once. There's an integration test asserting precisely that against a real server.
Failures are swallowed. Not everything is explainable — VACUUM, SET. A statement PostgreSQL rejects for EXPLAIN is logged at DEBUG and skipped. A diagnostic never becomes the reason a query fails.
executemany is skipped. EXPLAIN takes one parameter set; a batch has many.
It costs one extra round trip per query, so treat it as a debugging aid rather than a production default. For a single plan, prefer explain().
Notes
No breaking changes. explain defaults to False, so upgrading changes nothing until you opt in.
Test suite is now 143 unit tests, up from 121.
release-v1.0.0
Here’s a cleaned-up, GitHub-ready version with the Markdown formatting fixed and the wording polished while preserving your technical content:
v0.1.0 — Multi-database PostgreSQL orchestration for asyncio
First release of pgmesh — an async orchestration layer for applications that communicate with multiple PostgreSQL databases. Register your databases once, address them by index or label, and let pgmesh manage connection pools, concurrency, timeouts, and failure isolation.
pip install pgmeshfrom pgmesh import PGCluster
async with PGCluster(
{
1: "postgresql://user:pass@db1/app",
2: "postgresql://user:pass@db2/app",
"analytics": "postgresql://user:pass@db3/analytics",
},
max_concurrency=10,
query_timeout=5,
) as db:
users = await db.connection(1).execute(
"SELECT * FROM users LIMIT 10"
)
results = await db.parallel(
[
(1, "SELECT count(*) FROM users"),
(2, "SELECT count(*) FROM orders"),
("analytics", "SELECT count(*) FROM events"),
]
)What's Included
-
One pool per database. Each registered database gets its own
asyncpgpool, created on first use or upfront viastartup(). Connections are reused rather than opened for every query. -
Routing by index or label. Use
db.connection(1)ordb.connection("analytics")to access a database. Numeric IDs and their string equivalents resolve to the same database, while an unknown ID raisesDatabaseNotFoundError. -
Bounded parallel execution.
max_concurrencylimits the number of operations that can run simultaneously. For example, if you submit 100 operations with a concurrency limit of 20, only 20 run at a time while the remaining operations wait without creating an unbounded number of tasks. -
Timeouts that release connections. Configure cluster-wide or per-query timeouts. When a query exceeds its timeout,
QueryTimeoutErroris raised and the connection is safely returned to the pool. -
Failure isolation. A slow or unreachable database does not cancel operations against other databases.
parallel()returns aSuccessorFailureresult for each operation, allowing you to identify exactly which operations succeeded or failed. Nothing is raised unless you explicitly request it. -
A real error model. Driver exceptions are mapped to
PGMeshErrorand its subclasses, with the original exception preserved as__cause__.DatabaseNotFoundErroralso behaves as aKeyError, whileQueryTimeoutErroralso behaves as aTimeoutError. -
No secrets in logs. Passwords are masked wherever connection strings could appear, including log messages, representations, and exception messages.
-
Fully typed. pgmesh ships with
py.typedand is checked withmypy --strict.
Also included:
- Transactions
- Raw connection escape hatch via
acquire() parallel_map()fan-out executionhealth()andping()utilities
Requirements
- Python 3.10+
- One runtime dependency:
asyncpg
Scope
Included: Registration, routing, connection pooling, query execution, bounded parallelism, timeouts, failure isolation, and a clean error model.
Intentionally out of scope: Proxying, SQL parsing, distributed transactions, cross-database joins, automatic sharding, query rewriting, and replication management.
Retries, circuit breakers, structured logging, and metrics are planned for future releases.
Testing
The project includes 121 unit tests running against a fake database driver, so the unit test suite does not require PostgreSQL.
Integration tests run in CI against a real postgres:16 instance.
CI currently covers:
- Python 3.10–3.13
- Linux and Windows
- Ruff
- Mypy
📦 [pgmesh on PyPI](https://pypi.org/project/pgmesh/) · 📖 [README](https://github.com/Mayuradlak123/pgmesh#readme)