100 lines
4.2 KiB
Rust
100 lines
4.2 KiB
Rust
// file: crates/ksp-onchain-transport-lib/src/grpc_channel.rs
|
|
// version: 1
|
|
|
|
/// Prepared Yellowstone gRPC channel owned by KSP Transport.
|
|
///
|
|
/// `pre.002` intentionally prepares a lazy HTTP/2 channel without performing network I/O. TLS configuration, provider-neutral metadata injection and live
|
|
/// connection/error semantics are added by `pre.003`. The underlying Tonic channel and upstream Yellowstone protobuf types are never exposed publicly.
|
|
pub struct YellowstoneGrpcChannel {
|
|
endpoint_name: std::string::String,
|
|
provider: crate::YellowstoneGrpcProviderName,
|
|
cluster: crate::YellowstoneGrpcClusterName,
|
|
channel: tonic::transport::Channel,
|
|
}
|
|
|
|
impl YellowstoneGrpcChannel {
|
|
/// Prepares one lazy Yellowstone gRPC channel from validated Transport-owned endpoint settings.
|
|
///
|
|
/// This operation performs no network connection. HTTPS endpoints remain syntactically accepted here; TLS is deliberately completed in `pre.003`
|
|
/// before any live call is allowed.
|
|
pub fn prepare(endpoint: &crate::YellowstoneGrpcEndpointSettings) -> ksp_core_lib::Result<Self> {
|
|
if let std::result::Result::Err(error) = endpoint.validate() {
|
|
return std::result::Result::Err(error);
|
|
}
|
|
if !endpoint.enabled() {
|
|
return std::result::Result::Err(
|
|
ksp_core_lib::Error::new(crate::ERROR_CODE_INVALID_SETTINGS, "disabled Yellowstone gRPC endpoint cannot prepare a channel")
|
|
.with_context("field", "grpc_endpoint.enabled")
|
|
.with_context("endpoint_name", endpoint.name()),
|
|
);
|
|
}
|
|
let tonic_endpoint = match tonic::transport::Endpoint::from_shared(endpoint.url().as_str().to_owned()) {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(_) => {
|
|
ksp_logging_lib::warn!(
|
|
target: crate::TRACING_TARGET,
|
|
endpoint_name = endpoint.name(),
|
|
provider = endpoint.provider().as_str(),
|
|
cluster = endpoint.cluster().as_str(),
|
|
"failed to prepare Yellowstone gRPC channel URI"
|
|
);
|
|
return std::result::Result::Err(
|
|
ksp_core_lib::Error::new(crate::ERROR_CODE_GRPC_CHANNEL_FAILED, "Yellowstone gRPC channel could not be prepared")
|
|
.with_context("endpoint_name", endpoint.name()),
|
|
);
|
|
},
|
|
};
|
|
let tonic_endpoint = tonic_endpoint
|
|
.connect_timeout(endpoint.session().connect_timeout())
|
|
.timeout(endpoint.session().unary_timeout())
|
|
.buffer_size(endpoint.session().request_channel_capacity());
|
|
let channel = tonic_endpoint.connect_lazy();
|
|
ksp_logging_lib::debug!(
|
|
target: crate::TRACING_TARGET,
|
|
endpoint_name = endpoint.name(),
|
|
provider = endpoint.provider().as_str(),
|
|
cluster = endpoint.cluster().as_str(),
|
|
"prepared lazy Yellowstone gRPC channel"
|
|
);
|
|
return std::result::Result::Ok(Self {
|
|
endpoint_name: endpoint.name().to_owned(),
|
|
provider: endpoint.provider().clone(),
|
|
cluster: endpoint.cluster().clone(),
|
|
channel,
|
|
});
|
|
}
|
|
|
|
/// Returns the safe logical endpoint name.
|
|
#[must_use]
|
|
pub fn endpoint_name(&self) -> &str {
|
|
return self.endpoint_name.as_str();
|
|
}
|
|
|
|
/// Returns the safe open provider descriptor.
|
|
#[must_use]
|
|
pub const fn provider(&self) -> &crate::YellowstoneGrpcProviderName {
|
|
return &self.provider;
|
|
}
|
|
|
|
/// Returns the safe open cluster descriptor.
|
|
#[must_use]
|
|
pub const fn cluster(&self) -> &crate::YellowstoneGrpcClusterName {
|
|
return &self.cluster;
|
|
}
|
|
}
|
|
|
|
impl std::fmt::Debug for YellowstoneGrpcChannel {
|
|
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
return formatter
|
|
.debug_struct("YellowstoneGrpcChannel")
|
|
.field("endpoint_name", &self.endpoint_name)
|
|
.field("provider", &self.provider)
|
|
.field("cluster", &self.cluster)
|
|
.finish();
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
#[path = "../unit_tests/grpc_channel.rs"]
|
|
mod tests;
|