Files
khadhroony-solana-project/crates/ksp-app-backfill-desk/src/app_state.rs
2026-09-02 16:07:57 +02:00

228 lines
11 KiB
Rust

// file: crates/ksp-app-backfill-desk/src/app_state.rs
// version: 5
//! Shared backend state owned by the Backfill Desk Tauri application.
/// Shared Backfill Desk application state managed by Tauri.
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>,
}
impl crate::AppState {
/// Initializes the scaffold Config ownership, Logging runtime and splash settings.
pub(crate) fn initialize(arguments: &[std::ffi::OsString]) -> ksp_core_lib::Result<Self> {
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 transport_startup = crate::initialize_transport(&config_management);
let (transport_runtime, transport_startup_diagnostic) = match transport_startup {
std::result::Result::Ok(value) => (std::option::Option::Some(value), std::option::Option::None),
std::result::Result::Err(error) => {
let diagnostic = crate::CommandErrorDto::from_error(&error);
ksp_logging_lib::warn!(
target: crate::TRACING_TARGET,
domain = crate::TRACING_DOMAIN_TRANSPORT,
error_domain = diagnostic.domain.as_str(),
error_code = diagnostic.code.as_str(),
"Backfill Desk Transport readiness is unavailable; keeping desktop shell available"
);
(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,
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 Backfill Desk splash timings"
);
return std::result::Result::Ok(Self {
config_management,
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,
}),
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,
});
}
/// Builds the safe scaffold status exposed by the Backfill Desk shell.
pub(crate) fn shell_status(&self) -> ksp_core_lib::Result<crate::ShellStatusDto> {
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 count cannot be represented by Backfill Desk")
.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,
"Backfill Desk Logging runtime state lock is poisoned",
));
},
};
let _keep_guard_alive = &runtime.guard;
return std::result::Result::Ok(crate::ShellStatusDto {
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.007-request-mapping".to_owned(),
startup_diagnostic: runtime.startup_diagnostic.clone(),
});
}
/// 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();
let options = match runtime {
std::option::Option::Some(value) => value.options(),
std::option::Option::None => {
let limits = crate::backfill_request_limits();
let limits = match limits {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
std::result::Result::Ok(crate::BackfillDeskOptionsDto {
commitments: crate::backfill_commitment_codes(),
composition_ready: false,
configured_networks: std::vec::Vec::new(),
http_routes: std::vec::Vec::new(),
limits,
network_coherent: false,
scope_kinds: crate::backfill_scope_kind_codes(),
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);
}
/// Validates and maps one frontend campaign request without starting a Backfill Job.
pub(crate) fn validate_backfill_request(&self, request: crate::BackfillStartRequestDto) -> ksp_core_lib::Result<crate::BackfillRequestPreviewDto> {
let options = self.backfill_options();
let options = match options {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let job_id = ksp_job_api::JobId::new("backfill-desk-validation");
let job_id = match job_id {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let mapped = crate::map_backfill_request(request, &options, job_id);
let mapped = match mapped {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let preview = crate::project_backfill_request(&mapped);
let preview = match preview {
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_REQUEST,
commitment = preview.commitment.as_str(),
http_role = preview.http_role.as_str(),
scope_kind = preview.scope_kind.as_str(),
"validated Backfill Desk campaign request without starting a Job"
);
return std::result::Result::Ok(preview);
}
/// 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.
#[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<String>,
fallback_active: bool,
startup_diagnostic: std::option::Option<crate::CommandErrorDto>,
}