Skip to main content
Glama
main.rs4.79 kB
use std::{ env, fs::File, io::{ Read as _, Write, }, }; use dal::{ EdgeWeightKind, NodeWeightDiscriminants, Ulid, WorkspaceSnapshotGraph, workspace_snapshot::node_weight::NodeWeight, }; use itertools::Itertools as _; use petgraph::prelude::*; use si_layer_cache::db::serialize; use tokio::time::Instant; type Result<T> = std::result::Result<T, Box<dyn std::error::Error + 'static>>; #[tokio::main] async fn main() -> Result<()> { // To fix a snapshot, first download the snapshot from the admin portal // Then run this like so in dal/examples: // cargo run --example snapshot-surfer <PATH> <NODE_ID> ... // ex: cargo run --example snapshot-surfer ~/Downloads/head.snapshot 01JTXGMYKFFPY7H2ZNV7SKFQ9X 01JPT6SHX1X43GTM8XHQ6VJRTM let mut args = env::args(); args.next(); // skip program name let snap_path = args .next() .expect("usage: program <SNAPSHOT_FILE_PATH> <NODE_ID> ..."); let mut snap_file = File::open(snap_path)?; let mut snap_bytes = vec![]; snap_file.read_to_end(&mut snap_bytes)?; println!("snap bytes compressed: {}", snap_bytes.len()); let decompressed = serialize::decompress_to_vec(&snap_bytes)?; println!("decompressed: {}", decompressed.len()); let now = Instant::now(); let mut graph: WorkspaceSnapshotGraph = serialize::from_bytes(&snap_bytes)?; println!("deserialization took: {:?}", now.elapsed()); // Make your edits: // Example: We were seeing: // attribute value error: attribute value 01JTXGMYKFFPY7H2ZNV7SKFQ9X has no outgoing edge to a prop or socket" // so we needed to remove it // let node_id = "01JTXGMYKFFPY7H2ZNV7SKFQ9X"; // remove_node_by_id(&mut graph, node_id)?; println!("root id: {}", graph.get_node_weight(graph.root())?.id()); for arg in args { let node_id = Ulid::from_string(&arg)?; let node_idx = graph.get_node_index_by_id(node_id)?; let ident = node_ident(&graph, node_idx)?; println!(); println!("{}", "=".repeat(ident.len())); println!("{ident}"); println!(); println!("{:#?}", graph.get_node_weight(node_idx)?); print_edges(&graph, node_idx)?; } // Cleanup and update merkle tree graph.cleanup_and_merkle_tree_hash()?; // write snapshot write_snapshot_graph("./fixed.snapshot", &graph)?; // then head back to the admin portal and replace snapshot with this new fixed snapshot Ok(()) } fn print_edges(graph: &WorkspaceSnapshotGraph, index: NodeIndex) -> Result<()> { let incoming: Vec<_> = graph .edges_directed(index, Direction::Incoming) .map(|edge| { node_ident(graph, edge.source()) .map(|source| format!(" ← {:?} - {}", edge.weight().kind(), source)) }) .try_collect()?; println!(); for incoming in incoming { println!(" {incoming}"); } println!(); let outgoing: Vec<_> = graph .edges_directed(index, Direction::Outgoing) .map(|edge| { node_ident(graph, edge.target()) .map(|target| format!(" → {:?} - {}", edge.weight().kind(), target)) }) .try_collect()?; for outgoing in outgoing { println!(" {outgoing}"); } Ok(()) } fn node_ident(graph: &WorkspaceSnapshotGraph, index: NodeIndex) -> Result<String> { let node = graph.get_node_weight(index)?; let discrim = match node.content_address_discriminants() { Some(discrim) => discrim.to_string(), None => NodeWeightDiscriminants::from(node).to_string(), }; let extra = match node { NodeWeight::Category(category) => Some(format!(" ({})", category.kind())), NodeWeight::AttributeValue(_) => match graph.target_opt(index, EdgeWeightKind::Prop)? { Some(prop_index) => { let prop = graph.get_node_weight(prop_index)?.as_prop_node_weight()?; Some(format!(" (prop {} - {})", prop.id(), prop.name())) } None => None, }, NodeWeight::Prop(prop) => Some(format!(" ({})", prop.name())), _ => None, }; Ok(format!( "{} {}{}", discrim, node.id(), extra.unwrap_or("".to_string()) )) } fn write_snapshot_graph(path: &str, graph: &WorkspaceSnapshotGraph) -> Result<()> { let mut file = File::create(path)?; let (bytes, _) = serialize::to_vec(graph)?; file.write_all(&bytes)?; Ok(()) } #[allow(unused)] fn remove_node_by_id(graph: &mut WorkspaceSnapshotGraph, id: &str) -> Result<()> { let node_id = si_id::ulid::Ulid::from_string(id)?; let node_idx = graph.get_node_index_by_id(node_id)?; graph.remove_node(node_idx); Ok(()) }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/systeminit/si'

If you have feedback or need assistance with the MCP directory API, please join our Discord server