TransactionsΒΆ

Fastapi-icontract is not aware of the transactions.

This is especially relevant for concurrent systems where multiple clients modify a shared resource (e.g., a database) at the same time. If you are not careful, you can end up with quite a few time-of-check-time-of-use (TOCTOU) errors.

A possible approach to use transaction both in the contracts and the endpoint is to introduce a decorator on top of fastapi-icontract decorators which will start a transaction and pass it down to the contracts and the function, and then close it when the underlying call stack is executed.

For example:

from fastapi_icontract import require

@app.get("/books_in_category", response_model=List[Book])
@start_transaction  # This passes ``txn`` to the underlying function and contracts
@require(
    lambda txn, category: has_category(txn, category),
    status_code=404,
    description="The category must exist."
)
async def books_in_category(category: str) -> Any:
    """Retrieve the books of the given category from the database."""
    ...

How you implement the start_transaction depends on your particular system, and we present its usage here just for illustration.