mirror of
https://github.com/neondatabase/neon.git
synced 2026-01-14 17:02:56 +00:00
proxy: force no retry some errors
This commit is contained in:
@@ -95,6 +95,20 @@ pub mod errors {
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn cannot_retry(&self) -> bool {
|
||||
match self {
|
||||
// retry some transport errors
|
||||
Self::Transport(io) => io.cannot_retry(),
|
||||
// locked can be returned when the endpoint was in transition
|
||||
// or when quotas are exceeded. don't retry when quotas are exceeded
|
||||
Self::Console {
|
||||
status: http::StatusCode::LOCKED,
|
||||
ref text,
|
||||
} => text.contains("quota"),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<reqwest::Error> for ApiError {
|
||||
|
||||
@@ -414,6 +414,9 @@ where
|
||||
Ok(res) => return Ok(res),
|
||||
Err(e) => {
|
||||
error!(error = ?e, "could not connect to compute node");
|
||||
if e.cannot_retry() {
|
||||
return Err(e.into());
|
||||
}
|
||||
(invalidate_cache(node_info), e)
|
||||
}
|
||||
};
|
||||
@@ -501,6 +504,8 @@ pub fn handle_try_wake(
|
||||
|
||||
pub trait ShouldRetry {
|
||||
fn could_retry(&self) -> bool;
|
||||
/// return true if retrying definitely won't make a difference - or is harmful
|
||||
fn cannot_retry(&self) -> bool;
|
||||
fn should_retry(&self, num_retries: u32) -> bool {
|
||||
match self {
|
||||
_ if num_retries >= NUM_RETRIES_CONNECT => false,
|
||||
@@ -517,6 +522,9 @@ impl ShouldRetry for io::Error {
|
||||
ErrorKind::ConnectionRefused | ErrorKind::AddrNotAvailable | ErrorKind::TimedOut
|
||||
)
|
||||
}
|
||||
fn cannot_retry(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl ShouldRetry for tokio_postgres::error::DbError {
|
||||
@@ -530,6 +538,22 @@ impl ShouldRetry for tokio_postgres::error::DbError {
|
||||
| &SqlState::SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION,
|
||||
)
|
||||
}
|
||||
fn cannot_retry(&self) -> bool {
|
||||
use tokio_postgres::error::SqlState;
|
||||
match self.code() {
|
||||
&SqlState::TOO_MANY_CONNECTIONS
|
||||
| &SqlState::INVALID_CATALOG_NAME
|
||||
| &SqlState::INVALID_PASSWORD => true,
|
||||
// pgbouncer errors?
|
||||
&SqlState::PROTOCOL_VIOLATION => matches!(
|
||||
self.message(),
|
||||
"no more connections allowed (max_client_conn)"
|
||||
| "server login has been failing, try again later (server_login_retry)"
|
||||
| "query_wait_timeout"
|
||||
),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ShouldRetry for tokio_postgres::Error {
|
||||
@@ -542,6 +566,13 @@ impl ShouldRetry for tokio_postgres::Error {
|
||||
false
|
||||
}
|
||||
}
|
||||
fn cannot_retry(&self) -> bool {
|
||||
if let Some(db_err) = self.source().and_then(|x| x.downcast_ref()) {
|
||||
tokio_postgres::error::DbError::cannot_retry(db_err)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ShouldRetry for compute::ConnectionError {
|
||||
@@ -552,6 +583,13 @@ impl ShouldRetry for compute::ConnectionError {
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
fn cannot_retry(&self) -> bool {
|
||||
match self {
|
||||
compute::ConnectionError::Postgres(err) => err.cannot_retry(),
|
||||
compute::ConnectionError::CouldNotConnect(err) => err.cannot_retry(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn retry_after(num_retries: u32) -> time::Duration {
|
||||
|
||||
@@ -365,6 +365,9 @@ impl ShouldRetry for TestConnectError {
|
||||
fn could_retry(&self) -> bool {
|
||||
self.retryable
|
||||
}
|
||||
fn cannot_retry(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
|
||||
Reference in New Issue
Block a user