v0.5.3-pre.002
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
// file: ks-pipeline-demo-scenarios/src/environment.rs
|
||||
// version: 7
|
||||
// version: 9
|
||||
|
||||
//! Environment initialization for opt-in demonstration scenarios.
|
||||
|
||||
@@ -83,28 +83,53 @@ pub fn resolve_demo_devnet_profile(
|
||||
};
|
||||
}
|
||||
|
||||
/// Readiness report for one Devnet profile PostgreSQL store.
|
||||
/// Backend-agnostic readiness report for one Devnet profile store.
|
||||
#[derive(Clone, Debug, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct DevnetProfileStoreReadiness {
|
||||
/// Selected Devnet profile.
|
||||
pub profile_name: std::string::String,
|
||||
/// Selected backend code.
|
||||
pub backend: std::string::String,
|
||||
/// Whether schema creation was allowed by configuration.
|
||||
pub auto_initialize_schema: bool,
|
||||
/// Number of known tables already present before preparation.
|
||||
pub existing_tables_before: usize,
|
||||
/// Number of known tables created during preparation.
|
||||
pub created_tables: usize,
|
||||
/// Number of known tables present after preparation.
|
||||
pub existing_tables_after: usize,
|
||||
/// Total number of known tables expected by the current store.
|
||||
pub expected_tables: usize,
|
||||
/// Number of known logical resources already present before preparation.
|
||||
pub available_resources_before: usize,
|
||||
/// Number of known logical resources created during preparation.
|
||||
pub created_resources: usize,
|
||||
/// Number of known logical resources present after preparation.
|
||||
pub available_resources_after: usize,
|
||||
/// Total number of logical resources expected by the current store contract.
|
||||
pub expected_resources: usize,
|
||||
}
|
||||
|
||||
/// Verifies or initializes the PostgreSQL schema selected by one Devnet profile.
|
||||
/// Builds backend-agnostic store-open options from one resolved profile.
|
||||
fn store_open_options_from_profile(
|
||||
profile: &ks_config::ProfileConfig,
|
||||
) -> ks_core::Result<ks_store::StoreOpenOptions> {
|
||||
return ks_store::StoreOpenOptions::new(
|
||||
profile.database.enabled,
|
||||
profile.database.backend.clone(),
|
||||
profile.database.backend_options.clone(),
|
||||
);
|
||||
}
|
||||
|
||||
/// Opens the backend-agnostic store selected by one resolved profile.
|
||||
#[cfg(test)]
|
||||
pub(crate) async fn open_profile_store(
|
||||
profile: &ks_config::ProfileConfig,
|
||||
) -> ks_core::Result<ks_store::Store> {
|
||||
let options = match store_open_options_from_profile(profile) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
return ks_store::Store::open(options).await;
|
||||
}
|
||||
|
||||
/// Verifies or initializes the store selected by one Devnet profile.
|
||||
pub async fn prepare_demo_devnet_profile_store(
|
||||
profile: &ks_config::ProfileConfig,
|
||||
) -> ks_core::Result<DevnetProfileStoreReadiness> {
|
||||
) -> ks_core::Result<crate::DevnetProfileStoreReadiness> {
|
||||
if profile.wallet.cluster != "devnet" {
|
||||
return std::result::Result::Err(ks_core::Error::config(format!(
|
||||
"profile '{}' is not configured for Devnet",
|
||||
@@ -117,65 +142,78 @@ pub async fn prepare_demo_devnet_profile_store(
|
||||
profile.name
|
||||
)));
|
||||
}
|
||||
if profile.database.backend != "postgres" {
|
||||
let options = match store_open_options_from_profile(profile) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let configuration = match options.configuration_summary() {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let store = match ks_store::Store::open(options).await {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let initialization = store.initialization_summary();
|
||||
if initialization.status != ks_store::StoreInitializationStatus::Ready {
|
||||
return std::result::Result::Err(ks_core::Error::config(format!(
|
||||
"Devnet profile '{}' must use the PostgreSQL backend",
|
||||
profile.name
|
||||
"Devnet profile '{}' store model is incomplete and automatic initialization is {}",
|
||||
profile.name,
|
||||
if configuration.auto_initialize_schema { "enabled" } else { "disabled" }
|
||||
)));
|
||||
}
|
||||
let options = match ks_store::PostgresStoreOptions::new(
|
||||
profile.database.postgres.url.clone(),
|
||||
profile.database.postgres.max_connections,
|
||||
profile.database.postgres.connect_timeout_ms,
|
||||
false,
|
||||
return std::result::Result::Ok(crate::DevnetProfileStoreReadiness {
|
||||
profile_name: profile.name.clone(),
|
||||
backend: configuration.backend_code,
|
||||
auto_initialize_schema: configuration.auto_initialize_schema,
|
||||
available_resources_before: initialization
|
||||
.available_resource_count
|
||||
.saturating_sub(initialization.created_resource_count)
|
||||
as usize,
|
||||
created_resources: initialization.created_resource_count as usize,
|
||||
available_resources_after: initialization.available_resource_count as usize,
|
||||
expected_resources: initialization.expected_resource_count as usize,
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn override_profile_store_url_for_test(
|
||||
profile: &mut ks_config::ProfileConfig,
|
||||
database_url: std::string::String,
|
||||
) -> ks_core::Result<()> {
|
||||
profile.database.enabled = true;
|
||||
profile.database.backend = "postgres".to_string();
|
||||
let backend_options = match profile.database.backend_options.as_object_mut() {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => {
|
||||
return std::result::Result::Err(ks_core::Error::config(
|
||||
"test store backend options must be an object",
|
||||
));
|
||||
},
|
||||
};
|
||||
backend_options.insert("url".to_string(), serde_json::Value::String(database_url));
|
||||
backend_options.insert("auto_initialize_schema".to_string(), serde_json::Value::Bool(true));
|
||||
return std::result::Result::Ok(());
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) async fn open_test_store(
|
||||
database_url: std::string::String,
|
||||
) -> ks_core::Result<ks_store::Store> {
|
||||
let options = match ks_store::StoreOpenOptions::new(
|
||||
true,
|
||||
"postgres",
|
||||
serde_json::json!({
|
||||
"url": database_url,
|
||||
"max_connections": 5,
|
||||
"connect_timeout_ms": 5_000,
|
||||
"auto_initialize_schema": true
|
||||
}),
|
||||
) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let store = match ks_store::PostgresStore::connect(options).await {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let before = match store.known_table_diagnostics().await {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let existing_tables_before = before.iter().filter(|table| return table.exists).count();
|
||||
if profile.database.postgres.auto_initialize_schema
|
||||
&& let std::result::Result::Err(error) = store.initialize_store_schema().await
|
||||
{
|
||||
return std::result::Result::Err(error);
|
||||
}
|
||||
let after = match store.known_table_diagnostics().await {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let existing_tables_after = after.iter().filter(|table| return table.exists).count();
|
||||
if existing_tables_after != after.len() {
|
||||
let missing = after
|
||||
.iter()
|
||||
.filter(|table| return !table.exists)
|
||||
.map(|table| return table.table_name.clone())
|
||||
.collect::<std::vec::Vec<_>>();
|
||||
return std::result::Result::Err(ks_core::Error::config(format!(
|
||||
"Devnet profile '{}' PostgreSQL schema is incomplete and auto initialization is {}: missing {}",
|
||||
profile.name,
|
||||
if profile.database.postgres.auto_initialize_schema {
|
||||
"enabled"
|
||||
} else {
|
||||
"disabled"
|
||||
},
|
||||
missing.join(", ")
|
||||
)));
|
||||
}
|
||||
return std::result::Result::Ok(DevnetProfileStoreReadiness {
|
||||
profile_name: profile.name.clone(),
|
||||
auto_initialize_schema: profile.database.postgres.auto_initialize_schema,
|
||||
existing_tables_before,
|
||||
created_tables: existing_tables_after.saturating_sub(existing_tables_before),
|
||||
existing_tables_after,
|
||||
expected_tables: after.len(),
|
||||
});
|
||||
return ks_store::Store::open(options).await;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
Reference in New Issue
Block a user