feat(bootstrap): add env check and improve config update logic

Introduce environment existence check to prevent redundant bootstrap runs and ensure smoother startup. Refactor `update_bot_config` to use globally unique config keys and atomic updates for better data consistency.
This commit is contained in:
Rodrigo Rodriguez (Pragmatismo) 2025-10-28 21:06:31 -03:00
parent 44c745ef57
commit 78d154cc7f
2 changed files with 42 additions and 24 deletions

View file

@ -307,22 +307,27 @@ impl BootstrapManager {
} }
fn update_bot_config(&self, bot_id: &uuid::Uuid, component: &str) -> Result<()> { fn update_bot_config(&self, bot_id: &uuid::Uuid, component: &str) -> Result<()> {
use diesel::sql_types::{Uuid as SqlUuid, Text};
let database_url = std::env::var("DATABASE_URL") let database_url = std::env::var("DATABASE_URL")
.unwrap_or_else(|_| "postgres://gbuser:@localhost:5432/botserver".to_string()); .unwrap_or_else(|_| "postgres://gbuser:@localhost:5432/botserver".to_string());
let mut conn = diesel::pg::PgConnection::establish(&database_url)?; let mut conn = diesel::pg::PgConnection::establish(&database_url)?;
let new_id: uuid::Uuid = uuid::Uuid::new_v4(); // Ensure globally unique keys and update values atomically
let config_key = format!("{}_{}", bot_id, component);
let config_value = "true".to_string();
let new_id = uuid::Uuid::new_v4();
for (k, v) in vec![(component.to_string(), "true".to_string())] { diesel::sql_query(
diesel::sql_query( "INSERT INTO bot_configuration (id, bot_id, config_key, config_value, config_type)
"INSERT INTO bot_configuration (id, bot_id, config_key, config_value, config_type) VALUES ($1, $2, $3, $4, 'string') ON CONFLICT (bot_id, config_key) DO UPDATE SET config_value = EXCLUDED.config_value, updated_at = NOW()", VALUES ($1, $2, $3, $4, 'string')
) ON CONFLICT (config_key)
.bind::<diesel::sql_types::Uuid, _>(new_id) DO UPDATE SET config_value = EXCLUDED.config_value, updated_at = NOW()"
.bind::<diesel::sql_types::Uuid, _>(bot_id) )
.bind::<diesel::sql_types::Text, _>(&k) .bind::<SqlUuid, _>(new_id)
.bind::<diesel::sql_types::Text, _>(&v) .bind::<SqlUuid, _>(bot_id)
.execute(&mut conn)?; .bind::<Text, _>(&config_key)
} .bind::<Text, _>(&config_value)
.execute(&mut conn)?;
Ok(()) Ok(())
} }

View file

@ -107,25 +107,38 @@ async fn main() -> std::io::Result<()> {
}; };
let mut bootstrap = BootstrapManager::new(install_mode.clone(), tenant.clone()); let mut bootstrap = BootstrapManager::new(install_mode.clone(), tenant.clone());
let cfg = match bootstrap.bootstrap() {
Ok(config) => { // Prevent double bootstrap: skip if environment already initialized
info!("Bootstrap completed successfully"); let env_path = std::env::current_dir()?.join("botserver-stack").join(".env");
config let cfg = if env_path.exists() {
info!("Environment already initialized, skipping bootstrap");
match diesel::Connection::establish(
&std::env::var("DATABASE_URL")
.unwrap_or_else(|_| "postgres://gbuser:@localhost:5432/botserver".to_string()),
) {
Ok(mut conn) => AppConfig::from_database(&mut conn),
Err(_) => AppConfig::from_env(),
} }
Err(e) => { } else {
log::error!("Bootstrap failed: {}", e); match bootstrap.bootstrap() {
match diesel::Connection::establish( Ok(config) => {
&std::env::var("DATABASE_URL") info!("Bootstrap completed successfully");
.unwrap_or_else(|_| "postgres://gbuser:@localhost:5432/botserver".to_string()), config
) { }
Ok(mut conn) => AppConfig::from_database(&mut conn), Err(e) => {
Err(_) => { log::error!("Bootstrap failed: {}", e);
AppConfig::from_env() match diesel::Connection::establish(
&std::env::var("DATABASE_URL")
.unwrap_or_else(|_| "postgres://gbuser:@localhost:5432/botserver".to_string()),
) {
Ok(mut conn) => AppConfig::from_database(&mut conn),
Err(_) => AppConfig::from_env(),
} }
} }
} }
}; };
let _ = bootstrap.start_all(); let _ = bootstrap.start_all();
if let Err(e) = bootstrap.upload_templates_to_minio(&cfg).await { if let Err(e) = bootstrap.upload_templates_to_minio(&cfg).await {
log::warn!("Failed to upload templates to MinIO: {}", e); log::warn!("Failed to upload templates to MinIO: {}", e);