mirror of
https://github.com/d3vyce/fastapi-toolsets.git
synced 2026-03-01 17:00:48 +01:00
* chore: update docstring example to use python code block * docs: add documentation * feat: add docs build + fix other workdlows * fix: add missing return type
90 lines
2.8 KiB
Markdown
90 lines
2.8 KiB
Markdown
# DB
|
|
|
|
SQLAlchemy async session management with transactions, table locking, and row-change polling.
|
|
|
|
## Overview
|
|
|
|
The `db` module provides helpers to create FastAPI dependencies and context managers for `AsyncSession`, along with utilities for nested transactions, PostgreSQL advisory locks, and polling for row changes.
|
|
|
|
## Session dependency
|
|
|
|
Use [`create_db_dependency`](../reference/db.md#fastapi_toolsets.db.create_db_dependency) to create a FastAPI dependency that yields a session and auto-commits on success:
|
|
|
|
```python
|
|
from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker
|
|
from fastapi_toolsets.db import create_db_dependency
|
|
|
|
engine = create_async_engine("postgresql+asyncpg://...")
|
|
session_maker = async_sessionmaker(engine)
|
|
|
|
get_db = create_db_dependency(session_maker)
|
|
|
|
@router.get("/users")
|
|
async def list_users(session: AsyncSession = Depends(get_db)):
|
|
...
|
|
```
|
|
|
|
## Session context manager
|
|
|
|
Use [`create_db_context`](../reference/db.md#fastapi_toolsets.db.create_db_context) for sessions outside request handlers (e.g. background tasks, CLI commands):
|
|
|
|
```python
|
|
from fastapi_toolsets.db import create_db_context
|
|
|
|
db_context = create_db_context(session_maker)
|
|
|
|
async def seed():
|
|
async with db_context() as session:
|
|
session.add(User(name="admin"))
|
|
```
|
|
|
|
## Nested transactions
|
|
|
|
[`get_transaction`](../reference/db.md#fastapi_toolsets.db.get_transaction) handles savepoints automatically, allowing safe nesting:
|
|
|
|
```python
|
|
from fastapi_toolsets.db import get_transaction
|
|
|
|
async def create_user_with_role(session):
|
|
async with get_transaction(session):
|
|
session.add(role)
|
|
async with get_transaction(session): # uses savepoint
|
|
session.add(user)
|
|
```
|
|
|
|
## Table locking
|
|
|
|
[`lock_tables`](../reference/db.md#fastapi_toolsets.db.lock_tables) acquires PostgreSQL table-level locks before executing critical sections:
|
|
|
|
```python
|
|
from fastapi_toolsets.db import lock_tables
|
|
|
|
async with lock_tables(session, tables=[User], mode="EXCLUSIVE"):
|
|
# No other transaction can modify User until this block exits
|
|
...
|
|
```
|
|
|
|
Available lock modes are defined in [`LockMode`](../reference/db.md#fastapi_toolsets.db.LockMode): `ACCESS_SHARE`, `ROW_SHARE`, `ROW_EXCLUSIVE`, `SHARE_UPDATE_EXCLUSIVE`, `SHARE`, `SHARE_ROW_EXCLUSIVE`, `EXCLUSIVE`, `ACCESS_EXCLUSIVE`.
|
|
|
|
## Row-change polling
|
|
|
|
[`wait_for_row_change`](../reference/db.md#fastapi_toolsets.db.wait_for_row_change) polls a row until a specific column changes value, useful for waiting on async side effects:
|
|
|
|
```python
|
|
from fastapi_toolsets.db import wait_for_row_change
|
|
|
|
# Wait up to 30s for order.status to change
|
|
await wait_for_row_change(
|
|
session,
|
|
model=Order,
|
|
pk_value=order_id,
|
|
columns=[Order.status],
|
|
interval=1.0,
|
|
timeout=30.0,
|
|
)
|
|
```
|
|
|
|
---
|
|
|
|
[:material-api: API Reference](../reference/db.md)
|