blob: 7d6a0e34de2a7a4dd0b60b2e6698036ec217b0c5 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
use anyhow::Result;
use std::sync::Arc;
/// Unit of Work pattern for managing transactional boundaries
pub trait UnitOfWork: Send + Sync {
/// Begin a new transaction
fn begin(&self) -> Result<Box<dyn Transaction>>;
}
/// Transaction interface for atomic operations
pub trait Transaction: Send + Sync {
/// Commit all changes in this transaction
fn commit(self: Box<Self>) -> Result<()>;
/// Rollback all changes in this transaction
fn rollback(self: Box<Self>) -> Result<()>;
/// Get repositories within this transaction context
fn client_repository(&self) -> Arc<dyn crate::domain::DomainClientRepository>;
fn auth_code_repository(&self) -> Arc<dyn crate::domain::DomainAuthCodeRepository>;
fn token_repository(&self) -> Arc<dyn crate::domain::DomainTokenRepository>;
fn audit_repository(&self) -> Arc<dyn crate::domain::DomainAuditRepository>;
}
/// OAuth2-specific transactional operations
pub struct OAuthUnitOfWork {
uow: Arc<dyn UnitOfWork>,
}
impl OAuthUnitOfWork {
pub fn new(uow: Arc<dyn UnitOfWork>) -> Self {
Self { uow }
}
/// Execute OAuth2 authorization code exchange atomically
pub fn exchange_authorization_code<F>(&self, operation: F) -> Result<()>
where
F: FnOnce(&dyn Transaction) -> Result<()>,
{
let tx = self.uow.begin()?;
match operation(tx.as_ref()) {
Ok(_) => tx.commit(),
Err(e) => {
let _ = tx.rollback(); // Log but don't override original error
Err(e)
}
}
}
/// Execute token refresh atomically
pub fn refresh_tokens<F>(&self, operation: F) -> Result<()>
where
F: FnOnce(&dyn Transaction) -> Result<()>,
{
let tx = self.uow.begin()?;
match operation(tx.as_ref()) {
Ok(_) => tx.commit(),
Err(e) => {
let _ = tx.rollback();
Err(e)
}
}
}
}
|