postgres_notify/
error.rs

1use {std::time::Duration, thiserror::Error};
2
3#[derive(Debug, Error)]
4pub enum PGError {
5    #[error(transparent)]
6    Postgres(tokio_postgres::Error),
7    #[error("Query timed out after {0:?}")]
8    Timeout(Duration),
9    #[error("Failed to reconnect after {0} attempts")]
10    FailedToReconnect(u32),
11}
12
13impl PGError {
14    pub fn is_pg_connection_issue(&self) -> bool {
15        matches!(self, PGError::Postgres(e) if is_pg_connection_issue(e))
16    }
17    pub fn is_timeout(&self) -> bool {
18        matches!(self, PGError::Timeout(_))
19    }
20}
21
22impl From<tokio_postgres::Error> for PGError {
23    fn from(e: tokio_postgres::Error) -> Self {
24        PGError::Postgres(e)
25    }
26}
27
28///
29/// PRIVATE
30/// Returns true if the error is a connection issue.
31///
32pub(crate) fn is_pg_connection_issue(err: &tokio_postgres::Error) -> bool {
33    if err.is_closed() {
34        return true;
35    }
36    let code = err.code().map(|state| state.code()).unwrap_or_default();
37    if code.starts_with("08") || code.starts_with("57") {
38        return true;
39    }
40
41    let msg = err.to_string();
42    msg.starts_with("error connecting to server")
43        || msg.starts_with("timeout waiting for server")
44        || msg.starts_with("error communicating with the server")
45}