pub struct Db { /* private fields */ }Expand description
Database handle for secure operations.
§Security
This type is Clone to support ergonomic sharing in runtimes and service containers.
Transaction-bypass is still prevented by the task-local guard: any attempt to call
conn() inside a transaction closure fails with DbError::ConnRequestedInsideTx.
Services and repositories must NOT store this type. They should receive
&impl DBRunner as a parameter to all methods that need database access.
§Usage
// At the entrypoint (handler/command)
let db: Db = ctx.db()?;
// Pass runner to service methods
let conn = db.conn()?;
let result = service.do_something(&conn, &scope).await?;
// Or use a transaction
let (db, result) = db.transaction(|tx| {
Box::pin(async move {
service.do_something(tx, &scope).await
})
}).await;Implementations§
Source§impl Db
impl Db
Sourcepub fn conn(&self) -> Result<DbConn<'_>, DbError>
pub fn conn(&self) -> Result<DbConn<'_>, DbError>
Get a reference to the underlying DbHandle.
§Security
This is pub(crate) to allow internal infrastructure access (migrations, etc.)
but prevents service code from extracting the handle.
Create a non-transactional database runner.
The returned DbConn borrows from self, ensuring that while a DbConn
exists, the Db cannot be used for other purposes (like starting a transaction).
§Errors
Returns DbError::ConnRequestedInsideTx if called from within a transaction
closure. This prevents the transaction bypass vulnerability where code could
create a non-transactional runner that persists writes outside the transaction.
§Example
let db: Db = ctx.db()?;
let conn = db.conn()?;
// Use conn for queries
let users = Entity::find()
.secure()
.scope_with(&scope)
.all(&conn)
.await?;The Result itself is #[must_use]; this method does not add an extra must-use
marker to avoid clippy double_must_use.
Sourcepub async fn lock(&self, module: &str, key: &str) -> Result<DbLockGuard>
pub async fn lock(&self, module: &str, key: &str) -> Result<DbLockGuard>
Acquire an advisory lock with the given key and module namespace.
§Errors
Returns an error if the lock cannot be acquired.
Sourcepub async fn try_lock(
&self,
module: &str,
key: &str,
config: LockConfig,
) -> Result<Option<DbLockGuard>>
pub async fn try_lock( &self, module: &str, key: &str, config: LockConfig, ) -> Result<Option<DbLockGuard>>
Try to acquire an advisory lock with configurable retry/backoff policy.
§Errors
Returns an error if an unrecoverable lock error occurs.
Sourcepub async fn transaction_ref<F, T>(&self, f: F) -> Result<T, DbError>
pub async fn transaction_ref<F, T>(&self, f: F) -> Result<T, DbError>
Execute a closure inside a database transaction (borrowed form).
This variant keeps the call site ergonomic for service containers that store a
reusable DB entrypoint (e.g. DBProvider) without exposing DbHandle.
§Security
The task-local guard is still enforced: any call to Db::conn() within the closure
will fail with DbError::ConnRequestedInsideTx.
§Errors
Returns DbError if:
- starting the transaction fails
- the closure returns an error
- commit fails (rollback is attempted on closure error)
Sourcepub async fn transaction_ref_mapped<F, T, E>(&self, f: F) -> Result<T, E>
pub async fn transaction_ref_mapped<F, T, E>(&self, f: F) -> Result<T, E>
Execute a closure inside a database transaction, mapping infrastructure errors into E.
This is the preferred building block for service-facing entrypoints (like DBProvider)
that must return domain errors while still acquiring connections internally.
- The transaction closure returns
Result<T, E>(domain error). - Begin/commit failures are
DbErrorand are mapped viaE: From<DbError>.
§Security
The task-local guard is enforced for the duration of the closure.
§Errors
Returns E if:
- starting the transaction fails (mapped from
DbError) - the closure returns an error
- commit fails (mapped from
DbError)
Sourcepub async fn transaction<F, T>(self, f: F) -> (Self, Result<T>)
pub async fn transaction<F, T>(self, f: F) -> (Self, Result<T>)
Execute a closure inside a database transaction.
§Security
This method consumes self and returns it after the transaction completes.
This is critical for security: inside the closure, the original Db is not
accessible, so code cannot call db.conn() to create a non-transactional runner.
Additionally, a task-local guard is set during the transaction, so any call
to conn() on any Db instance will fail with DbError::ConnRequestedInsideTx.
§Example
let db: Db = ctx.db()?;
let (db, result) = db.transaction(|tx| {
Box::pin(async move {
// Only `tx` is available here
service.create_user(tx, &scope, data).await?;
Ok(user_id)
})
}).await;
let user_id = result?;§Returns
Returns (Self, Result<T>) where:
Selfis always returned (even on error) so the connection can be reusedResult<T>contains the transaction result or error
Sourcepub async fn in_transaction<T, E, F>(
self,
f: F,
) -> (Self, Result<T, TxError<E>>)
pub async fn in_transaction<T, E, F>( self, f: F, ) -> (Self, Result<T, TxError<E>>)
Execute a transaction with typed domain errors.
This variant separates infrastructure errors (connection issues, commit failures) from domain errors returned by the closure.
§Example
let (db, result) = db.in_transaction(|tx| {
Box::pin(async move {
service.create_user(tx, &scope, data).await
})
}).await;
match result {
Ok(user) => println!("Created: {:?}", user),
Err(TxError::Domain(e)) => println!("Business error: {}", e),
Err(TxError::Infra(e)) => println!("DB error: {}", e),
}Sourcepub async fn transaction_with_config<T, F>(
self,
config: TxConfig,
f: F,
) -> (Self, Result<T>)
pub async fn transaction_with_config<T, F>( self, config: TxConfig, f: F, ) -> (Self, Result<T>)
Execute a transaction with custom configuration (isolation level, access mode).
§Example
use modkit_db::secure::{TxConfig, TxIsolationLevel};
let config = TxConfig {
isolation: Some(TxIsolationLevel::Serializable),
access_mode: None,
};
let (db, result) = db.transaction_with_config(config, |tx| {
Box::pin(async move {
// Serializable isolation
service.reconcile(tx, &scope).await
})
}).await;Trait Implementations§
Auto Trait Implementations§
impl Freeze for Db
impl RefUnwindSafe for Db
impl Send for Db
impl Sync for Db
impl Unpin for Db
impl UnsafeUnpin for Db
impl UnwindSafe for Db
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> Paint for Twhere
T: ?Sized,
impl<T> Paint for Twhere
T: ?Sized,
Source§fn fg(&self, value: Color) -> Painted<&T>
fn fg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self with the foreground set to
value.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like red() and
green(), which have the same functionality but are
pithier.
§Example
Set foreground color to white using fg():
use yansi::{Paint, Color};
painted.fg(Color::White);Set foreground color to white using white().
use yansi::Paint;
painted.white();Source§fn bright_black(&self) -> Painted<&T>
fn bright_black(&self) -> Painted<&T>
Source§fn bright_red(&self) -> Painted<&T>
fn bright_red(&self) -> Painted<&T>
Source§fn bright_green(&self) -> Painted<&T>
fn bright_green(&self) -> Painted<&T>
Source§fn bright_yellow(&self) -> Painted<&T>
fn bright_yellow(&self) -> Painted<&T>
Source§fn bright_blue(&self) -> Painted<&T>
fn bright_blue(&self) -> Painted<&T>
Source§fn bright_magenta(&self) -> Painted<&T>
fn bright_magenta(&self) -> Painted<&T>
Source§fn bright_cyan(&self) -> Painted<&T>
fn bright_cyan(&self) -> Painted<&T>
Source§fn bright_white(&self) -> Painted<&T>
fn bright_white(&self) -> Painted<&T>
Source§fn bg(&self, value: Color) -> Painted<&T>
fn bg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self with the background set to
value.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like on_red() and
on_green(), which have the same functionality but
are pithier.
§Example
Set background color to red using fg():
use yansi::{Paint, Color};
painted.bg(Color::Red);Set background color to red using on_red().
use yansi::Paint;
painted.on_red();Source§fn on_primary(&self) -> Painted<&T>
fn on_primary(&self) -> Painted<&T>
Source§fn on_magenta(&self) -> Painted<&T>
fn on_magenta(&self) -> Painted<&T>
Source§fn on_bright_black(&self) -> Painted<&T>
fn on_bright_black(&self) -> Painted<&T>
Source§fn on_bright_red(&self) -> Painted<&T>
fn on_bright_red(&self) -> Painted<&T>
Source§fn on_bright_green(&self) -> Painted<&T>
fn on_bright_green(&self) -> Painted<&T>
Source§fn on_bright_yellow(&self) -> Painted<&T>
fn on_bright_yellow(&self) -> Painted<&T>
Source§fn on_bright_blue(&self) -> Painted<&T>
fn on_bright_blue(&self) -> Painted<&T>
Source§fn on_bright_magenta(&self) -> Painted<&T>
fn on_bright_magenta(&self) -> Painted<&T>
Source§fn on_bright_cyan(&self) -> Painted<&T>
fn on_bright_cyan(&self) -> Painted<&T>
Source§fn on_bright_white(&self) -> Painted<&T>
fn on_bright_white(&self) -> Painted<&T>
Source§fn attr(&self, value: Attribute) -> Painted<&T>
fn attr(&self, value: Attribute) -> Painted<&T>
Enables the styling Attribute value.
This method should be used rarely. Instead, prefer to use
attribute-specific builder methods like bold() and
underline(), which have the same functionality
but are pithier.
§Example
Make text bold using attr():
use yansi::{Paint, Attribute};
painted.attr(Attribute::Bold);Make text bold using using bold().
use yansi::Paint;
painted.bold();Source§fn rapid_blink(&self) -> Painted<&T>
fn rapid_blink(&self) -> Painted<&T>
Source§fn quirk(&self, value: Quirk) -> Painted<&T>
fn quirk(&self, value: Quirk) -> Painted<&T>
Enables the yansi Quirk value.
This method should be used rarely. Instead, prefer to use quirk-specific
builder methods like mask() and
wrap(), which have the same functionality but are
pithier.
§Example
Enable wrapping using .quirk():
use yansi::{Paint, Quirk};
painted.quirk(Quirk::Wrap);Enable wrapping using wrap().
use yansi::Paint;
painted.wrap();Source§fn clear(&self) -> Painted<&T>
👎Deprecated since 1.0.1: renamed to resetting() due to conflicts with Vec::clear().
The clear() method will be removed in a future release.
fn clear(&self) -> Painted<&T>
resetting() due to conflicts with Vec::clear().
The clear() method will be removed in a future release.Source§fn whenever(&self, value: Condition) -> Painted<&T>
fn whenever(&self, value: Condition) -> Painted<&T>
Conditionally enable styling based on whether the Condition value
applies. Replaces any previous condition.
See the crate level docs for more details.
§Example
Enable styling painted only when both stdout and stderr are TTYs:
use yansi::{Paint, Condition};
painted.red().on_yellow().whenever(Condition::STDOUTERR_ARE_TTY);