Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ rstest = "0.18.2"
serde_json = "1"
serial_test = "0.5.0"
tempfile = "=3.14.0"
tokio = { version = "1", features = ["sync", "rt-multi-thread", "macros"] }
tokio = { version = "1", features = ["sync", "rt-multi-thread", "macros", "test-util"] }

[[test]]
name = "failpoint_tests"
Expand Down
29 changes: 27 additions & 2 deletions src/common/security.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,27 @@ impl SecurityManager {
}

/// Connect to gRPC server using TLS connection. If TLS is not configured, use normal connection.
pub async fn connect<Factory, Client>(
///
/// The dial is bounded by the default request timeout — see
/// [`Self::connect_with_timeout`] to choose the bound.
pub async fn connect<Factory, Client>(&self, addr: &str, factory: Factory) -> Result<Client>
where
Factory: FnOnce(Channel) -> Client,
{
self.connect_with_timeout(addr, crate::config::DEFAULT_REQUEST_TIMEOUT, factory)
.await
}

/// Like [`Self::connect`], with `connect_timeout` bounding the whole dial,
/// HTTP/2 handshake included. A frozen peer can complete the TCP handshake
/// from its kernel (which keeps running when the process does not) and then
/// never answer the HTTP/2 preface, hanging an unbounded connect until the
/// peer thaws (#516).
pub async fn connect_with_timeout<Factory, Client>(
&self,
// env: Arc<Environment>,
addr: &str,
connect_timeout: Duration,
factory: Factory,
) -> Result<Client>
where
Expand All @@ -91,7 +108,15 @@ impl SecurityManager {
} else {
self.default_channel(addr).await?
};
let ch = channel.connect().await?;
let ch = tokio::time::timeout(connect_timeout, channel.connect())
.await
.map_err(|_| {
internal_err!(
"connecting to {} timed out after {:?}",
addr,
connect_timeout
)
})??;

Ok(factory(ch))
}
Expand Down
2 changes: 1 addition & 1 deletion src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ pub struct Config {
pub keyspace: Option<String>,
}

const DEFAULT_REQUEST_TIMEOUT: Duration = Duration::from_secs(2);
pub(crate) const DEFAULT_REQUEST_TIMEOUT: Duration = Duration::from_secs(2);
const DEFAULT_GRPC_MAX_DECODING_MESSAGE_SIZE: usize = 4 * 1024 * 1024; // 4MB

impl Default for Config {
Expand Down
24 changes: 15 additions & 9 deletions src/pd/cluster.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ impl Connection {
let members = self.validate_endpoints(endpoints, timeout).await?;
let (client, keyspace_client, members) = self.try_connect_leader(&members, timeout).await?;
let id = members.header.as_ref().unwrap().cluster_id;
let tso = TimestampOracle::new(id, &client)?;
let tso = TimestampOracle::new(id, &client, timeout)?;
let cluster = Cluster {
id,
client,
Expand All @@ -145,7 +145,7 @@ impl Connection {
let start = Instant::now();
let (client, keyspace_client, members) =
self.try_connect_leader(&cluster.members, timeout).await?;
let tso = TimestampOracle::new(cluster.id, &client)?;
let tso = TimestampOracle::new(cluster.id, &client, timeout)?;
*cluster = Cluster {
id: cluster.id,
client,
Expand Down Expand Up @@ -213,27 +213,33 @@ impl Connection {
async fn connect(
&self,
addr: &str,
_timeout: Duration,
timeout: Duration,
) -> Result<(
pdpb::pd_client::PdClient<Channel>,
keyspacepb::keyspace_client::KeyspaceClient<Channel>,
pdpb::GetMembersResponse,
)> {
let mut client = self
.security_mgr
.connect(addr, pdpb::pd_client::PdClient::<Channel>::new)
.connect_with_timeout(addr, timeout, pdpb::pd_client::PdClient::<Channel>::new)
.await?;
let keyspace_client = self
.security_mgr
.connect(
.connect_with_timeout(
addr,
timeout,
keyspacepb::keyspace_client::KeyspaceClient::<Channel>::new,
)
.await?;
let resp: pdpb::GetMembersResponse = client
.get_members(pdpb::GetMembersRequest::default())
.await?
.into_inner();
// Bounded like every other request in this path: this is the first RPC
// on a fresh connection, exactly where a frozen peer would hang it.
let resp: pdpb::GetMembersResponse = tokio::time::timeout(
timeout,
client.get_members(pdpb::GetMembersRequest::default()),
)
.await
.map_err(|_| internal_err!("get_members timed out after {:?}", timeout))??
.into_inner();
if let Some(err) = resp
.header
.as_ref()
Expand Down
Loading
Loading