syrup_rail_postgres/
transactions.rs1use std::{error::Error, fmt, time::Duration};
2
3use async_trait::async_trait;
4use sqlx::PgConnection;
5use syrup_rail::{BillingEvent, BillingEventSubject};
6
7type BoxError = Box<dyn Error + Send + Sync + 'static>;
8
9#[derive(Debug)]
10pub struct BillingTransactionError {
11 source: BoxError,
12}
13
14impl BillingTransactionError {
15 pub fn new(source: impl Error + Send + Sync + 'static) -> Self {
16 Self {
17 source: Box::new(source),
18 }
19 }
20
21 pub fn into_source(self) -> BoxError {
22 self.source
23 }
24}
25
26impl fmt::Display for BillingTransactionError {
27 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
28 formatter.write_str("billing transaction operation failed")
29 }
30}
31
32impl Error for BillingTransactionError {
33 fn source(&self) -> Option<&(dyn Error + 'static)> {
34 Some(self.source.as_ref())
35 }
36}
37
38#[derive(Debug)]
39pub struct BillingEventWriteError {
40 source: BoxError,
41}
42
43impl BillingEventWriteError {
44 pub fn new(source: impl Error + Send + Sync + 'static) -> Self {
45 Self {
46 source: Box::new(source),
47 }
48 }
49
50 pub fn into_source(self) -> BoxError {
51 self.source
52 }
53}
54
55impl fmt::Display for BillingEventWriteError {
56 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
57 formatter.write_str("billing event append failed")
58 }
59}
60
61impl Error for BillingEventWriteError {
62 fn source(&self) -> Option<&(dyn Error + 'static)> {
63 Some(self.source.as_ref())
64 }
65}
66
67#[derive(Clone, Copy, Debug, Eq, PartialEq)]
68pub enum BillingTransactionSubjectState {
69 LiveRecipient,
70 RetainedSubject,
71}
72
73#[async_trait]
76pub trait BillingTransactionCoordinator: Send + Sync {
77 async fn begin(
78 &self,
79 subject: BillingEventSubject,
80 lock_timeout: Duration,
81 ) -> Result<Box<dyn BillingTransaction>, BillingTransactionError>;
82}
83
84#[async_trait]
89pub trait BillingTransaction: Send {
90 fn connection(&mut self) -> &mut PgConnection;
91
92 fn subject_state(&self) -> BillingTransactionSubjectState;
93
94 async fn append_event(&mut self, event: &BillingEvent) -> Result<(), BillingEventWriteError>;
95
96 async fn commit(self: Box<Self>) -> Result<(), BillingTransactionError>;
97
98 async fn rollback(self: Box<Self>) -> Result<(), BillingTransactionError>;
99}