use std::time::{Duration, Instant};
use crate::observability::ContentionThresholds;
use super::CasExecutionOutcome;
#[derive(Debug, Clone)]
pub struct CasExecutionReport {
attempts_total: u32,
conflicts: u32,
retry_errors: u32,
aborts: u32,
timeouts: u32,
started_at: Instant,
finished_at: Instant,
max_attempts: u32,
max_elapsed: Option<Duration>,
outcome: CasExecutionOutcome,
}
impl CasExecutionReport {
#[allow(clippy::too_many_arguments)]
pub(crate) fn new(
attempts_total: u32,
conflicts: u32,
retry_errors: u32,
aborts: u32,
timeouts: u32,
started_at: Instant,
finished_at: Instant,
max_attempts: u32,
max_elapsed: Option<Duration>,
outcome: CasExecutionOutcome,
) -> Self {
Self {
attempts_total,
conflicts,
retry_errors,
aborts,
timeouts,
started_at,
finished_at,
max_attempts,
max_elapsed,
outcome,
}
}
#[inline]
pub fn attempts_total(&self) -> u32 {
self.attempts_total
}
#[inline]
pub fn conflicts(&self) -> u32 {
self.conflicts
}
#[inline]
pub fn retry_errors(&self) -> u32 {
self.retry_errors
}
#[inline]
pub fn aborts(&self) -> u32 {
self.aborts
}
#[inline]
pub fn timeouts(&self) -> u32 {
self.timeouts
}
#[inline]
pub fn started_at(&self) -> Instant {
self.started_at
}
#[inline]
pub fn finished_at(&self) -> Instant {
self.finished_at
}
#[inline]
pub fn elapsed(&self) -> Duration {
self.finished_at.duration_since(self.started_at)
}
#[inline]
pub fn max_attempts(&self) -> u32 {
self.max_attempts
}
#[inline]
pub fn max_elapsed(&self) -> Option<Duration> {
self.max_elapsed
}
#[inline]
pub fn outcome(&self) -> CasExecutionOutcome {
self.outcome
}
#[inline]
pub fn conflict_ratio(&self) -> f64 {
if self.attempts_total == 0 {
0.0
} else {
self.conflicts as f64 / self.attempts_total as f64
}
}
#[inline]
pub fn retryable_failure_ratio(&self) -> f64 {
if self.attempts_total == 0 {
0.0
} else {
self.retry_errors as f64 / self.attempts_total as f64
}
}
#[inline]
pub fn is_contention_hot(&self, thresholds: &ContentionThresholds) -> bool {
self.attempts_total >= thresholds.min_attempts()
&& self.conflicts >= thresholds.min_conflicts()
&& self.conflict_ratio() >= thresholds.conflict_ratio()
}
}