Add cluster JSON state ledger status

This commit is contained in:
aaltshuler 2026-06-08 21:09:23 +03:00
parent 043b02e617
commit a7956ea5a9
8 changed files with 925 additions and 76 deletions

View file

@ -11,7 +11,8 @@ use omnigraph::db::{Omnigraph, ReadTarget, SnapshotId};
use omnigraph::loader::LoadMode;
use omnigraph::storage::normalize_root_uri;
use omnigraph_cluster::{
DiagnosticSeverity, PlanOutput, ValidateOutput, plan_config_dir, validate_config_dir,
DiagnosticSeverity, PlanOutput, StatusOutput, ValidateOutput, plan_config_dir,
status_config_dir, validate_config_dir,
};
use omnigraph_compiler::query::parser::parse_query;
use omnigraph_compiler::schema::parser::parse_schema;
@ -340,6 +341,15 @@ enum ClusterCommand {
#[arg(long)]
json: bool,
},
/// Read the local JSON state ledger without scanning live graph resources.
Status {
/// Cluster config directory containing cluster.yaml.
#[arg(long, default_value = ".")]
config: PathBuf,
/// Emit JSON instead of human text.
#[arg(long)]
json: bool,
},
}
/// Operations on the graph registry of a multi-graph server (MR-668).
@ -745,6 +755,34 @@ fn print_cluster_plan_human(output: &PlanOutput) {
print_cluster_diagnostics(&output.diagnostics);
}
fn print_cluster_status_human(output: &StatusOutput) {
if output.ok {
let state = &output.state_observations;
if state.state_found {
println!(
"cluster state: revision {}, {} resource(s)",
state.state_revision, state.resource_count
);
if let Some(digest) = state.applied_config_digest.as_deref() {
println!(" applied config: {digest}");
}
if state.locked {
match state.lock_id.as_deref() {
Some(lock_id) => println!(" lock: held ({lock_id})"),
None => println!(" lock: held"),
}
} else {
println!(" lock: not held");
}
} else {
println!("cluster state missing");
}
} else {
println!("cluster status failed");
}
print_cluster_diagnostics(&output.diagnostics);
}
fn print_cluster_diagnostics(diagnostics: &[omnigraph_cluster::Diagnostic]) {
for diagnostic in diagnostics {
let label = match diagnostic.severity {
@ -784,6 +822,19 @@ fn finish_cluster_plan(output: &PlanOutput, json: bool) -> Result<()> {
Ok(())
}
fn finish_cluster_status(output: &StatusOutput, json: bool) -> Result<()> {
if json {
print_json(output)?;
} else {
print_cluster_status_human(output);
}
if !output.ok {
io::stdout().flush()?;
std::process::exit(1);
}
Ok(())
}
fn is_remote_uri(uri: &str) -> bool {
uri.starts_with("http://") || uri.starts_with("https://")
}
@ -3217,6 +3268,10 @@ async fn main() -> Result<()> {
let output = plan_config_dir(config);
finish_cluster_plan(&output, json)?;
}
ClusterCommand::Status { config, json } => {
let output = status_config_dir(config);
finish_cluster_status(&output, json)?;
}
},
Command::Graphs { command } => match command {
GraphsCommand::List {