• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

payjoin / rust-payjoin / 22582242969

02 Mar 2026 03:13PM UTC coverage: 82.526% (+0.04%) from 82.484%
22582242969

Pull #1376

github

web-flow
Merge 3e447f9ac into 55fbc08be
Pull Request #1376: Guard concurrent sends with exclusive DB lock and URI/RK checks

63 of 70 new or added lines in 4 files covered. (90.0%)

11 existing lines in 1 file now uncovered.

10683 of 12945 relevant lines covered (82.53%)

407.72 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/payjoin-cli/src/db/error.rs
1
use std::fmt;
2

3
use payjoin::ImplementationError;
4
use r2d2::Error as R2d2Error;
5
use rusqlite::Error as RusqliteError;
6

7
pub(crate) type Result<T> = std::result::Result<T, Error>;
8

9
#[derive(Debug)]
10
pub(crate) enum Error {
11
    Rusqlite(RusqliteError),
12
    R2d2(R2d2Error),
13
    #[cfg(feature = "v2")]
14
    Serialize(serde_json::Error),
15
    #[cfg(feature = "v2")]
16
    Deserialize(serde_json::Error),
17
    #[cfg(feature = "v2")]
18
    DuplicateUri,
19
    #[cfg(feature = "v2")]
20
    DuplicateRk,
21
}
22

23
impl fmt::Display for Error {
24
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
×
25
        match self {
×
UNCOV
26
            Error::Rusqlite(e) => write!(f, "Database operation failed: {e}"),
×
UNCOV
27
            Error::R2d2(e) => write!(f, "Connection pool error: {e}"),
×
28
            #[cfg(feature = "v2")]
29
            Error::Serialize(e) => write!(f, "Serialization failed: {e}"),
×
30
            #[cfg(feature = "v2")]
31
            Error::Deserialize(e) => write!(f, "Deserialization failed: {e}"),
×
32
            #[cfg(feature = "v2")]
NEW
UNCOV
33
            Error::DuplicateUri => write!(f, "A send session for this URI is already active"),
×
34
            #[cfg(feature = "v2")]
NEW
UNCOV
35
            Error::DuplicateRk => write!(
×
NEW
36
                f,
×
37
                "A send session with this receiver pubkey is already active under a different URI"
38
            ),
39
        }
40
    }
×
41
}
42

43
impl std::error::Error for Error {
44
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
×
45
        match self {
×
46
            Error::Rusqlite(e) => Some(e),
×
47
            Error::R2d2(e) => Some(e),
×
48
            #[cfg(feature = "v2")]
UNCOV
49
            Error::Serialize(e) => Some(e),
×
50
            #[cfg(feature = "v2")]
51
            Error::Deserialize(e) => Some(e),
×
52
            #[cfg(feature = "v2")]
NEW
53
            Error::DuplicateUri => None,
×
54
            #[cfg(feature = "v2")]
NEW
UNCOV
55
            Error::DuplicateRk => None,
×
56
        }
UNCOV
57
    }
×
58
}
59

60
impl From<RusqliteError> for Error {
61
    fn from(error: RusqliteError) -> Self { Error::Rusqlite(error) }
×
62
}
63

64
impl From<R2d2Error> for Error {
UNCOV
65
    fn from(error: R2d2Error) -> Self { Error::R2d2(error) }
×
66
}
67

68
#[cfg(feature = "v2")]
69
impl From<serde_json::Error> for Error {
70
    fn from(error: serde_json::Error) -> Self {
×
UNCOV
71
        match error.classify() {
×
UNCOV
72
            serde_json::error::Category::Io => Error::Serialize(error), // I/O errors during writing/serialization
×
73
            serde_json::error::Category::Syntax
74
            | serde_json::error::Category::Data
75
            | serde_json::error::Category::Eof => Error::Deserialize(error), // All parsing/reading errors
×
76
        }
77
    }
×
78
}
79

80
impl From<Error> for ImplementationError {
UNCOV
81
    fn from(error: Error) -> Self { ImplementationError::new(error) }
×
82
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc