v0.3.7-pre.005

This commit is contained in:
2026-09-02 12:01:35 +02:00
parent 46a4ad7487
commit 500b87ef57
19 changed files with 686 additions and 29 deletions

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-app-backfill-desk/src/app_state.rs
// version: 2
// version: 3
//! Shared backend state owned by the Backfill Desk Tauri application.
@@ -7,8 +7,10 @@
pub(crate) struct AppState {
config_management: ksp_config_lib::ConfigManagement,
logging_runtime: std::sync::Mutex<LoggingRuntimeState>,
shutdown_started: std::sync::atomic::AtomicBool,
splash_settings: crate::SplashSettings,
splash_sequence_started: std::sync::atomic::AtomicBool,
store_startup: crate::StoreStartup,
transport_runtime: std::option::Option<crate::TransportRuntime>,
transport_startup_diagnostic: std::option::Option<crate::CommandErrorDto>,
}
@@ -46,6 +48,7 @@ impl crate::AppState {
(std::option::Option::None, std::option::Option::Some(diagnostic))
},
};
let store_startup = tauri::async_runtime::block_on(crate::initialize_store(&config_management, transport_runtime.as_ref()));
let splash_settings = crate::SplashSettings::load();
let splash_settings = match splash_settings {
std::result::Result::Ok(value) => value,
@@ -80,8 +83,10 @@ impl crate::AppState {
fallback_active: logging_startup.fallback_active,
startup_diagnostic: logging_startup.startup_diagnostic,
}),
shutdown_started: std::sync::atomic::AtomicBool::new(false),
splash_settings,
splash_sequence_started: std::sync::atomic::AtomicBool::new(false),
store_startup,
transport_runtime,
transport_startup_diagnostic,
});
@@ -116,23 +121,44 @@ impl crate::AppState {
application_version: env!("CARGO_PKG_VERSION").to_owned(),
config_document_count: document_count,
fallback_logging_active: runtime.fallback_active,
shell_phase: "pre.004-transport-readiness".to_owned(),
shell_phase: "pre.005-store-readiness".to_owned(),
startup_diagnostic: runtime.startup_diagnostic.clone(),
});
}
/// Builds the safe Transport-readiness subset of Backfill Desk options.
/// Builds the safe Transport-and-Store readiness subset of Backfill Desk options.
pub(crate) fn backfill_options(&self) -> ksp_core_lib::Result<crate::BackfillDeskOptionsDto> {
let runtime = self.transport_runtime.as_ref();
return match runtime {
let options = match runtime {
std::option::Option::Some(value) => value.options(),
std::option::Option::None => std::result::Result::Ok(crate::BackfillDeskOptionsDto {
compatible_roles: std::vec::Vec::new(),
composition_ready: false,
configured_networks: std::vec::Vec::new(),
network_coherent: false,
store_diagnostic: std::option::Option::None,
store_network: std::option::Option::None,
store_ready: false,
transport_diagnostic: self.transport_startup_diagnostic.clone(),
transport_ready: false,
}),
};
let mut options = match options {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
self.store_startup.apply_to(&mut options);
return std::result::Result::Ok(options);
}
/// Marks graceful application shutdown as started and reports whether this caller won the one-shot transition.
pub(crate) fn begin_shutdown(&self) -> bool {
return self.shutdown_started.compare_exchange(false, true, std::sync::atomic::Ordering::AcqRel, std::sync::atomic::Ordering::Acquire).is_ok();
}
/// Explicitly closes the retained Store runtime when application shutdown begins.
pub(crate) async fn close_store(&self) -> ksp_core_lib::Result<()> {
return self.store_startup.close().await;
}
/// Returns the resolved splash timings captured during application bootstrap.

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-app-backfill-desk/src/constants.rs
// version: 3
// version: 4
//! Application-owned tracing targets and domains.
@@ -15,6 +15,8 @@ pub(crate) const TRACING_DOMAIN_BOOTSTRAP: &str = "backfill.bootstrap";
pub(crate) const TRACING_DOMAIN_FRONTEND: &str = "frontend";
/// Structured domain used by the Backfill Desk shell.
pub(crate) const TRACING_DOMAIN_SHELL: &str = "backfill.shell";
/// Structured domain used by Store readiness and shutdown operations.
pub(crate) const TRACING_DOMAIN_STORE: &str = "backfill.store";
/// Structured domain used by Transport readiness and role inventory operations.
pub(crate) const TRACING_DOMAIN_TRANSPORT: &str = "backfill.transport";
/// Structured domain used by Tauri window lifecycle operations.

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-app-backfill-desk/src/dto_common.rs
// version: 2
// version: 3
//! Common Tauri DTOs shared by the Backfill Desk shell.
@@ -15,8 +15,18 @@ use ts_rs::TS; // rust-rules: trait-import
pub(crate) struct BackfillDeskOptionsDto {
/// Logical roles that can route both RPC methods required by the Backfill runtime.
pub(crate) compatible_roles: std::vec::Vec<String>,
/// Whether the Transport and Store readiness gates jointly permit later Backfill composition.
pub(crate) composition_ready: bool,
/// Distinct enabled HTTP cluster labels selected by the active Transport profile.
pub(crate) configured_networks: std::vec::Vec<String>,
/// Whether the selected Store network exactly matches the one coherent Transport network.
pub(crate) network_coherent: bool,
/// Safe startup diagnostic when Store configuration, opening or readiness could not be proven.
pub(crate) store_diagnostic: std::option::Option<CommandErrorDto>,
/// Logical network selected by the active Store profile, without backend connection details.
pub(crate) store_network: std::option::Option<String>,
/// Whether Store opened successfully and its bounded health probe proved readiness.
pub(crate) store_ready: bool,
/// Safe startup diagnostic when Transport configuration could not be resolved or constructed.
pub(crate) transport_diagnostic: std::option::Option<CommandErrorDto>,
/// Whether Transport currently has one coherent network and at least one compatible available role.

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-app-backfill-desk/src/errors.rs
// version: 4
// version: 5
//! Application-local error codes for Backfill Desk composition and desktop runtime surfaces.
@@ -19,6 +19,12 @@ pub(crate) const ERROR_CODE_LOGGING_BOOTSTRAP_FAILED: ksp_core_lib::ErrorCode =
pub(crate) const ERROR_CODE_SPLASH_ORIGIN_INVALID: ksp_core_lib::ErrorCode = ksp_core_lib::ErrorCode::new("backfill_desk", "splash_origin_invalid");
/// A KSP desk splash environment duration is malformed or exceeds its safety bound.
pub(crate) const ERROR_CODE_SPLASH_SETTING_INVALID: ksp_core_lib::ErrorCode = ksp_core_lib::ErrorCode::new("backfill_desk", "splash_setting_invalid");
/// Backfill Desk Store and Transport configuration target different logical networks.
pub(crate) const ERROR_CODE_STORE_NETWORK_MISMATCH: ksp_core_lib::ErrorCode = ksp_core_lib::ErrorCode::new("backfill_desk", "store_network_mismatch");
/// Backfill Desk cannot prove a single Transport network before Store opening.
pub(crate) const ERROR_CODE_STORE_NETWORK_UNAVAILABLE: ksp_core_lib::ErrorCode = ksp_core_lib::ErrorCode::new("backfill_desk", "store_network_unavailable");
/// Backfill Desk cannot complete the bounded Store shutdown lifecycle.
pub(crate) const ERROR_CODE_STORE_SHUTDOWN_FAILED: ksp_core_lib::ErrorCode = ksp_core_lib::ErrorCode::new("backfill_desk", "store_shutdown_failed");
/// Tauri runtime assembly or execution failed.
pub(crate) const ERROR_CODE_TAURI_RUNTIME_FAILED: ksp_core_lib::ErrorCode = ksp_core_lib::ErrorCode::new("backfill_desk", "tauri_runtime_failed");
/// A required Tauri window is missing from the configured application runtime.

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-app-backfill-desk/src/lib.rs
// version: 3
// version: 4
//! Tauri desktop application scaffold for controlling and inspecting KSP RAW backfill jobs.
@@ -15,6 +15,7 @@ mod errors;
mod frontend_logging;
mod logging_runtime;
mod splash;
mod store_runtime;
mod tauri;
mod transport_runtime;
mod tw_main;
@@ -47,6 +48,8 @@ pub(crate) use self::constants::TRACING_DOMAIN_BOOTSTRAP;
pub(crate) use self::constants::TRACING_DOMAIN_FRONTEND;
/// Structured domain used by the Backfill Desk shell.
pub(crate) use self::constants::TRACING_DOMAIN_SHELL;
/// Structured domain used by Store readiness and shutdown operations.
pub(crate) use self::constants::TRACING_DOMAIN_STORE;
/// Structured domain used by Transport readiness and role inventory operations.
pub(crate) use self::constants::TRACING_DOMAIN_TRANSPORT;
/// Structured domain used by Tauri window lifecycle operations.
@@ -81,6 +84,12 @@ pub(crate) use self::errors::ERROR_CODE_LOGGING_BOOTSTRAP_FAILED;
pub(crate) use self::errors::ERROR_CODE_SPLASH_ORIGIN_INVALID;
/// A KSP desk splash environment duration is malformed or exceeds its safety bound.
pub(crate) use self::errors::ERROR_CODE_SPLASH_SETTING_INVALID;
/// Backfill Desk Store and Transport configuration target different logical networks.
pub(crate) use self::errors::ERROR_CODE_STORE_NETWORK_MISMATCH;
/// Backfill Desk cannot prove a single Transport network before Store opening.
pub(crate) use self::errors::ERROR_CODE_STORE_NETWORK_UNAVAILABLE;
/// Backfill Desk cannot complete the bounded Store shutdown lifecycle.
pub(crate) use self::errors::ERROR_CODE_STORE_SHUTDOWN_FAILED;
/// Tauri runtime assembly or execution failed.
pub(crate) use self::errors::ERROR_CODE_TAURI_RUNTIME_FAILED;
/// A required Tauri window is missing from the configured application runtime.
@@ -99,6 +108,10 @@ pub(crate) use self::logging_runtime::launch_identity;
pub(crate) use self::splash::SplashOrderDto;
/// Runtime timings used by the common desk splash lifecycle.
pub(crate) use self::splash::SplashSettings;
/// Store startup state retained by the application shell.
pub(crate) use self::store_runtime::StoreStartup;
/// Initializes Store only after composite-selected Transport/Store network coherence is proven.
pub(crate) use self::store_runtime::initialize_store;
/// Safe and executable Transport runtime retained by application state.
pub(crate) use self::transport_runtime::TransportRuntime;
/// Initializes the composite-selected HTTP Transport runtime.

View File

@@ -0,0 +1,220 @@
// file: crates/ksp-app-backfill-desk/src/store_runtime.rs
// version: 1
//! Composite-selected Store readiness and shutdown lifecycle owned by Backfill Desk.
/// Startup result for the Store layer, including safe diagnostics when the desktop shell remains available without a ready Store.
pub(crate) struct StoreStartup {
diagnostic: std::option::Option<crate::CommandErrorDto>,
network_coherent: bool,
runtime: std::option::Option<StoreRuntime>,
store_network: std::option::Option<String>,
}
impl StoreStartup {
/// Applies Store readiness to the application-owned options DTO without exposing backend connection details.
pub(crate) fn apply_to(&self, options: &mut crate::BackfillDeskOptionsDto) {
options.network_coherent = self.network_coherent;
options.store_diagnostic = self.diagnostic.clone();
options.store_network = self.store_network.clone();
options.store_ready = self.runtime.as_ref().is_some_and(StoreRuntime::health_ready);
options.composition_ready = options.transport_ready && options.network_coherent && options.store_ready;
}
/// Closes the retained Store runtime if startup reached the physical Store-open phase.
pub(crate) async fn close(&self) -> ksp_core_lib::Result<()> {
let runtime = self.runtime.as_ref();
return match runtime {
std::option::Option::Some(value) => value.close().await,
std::option::Option::None => std::result::Result::Ok(()),
};
}
}
/// Executable Store runtime retained after network coherence and bounded Store health checks.
pub(crate) struct StoreRuntime {
health_ready: bool,
profile_id: String,
store: std::sync::Mutex<std::option::Option<ksp_store_lib::Store>>,
store_network: String,
}
impl StoreRuntime {
/// Returns whether the startup health probe proved the Store ready.
#[must_use]
pub(crate) const fn health_ready(&self) -> bool {
return self.health_ready;
}
/// Explicitly closes the Store exactly once through its backend-neutral facade.
pub(crate) async fn close(&self) -> ksp_core_lib::Result<()> {
let store = take_store(&self.store);
let store = match store {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let store = match store {
std::option::Option::Some(value) => value,
std::option::Option::None => return std::result::Result::Ok(()),
};
let closed = store.close().await;
return match closed {
std::result::Result::Ok(()) => {
ksp_logging_lib::debug!(
target: crate::TRACING_TARGET,
domain = crate::TRACING_DOMAIN_STORE,
store_profile = self.profile_id.as_str(),
store_network = self.store_network.as_str(),
"closed Backfill Desk Store runtime"
);
std::result::Result::Ok(())
},
std::result::Result::Err(error) => std::result::Result::Err(
ksp_core_lib::Error::new(crate::ERROR_CODE_STORE_SHUTDOWN_FAILED, "Backfill Desk Store shutdown failed").with_source(error),
),
};
}
}
/// Resolves the composite Store target, proves Transport/Store network coherence before Store I/O, opens Store and captures one health probe.
pub(crate) async fn initialize_store(
management: &ksp_config_lib::ConfigManagement,
transport_runtime: std::option::Option<&crate::TransportRuntime>,
) -> StoreStartup {
let environment = ksp_config_lib::ConfigEnvironment::load();
let environment = match environment {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return unavailable_startup(std::option::Option::None, false, 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 unavailable_startup(std::option::Option::None, false, error),
};
let profile = crate::required_composite_component_profile(&composite, crate::COMPOSITE_COMPONENT_ID_STORE, ksp_config_lib::FILE_ID_STD_STORE);
let profile = match profile {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return unavailable_startup(std::option::Option::None, false, error),
};
let resolved = management.engine().resolve_store_config_profile(&profile, &environment);
let resolved = match resolved {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return unavailable_startup(std::option::Option::None, false, error),
};
let profile_id = resolved.profile_id().to_owned();
let store_network = resolved.settings().network().as_str().to_owned();
let transport_network = transport_runtime.and_then(crate::TransportRuntime::coherent_network);
let transport_network = match transport_network {
std::option::Option::Some(value) => value,
std::option::Option::None => {
let error = ksp_core_lib::Error::new(
crate::ERROR_CODE_STORE_NETWORK_UNAVAILABLE,
"Backfill Desk cannot open Store before one coherent Transport network is available",
);
return unavailable_startup(std::option::Option::Some(store_network), false, error);
},
};
let coherence = validate_network_coherence(store_network.as_str(), transport_network.as_str());
if let std::result::Result::Err(error) = coherence {
return unavailable_startup(std::option::Option::Some(store_network), false, error);
}
let store = ksp_store_lib::Store::open(resolved.into_settings()).await;
let store = match store {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return unavailable_startup(std::option::Option::Some(store_network), true, error),
};
let health = store.health().await;
let health_ready = store_health_ready(health.state());
let diagnostic = if health_ready { std::option::Option::None } else { std::option::Option::Some(non_ready_health_diagnostic(&health)) };
ksp_logging_lib::debug!(
target: crate::TRACING_TARGET,
domain = crate::TRACING_DOMAIN_STORE,
store_profile = profile_id.as_str(),
store_network = store_network.as_str(),
store_ready = health_ready,
pending_migration_count = health.pending_migration_count(),
"initialized Backfill Desk Store readiness from composite-managed configuration"
);
return StoreStartup {
diagnostic,
network_coherent: true,
runtime: std::option::Option::Some(StoreRuntime {
health_ready,
profile_id,
store: std::sync::Mutex::new(std::option::Option::Some(store)),
store_network: store_network.clone(),
}),
store_network: std::option::Option::Some(store_network),
};
}
fn non_ready_health_diagnostic(health: &ksp_store_lib::StoreHealthSnapshot) -> crate::CommandErrorDto {
let code = health.last_error_code();
return match code {
std::option::Option::Some(value) => crate::CommandErrorDto {
code: value.code().to_owned(),
domain: value.domain().to_owned(),
message: "Store health probe did not prove readiness".to_owned(),
},
std::option::Option::None => crate::CommandErrorDto {
code: "store_not_ready".to_owned(),
domain: "backfill_desk".to_owned(),
message: "Store health probe did not prove readiness".to_owned(),
},
};
}
fn store_health_ready(state: ksp_store_lib::StoreHealthState) -> bool {
return match state {
ksp_store_lib::StoreHealthState::Ready => true,
ksp_store_lib::StoreHealthState::NotReady => false,
_ => false,
};
}
fn take_store(store: &std::sync::Mutex<std::option::Option<ksp_store_lib::Store>>) -> ksp_core_lib::Result<std::option::Option<ksp_store_lib::Store>> {
let locked = store.lock();
let mut locked = match locked {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => {
return std::result::Result::Err(ksp_core_lib::Error::new(
crate::ERROR_CODE_APP_STATE_LOCK_FAILED,
"Backfill Desk Store runtime state lock is poisoned",
));
},
};
return std::result::Result::Ok(locked.take());
}
fn unavailable_startup(store_network: std::option::Option<String>, network_coherent: bool, error: ksp_core_lib::Error) -> StoreStartup {
let diagnostic = crate::CommandErrorDto::from_error(&error);
ksp_logging_lib::warn!(
target: crate::TRACING_TARGET,
domain = crate::TRACING_DOMAIN_STORE,
error_domain = diagnostic.domain.as_str(),
error_code = diagnostic.code.as_str(),
network_coherent = network_coherent,
"Backfill Desk Store readiness is unavailable; keeping desktop shell available"
);
return StoreStartup {
diagnostic: std::option::Option::Some(diagnostic),
network_coherent,
runtime: std::option::Option::None,
store_network,
};
}
fn validate_network_coherence(store_network: &str, transport_network: &str) -> ksp_core_lib::Result<()> {
if store_network == transport_network {
return std::result::Result::Ok(());
}
return std::result::Result::Err(
ksp_core_lib::Error::new(crate::ERROR_CODE_STORE_NETWORK_MISMATCH, "Backfill Desk Store and Transport networks do not match")
.with_context("store_network", store_network)
.with_context("transport_network", transport_network),
);
}
#[cfg(test)]
#[path = "../unit_tests/store_runtime.rs"]
mod tests;

View File

@@ -1,8 +1,10 @@
// file: crates/ksp-app-backfill-desk/src/tauri.rs
// version: 3
// version: 4
//! Tauri runtime assembly for the KSP Backfill desktop application.
use tauri::Manager; // rust-rules: trait-import
/// Runs the Backfill desktop application.
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run(arguments: &[std::ffi::OsString]) -> ksp_core_lib::Result<()> {
@@ -21,6 +23,7 @@ pub fn run(arguments: &[std::ffi::OsString]) -> ksp_core_lib::Result<()> {
builder = configure_plugins(builder);
builder = configure_commands(builder);
builder = configure_setup(builder);
builder = configure_window_events(builder);
let run_result = builder.run(context);
return match run_result {
std::result::Result::Ok(()) => std::result::Result::Ok(()),
@@ -90,6 +93,50 @@ fn configure_setup(builder: tauri::Builder<tauri::Wry>) -> tauri::Builder<tauri:
});
}
fn configure_window_events(builder: tauri::Builder<tauri::Wry>) -> tauri::Builder<tauri::Wry> {
return builder.on_window_event(|window, event| {
if window.label() != "main" {
return;
}
if let tauri::WindowEvent::CloseRequested { api, .. } = event {
api.prevent_close();
let app_handle = window.app_handle().clone();
let state = app_handle.state::<crate::AppState>();
if !state.begin_shutdown() {
return;
}
ksp_logging_lib::debug!(
target: crate::TRACING_TARGET,
domain = crate::TRACING_DOMAIN_WINDOWS,
"Backfill Desk main-window close requested; starting bounded Store shutdown"
);
tauri::async_runtime::spawn(async move {
let state = app_handle.state::<crate::AppState>();
let closed = state.close_store().await;
match closed {
std::result::Result::Ok(()) => {
ksp_logging_lib::debug!(
target: crate::TRACING_TARGET,
domain = crate::TRACING_DOMAIN_WINDOWS,
"Backfill Desk Store shutdown completed; exiting application"
);
},
std::result::Result::Err(error) => {
ksp_logging_lib::warn!(
target: crate::TRACING_TARGET,
domain = crate::TRACING_DOMAIN_WINDOWS,
error_domain = error.code().domain(),
error_code = error.code().code(),
"Backfill Desk Store shutdown failed; exiting application after bounded close attempt"
);
},
}
app_handle.exit(0);
});
}
});
}
fn project_command_error(command: &'static str, domain: &'static str, error: &ksp_core_lib::Error) -> crate::CommandErrorDto {
ksp_logging_lib::warn!(
target: crate::TRACING_TARGET,

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-app-backfill-desk/src/transport_runtime.rs
// version: 1
// version: 2
//! Composite-selected HTTP Transport readiness owned by Backfill Desk.
@@ -16,6 +16,16 @@ impl TransportRuntime {
return self.profile_id.as_str();
}
/// Returns the one configured Transport network only when the active HTTP pool is logically coherent.
#[must_use]
pub(crate) fn coherent_network(&self) -> std::option::Option<String> {
let networks = configured_networks(&self.pool.snapshot());
if networks.len() != 1 {
return std::option::Option::None;
}
return networks.into_iter().next();
}
/// 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();
@@ -28,7 +38,12 @@ impl TransportRuntime {
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,
composition_ready: false,
configured_networks,
network_coherent: false,
store_diagnostic: std::option::Option::None,
store_network: std::option::Option::None,
store_ready: false,
transport_diagnostic: std::option::Option::None,
transport_ready,
});