diff --git a/docs/modules/ROOT/partials/rust/errors/ConnectionError.adoc b/docs/modules/ROOT/partials/rust/errors/ConnectionError.adoc
index 6e11711945..da2d1ddf08 100644
--- a/docs/modules/ROOT/partials/rust/errors/ConnectionError.adoc
+++ b/docs/modules/ROOT/partials/rust/errors/ConnectionError.adoc
@@ -17,6 +17,7 @@ a| `CloudSSLCertificateNotValidated`
a| `CloudTokenCredentialInvalid`
a| `ConnectionFailed`
a| `ConnectionIsClosed`
+a| `ConnectionTimedOut`
a| `DatabaseDoesNotExist`
a| `InvalidResponseField`
a| `MissingPort`
diff --git a/rust/src/common/error.rs b/rust/src/common/error.rs
index d6fb3908f0..2c226de5ec 100644
--- a/rust/src/common/error.rs
+++ b/rust/src/common/error.rs
@@ -74,6 +74,8 @@ error_messages! { ConnectionError
23: "Invalid URL '{address}': missing port.",
AddressTranslationMismatch { unknown: HashSet
, unmapped: HashSet } =
24: "Address translation map does not match the server's advertised address list. User-provided servers not in the advertised list: {unknown:?}. Advertised servers not mapped by user: {unmapped:?}.",
+ ConnectionTimedOut =
+ 25: "Connection to the server timed out."
}
error_messages! { InternalError
@@ -196,6 +198,8 @@ impl From for Error {
Self::Connection(ConnectionError::ServerConnectionFailedStatusError { error: status.message().to_owned() })
} else if status.code() == Code::Unimplemented {
Self::Connection(ConnectionError::RPCMethodUnavailable { message: status.message().to_owned() })
+ } else if status.code() == Code::Cancelled && status.message() == "Timeout expired" {
+ Self::Connection(ConnectionError::ConnectionTimedOut)
} else {
Self::from_message(status.message())
}
diff --git a/rust/src/connection/network/channel.rs b/rust/src/connection/network/channel.rs
index efe852086d..88ea721eb1 100644
--- a/rust/src/connection/network/channel.rs
+++ b/rust/src/connection/network/channel.rs
@@ -17,7 +17,10 @@
* under the License.
*/
-use std::sync::{Arc, RwLock};
+use std::{
+ sync::{Arc, RwLock},
+ time::Duration,
+};
use tonic::{
body::BoxBody,
@@ -49,8 +52,10 @@ impl GRPCChannel for PlainTextChannel {}
impl GRPCChannel for CallCredChannel {}
+const TIMEOUT: Duration = Duration::from_secs(60);
+
pub(super) fn open_plaintext_channel(address: Address) -> PlainTextChannel {
- PlainTextChannel::new(Channel::builder(address.into_uri()).connect_lazy(), PlainTextFacade)
+ PlainTextChannel::new(Channel::builder(address.into_uri()).timeout(TIMEOUT).connect_lazy(), PlainTextFacade)
}
#[derive(Clone, Debug)]
@@ -66,7 +71,7 @@ pub(super) fn open_callcred_channel(
address: Address,
credential: Credential,
) -> Result<(CallCredChannel, Arc)> {
- let mut builder = Channel::builder(address.into_uri());
+ let mut builder = Channel::builder(address.into_uri()).timeout(TIMEOUT);
if credential.is_tls_enabled() {
builder = builder.tls_config(credential.tls_config().clone().unwrap())?;
}