Skip to main content
Glama
component.rs8.9 kB
use dal::{ AttributePrototype, Component, DalContext, attribute::value::debug::AttributeDebugView, component::debug::ComponentDebugView, }; use dal_test::{ Result, expected::{ self, ExpectComponent, apply_change_set_to_base, fork_from_head_change_set, update_visibility_and_snapshot_to_visibility, }, helpers::{ ChangeSetTestHelpers, attribute::value::{ self, AttributeValueKey, }, component, }, test, }; #[test] async fn deleting_a_component_deletes_component_in_other_change_sets(ctx: &mut DalContext) { let docker_image_1 = ExpectComponent::create_named(ctx, "Docker Image", "docker 1").await; expected::apply_change_set_to_base(ctx).await; // fork this change set and place docker image in a frame let cs_1 = fork_from_head_change_set(ctx).await; expected::commit_and_update_snapshot_to_visibility(ctx).await; // fork and delete a docker image fork_from_head_change_set(ctx).await; Component::remove(ctx, docker_image_1.id()) .await .expect("able to remove"); apply_change_set_to_base(ctx).await; update_visibility_and_snapshot_to_visibility(ctx, cs_1.id).await; assert!( !ctx.workspace_snapshot() .expect("get snap") .node_exists(docker_image_1.id()) .await ); } #[test] async fn deleting_a_value_source_component_does_not_break_other_change_sets( ctx: &mut DalContext, ) -> Result<()> { // Create two components with an inter-component subscription. let component_to_erase_id = component::create(ctx, "Docker Image", "hammerfell").await?; value::set(ctx, ("hammerfell", "/domain/image"), "neloth").await?; // Apply to HEAD ChangeSetTestHelpers::apply_change_set_to_base(ctx).await?; // In a new change set, create a component connected to the component_to_erase let subscriber_cs = ChangeSetTestHelpers::fork_from_head_change_set(ctx).await?; let subscriber_component_id = component::create(ctx, "Docker Image", "highrock").await?; value::subscribe( ctx, ("highrock", "/domain/image"), ("hammerfell", "/domain/image"), ) .await?; ChangeSetTestHelpers::commit_and_update_snapshot_to_visibility(ctx).await?; assert_eq!( "neloth", // expected value::get(ctx, ("highrock", "/domain/image")).await?, // actual ); // Now, in a second change set, erase `component_to_erase` and apply to head Component::remove(ctx, component_to_erase_id).await?; ChangeSetTestHelpers::apply_change_set_to_base(ctx).await?; ChangeSetTestHelpers::switch_to_change_set(ctx, subscriber_cs.id).await?; let subscriber_av_id = AttributeValueKey::id(ctx, ("highrock", "/domain/image")).await?; // ensure debug view does not fail let _component_debug_view = ComponentDebugView::new(ctx, subscriber_component_id).await?; let debug_view = AttributeDebugView::new(ctx, subscriber_av_id, None, None).await?; let prototype_id = debug_view.prototype_id.expect("prototype found"); let apas = AttributePrototype::list_arguments(ctx, prototype_id).await?; assert!(apas.is_empty()); // Ensure we can build the component's mvs dal_materialized_views::component::assemble(ctx.clone(), subscriber_component_id).await?; dal_materialized_views::component::attribute_tree::assemble( ctx.clone(), subscriber_component_id, ) .await?; Ok(()) } // TODO restore this using subscriptions! // #[test] // async fn deleting_a_connected_component_doesnt_cause_nonconnected_components_to_process( // ctx: &mut DalContext, // ) { // let docker_image_1 = ExpectComponent::create_named(ctx, "Docker Image", "docker 1").await; // let docker_image_1_id = docker_image_1.id(); // let docker_image_2 = ExpectComponent::create_named(ctx, "Docker Image", "docker 2").await; // let butane_1 = ExpectComponent::create_named(ctx, "Butane", "butane 1") // .await // .component(ctx) // .await; // let butane_1_id = butane_1.id(); // let butane_2 = ExpectComponent::create_named(ctx, "Butane", "butane 2") // .await // .component(ctx) // .await; // // connect both pairs of Docker -> Butane // connect_components_with_socket_names( // ctx, // docker_image_1.id(), // "Container Image", // butane_1.id(), // "Container Image", // ) // .await // .expect("able to connect"); // connect_components_with_socket_names( // ctx, // docker_image_2.id(), // "Container Image", // butane_2.id(), // "Container Image", // ) // .await // .expect("able to connect"); // expected::commit_and_update_snapshot_to_visibility(ctx).await; // expected::apply_change_set_to_base(ctx).await; // let prop_path = &["root", "domain", "systemd", "units"]; // // open 2 new change sets // let cs_1 = fork_from_head_change_set(ctx).await; // // ensure this butane component has a value for the input socket // let butane_1_input_socket = // get_component_input_socket_value(ctx, butane_1_id, "Container Image") // .await // .expect("couldn't find value"); // // get the attribute value id for the second butane component to check when it's function was last run // assert!(butane_1_input_socket.is_some()); // let mut attribute_value_ids = butane_2 // .attribute_values_for_prop(ctx, prop_path) // .await // .expect("couldn't find attribute values"); // let attribute_value_id = attribute_value_ids.pop().expect("has an attribute value"); // // I'm not actually looking for a qualification but there's nothing qualification specific here anyways // // using this to validate that this func didn't re-run unnecessarily after removing the docker image // // connected to the other butane component // let func_run_pre_delete: Option<FuncRun> = ctx // .layer_db() // .func_run() // .get_last_qualification_for_attribute_value_id( // ctx.workspace_pk().expect("has a workspace"), // attribute_value_id, // ) // .await // .expect("could not get func run"); // // remove one of the connected docker images // let docker = Component::get_by_id(ctx, docker_image_1_id) // .await // .expect("couldn't get component"); // docker.delete(ctx).await.expect("couldn't delete"); // expected::commit_and_update_snapshot_to_visibility(ctx).await; // // ensure the butane component no longer has value for that input socket // let butane_1_after_commit = // get_component_input_socket_value(ctx, butane_1_id, "Container Image") // .await // .expect("couldn't find value"); // assert!(butane_1_after_commit.is_none()); // // ensure the func that sets the prop for butane_2 didn't rerun (it should have the same func_run_id!) // let func_run_post_delete: Option<FuncRun> = ctx // .layer_db() // .func_run() // .get_last_qualification_for_attribute_value_id( // ctx.workspace_pk().expect("has a workspace"), // attribute_value_id, // ) // .await // .expect("could not get func run"); // assert_eq!( // func_run_post_delete.as_ref().expect("has a value").id(), // func_run_pre_delete.expect("has a value").id() // ); // // before we apply, create a second fork of head // let cs_2 = fork_from_head_change_set(ctx).await; // update_visibility_and_snapshot_to_visibility(ctx, cs_1.id).await; // // now apply // expected::apply_change_set_to_base(ctx).await; // update_visibility_and_snapshot_to_visibility(ctx, cs_2.id).await; // //now switch to cs_2 and ensure the butane_1 component is updated correctly but the butane_2 component is as it was // // and we haven't re-ran the existing input socket // let func_run_post_apply: Option<FuncRun> = ctx // .layer_db() // .func_run() // .get_last_qualification_for_attribute_value_id( // ctx.workspace_pk().expect("has a workspace"), // attribute_value_id, // ) // .await // .expect("could not get func run"); // assert_eq!( // func_run_post_delete.expect("has a value").id(), // func_run_post_apply.expect("has a value").id() // ); // let butane_1_after_apply = // get_component_input_socket_value(ctx, butane_1_id, "Container Image") // .await // .expect("couldn't find value"); // assert!(butane_1_after_apply.is_none()); // }

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