From d66684bafbb922a88c4a71d7970bd81930b39165 Mon Sep 17 00:00:00 2001 From: James Gilles Date: Mon, 16 Dec 2024 15:58:18 -0500 Subject: [PATCH] Add plumbing to print auto migration plans --- Cargo.lock | 2 ++ crates/cli/src/subcommands/publish.rs | 4 ++++ crates/client-api-messages/src/name.rs | 5 +++++ crates/client-api/src/routes/database.rs | 10 +++++++--- crates/core/src/host/host_controller.rs | 2 +- crates/core/src/host/module_host.rs | 6 ++++-- crates/core/src/host/wasm_common/module_host_actor.rs | 7 ++++++- crates/schema/src/auto_migrate/pretty_print.rs | 7 +++++-- 8 files changed, 34 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 78d877eb29e..d033ee3729b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5151,6 +5151,7 @@ name = "spacetimedb-schema" version = "1.0.0-rc2" dependencies = [ "anyhow", + "colored", "enum-as-inner", "hashbrown 0.15.1", "indexmap 2.6.0", @@ -5159,6 +5160,7 @@ dependencies = [ "petgraph", "pretty_assertions", "proptest", + "regex", "serde_json", "smallvec", "spacetimedb-cli", diff --git a/crates/cli/src/subcommands/publish.rs b/crates/cli/src/subcommands/publish.rs index 397c8ab762f..8f326b78ba7 100644 --- a/crates/cli/src/subcommands/publish.rs +++ b/crates/cli/src/subcommands/publish.rs @@ -170,6 +170,7 @@ pub async fn exec(config: Config, args: &ArgMatches) -> Result<(), anyhow::Error domain, database_identity, op, + update_summary, } => { let op = match op { PublishOp::Created => "Created new", @@ -180,6 +181,9 @@ pub async fn exec(config: Config, args: &ArgMatches) -> Result<(), anyhow::Error } else { println!("{} database with identity: {}", op, database_identity); } + if let Some(update_summary) = update_summary { + println!("{}", update_summary); + } } PublishResult::TldNotRegistered { domain } => { return Err(anyhow::anyhow!( diff --git a/crates/client-api-messages/src/name.rs b/crates/client-api-messages/src/name.rs index 0678992303b..302366e0524 100644 --- a/crates/client-api-messages/src/name.rs +++ b/crates/client-api-messages/src/name.rs @@ -57,6 +57,11 @@ pub enum PublishResult { /// or not. database_identity: Identity, op: PublishOp, + + /// If the database was updated, may contain a string describing the update. + /// Contains ANSI escape codes for color. + /// Suitable for printing to the console. + update_summary: Option, }, // TODO: below variants are obsolete with control db module diff --git a/crates/client-api/src/routes/database.rs b/crates/client-api/src/routes/database.rs index 55412d7dada..46f364c5a32 100644 --- a/crates/client-api/src/routes/database.rs +++ b/crates/client-api/src/routes/database.rs @@ -658,7 +658,7 @@ pub async fn publish( .await .map_err(log_and_500)?; - if let Some(updated) = maybe_updated { + let update_summary = if let Some(updated) = maybe_updated { match updated { UpdateDatabaseResult::AutoMigrateError(errs) => { return Err((StatusCode::BAD_REQUEST, format!("Database update rejected: {errs}")).into()); @@ -670,14 +670,18 @@ pub async fn publish( ) .into()); } - UpdateDatabaseResult::NoUpdateNeeded | UpdateDatabaseResult::UpdatePerformed => {} + UpdateDatabaseResult::NoUpdateNeeded => None, + UpdateDatabaseResult::UpdatePerformed(summary) => Some(summary), } - } + } else { + None + }; Ok(axum::Json(PublishResult::Success { domain: db_name.as_ref().map(ToString::to_string), database_identity, op, + update_summary, })) } diff --git a/crates/core/src/host/host_controller.rs b/crates/core/src/host/host_controller.rs index 7e6308779b4..270250bbb3b 100644 --- a/crates/core/src/host/host_controller.rs +++ b/crates/core/src/host/host_controller.rs @@ -426,7 +426,7 @@ impl HostController { ) .await?; match update_result { - UpdateDatabaseResult::NoUpdateNeeded | UpdateDatabaseResult::UpdatePerformed => { + UpdateDatabaseResult::NoUpdateNeeded | UpdateDatabaseResult::UpdatePerformed(_) => { *guard = Some(host); } UpdateDatabaseResult::AutoMigrateError(e) => { diff --git a/crates/core/src/host/module_host.rs b/crates/core/src/host/module_host.rs index 1a7258d159f..feb2d1b9b19 100644 --- a/crates/core/src/host/module_host.rs +++ b/crates/core/src/host/module_host.rs @@ -448,7 +448,9 @@ pub struct WeakModuleHost { #[derive(Debug)] pub enum UpdateDatabaseResult { NoUpdateNeeded, - UpdatePerformed, + /// The string is a printable summary of the update that happened. + /// Contains ANSI escape sequences for color. + UpdatePerformed(String), AutoMigrateError(ErrorStream), ErrorExecutingMigration(anyhow::Error), } @@ -457,7 +459,7 @@ impl UpdateDatabaseResult { pub fn was_successful(&self) -> bool { matches!( self, - UpdateDatabaseResult::UpdatePerformed | UpdateDatabaseResult::NoUpdateNeeded + UpdateDatabaseResult::UpdatePerformed(_) | UpdateDatabaseResult::NoUpdateNeeded ) } } diff --git a/crates/core/src/host/wasm_common/module_host_actor.rs b/crates/core/src/host/wasm_common/module_host_actor.rs index 5ee0d84cb5d..7582f316b86 100644 --- a/crates/core/src/host/wasm_common/module_host_actor.rs +++ b/crates/core/src/host/wasm_common/module_host_actor.rs @@ -3,6 +3,7 @@ use bytes::Bytes; use spacetimedb_client_api_messages::timestamp::Timestamp; use spacetimedb_primitives::TableId; use spacetimedb_schema::auto_migrate::ponder_migrate; +use spacetimedb_schema::auto_migrate::pretty_print::pretty_print; use spacetimedb_schema::def::ModuleDef; use spacetimedb_schema::schema::{Schema, TableSchema}; use std::sync::Arc; @@ -340,6 +341,10 @@ impl ModuleInstance for WasmModuleInstance { return Ok(UpdateDatabaseResult::AutoMigrateError(errs)); } }; + let summary = pretty_print(&plan).unwrap_or_else(|_| { + log::warn!("Failed to pretty-print migration plan: {plan:#?}"); + "(plan not rendered, but succeeded)".to_string() + }); let stdb = &*self.replica_context().relational_db; let program_hash = program.hash; @@ -361,7 +366,7 @@ impl ModuleInstance for WasmModuleInstance { stdb.commit_tx(tx)?; self.system_logger().info("Database updated"); log::info!("Database updated, {}", stdb.database_identity()); - Ok(UpdateDatabaseResult::UpdatePerformed) + Ok(UpdateDatabaseResult::UpdatePerformed(summary)) } } } diff --git a/crates/schema/src/auto_migrate/pretty_print.rs b/crates/schema/src/auto_migrate/pretty_print.rs index b77c1aaf08f..58de24e64af 100644 --- a/crates/schema/src/auto_migrate/pretty_print.rs +++ b/crates/schema/src/auto_migrate/pretty_print.rs @@ -1,6 +1,6 @@ //! This module provides a function [`pretty_print`](pretty_print) that renders an automatic migration plan to a string. -use super::{AutoMigratePlan, IndexAlgorithm, TableDef}; +use super::{IndexAlgorithm, MigratePlan, TableDef}; use crate::{auto_migrate::AutoMigrateStep, def::ConstraintData}; use colored::{self, ColoredString, Colorize}; use lazy_static::lazy_static; @@ -33,7 +33,10 @@ pub fn strip_ansi_escape_codes(s: &str) -> String { /// Pretty print a migration plan, resulting in a string (containing ANSI escape codes). /// If you are printing -pub fn pretty_print(plan: &AutoMigratePlan) -> Result { +pub fn pretty_print(plan: &MigratePlan) -> Result { + let plan = match plan { + MigratePlan::Auto(plan) => plan, + }; let mut out = String::new(); let outr = &mut out;