Expand description
The connection port — Connection and Database.
Rainier ORM’s Executor trait is deliberately not dyn-safe: it uses
async fn in trait and carries no Send + Sync bound, so the same generic
code can run inside a single-threaded Cloudflare Worker over a !Send D1
binding. That is the right call for the ORM, and it means a framework
cannot put an Arc<dyn Executor> in its container.
Connection is Rainier’s dyn-safe mirror of that port, and Database
is the shared handle the container holds.
§Two ways to read rows
Connection exposes fetching twice, and both futures are Send:
| Yields | For | |
|---|---|---|
fetch | OwnedRow — a Send snapshot | the repository layer, which decodes later |
fetch_raw | the driver’s own Box<dyn Row> | Database’s Executor impl, and so Rainier ORM’s repo:: |
A future’s output need not be Send for the future to be Send — the
value is moved out on the final poll rather than held across a suspension —
so fetch_raw can hand back !Send rows from a Send future. What the
caller must not do is hold those rows across a further await; decoding
them immediately, as Entity::from_row does, is the whole pattern.
fetch exists on top of that because the repository decodes into an entity
some way after the query, and an OwnedRow can be carried there safely.
§repo:: on the request path
Rainier ORM used to hold a sea_query statement across its awaits, which
made every repo:: future !Send and unusable from a handler the server
will tokio::spawn. That is fixed upstream (the statement is now built and
dropped in a scope that ends before the await), so
repo::/Query work directly against a Database.
statement predates the fix and still backs the
repository. It is no longer a workaround — it is how the repository renders
SQL — but the constraint that forced it is gone, and the
the_orms_own_futures_are_send… test in this crate’s root asserts as much.
Structs§
- Database
- A database handle: a shared
Connection, cheap to clone.
Traits§
- Connection
- A
dyn-safe database backend.