// file: crates/ksp-app-raw-transaction-ingest-desk/src/app_state.rs // version: 9 //! Shared backend state owned by the Raw Transaction Ingest Desk Tauri application. /// Shared Raw Transaction Ingest Desk application state managed by Tauri. pub(crate) struct AppState { active_composite_profile: std::option::Option, config_management: ksp_config_lib::ConfigManagement, inventory_generation: std::sync::Mutex, logging_runtime: std::sync::Mutex, route_runtime: std::sync::Arc, splash_settings: crate::SplashSettings, splash_sequence_started: std::sync::atomic::AtomicBool, } impl crate::AppState { /// Initializes Config ownership and composite-managed Logging without constructing Transport, Store or Worker resources. pub(crate) fn initialize(arguments: &[std::ffi::OsString]) -> ksp_core_lib::Result { let config_management = crate::config_management(arguments); let config_management = match config_management { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; let runtime_identity = crate::launch_identity(); let runtime_identity = match runtime_identity { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; let logging_startup = crate::initialize_logging(&config_management, &runtime_identity); let logging_startup = match logging_startup { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; let composite = crate::load_raw_transaction_ingest_desk_composite(&config_management); let active_composite_profile = match composite { std::result::Result::Ok(value) => std::option::Option::Some(value.profile_id().to_owned()), std::result::Result::Err(_) => std::option::Option::None, }; let splash_settings = crate::SplashSettings::load(); let splash_settings = match splash_settings { std::result::Result::Ok(value) => value, 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(), "managed splash timings are invalid; using transient in-memory defaults"); crate::SplashSettings::fallback() }, }; ksp_logging_lib::debug!(target: crate::TRACING_TARGET, domain = crate::TRACING_DOMAIN_WINDOWS, minimum_ms = splash_settings.minimum_ms(), minimum_source = splash_settings.minimum_source(), fade_in_ms = splash_settings.fade_in_ms(), fade_in_source = splash_settings.fade_in_source(), fade_out_ms = splash_settings.fade_out_ms(), fade_out_source = splash_settings.fade_out_source(), expected_backend_lifecycle_ms = splash_settings.expected_backend_lifecycle_ms(), "resolved Raw Transaction Ingest Desk splash timings"); return std::result::Result::Ok(Self { active_composite_profile, config_management, inventory_generation: std::sync::Mutex::new(0), logging_runtime: std::sync::Mutex::new(LoggingRuntimeState { guard: logging_startup.guard, active_profile_id: logging_startup.active_profile_id, fallback_active: logging_startup.fallback_active, startup_diagnostic: logging_startup.startup_diagnostic, }), route_runtime: std::sync::Arc::new(crate::RouteRuntimeState::new()), splash_settings, splash_sequence_started: std::sync::atomic::AtomicBool::new(false), }); } /// Returns the static V1 route/state vocabulary without making any Config composability claim. #[must_use] pub(crate) fn route_foundation(&self) -> crate::RawIngestRouteFoundationDto { let _keep_config_owner_alive = &self.config_management; return crate::RawIngestRouteFoundationDto::scaffold(); } /// Rebuilds the complete Config-only route inventory and publishes a fresh monotonic generation. pub(crate) fn route_inventory(&self) -> ksp_core_lib::Result { let generation = self.inventory_generation.lock(); let mut generation = match generation { 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, "Raw Transaction Ingest Desk route inventory generation lock is poisoned", )); }, }; let next_generation = generation.checked_add(1); let next_generation = match next_generation { std::option::Option::Some(value) => value, std::option::Option::None => { return std::result::Result::Err(ksp_core_lib::Error::new( crate::ERROR_CODE_ROUTE_INVENTORY_INVALID, "Raw Transaction Ingest Desk route inventory generation is exhausted", )); }, }; let inventory = crate::build_route_inventory(&self.config_management, next_generation); let inventory = match inventory { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; *generation = next_generation; return std::result::Result::Ok(inventory); } /// Revalidates one future Start request and reconstructs its exact Transport/Worker source contract without launching a Worker. pub(crate) fn validate_route_start(&self, request: &crate::RawIngestRouteStartRequestDto) -> ksp_core_lib::Result { let generation = self.inventory_generation.lock(); let generation = match generation { 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, "Raw Transaction Ingest Desk route inventory generation lock is poisoned", )); }, }; return crate::validate_route_start(&self.config_management, generation, request); } /// Starts one independent route Worker after repeating complete Start-time revalidation, sharing Store only on an exact network match. pub(crate) async fn start_route(&self, request: &crate::RawIngestRouteStartRequestDto) -> ksp_core_lib::Result { let admission = self.route_runtime.ensure_start_admission_open(); if let std::result::Result::Err(error) = admission { return std::result::Result::Err(error); } let prepared = { let generation = self.inventory_generation.lock(); let generation = match generation { 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, "Raw Transaction Ingest Desk route inventory generation lock is poisoned", )); }, }; let prepared = crate::prepare_route_start(&self.config_management, *generation, request); match prepared { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), } }; return crate::start_route_runtime(std::sync::Arc::clone(&self.route_runtime), prepared).await; } /// Returns complete latest-value monitoring projections for active and recent terminal routes in the current same-network runtime session. pub(crate) fn route_monitoring(&self) -> ksp_core_lib::Result> { return self.route_runtime.monitoring_statuses(); } /// Requests cooperative Stop for one exact logical route and waits until its Worker cleanup is complete. pub(crate) async fn stop_route(&self, request: &crate::RawIngestRouteStopRequestDto) -> ksp_core_lib::Result { return self.route_runtime.stop_and_wait(request).await; } /// Closes route Start admission once and requests cooperative Stop for all routes during application shutdown. pub(crate) fn begin_shutdown(&self) -> ksp_core_lib::Result { return self.route_runtime.begin_shutdown(); } /// Waits for bounded cleanup of all route Workers and the shared Store during application shutdown. pub(crate) async fn shutdown_routes(&self) -> ksp_core_lib::Result<()> { return self.route_runtime.shutdown_and_wait().await; } /// Builds the safe scaffold status exposed by the shell. pub(crate) fn shell_status(&self) -> ksp_core_lib::Result { let document_count = self.config_management.engine().registry().descriptors().count(); let document_count = u32::try_from(document_count); let document_count = match document_count { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { return std::result::Result::Err( ksp_core_lib::Error::new( crate::ERROR_CODE_APP_STATE_INVALID, "Config registry contains too many descriptors for the Raw Transaction Ingest Desk runtime DTO", ) .with_source(error), ); }, }; let runtime = self.logging_runtime.lock(); let runtime = match runtime { 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, "Raw Transaction Ingest Desk Logging runtime state lock is poisoned", )); }, }; let _keep_guard_alive = &runtime.guard; return std::result::Result::Ok(crate::ShellStatusDto { active_composite_profile: self.active_composite_profile.clone(), active_logging_profile: runtime.active_profile_id.clone(), application_version: env!("CARGO_PKG_VERSION").to_owned(), config_document_count: document_count, fallback_logging_active: runtime.fallback_active, shell_phase: "pre.010-runtime-monitoring".to_owned(), startup_diagnostic: runtime.startup_diagnostic.clone(), }); } /// Returns the resolved splash timings captured during application bootstrap. #[must_use] pub(crate) const fn splash_settings(&self) -> crate::SplashSettings { return self.splash_settings; } /// Marks the one-shot splash lifecycle as started and reports whether this caller won the transition. pub(crate) fn begin_splash_sequence(&self) -> bool { return self .splash_sequence_started .compare_exchange(false, true, std::sync::atomic::Ordering::AcqRel, std::sync::atomic::Ordering::Acquire) .is_ok(); } } struct LoggingRuntimeState { guard: ksp_logging_lib::LoggingGuard, active_profile_id: std::option::Option, fallback_active: bool, startup_diagnostic: std::option::Option, }