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

payjoin / rust-payjoin / 23953420148

03 Apr 2026 04:25PM UTC coverage: 84.381% (+0.04%) from 84.34%
23953420148

Pull #1376

github

web-flow
Merge 4d37434a9 into 9ed621f78
Pull Request #1376: Guard concurrent sends with exclusive DB lock and URI/RK checks

65 of 71 new or added lines in 4 files covered. (91.55%)

7 existing lines in 1 file now uncovered.

10859 of 12869 relevant lines covered (84.38%)

410.36 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
#[cfg(feature = "v2")]
10
#[derive(Debug)]
11
pub(crate) enum DuplicateKind {
12
    Uri,
13
    ReceiverPubkey,
14
}
15

16
#[derive(Debug)]
17
pub(crate) enum Error {
18
    Rusqlite(RusqliteError),
19
    R2d2(R2d2Error),
20
    #[cfg(feature = "v2")]
21
    Serialize(serde_json::Error),
22
    #[cfg(feature = "v2")]
23
    Deserialize(serde_json::Error),
24
    #[cfg(feature = "v2")]
25
    DuplicateSendSession(DuplicateKind),
26
}
27

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

50
impl std::error::Error for Error {
51
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
×
52
        match self {
×
53
            Error::Rusqlite(e) => Some(e),
×
54
            Error::R2d2(e) => Some(e),
×
55
            #[cfg(feature = "v2")]
56
            Error::Serialize(e) => Some(e),
×
57
            #[cfg(feature = "v2")]
58
            Error::Deserialize(e) => Some(e),
×
59
            #[cfg(feature = "v2")]
NEW
60
            Error::DuplicateSendSession(_) => None,
×
61
        }
62
    }
×
63
}
64

65
impl From<RusqliteError> for Error {
66
    fn from(error: RusqliteError) -> Self { Error::Rusqlite(error) }
×
67
}
68

69
impl From<R2d2Error> for Error {
70
    fn from(error: R2d2Error) -> Self { Error::R2d2(error) }
×
71
}
72

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

85
impl From<Error> for ImplementationError {
86
    fn from(error: Error) -> Self { ImplementationError::new(error) }
×
87
}
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