v0.3.7-pre.004

This commit is contained in:
2026-09-02 11:00:20 +02:00
parent 03a94f4fb6
commit 46a4ad7487
17 changed files with 630 additions and 60 deletions

View File

@@ -0,0 +1,148 @@
// file: crates/ksp-app-backfill-desk/src/transport_runtime.rs
// version: 1
//! Composite-selected HTTP Transport readiness owned by Backfill Desk.
/// Safe and executable Transport runtime retained by the application state.
pub(crate) struct TransportRuntime {
pool: ksp_onchain_transport_lib::HttpTransportPool,
profile_id: String,
}
impl TransportRuntime {
/// Returns the composite-selected Transport profile identifier.
#[must_use]
pub(crate) fn profile_id(&self) -> &str {
return self.profile_id.as_str();
}
/// Builds the current safe Transport-only projection for the Backfill options surface.
pub(crate) fn options(&self) -> ksp_core_lib::Result<crate::BackfillDeskOptionsDto> {
let snapshot = self.pool.snapshot();
let configured_networks = configured_networks(&snapshot);
let compatible_roles = compatible_backfill_roles(&self.pool, &snapshot);
let compatible_roles = match compatible_roles {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let transport_ready = configured_networks.len() == 1 && !compatible_roles.is_empty() && snapshot.available_endpoint_count() > 0;
return std::result::Result::Ok(crate::BackfillDeskOptionsDto {
compatible_roles,
configured_networks,
transport_diagnostic: std::option::Option::None,
transport_ready,
});
}
}
/// Resolves the composite-selected Transport profile and builds the executable HTTP pool.
pub(crate) fn initialize_transport(management: &ksp_config_lib::ConfigManagement) -> ksp_core_lib::Result<TransportRuntime> {
let environment = ksp_config_lib::ConfigEnvironment::load();
let environment = match environment {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let composite = crate::load_backfill_desk_composite(management);
let composite = match composite {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let profile = crate::required_composite_component_profile(&composite, crate::COMPOSITE_COMPONENT_ID_TRANSPORT, ksp_config_lib::FILE_ID_STD_TRANSPORT);
let profile = match profile {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let resolved = management.engine().resolve_transport_config_profile(&profile, &environment);
let resolved = match resolved {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let profile_id = resolved.profile_id().to_owned();
let pool = ksp_onchain_transport_lib::HttpTransportPool::new(resolved.into_settings());
let pool = match pool {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let runtime = TransportRuntime { pool, profile_id };
let options = runtime.options();
let options = match options {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
ksp_logging_lib::debug!(
target: crate::TRACING_TARGET,
domain = crate::TRACING_DOMAIN_TRANSPORT,
transport_profile = runtime.profile_id(),
network_count = options.configured_networks.len(),
compatible_role_count = options.compatible_roles.len(),
transport_ready = options.transport_ready,
"initialized Backfill Desk HTTP Transport readiness from composite-managed configuration"
);
return std::result::Result::Ok(runtime);
}
fn compatible_backfill_roles(
pool: &ksp_onchain_transport_lib::HttpTransportPool,
snapshot: &ksp_onchain_transport_lib::HttpTransportPoolSnapshot,
) -> ksp_core_lib::Result<std::vec::Vec<String>> {
let signatures = required_http_rpc_method("getSignaturesForAddress");
let signatures = match signatures {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let transaction = required_http_rpc_method("getTransaction");
let transaction = match transaction {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let mut candidates = std::collections::BTreeSet::new();
for endpoint in snapshot.endpoints() {
if !endpoint.enabled() {
continue;
}
for role in endpoint.roles() {
if role.enabled() {
candidates.insert(role.role().to_owned());
}
}
}
let mut compatible = std::vec::Vec::new();
for candidate in candidates {
let role = ksp_onchain_transport_lib::HttpRoleName::new(candidate.clone());
if pool.select_for_method(&role, signatures).is_ok() && pool.select_for_method(&role, transaction).is_ok() {
compatible.push(candidate);
}
}
return std::result::Result::Ok(compatible);
}
fn configured_networks(snapshot: &ksp_onchain_transport_lib::HttpTransportPoolSnapshot) -> std::vec::Vec<String> {
let mut values = snapshot
.endpoints()
.iter()
.filter_map(|endpoint| {
if endpoint.enabled() {
return std::option::Option::Some(endpoint.cluster().to_owned());
}
return std::option::Option::None;
})
.collect::<std::vec::Vec<_>>();
values.sort();
values.dedup();
return values;
}
fn required_http_rpc_method(method: &'static str) -> ksp_core_lib::Result<&'static ksp_onchain_transport_lib::HttpRpcMethodDescriptor> {
let descriptor = ksp_onchain_transport_lib::find_http_rpc_method(method);
return match descriptor {
std::option::Option::Some(value) => std::result::Result::Ok(value),
std::option::Option::None => std::result::Result::Err(
ksp_core_lib::Error::new(crate::ERROR_CODE_TRANSPORT_READINESS_INVALID, "Backfill Desk Transport registry is missing a required HTTP RPC method")
.with_context("rpc_method", method),
),
};
}
#[cfg(test)]
#[path = "../unit_tests/transport_runtime.rs"]
mod tests;