v0.2.7-pre.002-fix.001

This commit is contained in:
2026-08-22 16:49:43 +02:00
parent b64a799c85
commit b6908cb573
5 changed files with 209 additions and 31 deletions

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-onchain-transport-lib/src/ws_lifecycle.rs
// version: 1
// version: 2
/// Stable local identity assigned to one physical WebSocket session.
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
@@ -104,7 +104,7 @@ impl WsSubscriptionKind {
/// Returns the stable KSP descriptor for this standard subscription family.
#[must_use]
pub const fn as_str(self) -> &'static str {
match self {
return match self {
Self::Account => "account",
Self::Block => "block",
Self::Logs => "logs",
@@ -114,7 +114,7 @@ impl WsSubscriptionKind {
Self::Slot => "slot",
Self::SlotsUpdates => "slots_updates",
Self::Vote => "vote",
}
};
}
}
@@ -130,6 +130,7 @@ pub struct WsSubscriptionSnapshot {
impl WsSubscriptionSnapshot {
/// Creates one safe subscription lifecycle projection for Transport runtime internals.
#[must_use]
#[cfg(test)]
pub(crate) const fn new(id: crate::WsSubscriptionId, kind: crate::WsSubscriptionKind, state: crate::WsSubscriptionState, remote_bound: bool) -> Self {
return Self { id, kind, state, remote_bound };
}
@@ -182,6 +183,7 @@ pub struct WsSessionSnapshot {
impl WsSessionSnapshot {
/// Creates one safe session projection for Transport runtime internals.
#[must_use]
#[cfg(test)]
#[allow(clippy::too_many_arguments)]
pub(crate) fn new(
id: crate::WsSessionId,

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-onchain-transport-lib/src/ws_settings.rs
// version: 2
// version: 3
const DEFAULT_WS_CLOSE_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(5);
const DEFAULT_WS_COMMAND_QUEUE_CAPACITY: usize = 128;
@@ -132,9 +132,9 @@ impl WsProtocolKind {
/// Returns the stable KSP descriptor for this protocol family.
#[must_use]
pub const fn as_str(self) -> &'static str {
match self {
return match self {
Self::SolanaStandard => "solana_standard",
}
};
}
}
@@ -174,7 +174,11 @@ impl WsReconnectSettings {
impl std::default::Default for WsReconnectSettings {
fn default() -> Self {
return Self::new(DEFAULT_WS_RECONNECT_MAX_RETRIES, DEFAULT_WS_RECONNECT_INITIAL_BACKOFF, DEFAULT_WS_RECONNECT_MAX_BACKOFF);
return Self::new(
DEFAULT_WS_RECONNECT_MAX_RETRIES,
DEFAULT_WS_RECONNECT_INITIAL_BACKOFF,
DEFAULT_WS_RECONNECT_MAX_BACKOFF,
);
}
}
@@ -323,13 +327,27 @@ impl WsSessionSettings {
"ws_session.reconnect.max_backoff",
);
}
validate_non_zero_bound(self.command_queue_capacity, "ws_session.command_queue_capacity")?;
validate_non_zero_bound(self.notification_queue_capacity, "ws_session.notification_queue_capacity")?;
validate_non_zero_bound(self.max_active_subscriptions, "ws_session.max_active_subscriptions")?;
validate_non_zero_bound(self.max_pending_requests, "ws_session.max_pending_requests")?;
validate_non_zero_bound(self.max_message_size_bytes, "ws_session.max_message_size_bytes")?;
validate_non_zero_bound(self.max_frame_size_bytes, "ws_session.max_frame_size_bytes")?;
validate_non_zero_bound(self.max_write_buffer_size_bytes, "ws_session.max_write_buffer_size_bytes")?;
if let std::result::Result::Err(error) = validate_non_zero_bound(self.command_queue_capacity, "ws_session.command_queue_capacity") {
return std::result::Result::Err(error);
}
if let std::result::Result::Err(error) = validate_non_zero_bound(self.notification_queue_capacity, "ws_session.notification_queue_capacity") {
return std::result::Result::Err(error);
}
if let std::result::Result::Err(error) = validate_non_zero_bound(self.max_active_subscriptions, "ws_session.max_active_subscriptions") {
return std::result::Result::Err(error);
}
if let std::result::Result::Err(error) = validate_non_zero_bound(self.max_pending_requests, "ws_session.max_pending_requests") {
return std::result::Result::Err(error);
}
if let std::result::Result::Err(error) = validate_non_zero_bound(self.max_message_size_bytes, "ws_session.max_message_size_bytes") {
return std::result::Result::Err(error);
}
if let std::result::Result::Err(error) = validate_non_zero_bound(self.max_frame_size_bytes, "ws_session.max_frame_size_bytes") {
return std::result::Result::Err(error);
}
if let std::result::Result::Err(error) = validate_non_zero_bound(self.max_write_buffer_size_bytes, "ws_session.max_write_buffer_size_bytes") {
return std::result::Result::Err(error);
}
ksp_logging_lib::debug!(
target: crate::TRACING_TARGET,
command_queue_capacity = self.command_queue_capacity,
@@ -369,10 +387,10 @@ impl WsResubscribePolicy {
/// Returns the stable KSP descriptor for this policy.
#[must_use]
pub const fn as_str(self) -> &'static str {
match self {
return match self {
Self::Never => "never",
Self::ActiveSubscriptions => "active_subscriptions",
}
};
}
}
@@ -473,7 +491,9 @@ impl WsTransportSettings {
}
let mut enabled_endpoint_count = 0_usize;
for (endpoint_index, endpoint) in self.endpoints.iter().enumerate() {
validate_ws_endpoint(endpoint, endpoint_index)?;
if let std::result::Result::Err(error) = validate_ws_endpoint(endpoint, endpoint_index) {
return std::result::Result::Err(error);
}
if endpoint.enabled() {
enabled_endpoint_count += 1;
}
@@ -501,10 +521,21 @@ impl WsTransportSettings {
}
fn validate_ws_endpoint(endpoint: &crate::WsEndpointSettings, endpoint_index: usize) -> ksp_core_lib::Result<()> {
validate_ws_descriptor(endpoint.name(), format!("ws_endpoints[{endpoint_index}].name").as_str())?;
validate_ws_descriptor(endpoint.provider().as_str(), format!("ws_endpoints[{endpoint_index}].provider").as_str())?;
validate_ws_descriptor(endpoint.cluster().as_str(), format!("ws_endpoints[{endpoint_index}].cluster").as_str())?;
endpoint.session().validate()?;
let name_field = format!("ws_endpoints[{endpoint_index}].name");
if let std::result::Result::Err(error) = validate_ws_descriptor(endpoint.name(), name_field.as_str()) {
return std::result::Result::Err(error);
}
let provider_field = format!("ws_endpoints[{endpoint_index}].provider");
if let std::result::Result::Err(error) = validate_ws_descriptor(endpoint.provider().as_str(), provider_field.as_str()) {
return std::result::Result::Err(error);
}
let cluster_field = format!("ws_endpoints[{endpoint_index}].cluster");
if let std::result::Result::Err(error) = validate_ws_descriptor(endpoint.cluster().as_str(), cluster_field.as_str()) {
return std::result::Result::Err(error);
}
if let std::result::Result::Err(error) = endpoint.session().validate() {
return std::result::Result::Err(error);
}
ksp_logging_lib::trace!(
target: crate::TRACING_TARGET,
endpoint_name = endpoint.name(),