feat(storage): use mdbx_txn_reset to time out transactions (#6850)

Co-authored-by: Emilia Hane <elsaemiliaevahane@gmail.com>
This commit is contained in:
Alexey Shekhirin
2024-02-29 20:44:56 +00:00
committed by GitHub
parent 771951429e
commit 74dc0e36d3
11 changed files with 289 additions and 335 deletions

View File

@ -123,17 +123,19 @@ impl Database for DatabaseEnv {
type TXMut = tx::Tx<RW>;
fn tx(&self) -> Result<Self::TX, DatabaseError> {
Ok(Tx::new_with_metrics(
Tx::new_with_metrics(
self.inner.begin_ro_txn().map_err(|e| DatabaseError::InitTx(e.into()))?,
self.metrics.as_ref().cloned(),
))
)
.map_err(|e| DatabaseError::InitTx(e.into()))
}
fn tx_mut(&self) -> Result<Self::TXMut, DatabaseError> {
Ok(Tx::new_with_metrics(
Tx::new_with_metrics(
self.inner.begin_rw_txn().map_err(|e| DatabaseError::InitTx(e.into()))?,
self.metrics.as_ref().cloned(),
))
)
.map_err(|e| DatabaseError::InitTx(e.into()))
}
}
@ -202,6 +204,12 @@ impl DatabaseMetrics for DatabaseEnv {
metrics.push(("db.freelist", freelist as f64, vec![]));
}
metrics.push((
"db.timed_out_not_aborted_transactions",
self.timed_out_not_aborted_transactions() as f64,
vec![],
));
metrics
}
}

View File

@ -53,14 +53,16 @@ impl<K: TransactionKind> Tx<K> {
pub fn new_with_metrics(
inner: Transaction<K>,
env_metrics: Option<Arc<DatabaseEnvMetrics>>,
) -> Self {
let metrics_handler = env_metrics.map(|env_metrics| {
let handler = MetricsHandler::<K>::new(inner.id(), env_metrics);
handler.env_metrics.record_opened_transaction(handler.transaction_mode());
handler.log_transaction_opened();
handler
});
Self::new_inner(inner, metrics_handler)
) -> reth_libmdbx::Result<Self> {
let metrics_handler = env_metrics
.map(|env_metrics| {
let handler = MetricsHandler::<K>::new(inner.id()?, env_metrics);
handler.env_metrics.record_opened_transaction(handler.transaction_mode());
handler.log_transaction_opened();
Ok(handler)
})
.transpose()?;
Ok(Self::new_inner(inner, metrics_handler))
}
#[inline]
@ -76,8 +78,8 @@ impl<K: TransactionKind> Tx<K> {
}
/// Gets this transaction ID.
pub fn id(&self) -> u64 {
self.metrics_handler.as_ref().map_or_else(|| self.inner.id(), |handler| handler.txn_id)
pub fn id(&self) -> reth_libmdbx::Result<u64> {
self.metrics_handler.as_ref().map_or_else(|| self.inner.id(), |handler| Ok(handler.txn_id))
}
/// Gets a table database handle if it exists, otherwise creates it.
@ -437,7 +439,7 @@ mod tests {
assert_eq!(
tx.get::<tables::Transactions>(0).err(),
Some(DatabaseError::Open(reth_libmdbx::Error::ReadTransactionAborted.into()))
Some(DatabaseError::Open(reth_libmdbx::Error::ReadTransactionTimeout.into()))
); // Transaction is timeout-ed
assert!(tx.metrics_handler.unwrap().backtrace_recorded.load(Ordering::Relaxed));
// Backtrace is recorded