dorm.budget¶
Per-block query budget — wall-clock timeout + max-rows ceiling.
Both context-manager forms, sync and async; BudgetExceeded
subclasses DatabaseError.
See framework-agnostic helpers for recipes.
API¶
dorm.budget.budget(*, timeout_ms: int | None = None, max_rows: int | None = None, using: str = 'default')
¶
Enter a query budget block.
timeout_ms — wall-clock ceiling per statement.
- On PostgreSQL the budget opens an implicit
atomic()block so it canSET LOCAL statement_timeout; the database side aborts the query when the budget is exceeded. Side-effect: every write inside the block participates in one transaction — on rollback all the writes revert together. Code that is already insideatomic()reuses the outer transaction (savepoint). - Other backends ignore timeout_ms — there is no portable statement-timeout primitive.
max_rows — fail with :class:BudgetExceeded when a query
materialises more than this many rows (post-fetch check, so the
abort happens after the row count is known). Backend-agnostic.
using — alias whose connection receives the timeout. Only the named alias is touched.
Nested blocks combine via minimum — inner blocks can tighten but never relax the outer budget.
dorm.budget.abudget(*, timeout_ms: int | None = None, max_rows: int | None = None, using: str = 'default')
async
¶
Async counterpart of :func:budget. On PG opens an implicit
aatomic() block; see :func:budget for the side-effects.
dorm.budget.BudgetExceeded
¶
Bases: DatabaseError
Raised when a query inside an active :func:budget block
exceeds either the wall-clock timeout or the row ceiling.
Subclasses :class:DatabaseError so generic except DatabaseError
handlers swallow it gracefully — a budget violation is, after
all, a database-level signal that the call should be aborted.
dorm.budget.current() -> _BudgetState | None
¶
Return the currently-effective budget for inspection.
Backends call this before issuing a query to know whether to
pre-set statement_timeout and how many rows to allow.
dorm.budget.check_rowcount(n: int) -> None
¶
Raise :class:BudgetExceeded when n exceeds the active
max_rows ceiling. Backends call this once per fetch so the
abort happens before the rows escape into the caller's buffer.