Skip to content

Commit a4b9a86

Browse files
authored
Merge pull request #7 from modern-python/rename
rename to db-retry
2 parents bec48ed + dfb4f49 commit a4b9a86

19 files changed

Lines changed: 61 additions & 53 deletions

AGENTS.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## Project Overview
44

5-
This is a Python library called `db-try` that provides PostgreSQL and SQLAlchemy utilities, specifically focusing on:
5+
This is a Python library called `db-retry` that provides PostgreSQL and SQLAlchemy utilities, specifically focusing on:
66

77
1. **Retry decorators** for handling database connection issues and serialization errors
88
2. **Connection factory builders** for managing PostgreSQL connections with multiple hosts
@@ -25,7 +25,7 @@ The library is built with modern Python practices (3.13+) and uses type hints ex
2525
## Project Structure
2626

2727
```
28-
db_try/
28+
db_retry/
2929
├── __init__.py # Exports all public APIs
3030
├── connections.py # Connection factory builders
3131
├── dsn.py # DSN parsing and manipulation utilities
@@ -130,4 +130,4 @@ The library can be configured using environment variables:
130130
The retry behavior is defined in `retry.py` and uses the tenacity library. Modify the `_retry_handler` function to change which exceptions trigger retries.
131131

132132
### Working with Connections
133-
Connection handling is in `connections.py`. The `build_connection_factory` function handles connecting to PostgreSQL with support for multiple hosts and fallback mechanisms.
133+
Connection handling is in `connections.py`. The `build_connection_factory` function handles connecting to PostgreSQL with support for multiple hosts and fallback mechanisms.

Dockerfile

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@ RUN apt update \
1111
COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/uv
1212
RUN useradd --no-create-home --gid root runner
1313

14-
ENV UV_PYTHON_PREFERENCE=only-system
15-
ENV UV_NO_CACHE=true
14+
ENV UV_PROJECT_ENVIRONMENT=/code/.venv \
15+
UV_NO_MANAGED_PYTHON=1 \
16+
UV_NO_CACHE=true \
17+
UV_LINK_MODE=copy
1618

1719
WORKDIR /code
1820

Justfile

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,16 @@ install:
1717
uv sync --all-extras --all-groups --frozen
1818

1919
lint:
20-
uv run --frozen ruff format
21-
uv run --frozen ruff check --fix
22-
uv run --frozen mypy .
20+
uv run eof-fixer .
21+
uv run ruff format
22+
uv run ruff check --fix
23+
uv run mypy .
2324

2425
lint-ci:
25-
uv run --frozen ruff format --check
26-
uv run --frozen ruff check --no-fix
27-
uv run --frozen mypy .
26+
uv run eof-fixer . --check
27+
uv run ruff format --check
28+
uv run ruff check --no-fix
29+
uv run mypy .
2830

2931
publish:
3032
rm -rf dist

README.md

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# db-try
1+
# db-retry
22

33
A Python library providing robust retry mechanisms, connection utilities, and transaction helpers for PostgreSQL and SQLAlchemy applications.
44

@@ -14,13 +14,13 @@ A Python library providing robust retry mechanisms, connection utilities, and tr
1414
### Using uv
1515

1616
```bash
17-
uv add db-try
17+
uv add db-retry
1818
```
1919

2020
### Using pip
2121

2222
```bash
23-
pip install db-try
23+
pip install db-retry
2424
```
2525

2626
## ORM-Based Usage Examples
@@ -34,15 +34,17 @@ import asyncio
3434
import sqlalchemy as sa
3535
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
3636
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
37-
from db_try import postgres_retry
37+
from db_retry import postgres_retry
38+
3839

3940
class User(DeclarativeBase):
4041
__tablename__ = "users"
41-
42+
4243
id: Mapped[int] = mapped_column(primary_key=True)
4344
name: Mapped[str] = mapped_column(sa.String())
4445
email: Mapped[str] = mapped_column(sa.String(), index=True)
4546

47+
4648
# Apply retry logic to ORM operations
4749
@postgres_retry
4850
async def get_user_by_email(session: AsyncSession, email: str) -> User:
@@ -59,6 +61,7 @@ async def main():
5961
if user:
6062
print(f"Found user: {user.name}")
6163

64+
6265
asyncio.run(main())
6366
```
6467

@@ -70,8 +73,7 @@ Set up resilient database connections with multiple fallback hosts:
7073
import sqlalchemy as sa
7174
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
7275
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
73-
from db_try import build_connection_factory, build_db_dsn
74-
76+
from db_retry import build_connection_factory, build_db_dsn
7577

7678
# Configure multiple database hosts for high availability
7779
multi_host_dsn = (
@@ -91,7 +93,7 @@ dsn = build_db_dsn(
9193

9294
# Create connection factory with timeout
9395
connection_factory = build_connection_factory(
94-
url=dsn,
96+
url=dsn,
9597
timeout=5.0 # 5 second connection timeout
9698
)
9799

@@ -109,7 +111,7 @@ import datetime
109111
import typing
110112

111113
from schemas import AnalyticsEventCreate, AnalyticsEvent
112-
from db_try import Transaction, postgres_retry
114+
from db_retry import Transaction, postgres_retry
113115

114116
from your_service_name.database.tables import EventsTable
115117
from your_service_name.producers.analytics_service_events_producer import AnalyticsEventsProducer
@@ -125,8 +127,8 @@ class CreateEventUseCase:
125127

126128
@postgres_retry
127129
async def __call__(
128-
self,
129-
event_create_data: AnalyticsEventCreate,
130+
self,
131+
event_create_data: AnalyticsEventCreate,
130132
) -> AnalyticsEvent:
131133
async with self.transaction:
132134
model: typing.Final = EventsTable(
@@ -147,12 +149,12 @@ Use serializable isolation level to prevent race conditions with ORM:
147149

148150
```python
149151
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
150-
from db_try import Transaction
152+
from db_retry import Transaction
151153

152154

153155
async def main():
154156
engine = create_async_engine("postgresql+asyncpg://user:pass@localhost/mydb")
155-
157+
156158
async with AsyncSession(engine) as session:
157159
strict_transaction = Transaction(
158160
session=session,
@@ -167,7 +169,7 @@ The library can be configured using environment variables:
167169

168170
| Variable | Description | Default |
169171
|-------------------------|--------------------------------------------------|---------|
170-
| `DB_TRY_RETRIES_NUMBER` | Number of retry attempts for database operations | 3 |
172+
| `DB_RETRY_RETRIES_NUMBER` | Number of retry attempts for database operations | 3 |
171173

172174
Example:
173175
```bash

db_retry/__init__.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from db_retry.connections import build_connection_factory
2+
from db_retry.dsn import build_db_dsn, is_dsn_multihost
3+
from db_retry.retry import postgres_retry
4+
from db_retry.transaction import Transaction
5+
6+
7+
__all__ = [
8+
"Transaction",
9+
"build_connection_factory",
10+
"build_db_dsn",
11+
"is_dsn_multihost",
12+
"postgres_retry",
13+
]
File renamed without changes.
File renamed without changes.

db_try/retry.py renamed to db_retry/retry.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import tenacity
77
from sqlalchemy.exc import DBAPIError
88

9-
from db_try import settings
9+
from db_retry import settings
1010

1111

1212
logger = logging.getLogger(__name__)
@@ -29,7 +29,7 @@ def postgres_retry[**P, T](
2929
func: typing.Callable[P, typing.Coroutine[None, None, T]],
3030
) -> typing.Callable[P, typing.Coroutine[None, None, T]]:
3131
@tenacity.retry(
32-
stop=tenacity.stop_after_attempt(settings.DB_TRY_RETRIES_NUMBER),
32+
stop=tenacity.stop_after_attempt(settings.DB_RETRY_RETRIES_NUMBER),
3333
wait=tenacity.wait_exponential_jitter(),
3434
retry=tenacity.retry_if_exception(_retry_handler),
3535
reraise=True,

db_retry/settings.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import os
2+
import typing
3+
4+
5+
DB_RETRY_RETRIES_NUMBER: typing.Final = int(os.getenv("DB_RETRY_RETRIES_NUMBER", "3"))

0 commit comments

Comments
 (0)