uqa_storage/mvcc/
outcome.rs1use super::{CommitErrorOutcome, SerializableTransactionId, StorageTransactionId};
10use crate::StorageBackendError;
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14pub enum TransactionOutcomeId {
15 Records(StorageTransactionId),
16 Serializable(SerializableTransactionId),
17}
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub enum TransactionOutcome {
21 Indeterminate(TransactionOutcomeId),
22 Committed(TransactionOutcomeId),
23 Aborted(TransactionOutcomeId),
24}
25
26impl TransactionOutcome {
27 pub const fn id(self) -> TransactionOutcomeId {
28 match self {
29 Self::Indeterminate(id) | Self::Committed(id) | Self::Aborted(id) => id,
30 }
31 }
32}
33
34impl From<CommitErrorOutcome> for TransactionOutcome {
35 fn from(outcome: CommitErrorOutcome) -> Self {
36 match outcome {
37 CommitErrorOutcome::Indeterminate(id) => {
38 Self::Indeterminate(TransactionOutcomeId::Records(id))
39 }
40 CommitErrorOutcome::Committed(receipt) => {
41 Self::Committed(TransactionOutcomeId::Records(receipt.transaction))
42 }
43 CommitErrorOutcome::Aborted(id) => Self::Aborted(TransactionOutcomeId::Records(id)),
44 }
45 }
46}
47
48#[derive(Debug, thiserror::Error)]
50#[error("transaction completion {outcome:?}: {source}")]
51pub struct TransactionCompletionError {
52 pub outcome: TransactionOutcome,
53 pub publication: Option<CommitErrorOutcome>,
54 #[source]
55 pub source: StorageBackendError,
56}
57
58impl StorageBackendError {
59 pub fn transaction_outcome(&self) -> Option<TransactionOutcome> {
61 let mut cause: Option<&(dyn std::error::Error + 'static)> = Some(self);
62 while let Some(error) = cause {
63 if let Some(error) = error.downcast_ref::<TransactionCompletionError>() {
64 return Some(error.outcome);
65 }
66 if let Some(outcome) = super::persistence::error_commit_outcome(error) {
67 return Some(outcome.into());
68 }
69 cause = error.source();
70 }
71 None
72 }
73}