From 8f30afe95b4295facd2ab88156e3be6d553b3d14 Mon Sep 17 00:00:00 2001 From: Thomas Date: Fri, 6 Sep 2024 22:46:58 +0100 Subject: [PATCH 1/7] WiP holon spaces --- crates/coordinator/core_schema/src/loader.rs | 12 ++++++ .../src/relationship_type_loader.rs | 43 ++++++++++++++++++- .../descriptors/src/descriptor_types.rs | 1 + crates/coordinator/holons/src/context.rs | 4 ++ crates/coordinator/holons/src/holon_space.rs | 15 +++++++ crates/coordinator/holons/src/lib.rs | 1 + 6 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 crates/coordinator/holons/src/holon_space.rs diff --git a/crates/coordinator/core_schema/src/loader.rs b/crates/coordinator/core_schema/src/loader.rs index ec420ac4..1c3f5053 100644 --- a/crates/coordinator/core_schema/src/loader.rs +++ b/crates/coordinator/core_schema/src/loader.rs @@ -1,4 +1,5 @@ use hdi::prelude::debug; +use holons::{commit_manager, holon_space}; use strum::IntoEnumIterator; use hdk::prelude::info; use holons::commit_manager::{CommitManager, CommitResponse}; @@ -55,6 +56,14 @@ pub fn load_core_schema(context: &HolonsContext) -> Result Result RelationshipTypeLoader { + descriptor_name, + description : MapString( + format!("Specifies the HolonSpace(s) for which this Schema is used to create instances of L0 types.") + ), + label, + described_by: None, + owned_by: None, + relationship_type_name, + source_owns_relationship: MapBoolean(true), + deletion_semantic: DeletionSemantic::Allow, + load_links_immediate: MapBoolean(false), + target_collection_type: CollectionTypeSpec{ + semantic: CollectionSemantic::SingleInstance, + holon_type: CoreHolonTypeName::HolonSpaceType, + }, + has_inverse: Some(CoreSchema), + }, + CoreSchema => RelationshipTypeLoader { + descriptor_name, + description : MapString( + format!("Specifies the (single) Core Schema used to create instances of L0 types within this HolonSpace.") + ), + label, + described_by: None, + owned_by: None, + relationship_type_name, + source_owns_relationship: MapBoolean(false), + deletion_semantic: DeletionSemantic::Allow, + load_links_immediate: MapBoolean(false), + target_collection_type: CollectionTypeSpec{ + semantic: CollectionSemantic::SingleInstance, + holon_type: CoreHolonTypeName::SchemaType, + }, + has_inverse: None, // Should be None because `source_owns_relationship` is `false` + + }, CollectionFor => RelationshipTypeLoader { descriptor_name, description : MapString( diff --git a/crates/coordinator/descriptors/src/descriptor_types.rs b/crates/coordinator/descriptors/src/descriptor_types.rs index 040709ad..52210e19 100644 --- a/crates/coordinator/descriptors/src/descriptor_types.rs +++ b/crates/coordinator/descriptors/src/descriptor_types.rs @@ -79,6 +79,7 @@ pub struct RelationshipType { described_by: HolonReference, // MetaRelationshipType } + pub struct PropertyType { header: TypeDescriptor, property_type_name: PropertyName, diff --git a/crates/coordinator/holons/src/context.rs b/crates/coordinator/holons/src/context.rs index 92615574..4be38662 100644 --- a/crates/coordinator/holons/src/context.rs +++ b/crates/coordinator/holons/src/context.rs @@ -1,5 +1,6 @@ use crate::cache_manager::HolonCacheManager; use crate::commit_manager::CommitManager; +use crate::staged_reference::StagedReference; use std::cell::RefCell; use shared_types_holon::MapString; use crate::holon_error::HolonError; @@ -10,6 +11,7 @@ pub struct HolonsContext { pub commit_manager: RefCell, pub cache_manager: RefCell, pub dance_state: RefCell, + pub local_holon_space: HolonReference } impl HolonsContext { @@ -18,6 +20,7 @@ impl HolonsContext { commit_manager: CommitManager::new().into(), cache_manager: HolonCacheManager::new().into(), dance_state: TransientCollection::new().into(), + local_holon_space: HolonReference::Staged(StagedReference::new(0)).into() } } pub fn init_context(commit_manager: CommitManager, cache_manager: HolonCacheManager) -> HolonsContext { @@ -25,6 +28,7 @@ impl HolonsContext { commit_manager: RefCell::from(commit_manager), cache_manager: RefCell::from(cache_manager), dance_state: TransientCollection::new().into(), + local_holon_space: HolonReference::Staged(StagedReference::new(0)).into() } } pub fn add_references_to_dance_state(&self, holons: Vec) -> Result<(), HolonError> { diff --git a/crates/coordinator/holons/src/holon_space.rs b/crates/coordinator/holons/src/holon_space.rs new file mode 100644 index 00000000..d9e7fdc8 --- /dev/null +++ b/crates/coordinator/holons/src/holon_space.rs @@ -0,0 +1,15 @@ + +use crate::holon::Holon; + + +pub struct HolonSpace(pub Holon); + +impl HolonSpace { + pub fn new(holon: Holon) -> HolonSpace { + HolonSpace(holon) + } + + pub fn into_holon(self) -> Holon { + self.0 + } +} diff --git a/crates/coordinator/holons/src/lib.rs b/crates/coordinator/holons/src/lib.rs index c32858c7..c4b7fcb3 100644 --- a/crates/coordinator/holons/src/lib.rs +++ b/crates/coordinator/holons/src/lib.rs @@ -17,6 +17,7 @@ pub mod staged_reference; pub mod transient_collection; pub mod json_adapter; pub mod query; +pub mod holon_space; use hdk::prelude::*; From 47afb06558d4d0c1673c9cff1a24745a9a8a1471 Mon Sep 17 00:00:00 2001 From: evomimic Date: Sun, 8 Sep 2024 07:38:15 -0600 Subject: [PATCH 2/7] non-compiling checkpoint -- unresolved dependency issue --- crates/coordinator/core_schema/src/loader.rs | 8 -------- crates/coordinator/dances/src/dancer.rs | 15 ++++++++++++++- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/crates/coordinator/core_schema/src/loader.rs b/crates/coordinator/core_schema/src/loader.rs index 1c3f5053..38de9e16 100644 --- a/crates/coordinator/core_schema/src/loader.rs +++ b/crates/coordinator/core_schema/src/loader.rs @@ -56,14 +56,6 @@ pub fn load_core_schema(context: &HolonsContext) -> Result ExternResult { let commit_manager = request.clone().staging_area.to_commit_manager(); // assert_eq!(request.staging_area.staged_holons.len(),commit_manager.staged_holons.len()); //info!("initializing context"); - let context = HolonsContext::init_context(commit_manager, HolonCacheManager::new()); + + + let mut context = HolonsContext::init_context(commit_manager, HolonCacheManager::new()); + // If there is no HolonSpace, create one + let holon_space = holon_space::HolonSpace::new(Holon::new()); + + context.local_holon_space = HolonReference::Staged(context + .commit_manager + .borrow_mut() + .stage_new_holon(holon_space.into_holon()) + ?); // Get the Dancer let dancer = Dancer::new(); From e2b3bc05efef3541d2a6a12ed8213bb57d905eaf Mon Sep 17 00:00:00 2001 From: evomimic Date: Mon, 9 Sep 2024 11:56:05 -0600 Subject: [PATCH 3/7] non-compiling checkpoint --- .../coordinator/dances/src/dance_request.rs | 25 ++++++++++- crates/coordinator/dances/src/dancer.rs | 7 ++- .../coordinator/dances/src/session_state.rs | 45 +++++++++++++++++++ crates/coordinator/holons/src/context.rs | 22 ++++++--- 4 files changed, 90 insertions(+), 9 deletions(-) create mode 100644 crates/coordinator/dances/src/session_state.rs diff --git a/crates/coordinator/dances/src/dance_request.rs b/crates/coordinator/dances/src/dance_request.rs index 8e069e0f..a1ecfd86 100644 --- a/crates/coordinator/dances/src/dance_request.rs +++ b/crates/coordinator/dances/src/dance_request.rs @@ -7,6 +7,7 @@ use holons::relationship::RelationshipName; use holons::query::{NodeCollection, QueryExpression}; use shared_types_holon::{HolonId, MapString, PropertyMap}; +use crate::session_state::SessionState; #[hdk_entry_helper] #[derive(Clone, Eq, PartialEq)] @@ -14,10 +15,12 @@ pub struct DanceRequest { pub dance_name: MapString, // unique key within the (single) dispatch table pub dance_type: DanceType, pub body: RequestBody, - pub staging_area: StagingArea, + // pub staging_area: StagingArea, + state: SessionState, //pub descriptor: Option, // space_id+holon_id of DanceDescriptor } + #[hdk_entry_helper] #[derive(Clone, Eq, PartialEq)] pub enum DanceType { @@ -73,12 +76,30 @@ impl DanceRequest { dance_type: DanceType, body: RequestBody, staging_area: StagingArea, + local_holon_space : Option ) -> Self { + // Initialize the SessionState with staging_area and local_holon_space + let state = SessionState::new( + staging_area, + local_holon_space, + ); Self { dance_name, dance_type, body, - staging_area, + state, } } + pub fn get_state(&self) -> &SessionState { + &self.state + } + // Optionally, you can provide a mutable getter for state if needed + pub fn get_state_mut(&mut self) -> &mut SessionState { + &mut self.state + } + pub fn set_state(&mut self, state: SessionState) { + self.state = state; + } + + } diff --git a/crates/coordinator/dances/src/dancer.rs b/crates/coordinator/dances/src/dancer.rs index 1054bdf3..4e79d239 100644 --- a/crates/coordinator/dances/src/dancer.rs +++ b/crates/coordinator/dances/src/dancer.rs @@ -40,15 +40,18 @@ pub fn dance(request: DanceRequest) -> ExternResult { description: MapString("Invalid Request".to_string()), body: ResponseBody::None, descriptor: None, - staging_area: request.staging_area.clone(), + staging_area: request.get_state().get_staging_area(), }; return Ok(response); } // Initialize the context, mapping the StagingArea (if there is one) into a CommitManager //info!("initializing commit_manager from staging_area"); - let commit_manager = request.clone().staging_area.to_commit_manager(); + let commit_manager = request.get_state().get_staging_area().to_commit_manager(); // assert_eq!(request.staging_area.staged_holons.len(),commit_manager.staged_holons.len()); + + + //info!("initializing context"); diff --git a/crates/coordinator/dances/src/session_state.rs b/crates/coordinator/dances/src/session_state.rs new file mode 100644 index 00000000..7c47c4c8 --- /dev/null +++ b/crates/coordinator/dances/src/session_state.rs @@ -0,0 +1,45 @@ + +use hdk::prelude::*; +// use serde::Serialize; + + +use hdi::hdk_entry_helper; +use holons::holon_reference::HolonReference; +use crate::staging_area::StagingArea; + +/// SessionState provides a way to distinguish information associated with a specific request from +/// state info that is just being maintained via the ping pong process. This also should make it +/// easier to evolve to token-based state management approach where, say, the state token is +/// actually a reference into the ephemeral store. +#[hdk_entry_helper] +#[derive(Clone, Eq, PartialEq)] +pub struct SessionState { + staging_area : StagingArea, + local_holon_space: Option, +} + +impl SessionState { + pub fn new(staging_area: StagingArea, + local_holon_space: Option, + + ) -> Self { + Self { + staging_area, + local_holon_space, + } + } + pub fn get_local_holon_space(&self) -> Option<&HolonReference> { + self.local_holon_space.as_ref() + } + pub fn get_staging_area(&self) -> &StagingArea { + &self.staging_area + } + + pub fn set_local_holon_space(&mut self, local_holon_space: Option) { + self.local_holon_space = local_holon_space; + } + pub fn set_staging_area(&mut self, staging_area: StagingArea) { + self.staging_area = staging_area; + } + +} diff --git a/crates/coordinator/holons/src/context.rs b/crates/coordinator/holons/src/context.rs index 4be38662..a83e2ec1 100644 --- a/crates/coordinator/holons/src/context.rs +++ b/crates/coordinator/holons/src/context.rs @@ -6,12 +6,12 @@ use shared_types_holon::MapString; use crate::holon_error::HolonError; use crate::holon_reference::HolonReference; use crate::transient_collection::TransientCollection; - +/// HolonsContext provides a single place to information useful within a dance request pub struct HolonsContext { pub commit_manager: RefCell, pub cache_manager: RefCell, pub dance_state: RefCell, - pub local_holon_space: HolonReference + pub local_holon_space: RefCell>, } impl HolonsContext { @@ -20,17 +20,29 @@ impl HolonsContext { commit_manager: CommitManager::new().into(), cache_manager: HolonCacheManager::new().into(), dance_state: TransientCollection::new().into(), - local_holon_space: HolonReference::Staged(StagedReference::new(0)).into() + local_holon_space: RefCell::new(None), } } - pub fn init_context(commit_manager: CommitManager, cache_manager: HolonCacheManager) -> HolonsContext { + pub fn init_context( + commit_manager: CommitManager, + cache_manager: HolonCacheManager, + local_holon_space: Option + ) -> HolonsContext { + // Set local_holon_space to the provided value or None + let space_ref = RefCell::new(local_holon_space); + + // Return the initialized context HolonsContext { commit_manager: RefCell::from(commit_manager), cache_manager: RefCell::from(cache_manager), dance_state: TransientCollection::new().into(), - local_holon_space: HolonReference::Staged(StagedReference::new(0)).into() + local_holon_space: space_ref, // Uses the provided HolonReference or None } } + fn set_local_holon_space(&self, new_holon_space: HolonReference) { + // Borrow mutably and replace the None with Some(new_holon_space) + *self.local_holon_space.borrow_mut() = Some(new_holon_space); + } pub fn add_references_to_dance_state(&self, holons: Vec) -> Result<(), HolonError> { self.dance_state.borrow_mut().add_references(self, holons) } From 3c1df528dbc35abf41b827134b1522f19e5a2d2c Mon Sep 17 00:00:00 2001 From: evomimic Date: Sun, 22 Sep 2024 16:37:06 -0600 Subject: [PATCH 4/7] checkpoint commit -- does not compile --- .../coordinator/dances/src/dance_request.rs | 22 ++++++++++-- .../coordinator/dances/src/dance_response.rs | 19 ++++++++-- crates/coordinator/dances/src/dancer.rs | 36 +++++++------------ crates/coordinator/dances/src/lib.rs | 1 + .../coordinator/dances/src/session_state.rs | 13 +++++++ crates/coordinator/holons/src/context.rs | 2 +- crates/coordinator/holons/src/holon_space.rs | 2 ++ 7 files changed, 65 insertions(+), 30 deletions(-) diff --git a/crates/coordinator/dances/src/dance_request.rs b/crates/coordinator/dances/src/dance_request.rs index a1ecfd86..9b47ea60 100644 --- a/crates/coordinator/dances/src/dance_request.rs +++ b/crates/coordinator/dances/src/dance_request.rs @@ -1,6 +1,8 @@ use crate::{staging_area::StagingArea}; use hdk::prelude::*; +use holons::cache_manager::HolonCacheManager; use holons::commit_manager::StagedIndex; +use holons::context::HolonsContext; use holons::holon::Holon; use holons::holon_reference::HolonReference; use holons::relationship::RelationshipName; @@ -97,9 +99,23 @@ impl DanceRequest { pub fn get_state_mut(&mut self) -> &mut SessionState { &mut self.state } - pub fn set_state(&mut self, state: SessionState) { - self.state = state; - } + pub fn set_context_from_state(&self) { + let commit_manager = self.get_state().get_staging_area().to_commit_manager(); + // assert_eq!(request.staging_area.staged_holons.len(),commit_manager.staged_holons.len()); + + let local_holon_space = self.get_state().get_local_holon_space(); + //info!("initializing context"); + let mut context = HolonsContext::init_context( + commit_manager, + HolonCacheManager::new(), + local_holon_space, + ); + self.state.set_staging_area(StagingArea::from_commit_manager(&context.commit_manager.borrow())); + self.state.set_local_holon_space(context.local_holon_space.borrow().clone()); + } + } + + diff --git a/crates/coordinator/dances/src/dance_response.rs b/crates/coordinator/dances/src/dance_response.rs index 7e6fff25..41da2dbc 100644 --- a/crates/coordinator/dances/src/dance_response.rs +++ b/crates/coordinator/dances/src/dance_response.rs @@ -5,10 +5,12 @@ use holons::query::NodeCollection; use crate::staging_area::StagingArea; use hdk::prelude::*; use holons::commit_manager::StagedIndex; +use holons::context::HolonsContext; use holons::holon::Holon; use holons::holon_error::HolonError; use holons::holon_reference::HolonReference; use shared_types_holon::MapString; +use crate::session_state::SessionState; #[hdk_entry_helper] #[derive(Clone, Eq, PartialEq)] @@ -17,7 +19,7 @@ pub struct DanceResponse { pub description: MapString, pub body: ResponseBody, pub descriptor: Option, // space_id+holon_id of DanceDescriptor - pub staging_area: StagingArea, + pub state: SessionState, } /// Define a standard set of statuses that may be returned by DanceRequests. @@ -103,13 +105,26 @@ impl DanceResponse { body: ResponseBody, descriptor: Option, staging_area: StagingArea, + local_holon_space: Option<&HolonReference>, ) -> DanceResponse { + let state = SessionState::new( + staging_area, + local_holon_space.cloned() + ); DanceResponse { status_code, description, body, descriptor, - staging_area, + state, } } + /// Restores the session state within the DanceResponse from context. This should always + /// be called before returning DanceResponse since the state is intended to be "ping-ponged" + /// between client and guest. + pub fn restore_state(&mut self, context: &HolonsContext) { + self.state.set_staging_area(StagingArea::from_commit_manager(&context.commit_manager.borrow())); + self.state.set_local_holon_space(context.local_holon_space.borrow().clone()); + } + } diff --git a/crates/coordinator/dances/src/dancer.rs b/crates/coordinator/dances/src/dancer.rs index 4e79d239..377ae2da 100644 --- a/crates/coordinator/dances/src/dancer.rs +++ b/crates/coordinator/dances/src/dancer.rs @@ -13,11 +13,8 @@ use holons::holon_space; use shared_types_holon::MapString; use crate::dance_response::{DanceResponse, ResponseBody, ResponseStatusCode}; -use crate::descriptors_dance_adapter::load_core_schema_dance; - -use crate::holon_dance_adapter::{ - abandon_staged_changes_dance, add_related_holons_dance, commit_dance, get_all_holons_dance, get_holon_by_id_dance, query_relationships_dance, remove_related_holons_dance, stage_new_holon_dance, with_properties_dance -}; +use crate::descriptors_dance_adapter::*; +use crate::holon_dance_adapter::*; use crate::staging_area::StagingArea; @@ -35,27 +32,18 @@ pub fn dance(request: DanceRequest) -> ExternResult { let valid = true; // TODO: Validate the dance request if !valid { - let response = DanceResponse { - status_code: ResponseStatusCode::BadRequest, - description: MapString("Invalid Request".to_string()), - body: ResponseBody::None, - descriptor: None, - staging_area: request.get_state().get_staging_area(), - }; + let response = DanceResponse::new( + ResponseStatusCode::BadRequest, + MapString("Invalid Request".to_string()), + ResponseBody::None, + None, + request.get_state().get_staging_area().clone(), + request.get_state().get_local_holon_space().clone()); return Ok(response); } - // Initialize the context, mapping the StagingArea (if there is one) into a CommitManager - //info!("initializing commit_manager from staging_area"); - let commit_manager = request.get_state().get_staging_area().to_commit_manager(); - // assert_eq!(request.staging_area.staged_holons.len(),commit_manager.staged_holons.len()); - - - - //info!("initializing context"); - + let mut context = request.init_context_from_state(); - let mut context = HolonsContext::init_context(commit_manager, HolonCacheManager::new()); // If there is no HolonSpace, create one let holon_space = holon_space::HolonSpace::new(Holon::new()); @@ -83,8 +71,8 @@ pub fn dance(request: DanceRequest) -> ExternResult { let mut result = process_dispatch_result(dispatch_result); - // Restore the StagingArea from CommitManager - result.staging_area = StagingArea::from_commit_manager(&context.commit_manager.borrow()); + // Restore the SessionState from the context + result.restore_state(*context); // assert_eq!(result.staging_area.staged_holons.len(), context.commit_manager.borrow().staged_holons.len()); info!( diff --git a/crates/coordinator/dances/src/lib.rs b/crates/coordinator/dances/src/lib.rs index d6e7b978..2e6de69e 100644 --- a/crates/coordinator/dances/src/lib.rs +++ b/crates/coordinator/dances/src/lib.rs @@ -4,6 +4,7 @@ pub mod staging_area; pub mod holon_dance_adapter; pub mod dance_request; pub mod descriptors_dance_adapter; +pub mod session_state; // use hdk::prelude::*; diff --git a/crates/coordinator/dances/src/session_state.rs b/crates/coordinator/dances/src/session_state.rs index 7c47c4c8..5f4f4aaa 100644 --- a/crates/coordinator/dances/src/session_state.rs +++ b/crates/coordinator/dances/src/session_state.rs @@ -4,6 +4,8 @@ use hdk::prelude::*; use hdi::hdk_entry_helper; +use holons::cache_manager::HolonCacheManager; +use holons::context::HolonsContext; use holons::holon_reference::HolonReference; use crate::staging_area::StagingArea; @@ -34,6 +36,17 @@ impl SessionState { pub fn get_staging_area(&self) -> &StagingArea { &self.staging_area } + pub fn init_context_from_state(&self)-> HolonsContext { + let commit_manager = self.staging_area.to_commit_manager(); + let local_holon_space = self.get_local_holon_space(); + //info!("initializing context"); + HolonsContext::init_context( + commit_manager, + HolonCacheManager::new(), + local_holon_space, + ) + + } pub fn set_local_holon_space(&mut self, local_holon_space: Option) { self.local_holon_space = local_holon_space; diff --git a/crates/coordinator/holons/src/context.rs b/crates/coordinator/holons/src/context.rs index a83e2ec1..a3f033a4 100644 --- a/crates/coordinator/holons/src/context.rs +++ b/crates/coordinator/holons/src/context.rs @@ -26,7 +26,7 @@ impl HolonsContext { pub fn init_context( commit_manager: CommitManager, cache_manager: HolonCacheManager, - local_holon_space: Option + local_holon_space: Option<&HolonReference> ) -> HolonsContext { // Set local_holon_space to the provided value or None let space_ref = RefCell::new(local_holon_space); diff --git a/crates/coordinator/holons/src/holon_space.rs b/crates/coordinator/holons/src/holon_space.rs index d9e7fdc8..4f48914e 100644 --- a/crates/coordinator/holons/src/holon_space.rs +++ b/crates/coordinator/holons/src/holon_space.rs @@ -12,4 +12,6 @@ impl HolonSpace { pub fn into_holon(self) -> Holon { self.0 } + + } From 3c69f805aa010ad1351fc57a8e411c5c91cb5887 Mon Sep 17 00:00:00 2001 From: evomimic Date: Wed, 2 Oct 2024 09:41:21 -0600 Subject: [PATCH 5/7] checkpoint commit -- does not compile --- .../coordinator/dances/src/dance_request.rs | 12 ++--- .../coordinator/dances/src/dance_response.rs | 4 +- crates/coordinator/dances/src/dancer.rs | 7 +++ .../coordinator/dances/src/session_state.rs | 30 ++++++++++--- crates/coordinator/holons/src/context.rs | 16 ++++--- .../holons/src/holon_collection.rs | 2 +- .../coordinator/holons/src/holon_reference.rs | 4 +- crates/coordinator/holons/src/holon_space.rs | 45 ++++++++++++++++++- 8 files changed, 93 insertions(+), 27 deletions(-) diff --git a/crates/coordinator/dances/src/dance_request.rs b/crates/coordinator/dances/src/dance_request.rs index 9b47ea60..caac91ab 100644 --- a/crates/coordinator/dances/src/dance_request.rs +++ b/crates/coordinator/dances/src/dance_request.rs @@ -99,21 +99,17 @@ impl DanceRequest { pub fn get_state_mut(&mut self) -> &mut SessionState { &mut self.state } - pub fn set_context_from_state(&self) { + pub fn init_context_from_state(&self) -> HolonsContext { let commit_manager = self.get_state().get_staging_area().to_commit_manager(); // assert_eq!(request.staging_area.staged_holons.len(),commit_manager.staged_holons.len()); let local_holon_space = self.get_state().get_local_holon_space(); - //info!("initializing context"); - - - let mut context = HolonsContext::init_context( + info!("initializing context from session state in dance request"); + HolonsContext::init_context( commit_manager, HolonCacheManager::new(), local_holon_space, - ); - self.state.set_staging_area(StagingArea::from_commit_manager(&context.commit_manager.borrow())); - self.state.set_local_holon_space(context.local_holon_space.borrow().clone()); + ) } } diff --git a/crates/coordinator/dances/src/dance_response.rs b/crates/coordinator/dances/src/dance_response.rs index 41da2dbc..b6b56b74 100644 --- a/crates/coordinator/dances/src/dance_response.rs +++ b/crates/coordinator/dances/src/dance_response.rs @@ -105,11 +105,11 @@ impl DanceResponse { body: ResponseBody, descriptor: Option, staging_area: StagingArea, - local_holon_space: Option<&HolonReference>, + local_holon_space: Option, ) -> DanceResponse { let state = SessionState::new( staging_area, - local_holon_space.cloned() + local_holon_space.clone() ); DanceResponse { status_code, diff --git a/crates/coordinator/dances/src/dancer.rs b/crates/coordinator/dances/src/dancer.rs index 377ae2da..f211f8af 100644 --- a/crates/coordinator/dances/src/dancer.rs +++ b/crates/coordinator/dances/src/dancer.rs @@ -1,3 +1,4 @@ +use std::cell::Ref; use std::collections::HashMap; use hdk::prelude::*; @@ -44,6 +45,12 @@ pub fn dance(request: DanceRequest) -> ExternResult { let mut context = request.init_context_from_state(); + match context.get_local_holon_space().borrow() { + &_ => {} + } + + + // If there is no HolonSpace, create one let holon_space = holon_space::HolonSpace::new(Holon::new()); diff --git a/crates/coordinator/dances/src/session_state.rs b/crates/coordinator/dances/src/session_state.rs index 5f4f4aaa..f62b45d3 100644 --- a/crates/coordinator/dances/src/session_state.rs +++ b/crates/coordinator/dances/src/session_state.rs @@ -7,6 +7,8 @@ use hdi::hdk_entry_helper; use holons::cache_manager::HolonCacheManager; use holons::context::HolonsContext; use holons::holon_reference::HolonReference; +use holons::smart_reference::SmartReference; +use shared_types_holon::{HolonId, HolonSpaceId, LocalId}; use crate::staging_area::StagingArea; /// SessionState provides a way to distinguish information associated with a specific request from @@ -17,12 +19,12 @@ use crate::staging_area::StagingArea; #[derive(Clone, Eq, PartialEq)] pub struct SessionState { staging_area : StagingArea, - local_holon_space: Option, + local_holon_space: Option, } impl SessionState { pub fn new(staging_area: StagingArea, - local_holon_space: Option, + local_holon_space: Option, ) -> Self { Self { @@ -30,15 +32,16 @@ impl SessionState { local_holon_space, } } - pub fn get_local_holon_space(&self) -> Option<&HolonReference> { - self.local_holon_space.as_ref() + pub fn get_local_holon_space(&self) -> Option { + self.local_holon_space.clone() } pub fn get_staging_area(&self) -> &StagingArea { &self.staging_area } pub fn init_context_from_state(&self)-> HolonsContext { let commit_manager = self.staging_area.to_commit_manager(); - let local_holon_space = self.get_local_holon_space(); + + let local_holon_space = self.get_local_holon_space_reference(); //info!("initializing context"); HolonsContext::init_context( commit_manager, @@ -47,8 +50,23 @@ impl SessionState { ) } + /// This function constructs a (Smart variant) of a HolonReference to the HolonSpace from the + /// holon space id stored in SessionState (or None, if local_holon_space is None) + fn get_local_holon_space_reference(&self) -> Option { + // Check if local_holon_space is Some, then construct a HolonReference + self.local_holon_space.as_ref().map(|holon_space_id| { + // Convert HolonSpaceId to LocalId + let local_id = LocalId::from(holon_space_id.0.clone()); + + // Create the SmartReference with the Local variant of HolonId (no smart properties) + let smart_reference = SmartReference::new(HolonId::Local(local_id),None); + + // Return a HolonReference::Smart variant + HolonReference::Smart(smart_reference) + }) + } - pub fn set_local_holon_space(&mut self, local_holon_space: Option) { + pub fn set_local_holon_space(&mut self, local_holon_space: Option) { self.local_holon_space = local_holon_space; } pub fn set_staging_area(&mut self, staging_area: StagingArea) { diff --git a/crates/coordinator/holons/src/context.rs b/crates/coordinator/holons/src/context.rs index a3f033a4..ab9beb8c 100644 --- a/crates/coordinator/holons/src/context.rs +++ b/crates/coordinator/holons/src/context.rs @@ -1,7 +1,7 @@ use crate::cache_manager::HolonCacheManager; use crate::commit_manager::CommitManager; use crate::staged_reference::StagedReference; -use std::cell::RefCell; +use std::cell::{Ref, RefCell}; use shared_types_holon::MapString; use crate::holon_error::HolonError; use crate::holon_reference::HolonReference; @@ -11,7 +11,7 @@ pub struct HolonsContext { pub commit_manager: RefCell, pub cache_manager: RefCell, pub dance_state: RefCell, - pub local_holon_space: RefCell>, + pub local_holon_space: Option, } impl HolonsContext { @@ -20,25 +20,27 @@ impl HolonsContext { commit_manager: CommitManager::new().into(), cache_manager: HolonCacheManager::new().into(), dance_state: TransientCollection::new().into(), - local_holon_space: RefCell::new(None), + local_holon_space: None, } } pub fn init_context( commit_manager: CommitManager, cache_manager: HolonCacheManager, - local_holon_space: Option<&HolonReference> + local_holon_space: Option ) -> HolonsContext { - // Set local_holon_space to the provided value or None - let space_ref = RefCell::new(local_holon_space); // Return the initialized context HolonsContext { commit_manager: RefCell::from(commit_manager), cache_manager: RefCell::from(cache_manager), dance_state: TransientCollection::new().into(), - local_holon_space: space_ref, // Uses the provided HolonReference or None + local_holon_space: local_holon_space.clone(), } } + /// This method returns a reference to the LocalHolonSpace + pub fn get_local_holon_space(&self) -> Result { + self.local_holon_space.borrow() + } fn set_local_holon_space(&self, new_holon_space: HolonReference) { // Borrow mutably and replace the None with Some(new_holon_space) *self.local_holon_space.borrow_mut() = Some(new_holon_space); diff --git a/crates/coordinator/holons/src/holon_collection.rs b/crates/coordinator/holons/src/holon_collection.rs index 05711cba..bf286cd6 100644 --- a/crates/coordinator/holons/src/holon_collection.rs +++ b/crates/coordinator/holons/src/holon_collection.rs @@ -221,7 +221,7 @@ impl HolonCollection { ); for holon_reference in &self.members { // Only commit references to holons with id's (i.e., Saved) - if let Ok(target_id) = holon_reference.get_holon_id(context) { + if let Ok(target_id) = holon_reference.get_holon_id() { let key_option = holon_reference.get_key(context)?; let input: SmartLink = if let Some(key) = key_option { let mut prop_vals: PropertyMap = BTreeMap::new(); diff --git a/crates/coordinator/holons/src/holon_reference.rs b/crates/coordinator/holons/src/holon_reference.rs index dcffdc67..80a2a451 100644 --- a/crates/coordinator/holons/src/holon_reference.rs +++ b/crates/coordinator/holons/src/holon_reference.rs @@ -116,10 +116,10 @@ impl HolonReference { } } - pub fn get_holon_id(&self, context: &HolonsContext) -> Result { + pub fn get_holon_id(&self) -> Result { match self { HolonReference::Smart(smart_reference) => smart_reference.get_id(), - HolonReference::Staged(staged_reference) => + HolonReference::Staged(_staged_reference) => Err(HolonError::HolonNotFound("HolonId not yet assigned for Staged Holons".to_string())) } } diff --git a/crates/coordinator/holons/src/holon_space.rs b/crates/coordinator/holons/src/holon_space.rs index 4f48914e..42dc2bd9 100644 --- a/crates/coordinator/holons/src/holon_space.rs +++ b/crates/coordinator/holons/src/holon_space.rs @@ -1,5 +1,16 @@ - +use hdi::map_extern::ExternResult; +use hdi::prelude::Path; +use hdk::hdk::HDK; +use hdk::link::{get_links, GetLinksInputBuilder}; +use hdk::prelude::{GetInput, GetOptions}; +use holochain_integrity_types::Record; +use holons_integrity::LinkTypes; +use shared_types_holon::{HolonId, MapString}; +use crate::context::HolonsContext; use crate::holon::Holon; +use crate::holon_error::HolonError; +use crate::holon_reference::HolonReference; +use crate::smart_reference::SmartReference; pub struct HolonSpace(pub Holon); @@ -12,6 +23,38 @@ impl HolonSpace { pub fn into_holon(self) -> Holon { self.0 } + /// get_local_holon_space retrieves the local holon space from the persistent store + pub fn get_local_holon_space(context: &HolonsContext) -> Result { + // For now, it just uses a brute force linear search through all saved holons, searching + // for a holon with key "LocalHolonSpace". If found, it extracts its HolonId and + // A HolonReference to the cached HolonSpace Holon is then returned + // TODO: Scaffold a new `LocalHolonSpace` LinkType and search by path instead of linear search + let all_holons = Holon::get_all_holons()?; + let search_key = MapString("LocalHolonSpace".to_string()); + + for holon in &all_holons { + match holon.get_key()? { + Some(key) if key == search_key => { + let holon_id = HolonId::Local(holon.get_local_id()?); + // use get_rc_holon on the cache_manager to populate the HolonSpace holon in the cache + let holon_space_rc_holon = context + .cache_manager + .borrow_mut() + .get_rc_holon(&holon_id)?; + // build a HolonReference from the holon_space_rc_holon. + // TODO: We should have a helper function that creates a new SmartReference from a Holon. + // This function could populate the smart_property_values from the holon's descriptor + // But for now, we'll just construct the HolonReference from holon_id + + return Ok(HolonReference::Smart(SmartReference::new(holon_id, None))); + } + _ => continue, + } + } + + // Return HolonError::NotFound if no matching holon is found + Err(HolonError::HolonNotFound(search_key.to_string())) + } } From 4e2cb10773471675d7b5e4788ad0f1505a129243 Mon Sep 17 00:00:00 2001 From: evomimic Date: Mon, 7 Oct 2024 11:28:55 -0600 Subject: [PATCH 6/7] local holon space created on demand via dancer -- all tests pass --- .../src/boolean_value_type_loader.rs | 2 +- .../core_schema/src/collection_type_loader.rs | 2 +- .../core_schema/src/holon_type_loader.rs | 3 +- crates/coordinator/core_schema/src/loader.rs | 6 +- .../src/relationship_type_loader.rs | 10 +- .../core_schema/src/value_type_loader.rs | 5 +- .../coordinator/dances/src/dance_request.rs | 9 +- .../coordinator/dances/src/dance_response.rs | 12 +- crates/coordinator/dances/src/dancer.rs | 119 ++++++++++-------- .../dances/src/descriptors_dance_adapter.rs | 16 +-- .../dances/src/holon_dance_adapter.rs | 43 +++---- .../coordinator/dances/src/session_state.rs | 55 ++++---- crates/coordinator/dances/src/staging_area.rs | 7 +- .../tests/shared_test/dance_fixtures.rs | 36 ++++-- .../shared_test/descriptor_dance_fixtures.rs | 2 +- .../test_abandon_staged_changes.rs | 6 +- .../shared_test/test_add_related_holon.rs | 9 +- .../dances/tests/shared_test/test_commit.rs | 6 +- .../tests/shared_test/test_data_types.rs | 5 +- .../shared_test/test_ensure_database_count.rs | 16 +-- .../shared_test/test_load_core_schema.rs | 4 +- .../shared_test/test_match_db_content.rs | 4 +- .../tests/shared_test/test_print_database.rs | 4 +- .../shared_test/test_query_relationships.rs | 4 +- .../shared_test/test_remove_related_holon.rs | 9 +- .../tests/shared_test/test_stage_new_holon.rs | 6 +- .../test_with_properties_command.rs | 10 +- .../coordinator/holons/src/cache_manager.rs | 3 +- .../coordinator/holons/src/commit_manager.rs | 38 +++++- crates/coordinator/holons/src/context.rs | 30 +++-- crates/coordinator/holons/src/holon.rs | 6 +- .../holons/src/holon_collection.rs | 2 +- crates/coordinator/holons/src/holon_error.rs | 13 +- crates/coordinator/holons/src/holon_space.rs | 104 ++++++++------- .../holons/src/holon_space_manager.rs | 109 ++++++++++++++++ crates/coordinator/holons/src/lib.rs | 2 + .../coordinator/holons/src/smart_reference.rs | 7 ++ crates/coordinator/holons/src/smartlink.rs | 10 +- .../holons_integrity/src/holon_node.rs | 2 +- crates/shared_types/holon/src/value_types.rs | 5 + flake.lock | 87 +++++-------- 41 files changed, 511 insertions(+), 317 deletions(-) create mode 100644 crates/coordinator/holons/src/holon_space_manager.rs diff --git a/crates/coordinator/core_schema/src/boolean_value_type_loader.rs b/crates/coordinator/core_schema/src/boolean_value_type_loader.rs index a0b680a9..beb89d25 100644 --- a/crates/coordinator/core_schema/src/boolean_value_type_loader.rs +++ b/crates/coordinator/core_schema/src/boolean_value_type_loader.rs @@ -62,7 +62,7 @@ impl SchemaNamesTrait for CoreBooleanValueTypeName { impl CoreBooleanValueTypeName { /// This function returns the variant definition for a given variant type fn get_boolean_type_loader(&self) -> BooleanTypeLoader { - use CoreBooleanValueTypeName::*; + // use CoreBooleanValueTypeName::*; match self { CoreBooleanValueTypeName::MapBooleanType => BooleanTypeLoader { type_name: self.derive_type_name(), diff --git a/crates/coordinator/core_schema/src/collection_type_loader.rs b/crates/coordinator/core_schema/src/collection_type_loader.rs index 2c0669fc..67ebd8be 100644 --- a/crates/coordinator/core_schema/src/collection_type_loader.rs +++ b/crates/coordinator/core_schema/src/collection_type_loader.rs @@ -10,7 +10,7 @@ use shared_types_holon::{MapBoolean, MapInteger, MapString}; use crate::core_schema_types::SchemaNamesTrait; // use crate::core_schema_types::CoreSchemaTypeName::HolonType; use crate::holon_type_loader::CoreHolonTypeName; -use crate::property_type_loader::CorePropertyTypeName::{Description, Name}; +// use crate::property_type_loader::CorePropertyTypeName::{Description, Name}; #[derive(Debug)] pub struct CollectionTypeSpec { diff --git a/crates/coordinator/core_schema/src/holon_type_loader.rs b/crates/coordinator/core_schema/src/holon_type_loader.rs index 86725f2c..6df1f756 100644 --- a/crates/coordinator/core_schema/src/holon_type_loader.rs +++ b/crates/coordinator/core_schema/src/holon_type_loader.rs @@ -1,6 +1,6 @@ use hdi::prelude::info; use strum_macros::EnumIter; -use descriptors::descriptor_types::CoreSchemaRelationshipTypeName::TargetCollectionType; +// use descriptors::descriptor_types::CoreSchemaRelationshipTypeName::TargetCollectionType; use descriptors::holon_descriptor::{define_holon_type, HolonTypeDefinition}; use descriptors::type_descriptor::TypeDescriptorDefinition; use holons::context::HolonsContext; @@ -9,7 +9,6 @@ use holons::holon_reference::HolonReference; use holons::staged_reference::StagedReference; use shared_types_holon::{MapBoolean, MapString}; use crate::core_schema_types::{SchemaNamesTrait}; -use crate::holon_type_loader::CoreHolonTypeName::HolonType; // use crate::holon_type_loader::CoreHolonTypeName::{DanceRequestType, DanceResponseType, HolonSpaceType, HolonType, PropertyType, RelationshipType, SchemaType}; use crate::property_type_loader::CorePropertyTypeName; use crate::property_type_loader::CorePropertyTypeName::{Description, DescriptorName, Name, TypeName}; diff --git a/crates/coordinator/core_schema/src/loader.rs b/crates/coordinator/core_schema/src/loader.rs index 38de9e16..9fd81068 100644 --- a/crates/coordinator/core_schema/src/loader.rs +++ b/crates/coordinator/core_schema/src/loader.rs @@ -1,5 +1,5 @@ use hdi::prelude::debug; -use holons::{commit_manager, holon_space}; + use strum::IntoEnumIterator; use hdk::prelude::info; use holons::commit_manager::{CommitManager, CommitResponse}; @@ -13,7 +13,7 @@ use shared_types_holon::{MapString, PropertyName}; use descriptors::descriptor_types::{CoreSchemaName, Schema}; use holons::holon::Holon; -use holons::holon_api::get_all_holons; +// use holons::holon_api::get_all_holons; use holons::json_adapter::as_json; use crate::boolean_value_type_loader::CoreBooleanValueTypeName; // use descriptors::holon_descriptor::{define_holon_type}; @@ -26,7 +26,7 @@ use crate::enum_type_loader::CoreEnumTypeName; // use crate::string_value_type_loader::CoreStringValueTypeName; // use crate::enum_type_loader::CoreEnumTypeName; // use crate::holon_type_loader::CoreHolonTypeName; -use crate::holon_type_loader::CoreHolonTypeName::HolonType; +// use crate::holon_type_loader::CoreHolonTypeName::HolonType; use crate::integer_value_type_loader::CoreIntegerValueTypeName; use crate::meta_type_loader::CoreMetaTypeName; use crate::property_type_loader::CorePropertyTypeName; diff --git a/crates/coordinator/core_schema/src/relationship_type_loader.rs b/crates/coordinator/core_schema/src/relationship_type_loader.rs index 4d6245ba..06a5e7ec 100644 --- a/crates/coordinator/core_schema/src/relationship_type_loader.rs +++ b/crates/coordinator/core_schema/src/relationship_type_loader.rs @@ -1,8 +1,8 @@ use hdi::prelude::info; -use holons::smart_reference::SmartReference; +// use holons::smart_reference::SmartReference; use inflector::cases::screamingsnakecase::to_screaming_snake_case; use strum_macros::EnumIter; -use descriptors::descriptor_types::CoreSchemaRelationshipTypeName::CollectionFor; +// use descriptors::descriptor_types::CoreSchemaRelationshipTypeName::CollectionFor; // use inflector::cases::snakecase::to_snake_case; use descriptors::descriptor_types::DeletionSemantic; use descriptors::holon_descriptor::{define_holon_type, HolonTypeDefinition}; @@ -13,12 +13,12 @@ use holons::holon_error::HolonError; use holons::holon_reference::HolonReference; use holons::relationship::RelationshipName; use holons::staged_reference::StagedReference; -use shared_types_holon::{HolonId, MapBoolean, MapString}; +use shared_types_holon::{MapBoolean, MapString}; use crate::collection_type_loader::CollectionTypeSpec; use crate::core_schema_types::SchemaNamesTrait; use crate::holon_type_loader::CoreHolonTypeName; -use crate::relationship_type_loader::CoreRelationshipTypeName::{Components, DescribedBy, HasSubtype, IsA, OwnedBy, Owns, Predecessor}; -use crate::string_value_type_loader::CoreStringValueTypeName::RelationshipNameType; +// use crate::relationship_type_loader::CoreRelationshipTypeName::{Components, DescribedBy, HasSubtype, IsA, OwnedBy, Owns, Predecessor}; +// use crate::string_value_type_loader::CoreStringValueTypeName::RelationshipNameType; #[derive(Debug, Clone, Default, EnumIter)] pub enum CoreRelationshipTypeName { diff --git a/crates/coordinator/core_schema/src/value_type_loader.rs b/crates/coordinator/core_schema/src/value_type_loader.rs index caca65be..27d3a384 100644 --- a/crates/coordinator/core_schema/src/value_type_loader.rs +++ b/crates/coordinator/core_schema/src/value_type_loader.rs @@ -1,12 +1,11 @@ -use strum_macros::EnumIter; use holons::context::HolonsContext; use holons::holon_error::HolonError; use holons::holon_reference::HolonReference; use holons::staged_reference::StagedReference; use shared_types_holon::MapString; -use crate::boolean_value_type_loader::CoreBooleanValueTypeName; -use crate::core_schema_types::{SchemaNamesTrait}; +use crate::boolean_value_type_loader::CoreBooleanValueTypeName; +use crate::core_schema_types::SchemaNamesTrait; use crate::enum_type_loader::CoreEnumTypeName; use crate::integer_value_type_loader::CoreIntegerValueTypeName; use crate::string_value_type_loader::CoreStringValueTypeName; diff --git a/crates/coordinator/dances/src/dance_request.rs b/crates/coordinator/dances/src/dance_request.rs index caac91ab..cbcdec41 100644 --- a/crates/coordinator/dances/src/dance_request.rs +++ b/crates/coordinator/dances/src/dance_request.rs @@ -77,14 +77,9 @@ impl DanceRequest { dance_name: MapString, dance_type: DanceType, body: RequestBody, - staging_area: StagingArea, - local_holon_space : Option + state: SessionState, ) -> Self { - // Initialize the SessionState with staging_area and local_holon_space - let state = SessionState::new( - staging_area, - local_holon_space, - ); + Self { dance_name, dance_type, diff --git a/crates/coordinator/dances/src/dance_response.rs b/crates/coordinator/dances/src/dance_response.rs index b6b56b74..222693f2 100644 --- a/crates/coordinator/dances/src/dance_response.rs +++ b/crates/coordinator/dances/src/dance_response.rs @@ -60,6 +60,7 @@ impl From for ResponseStatusCode { match error { HolonError::EmptyField(_) => ResponseStatusCode::BadRequest, HolonError::InvalidParameter(_) => ResponseStatusCode::BadRequest, + HolonError::InvalidType(_) => ResponseStatusCode::ServerError, HolonError::HolonNotFound(_) => ResponseStatusCode::NotFound, HolonError::CommitFailure(_) => ResponseStatusCode::ServerError, HolonError::WasmError(_) => ResponseStatusCode::ServerError, @@ -104,13 +105,8 @@ impl DanceResponse { description: MapString, body: ResponseBody, descriptor: Option, - staging_area: StagingArea, - local_holon_space: Option, + state: SessionState, ) -> DanceResponse { - let state = SessionState::new( - staging_area, - local_holon_space.clone() - ); DanceResponse { status_code, description, @@ -122,9 +118,9 @@ impl DanceResponse { /// Restores the session state within the DanceResponse from context. This should always /// be called before returning DanceResponse since the state is intended to be "ping-ponged" /// between client and guest. + /// NOTE: Errors in restoring the state are not handled (i.e., will cause panic) pub fn restore_state(&mut self, context: &HolonsContext) { self.state.set_staging_area(StagingArea::from_commit_manager(&context.commit_manager.borrow())); - self.state.set_local_holon_space(context.local_holon_space.borrow().clone()); + self.state.set_local_holon_space(context.get_local_holon_space()); } - } diff --git a/crates/coordinator/dances/src/dancer.rs b/crates/coordinator/dances/src/dancer.rs index f211f8af..261e1748 100644 --- a/crates/coordinator/dances/src/dancer.rs +++ b/crates/coordinator/dances/src/dancer.rs @@ -1,35 +1,37 @@ -use std::cell::Ref; use std::collections::HashMap; use hdk::prelude::*; //use hdi::map_extern::ExternResult; use crate::dance_request::DanceRequest; -use holons::cache_manager::HolonCacheManager; use holons::context::HolonsContext; use holons::holon::Holon; use holons::holon_error::HolonError; use holons::holon_reference::HolonReference; use holons::holon_space; +use holons::holon_space::HolonSpace; +use holons::holon_space_manager::HolonSpaceManager; use shared_types_holon::MapString; use crate::dance_response::{DanceResponse, ResponseBody, ResponseStatusCode}; use crate::descriptors_dance_adapter::*; use crate::holon_dance_adapter::*; +use crate::session_state::SessionState; -use crate::staging_area::StagingArea; +// use crate::staging_area::StagingArea; /// The Dancer handles dance() requests on the uniform API and dispatches the Rust function /// associated with that Dance using its dispatch_table. dance() is also responsible for -/// initializing the context (including converting the StagingArea into CommitManager) and, -/// after getting the result of the call, converting the CommitManager back into StagingArea. +/// initializing the context from the session state and, after getting the result of the call, +/// restoring the session state from the context. /// /// This function always returns a DanceResponse (instead of an Error) because /// errors are encoded in the DanceResponse's status_code. - #[hdk_extern] pub fn dance(request: DanceRequest) -> ExternResult { info!("Entered Dancer::dance() with {:#?}", request); + +// -------------------------- ENSURE VALID REQUEST--------------------------------- let valid = true; // TODO: Validate the dance request if !valid { @@ -38,27 +40,31 @@ pub fn dance(request: DanceRequest) -> ExternResult { MapString("Invalid Request".to_string()), ResponseBody::None, None, - request.get_state().get_staging_area().clone(), - request.get_state().get_local_holon_space().clone()); + request.get_state().clone(), + ); return Ok(response); } - let mut context = request.init_context_from_state(); - - match context.get_local_holon_space().borrow() { - &_ => {} - } + let context = request.init_context_from_state(); + let holon_space_manager = HolonSpaceManager::new(&context); - // If there is no HolonSpace, create one - let holon_space = holon_space::HolonSpace::new(Holon::new()); + // ------------------ ENSURE LOCAL HOLON SPACE IS IN CONTEXT --------------------------------- + let space_reference = holon_space_manager.ensure_local_holon_space_in_context(); + if let Err(space_error) = space_reference { + let error_message = extract_error_message(&space_error); - context.local_holon_space = HolonReference::Staged(context - .commit_manager - .borrow_mut() - .stage_new_holon(holon_space.into_holon()) - ?); + // Construct DanceResponse with error details + let response = DanceResponse { + status_code: ResponseStatusCode::from(space_error), // Convert HolonError to ResponseStatusCode + description: MapString(error_message), + body: ResponseBody::None, // No body since it's an error + descriptor: None, // Provide appropriate value if needed + state: SessionState::restore_session_state_from_context(&context), + }; + return Ok(response) + } // Get the Dancer let dancer = Dancer::new(); @@ -76,10 +82,8 @@ pub fn dance(request: DanceRequest) -> ExternResult { info!("dispatching dance"); let dispatch_result = dancer.dispatch(&context, request); - let mut result = process_dispatch_result(dispatch_result); + let mut result = process_dispatch_result(&context, dispatch_result); - // Restore the SessionState from the context - result.restore_state(*context); // assert_eq!(result.staging_area.staged_holons.len(), context.commit_manager.borrow().staged_holons.len()); info!( @@ -176,15 +180,17 @@ impl Dancer { /// * `status_code` is set to Ok, /// * `description` is set to "Success". /// * `body` is set to the body returned in the dispatch_result -/// * `descriptor`, and `staging_area` are all initialized to None +/// * `descriptor` is all initialized to None +/// * `state` is restored from context /// /// If the `dispatch_result` is `Err`, -/// * status_code is set from the mapping of HolonError `ResponseStatusCode` +/// * `status_code` is set from the mapping of HolonError `ResponseStatusCode` /// * `description` holds the error message associated with the HolonError -/// * `body`, `descriptor` and `staging_area` are all set to None +/// * `body` and `descriptor` are set to None +/// * `state` is restored from context /// -fn process_dispatch_result(dispatch_result: Result) -> DanceResponse { +fn process_dispatch_result(context: &HolonsContext, dispatch_result: Result) -> DanceResponse { match dispatch_result { Ok(body) => { // If the dispatch_result is Ok, construct DanceResponse with appropriate fields @@ -192,34 +198,12 @@ fn process_dispatch_result(dispatch_result: Result) -> status_code: ResponseStatusCode::OK, description: MapString("Success".to_string()), body, - descriptor: None, // Provide appropriate value if needed - staging_area: StagingArea::new(), // Provide appropriate value if needed + descriptor: None, + state: SessionState::restore_session_state_from_context(context), } } Err(error) => { - // If the dispatch_result is an error, extract the associated string value - let error_message = match error.clone() { - HolonError::EmptyField(_) - | HolonError::InvalidParameter(_) - | HolonError::HolonNotFound(_) - | HolonError::CommitFailure(_) - | HolonError::WasmError(_) - | HolonError::RecordConversion(_) - | HolonError::InvalidHolonReference(_) - | HolonError::IndexOutOfRange(_) - | HolonError::NotImplemented(_) - | HolonError::Misc(_) - | HolonError::MissingStagedCollection(_) - | HolonError::FailedToBorrow(_) - | HolonError::UnableToAddHolons(_) - | HolonError::InvalidRelationship(_, _) - | HolonError::NotAccessible(_, _) - | HolonError::UnexpectedValueType(_, _) - | HolonError::Utf8Conversion(_, _) - | HolonError::HashConversion(_, _) - | HolonError::CacheError(_) => error.to_string(), - HolonError::ValidationError(validation_error) => validation_error.to_string(), - }; + let error_message = extract_error_message(&error); // Construct DanceResponse with error details DanceResponse { @@ -227,8 +211,37 @@ fn process_dispatch_result(dispatch_result: Result) -> description: MapString(error_message), body: ResponseBody::None, // No body since it's an error descriptor: None, // Provide appropriate value if needed - staging_area: StagingArea::new(), // Provide appropriate value if needed + state: SessionState::restore_session_state_from_context(context), } } } } +/// This helper function extracts the error message from a HolonError so that the message +/// can be included in the DanceResponse +fn extract_error_message(error:&HolonError)->String { + match error.clone() { + HolonError::EmptyField(_) + | HolonError::InvalidParameter(_) + | HolonError::HolonNotFound(_) + | HolonError::CommitFailure(_) + | HolonError::WasmError(_) + | HolonError::RecordConversion(_) + | HolonError::InvalidHolonReference(_) + | HolonError::InvalidType(_) + | HolonError::IndexOutOfRange(_) + | HolonError::NotImplemented(_) + | HolonError::Misc(_) + | HolonError::MissingStagedCollection(_) + | HolonError::FailedToBorrow(_) + | HolonError::UnableToAddHolons(_) + | HolonError::InvalidRelationship(_, _) + | HolonError::NotAccessible(_, _) + | HolonError::UnexpectedValueType(_, _) + | HolonError::Utf8Conversion(_, _) + | HolonError::HashConversion(_, _) + | HolonError::CacheError(_) => error.to_string(), + HolonError::ValidationError(validation_error) => validation_error.to_string(), + + } +} + diff --git a/crates/coordinator/dances/src/descriptors_dance_adapter.rs b/crates/coordinator/dances/src/descriptors_dance_adapter.rs index 33a4e178..6dface0b 100644 --- a/crates/coordinator/dances/src/descriptors_dance_adapter.rs +++ b/crates/coordinator/dances/src/descriptors_dance_adapter.rs @@ -15,25 +15,19 @@ //! mapping any errors into an appropriate ResponseStatus and returning results in the body. -use std::borrow::Borrow; -use std::rc::Rc; + + use hdk::prelude::*; use holons::commit_manager::CommitRequestStatus::*; -use holons::commit_manager::{CommitManager, StagedIndex}; use holons::context::HolonsContext; -use holons::holon::Holon; use holons::holon_error::HolonError; -use holons::holon_reference::HolonReference; use core_schema::loader::load_core_schema; -use holons::relationship::RelationshipName; use shared_types_holon::{MapString, MapInteger, PropertyMap}; use shared_types_holon::HolonId; - - - use crate::dance_request::{DanceRequest, DanceType,RequestBody}; use crate::dance_response::ResponseBody; +use crate::session_state::SessionState; use crate::staging_area::StagingArea; /// *DanceRequest:* @@ -71,9 +65,9 @@ pub fn load_core_schema_dance(context: &HolonsContext, request: DanceRequest) -> pub fn build_load_core_schema_dance_request( - staging_area: StagingArea, + session_state:&SessionState, )->Result { let body = RequestBody::new(); - Ok(DanceRequest::new(MapString("load_core_schema".to_string()), DanceType::Standalone,body, staging_area)) + Ok(DanceRequest::new(MapString("load_core_schema".to_string()), DanceType::Standalone,body, session_state.clone())) } diff --git a/crates/coordinator/dances/src/holon_dance_adapter.rs b/crates/coordinator/dances/src/holon_dance_adapter.rs index b85b727a..53ee501c 100644 --- a/crates/coordinator/dances/src/holon_dance_adapter.rs +++ b/crates/coordinator/dances/src/holon_dance_adapter.rs @@ -28,6 +28,7 @@ use shared_types_holon::{MapString, PropertyMap}; use crate::dance_request::{DanceRequest, DanceType, RequestBody}; use crate::dance_response::ResponseBody; +use crate::session_state::SessionState; use crate::staging_area::StagingArea; /// *DanceRequest:* @@ -153,7 +154,7 @@ pub fn remove_related_holons_dance( /// Builds a DanceRequest for removing related holons to a source_holon. pub fn build_remove_related_holons_dance_request( - staging_area: StagingArea, + session_state: SessionState, index: StagedIndex, relationship_name: RelationshipName, holons_to_remove: Vec, @@ -163,7 +164,7 @@ pub fn build_remove_related_holons_dance_request( MapString("remove_related_holons".to_string()), DanceType::CommandMethod(index), body, - staging_area, + session_state, )) } @@ -171,7 +172,7 @@ pub fn build_remove_related_holons_dance_request( /// /// Builds a DanceRequest for adding related holons to a source_holon. pub fn build_add_related_holons_dance_request( - staging_area: StagingArea, + session_state: &SessionState, index: StagedIndex, relationship_name: RelationshipName, holons_to_add: Vec, @@ -181,7 +182,7 @@ pub fn build_add_related_holons_dance_request( MapString("add_related_holons".to_string()), DanceType::CommandMethod(index), body, - staging_area, + session_state.clone(), )) } @@ -273,7 +274,7 @@ pub fn query_relationships_dance( /// Builds a DanceRequest for getting related holons optionally filtered by relationship name. pub fn build_query_relationships_dance_request( - staging_area: StagingArea, + session_state: &SessionState, node_collection: NodeCollection, query_expression: QueryExpression, ) -> Result { @@ -282,7 +283,7 @@ pub fn build_query_relationships_dance_request( MapString("query_relationships".to_string()), DanceType::QueryMethod(node_collection), body, - staging_area, + session_state.clone(), )) } @@ -301,7 +302,7 @@ pub fn stage_new_holon_dance( context: &HolonsContext, request: DanceRequest, ) -> Result { - debug!("== Entered staged new holon dance =="); + debug!("== Entered stage new holon dance =="); // Create and stage new Holon let mut new_holon = Holon::new(); @@ -341,7 +342,7 @@ pub fn stage_new_holon_dance( /// Builds a DanceRequest for staging a new holon. Properties, if supplied, they will be included /// in the body of the request. // pub fn build_stage_new_holon_dance_request( -// staging_area: StagingArea, +// session_state: &SessionState, // properties: PropertyMap, // ) -> Result { // let body = RequestBody::new_parameter_values(properties); @@ -349,11 +350,11 @@ pub fn stage_new_holon_dance( // MapString("stage_new_holon".to_string()), // DanceType::Standalone, // body, -// staging_area, +// session_state.clone(), // )) // } pub fn build_stage_new_holon_dance_request( - staging_area: StagingArea, + session_state: &SessionState, holon: Holon, ) -> Result { let body = RequestBody::new_holon(holon); @@ -361,7 +362,7 @@ pub fn build_stage_new_holon_dance_request( MapString("stage_new_holon".to_string()), DanceType::Standalone, body, - staging_area, + session_state.clone(), )) } @@ -424,7 +425,7 @@ pub fn with_properties_dance( /// Builds a DanceRequest for adding a new property value(s) to an already staged holon. pub fn build_with_properties_dance_request( - staging_area: StagingArea, + session_state: &SessionState, index: StagedIndex, properties: PropertyMap, ) -> Result { @@ -434,7 +435,7 @@ pub fn build_with_properties_dance_request( MapString("with_properties".to_string()), DanceType::CommandMethod(index), body, - staging_area, + session_state.clone(), )) } @@ -467,14 +468,14 @@ pub fn get_all_holons_dance( /// Builds a DanceRequest for retrieving all holons from the persistent store pub fn build_get_all_holons_dance_request( - staging_area: StagingArea, + session_state: &SessionState, ) -> Result { let body = RequestBody::new(); Ok(DanceRequest::new( MapString("get_all_holons".to_string()), DanceType::Standalone, body, - staging_area, + session_state.clone(), )) } @@ -514,7 +515,7 @@ pub fn get_holon_by_id_dance( /// Builds a DanceRequest for retrieving holon by HolonId from the persistent store pub fn build_get_holon_by_id_dance_request( - staging_area: StagingArea, + session_state: &SessionState, holon_id: HolonId, ) -> Result { let body = RequestBody::HolonId(holon_id); @@ -522,7 +523,7 @@ pub fn build_get_holon_by_id_dance_request( MapString("get_holon_by_id".to_string()), DanceType::Standalone, body, - staging_area, + session_state.clone(), )) } @@ -560,13 +561,13 @@ pub fn commit_dance( /// /// Builds a DanceRequest for staging a new holon. Properties, if supplied, they will be included /// in the body of the request. -pub fn build_commit_dance_request(staging_area: StagingArea) -> Result { +pub fn build_commit_dance_request(session_state: &SessionState) -> Result { let body = RequestBody::None; Ok(DanceRequest::new( MapString("commit".to_string()), DanceType::Standalone, body, - staging_area, + session_state.clone(), )) } /// Abandon staged changes @@ -615,7 +616,7 @@ pub fn abandon_staged_changes_dance( /// /// Builds a DanceRequest for abandoning changes to a staged Holon. pub fn build_abandon_staged_changes_dance_request( - staging_area: StagingArea, + session_state: &SessionState, index: StagedIndex, ) -> Result { let body = RequestBody::None; @@ -623,7 +624,7 @@ pub fn build_abandon_staged_changes_dance_request( MapString("abandon_staged_changes".to_string()), DanceType::CommandMethod(index), body, - staging_area, + session_state.clone(), )) } diff --git a/crates/coordinator/dances/src/session_state.rs b/crates/coordinator/dances/src/session_state.rs index f62b45d3..70e8f9c8 100644 --- a/crates/coordinator/dances/src/session_state.rs +++ b/crates/coordinator/dances/src/session_state.rs @@ -7,8 +7,6 @@ use hdi::hdk_entry_helper; use holons::cache_manager::HolonCacheManager; use holons::context::HolonsContext; use holons::holon_reference::HolonReference; -use holons::smart_reference::SmartReference; -use shared_types_holon::{HolonId, HolonSpaceId, LocalId}; use crate::staging_area::StagingArea; /// SessionState provides a way to distinguish information associated with a specific request from @@ -19,12 +17,18 @@ use crate::staging_area::StagingArea; #[derive(Clone, Eq, PartialEq)] pub struct SessionState { staging_area : StagingArea, - local_holon_space: Option, + local_holon_space: Option, } impl SessionState { + pub fn empty() -> Self { + Self { + staging_area: StagingArea::empty(), + local_holon_space: None, + } + } pub fn new(staging_area: StagingArea, - local_holon_space: Option, + local_holon_space: Option, ) -> Self { Self { @@ -32,16 +36,19 @@ impl SessionState { local_holon_space, } } - pub fn get_local_holon_space(&self) -> Option { + pub fn get_local_holon_space(&self) -> Option { self.local_holon_space.clone() } pub fn get_staging_area(&self) -> &StagingArea { &self.staging_area } + pub fn get_staging_area_mut(&mut self) -> &mut StagingArea { + &mut self.staging_area + } pub fn init_context_from_state(&self)-> HolonsContext { let commit_manager = self.staging_area.to_commit_manager(); - let local_holon_space = self.get_local_holon_space_reference(); + let local_holon_space = self.get_local_holon_space(); //info!("initializing context"); HolonsContext::init_context( commit_manager, @@ -50,23 +57,29 @@ impl SessionState { ) } - /// This function constructs a (Smart variant) of a HolonReference to the HolonSpace from the - /// holon space id stored in SessionState (or None, if local_holon_space is None) - fn get_local_holon_space_reference(&self) -> Option { - // Check if local_holon_space is Some, then construct a HolonReference - self.local_holon_space.as_ref().map(|holon_space_id| { - // Convert HolonSpaceId to LocalId - let local_id = LocalId::from(holon_space_id.0.clone()); - - // Create the SmartReference with the Local variant of HolonId (no smart properties) - let smart_reference = SmartReference::new(HolonId::Local(local_id),None); - - // Return a HolonReference::Smart variant - HolonReference::Smart(smart_reference) - }) + pub fn restore_session_state_from_context(context: &HolonsContext) -> SessionState { + SessionState::new( + StagingArea::from_commit_manager(&context.commit_manager.borrow()), + context.get_local_holon_space(), + ) } + // /// This function constructs a (Smart variant) of a HolonReference to the HolonSpace from the + // /// holon space id stored in SessionState (or None, if local_holon_space is None) + // fn get_local_holon_space_reference(&self) -> Option { + // // Check if local_holon_space is Some, then construct a HolonReference + // self.local_holon_space.as_ref().map(|holon_space_id| { + // // Convert HolonSpaceId to LocalId + // let local_id = LocalId::from(holon_space_id.0.clone()); + // + // // Create the SmartReference with the Local variant of HolonId (no smart properties) + // let smart_reference = SmartReference::new(HolonId::Local(local_id),None); + // + // // Return a HolonReference::Smart variant + // HolonReference::Smart(smart_reference) + // }) + // } - pub fn set_local_holon_space(&mut self, local_holon_space: Option) { + pub fn set_local_holon_space(&mut self, local_holon_space: Option) { self.local_holon_space = local_holon_space; } pub fn set_staging_area(&mut self, staging_area: StagingArea) { diff --git a/crates/coordinator/dances/src/staging_area.rs b/crates/coordinator/dances/src/staging_area.rs index 1841a8da..215fe2c5 100644 --- a/crates/coordinator/dances/src/staging_area.rs +++ b/crates/coordinator/dances/src/staging_area.rs @@ -2,10 +2,9 @@ use std::cell::RefCell; use std::collections::BTreeMap; use std::rc::Rc; use hdk::prelude::*; -use holons::commit_manager::{CommitManager, StagedIndex}; -use holons::holon::{Holon, HolonState}; +use holons::commit_manager::{CommitManager}; +use holons::holon::{Holon}; use holons::holon_error::HolonError; -use holons::staged_reference::StagedReference; use shared_types_holon::{MapString}; #[hdk_entry_helper] @@ -17,7 +16,7 @@ pub struct StagingArea { impl StagingArea { - pub fn new()->Self { + pub fn empty()->Self { StagingArea { staged_holons: Vec::new(), index: BTreeMap::new(), diff --git a/crates/coordinator/dances/tests/shared_test/dance_fixtures.rs b/crates/coordinator/dances/tests/shared_test/dance_fixtures.rs index 3d55f874..82dbb700 100644 --- a/crates/coordinator/dances/tests/shared_test/dance_fixtures.rs +++ b/crates/coordinator/dances/tests/shared_test/dance_fixtures.rs @@ -50,9 +50,11 @@ pub fn simple_create_test_fixture() -> Result { ); let mut expected_holons = Vec::new(); + // Set initial expected_database_count to 1 (to account for the HolonSpace Holon) + let mut expected_count:i64 = 1; // Ensure DB count // - test_case.add_ensure_database_count_step(MapInteger(0))?; + test_case.add_ensure_database_count_step(MapInteger(expected_count))?; // Create book Holon with properties // let mut book_holon = Holon::new(); @@ -72,6 +74,7 @@ pub fn simple_create_test_fixture() -> Result { //// Stage Holons & add properties test_case.add_stage_holon_step(book_holon.clone())?; expected_holons.push(book_holon.clone()); + expected_count += 1; let mut properties = PropertyMap::new(); properties.insert( @@ -84,6 +87,7 @@ pub fn simple_create_test_fixture() -> Result { let person_holon = Holon::new(); test_case.add_stage_holon_step(person_holon.clone())?; expected_holons.push(person_holon.clone()); + expected_count += 1; let mut properties = PropertyMap::new(); properties.insert( @@ -100,7 +104,7 @@ pub fn simple_create_test_fixture() -> Result { // Commit, match content, & ensure DB count again // test_case.add_commit_step()?; test_case.add_match_saved_content_step()?; - test_case.add_ensure_database_count_step(MapInteger(2))?; + test_case.add_ensure_database_count_step(MapInteger(expected_count))?; Ok(test_case.clone()) } @@ -113,8 +117,12 @@ pub fn simple_add_remove_related_holons_fixture() -> Result Result Result Result Author H2 & H3 // @@ -292,7 +303,8 @@ pub fn simple_add_remove_related_holons_fixture() -> Result Result = Vec::new(); @@ -326,6 +342,7 @@ pub fn simple_abandon_staged_changes_fixture() -> Result Result H3 // // Attempt add_related_holon dance -- expect Conflict/NotAccessible response @@ -352,7 +370,7 @@ pub fn simple_abandon_staged_changes_fixture() -> Result Result Result Result { //let mut expected_holons = Vec::new(); - test_case.add_ensure_database_count_step(MapInteger(0))?; + test_case.add_ensure_database_count_step(MapInteger(1))?; test_case.add_load_core_schema()?; diff --git a/crates/coordinator/dances/tests/shared_test/test_abandon_staged_changes.rs b/crates/coordinator/dances/tests/shared_test/test_abandon_staged_changes.rs index 233a85dc..b74d16b9 100644 --- a/crates/coordinator/dances/tests/shared_test/test_abandon_staged_changes.rs +++ b/crates/coordinator/dances/tests/shared_test/test_abandon_staged_changes.rs @@ -44,7 +44,7 @@ pub async fn execute_abandon_staged_changes( ) { info!("\n\n--- TEST STEP: Abandon Staged Changes ---"); let request = build_abandon_staged_changes_dance_request( - test_state.staging_area.clone(), + &test_state.session_state, staged_index.clone(), ); @@ -55,7 +55,7 @@ pub async fn execute_abandon_staged_changes( let response: DanceResponse = conductor .call(&cell.zome("dances"), "dance", valid_request) .await; - test_state.staging_area = response.staging_area.clone(); + test_state.session_state = response.state.clone(); assert_eq!(response.status_code, expected_response); @@ -66,7 +66,7 @@ pub async fn execute_abandon_staged_changes( // Dance response was OK, confirm that operations disallowed for Holons in an // Abandoned state return NotAccessible error. if let ResponseBody::Index(staged_index) = response.body.clone() { - match test_state.staging_area.get_holon_mut(staged_index) { + match test_state.session_state.get_staging_area_mut().get_holon_mut(staged_index) { Ok(abandoned_holon) => { // NOTE: We changed the access policies to ALLOW read access to // Abandoned holons, so disabling the following two checks diff --git a/crates/coordinator/dances/tests/shared_test/test_add_related_holon.rs b/crates/coordinator/dances/tests/shared_test/test_add_related_holon.rs index 90a1a166..a6cca425 100644 --- a/crates/coordinator/dances/tests/shared_test/test_add_related_holon.rs +++ b/crates/coordinator/dances/tests/shared_test/test_add_related_holon.rs @@ -53,7 +53,8 @@ pub async fn execute_add_related_holons( // Get the state of the holon prior to dancing the request let source_holon = test_state - .staging_area + .session_state + .get_staging_area() .staged_holons .get(source_holon_index); if source_holon.is_none() { @@ -68,7 +69,7 @@ pub async fn execute_add_related_holons( // Build the DanceRequest let request = build_add_related_holons_dance_request( - test_state.staging_area.clone(), + &test_state.session_state, source_holon_index, relationship_name, holons_to_add, @@ -83,7 +84,7 @@ pub async fn execute_add_related_holons( info!("Dance Response: {:#?}", response.clone()); let code = response.status_code; - test_state.staging_area = response.staging_area.clone(); + test_state.session_state = response.state.clone(); assert_eq!(code, expected_response); info!( @@ -98,7 +99,7 @@ pub async fn execute_add_related_holons( // An index was returned in the body, retrieve the Holon at that index within // the StagingArea and confirm it matches the expected Holon. - let source_holon = response.staging_area.staged_holons[index].clone(); + let source_holon = response.state.get_staging_area().staged_holons[index].clone(); assert_eq!(expected_holon, source_holon); diff --git a/crates/coordinator/dances/tests/shared_test/test_commit.rs b/crates/coordinator/dances/tests/shared_test/test_commit.rs index a506abb3..d531c382 100644 --- a/crates/coordinator/dances/tests/shared_test/test_commit.rs +++ b/crates/coordinator/dances/tests/shared_test/test_commit.rs @@ -37,7 +37,7 @@ pub async fn execute_commit(conductor: &SweetConductor, cell: &SweetCell, test_s // Build a commit DanceRequest - let request = build_commit_dance_request(test_state.staging_area.clone()); + let request = build_commit_dance_request(&test_state.session_state); debug!("Dance Request: {:#?}", request); match request { @@ -47,12 +47,12 @@ pub async fn execute_commit(conductor: &SweetConductor, cell: &SweetCell, test_s .await; debug!("Dance Response: {:#?}", response.clone()); - test_state.staging_area = response.staging_area.clone(); + test_state.session_state = response.state.clone(); let code = response.status_code; let description = response.description.clone(); if code == ResponseStatusCode::OK { // Check that staging area is empty - assert!(response.staging_area.staged_holons.is_empty()); + assert!(response.state.get_staging_area().staged_holons.is_empty()); info!("Success! Commit succeeded"); diff --git a/crates/coordinator/dances/tests/shared_test/test_data_types.rs b/crates/coordinator/dances/tests/shared_test/test_data_types.rs index d487f0a3..9cc7d727 100644 --- a/crates/coordinator/dances/tests/shared_test/test_data_types.rs +++ b/crates/coordinator/dances/tests/shared_test/test_data_types.rs @@ -9,6 +9,7 @@ use holons::relationship::RelationshipName; use shared_types_holon::{HolonId, MapInteger, MapString, PropertyMap, PropertyValue}; use std::collections::VecDeque; use std::fmt; +use dances::session_state::SessionState; #[derive(Clone, Debug)] pub struct DancesTestCase { @@ -110,14 +111,14 @@ impl fmt::Display for DanceTestStep { } pub struct DanceTestState { - pub staging_area: StagingArea, + pub session_state: SessionState, pub created_holons: Vec, } impl DanceTestState { pub fn new() -> DanceTestState { DanceTestState { - staging_area: StagingArea::new(), + session_state: SessionState::empty(), created_holons: Vec::new(), } } diff --git a/crates/coordinator/dances/tests/shared_test/test_ensure_database_count.rs b/crates/coordinator/dances/tests/shared_test/test_ensure_database_count.rs index 3d9e3f49..ce647aa9 100644 --- a/crates/coordinator/dances/tests/shared_test/test_ensure_database_count.rs +++ b/crates/coordinator/dances/tests/shared_test/test_ensure_database_count.rs @@ -40,9 +40,10 @@ pub async fn execute_ensure_database_count( ) { let expected_count_string = expected_count.0.to_string(); + let actual_count_string = "0".to_string(); info!("\n\n--- TEST STEP: Ensuring database holds {expected_count_string} holons ---"); // Build a get_all_holons DanceRequest - let request = build_get_all_holons_dance_request(test_state.staging_area.clone()); + let request = build_get_all_holons_dance_request(&test_state.session_state); debug!("Dance Request: {:#?}", request); match request { @@ -50,18 +51,19 @@ pub async fn execute_ensure_database_count( let response: DanceResponse = conductor .call(&cell.zome("dances"), "dance", valid_request) .await; - test_state.staging_area = response.staging_area.clone(); + test_state.session_state = response.state; if let Holons(holons) = response.body.clone() { - assert_eq!(expected_count, MapInteger(holons.len() as i64)); - let actual_count = holons.len().to_string(); + let actual_count = MapInteger(holons.len() as i64); + assert_eq!(expected_count, actual_count); + let actual_count_string = actual_count.0.to_string(); - info!("Success! DB has {actual_count} holons, as expected"); + info!("Success! DB has {actual_count_string} holons, as expected"); } else { panic!( - "Expected get_all_holons to return Holons response, but it returned {:?}", - response.body + "Expected get_all_holons to return {:?} holons, but it returned {:?}", + expected_count_string,actual_count_string ); } } diff --git a/crates/coordinator/dances/tests/shared_test/test_load_core_schema.rs b/crates/coordinator/dances/tests/shared_test/test_load_core_schema.rs index e6622d3d..140753b0 100644 --- a/crates/coordinator/dances/tests/shared_test/test_load_core_schema.rs +++ b/crates/coordinator/dances/tests/shared_test/test_load_core_schema.rs @@ -41,7 +41,7 @@ pub async fn execute_load_new_schema( info!("\n\n--- TEST STEP: Loading Core Schema:"); // println!("{:#?}", expected_holon.clone()); // Build a stage_holon DanceRequest - let request = build_load_core_schema_dance_request(test_state.staging_area.clone()); + let request = build_load_core_schema_dance_request(&test_state.session_state); debug!("Dance Request: {:#?}", request); match request { @@ -52,7 +52,7 @@ pub async fn execute_load_new_schema( debug!("Dance Response: {:#?}", response.clone()); let code = response.status_code; let description = response.description.clone(); - test_state.staging_area = response.staging_area.clone(); + test_state.session_state = response.state.clone(); if let ResponseStatusCode::OK = code { if let ResponseBody::None = response.body.clone() { info!("Success! Load Schema Completed without error"); diff --git a/crates/coordinator/dances/tests/shared_test/test_match_db_content.rs b/crates/coordinator/dances/tests/shared_test/test_match_db_content.rs index fa608cdf..5ae08eef 100644 --- a/crates/coordinator/dances/tests/shared_test/test_match_db_content.rs +++ b/crates/coordinator/dances/tests/shared_test/test_match_db_content.rs @@ -44,7 +44,7 @@ pub async fn execute_match_db_content( let holon_id : HolonId= expected_holon.get_local_id().unwrap().into(); // Build a get_holon_by_id DanceRequest let request = - build_get_holon_by_id_dance_request(test_state.staging_area.clone(), holon_id.clone()); + build_get_holon_by_id_dance_request(&test_state.session_state, holon_id.clone()); info!("Dance Request: {:#?}", request); match request { @@ -52,7 +52,7 @@ pub async fn execute_match_db_content( let response: DanceResponse = conductor .call(&cell.zome("dances"), "dance", valid_request) .await; - test_state.staging_area = response.staging_area.clone(); + test_state.session_state = response.state.clone(); if let ResponseBody::Holon(actual_holon) = response.body.clone() { assert_eq!( diff --git a/crates/coordinator/dances/tests/shared_test/test_print_database.rs b/crates/coordinator/dances/tests/shared_test/test_print_database.rs index de9457e7..8a109baf 100644 --- a/crates/coordinator/dances/tests/shared_test/test_print_database.rs +++ b/crates/coordinator/dances/tests/shared_test/test_print_database.rs @@ -42,7 +42,7 @@ pub async fn execute_database_print( info!("\n\n--- TEST STEP: print database contents ---"); // Build a get_all_holons DanceRequest - let request = build_get_all_holons_dance_request(test_state.staging_area.clone()); + let request = build_get_all_holons_dance_request(&test_state.session_state); debug!("Dance Request: {:#?}", request); match request { @@ -50,7 +50,7 @@ pub async fn execute_database_print( let response: DanceResponse = conductor .call(&cell.zome("dances"), "dance", valid_request) .await; - test_state.staging_area = response.staging_area.clone(); + test_state.session_state = response.state.clone(); if let Holons(holons) = response.body.clone() { let actual_count = holons.len().to_string(); diff --git a/crates/coordinator/dances/tests/shared_test/test_query_relationships.rs b/crates/coordinator/dances/tests/shared_test/test_query_relationships.rs index 2d246a37..cf3cc742 100644 --- a/crates/coordinator/dances/tests/shared_test/test_query_relationships.rs +++ b/crates/coordinator/dances/tests/shared_test/test_query_relationships.rs @@ -57,7 +57,7 @@ pub async fn execute_query_relationships( }; let request = build_query_relationships_dance_request( - test_state.staging_area.clone(), + &test_state.session_state, node_collection, query_expression, ); @@ -71,7 +71,7 @@ pub async fn execute_query_relationships( debug!("Dance Response: {:#?}", response.clone()); let code = response.status_code; let description = response.description.clone(); - test_state.staging_area = response.staging_area.clone(); + test_state.session_state = response.state.clone(); if let ResponseStatusCode::OK = code { if let Collection(_node_collection) = response.body { diff --git a/crates/coordinator/dances/tests/shared_test/test_remove_related_holon.rs b/crates/coordinator/dances/tests/shared_test/test_remove_related_holon.rs index bdc94006..05144db1 100644 --- a/crates/coordinator/dances/tests/shared_test/test_remove_related_holon.rs +++ b/crates/coordinator/dances/tests/shared_test/test_remove_related_holon.rs @@ -52,7 +52,8 @@ pub async fn execute_remove_related_holons( // Get the state of the holon prior to dancing the request let source_holon = test_state - .staging_area + .session_state + .get_staging_area() .staged_holons .get(source_holon_index); if source_holon.is_none() { @@ -67,7 +68,7 @@ pub async fn execute_remove_related_holons( // Build the DanceRequest let request = build_remove_related_holons_dance_request( - test_state.staging_area.clone(), + test_state.session_state.clone(), source_holon_index, relationship_name, holons_to_remove, @@ -82,7 +83,7 @@ pub async fn execute_remove_related_holons( info!("Dance Response: {:#?}", response.clone()); let code = response.status_code; - test_state.staging_area = response.staging_area.clone(); + test_state.session_state = response.state.clone(); assert_eq!(code, expected_response); info!( @@ -97,7 +98,7 @@ pub async fn execute_remove_related_holons( // An index was returned in the body, retrieve the Holon at that index within // the StagingArea and confirm it matches the expected Holon. - let source_holon = response.staging_area.staged_holons[index].clone(); + let source_holon = response.state.get_staging_area().staged_holons[index].clone(); assert_eq!(expected_holon, source_holon); diff --git a/crates/coordinator/dances/tests/shared_test/test_stage_new_holon.rs b/crates/coordinator/dances/tests/shared_test/test_stage_new_holon.rs index f982d91d..2842eae1 100644 --- a/crates/coordinator/dances/tests/shared_test/test_stage_new_holon.rs +++ b/crates/coordinator/dances/tests/shared_test/test_stage_new_holon.rs @@ -41,7 +41,7 @@ pub async fn execute_stage_new_holon( // println!("{:#?}", expected_holon.clone()); // Build a stage_holon DanceRequest let request = build_stage_new_holon_dance_request( - test_state.staging_area.clone(), + &test_state.session_state, expected_holon.clone(), ); debug!("Dance Request: {:#?}", request); @@ -52,7 +52,7 @@ pub async fn execute_stage_new_holon( .call(&cell.zome("dances"), "dance", valid_request) .await; debug!("Dance Response: {:#?}", response.clone()); - test_state.staging_area = response.staging_area.clone(); + test_state.session_state = response.state.clone(); let code = response.status_code; let description = response.description.clone(); if let ResponseStatusCode::OK = code { @@ -62,7 +62,7 @@ pub async fn execute_stage_new_holon( // An index was returned in the body, retrieve the Holon at that index within // the StagingArea and confirm it matches the expected Holon. - let holons = response.staging_area.staged_holons; + let holons = &response.state.get_staging_area().staged_holons; assert_eq!(expected_holon, holons[index as usize]); info!("Success! Holon has been staged, as expected"); diff --git a/crates/coordinator/dances/tests/shared_test/test_with_properties_command.rs b/crates/coordinator/dances/tests/shared_test/test_with_properties_command.rs index cb0e1006..ca644762 100644 --- a/crates/coordinator/dances/tests/shared_test/test_with_properties_command.rs +++ b/crates/coordinator/dances/tests/shared_test/test_with_properties_command.rs @@ -46,7 +46,7 @@ pub async fn execute_with_properties( info!("\n\n--- TEST STEP: with_properties Command:"); // Get the state of the holon prior to dancing the request debug!("trying to get staged_holon at staged_holon_index: {:#?}", staged_holon_index); - let staged_holon = test_state.staging_area.staged_holons.get(staged_holon_index); + let staged_holon = test_state.session_state.get_staging_area().staged_holons.get(staged_holon_index); match staged_holon { None => { panic!("Unable to get staged_holon from the staging_area"); @@ -57,11 +57,11 @@ pub async fn execute_with_properties( for (property_name, base_value) in properties.clone() { let result = expected_holon.with_property_value(property_name.clone(), base_value.clone()); if let Err(e) = result { - panic!("Unabled to add property value to expected holon, due to: {:#?}", e); + panic!("Unable to add property value to expected holon, due to: {:#?}", e); } } // Build a with_properties DanceRequest - let request = build_with_properties_dance_request(test_state.staging_area.clone(), staged_holon_index, properties.clone()); + let request = build_with_properties_dance_request(&test_state.session_state, staged_holon_index, properties.clone()); debug!("Dance Request: {:#?}", request); match request { @@ -72,7 +72,7 @@ pub async fn execute_with_properties( debug!("Dance Response: {:#?}", response.clone()); let code = response.status_code; let description = response.description.clone(); - test_state.staging_area = response.staging_area.clone(); + test_state.session_state= response.state.clone(); assert_eq!(expected_response,code.clone()); if let ResponseStatusCode::OK = code { @@ -82,7 +82,7 @@ pub async fn execute_with_properties( // An index was returned in the body, retrieve the Holon at that index within // the StagingArea and confirm it matches the expected Holon. - let holons = response.staging_area.staged_holons; + let holons = &response.state.get_staging_area().staged_holons; assert_eq!(expected_holon, holons[index]); diff --git a/crates/coordinator/holons/src/cache_manager.rs b/crates/coordinator/holons/src/cache_manager.rs index cdbe97fd..38b55bf4 100644 --- a/crates/coordinator/holons/src/cache_manager.rs +++ b/crates/coordinator/holons/src/cache_manager.rs @@ -5,7 +5,7 @@ use std::cell::RefCell; use std::collections::HashMap; // use hdk::prelude::*; use quick_cache::unsync::Cache; -use shared_types_holon::{HolonId, HolonSpaceId, ExternalId, LocalId}; +use shared_types_holon::{HolonId, HolonSpaceId, LocalId}; use std::rc::Rc; use shared_types_holon::HolonId::{Local,External}; @@ -16,7 +16,6 @@ pub struct HolonCache(Cache>>); #[derive(Debug)] pub struct HolonCacheManager { pub local_cache: Rc>, - // pub external_caches: HashMap, pub external_caches: HashMap>>, } diff --git a/crates/coordinator/holons/src/commit_manager.rs b/crates/coordinator/holons/src/commit_manager.rs index 39850ac8..ede75c60 100644 --- a/crates/coordinator/holons/src/commit_manager.rs +++ b/crates/coordinator/holons/src/commit_manager.rs @@ -11,7 +11,7 @@ use crate::json_adapter::as_json; use crate::relationship::RelationshipMap; use crate::smart_reference::SmartReference; use crate::staged_reference::StagedReference; -use shared_types_holon::{MapInteger, MapString}; +use shared_types_holon::{LocalId, MapInteger, MapString}; #[derive(Debug, Eq, PartialEq, Clone)] pub struct CommitManager { @@ -29,6 +29,37 @@ pub struct CommitResponse { pub saved_holons: Vec, // should this be index? where else used? pub abandoned_holons: Vec, // should this be index? } +impl CommitResponse { + /// This helper method returns true if the supplied CommitResponse indicates that the commit + /// was complete and false otherwise + pub fn is_complete(&self)->bool { + match self.status { + CommitRequestStatus::Complete => true, + CommitRequestStatus::Incomplete => false, + } + } + pub(crate) fn find_local_id_by_key(&self, k: &MapString) -> Result { + for holon in &self.saved_holons { + if let Some(key) = holon.get_key()? { + // Check if the key matches the given key `k` + if &key == k { + // Return the LocalId if a match is found + return holon.get_local_id(); + } + } + } + // Return an error if no matching Holon is found + Err(HolonError::HolonNotFound( + format!( + "No saved Holon with key {:?} was found in commit response", + k.to_string(), + ), + + )) + } + +} + #[derive(Debug, Eq, PartialEq, Clone)] /// *Complete* means all staged holons have been committed and staged_holons cleared @@ -279,8 +310,8 @@ impl CommitManager { } } - /// Private helper function the encapsulates the logic for getting a mutable reference to a - /// holon from a Staged + /// Private helper function that encapsulates the logic for getting a mutable reference to a + /// holon from a StagedReference fn get_mut_holon_internal( &self, holon_index: Option, @@ -315,6 +346,7 @@ impl CommitManager { self.get_mut_holon_internal(Some(staged_reference.holon_index)) } + // pub fn get_mut_holon_by_index( // &self, // holon_index: StagedIndex, diff --git a/crates/coordinator/holons/src/context.rs b/crates/coordinator/holons/src/context.rs index ab9beb8c..29ba71d9 100644 --- a/crates/coordinator/holons/src/context.rs +++ b/crates/coordinator/holons/src/context.rs @@ -1,7 +1,6 @@ use crate::cache_manager::HolonCacheManager; use crate::commit_manager::CommitManager; -use crate::staged_reference::StagedReference; -use std::cell::{Ref, RefCell}; +use std::cell::{RefCell}; use shared_types_holon::MapString; use crate::holon_error::HolonError; use crate::holon_reference::HolonReference; @@ -11,7 +10,7 @@ pub struct HolonsContext { pub commit_manager: RefCell, pub cache_manager: RefCell, pub dance_state: RefCell, - pub local_holon_space: Option, + pub local_holon_space: RefCell>, } impl HolonsContext { @@ -20,7 +19,7 @@ impl HolonsContext { commit_manager: CommitManager::new().into(), cache_manager: HolonCacheManager::new().into(), dance_state: TransientCollection::new().into(), - local_holon_space: None, + local_holon_space: RefCell::new(None), } } pub fn init_context( @@ -34,16 +33,25 @@ impl HolonsContext { commit_manager: RefCell::from(commit_manager), cache_manager: RefCell::from(cache_manager), dance_state: TransientCollection::new().into(), - local_holon_space: local_holon_space.clone(), + local_holon_space: RefCell::new(local_holon_space), } } - /// This method returns a reference to the LocalHolonSpace - pub fn get_local_holon_space(&self) -> Result { - self.local_holon_space.borrow() + /// This method returns a clone of the LocalHolonSpace reference from the context + /// NOTE: This will panic on borrow failure + pub fn get_local_holon_space(&self) -> Option { + let local_holon_space = self.local_holon_space.borrow(); + local_holon_space.clone() // If no panic, return cloned value } - fn set_local_holon_space(&self, new_holon_space: HolonReference) { - // Borrow mutably and replace the None with Some(new_holon_space) - *self.local_holon_space.borrow_mut() = Some(new_holon_space); + + /// This method sets the LocalHolonSpace reference within the context + pub fn set_local_holon_space(&self, new_holon_space: HolonReference) -> Result<(), HolonError> { + match self.local_holon_space.try_borrow_mut() { + Ok(mut local_holon_space) => { + *local_holon_space = Some(new_holon_space); // Successfully borrowed and mutated + Ok(()) + }, + Err(_) => Err(HolonError::FailedToBorrow("Failed to borrow local_holon_space mutably".into())), + } } pub fn add_references_to_dance_state(&self, holons: Vec) -> Result<(), HolonError> { self.dance_state.borrow_mut().add_references(self, holons) diff --git a/crates/coordinator/holons/src/holon.rs b/crates/coordinator/holons/src/holon.rs index a052d767..eee2fa7e 100644 --- a/crates/coordinator/holons/src/holon.rs +++ b/crates/coordinator/holons/src/holon.rs @@ -8,10 +8,10 @@ use hdi::prelude::ActionHash; use hdk::prelude::*; use shared_types_holon::holon_node::{HolonNode, PropertyMap, PropertyName, PropertyValue}; -use shared_types_holon::{HolonId, LocalId, MapInteger, MapString}; +use shared_types_holon::{LocalId, MapInteger, MapString}; use shared_types_holon::value_types::BaseValue; -use shared_validation::ValidationError; +// use shared_validation::ValidationError; use crate::all_holon_nodes::*; use crate::context::HolonsContext; @@ -351,7 +351,6 @@ impl Holon { /// returns a HolonError::UnexpectedValueType. pub fn get_key(&self) -> Result, HolonError> { self.is_accessible(AccessType::Read)?; - trace!(" in get_key()"); let key = self .property_map .get(&PropertyName(MapString("key".to_string()))); @@ -359,7 +358,6 @@ impl Holon { let string_value: String = key.try_into().map_err(|_| { HolonError::UnexpectedValueType(format!("{:?}", key), "MapString".to_string()) })?; - trace!(" returning from get_key() with Some(key)"); Ok(Some(MapString(string_value))) } else { trace!(" returning from get_key() with None"); diff --git a/crates/coordinator/holons/src/holon_collection.rs b/crates/coordinator/holons/src/holon_collection.rs index bf286cd6..3a0b9a7d 100644 --- a/crates/coordinator/holons/src/holon_collection.rs +++ b/crates/coordinator/holons/src/holon_collection.rs @@ -5,7 +5,7 @@ use crate::holon_reference::{HolonGettable, HolonReference}; use crate::relationship::RelationshipName; use crate::smartlink::{save_smartlink, SmartLink}; use hdk::prelude::*; -use shared_types_holon::{BaseValue, HolonId, LocalId, MapInteger, MapString, PropertyMap, PropertyName}; +use shared_types_holon::{BaseValue, LocalId, MapInteger, MapString, PropertyMap, PropertyName}; use std::collections::BTreeMap; #[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)] diff --git a/crates/coordinator/holons/src/holon_error.rs b/crates/coordinator/holons/src/holon_error.rs index d38f3cd0..023964e9 100644 --- a/crates/coordinator/holons/src/holon_error.rs +++ b/crates/coordinator/holons/src/holon_error.rs @@ -19,10 +19,12 @@ pub enum HolonError { RecordConversion(String), #[error("Couldn't convert {0} into {1} ")] HashConversion(String, String), - #[error("Invalid HolonReference, {0}")] - InvalidHolonReference(String), #[error("Index {0} into Holons Vector is Out of Range")] IndexOutOfRange(String), + #[error("Invalid HolonReference, {0}")] + InvalidHolonReference(String), + #[error("Invalid Type, {0}")] + InvalidType(String), #[error("{0} Not Implemented")] NotImplemented(String), #[error("Miscellaneous error: {0}")] @@ -53,9 +55,14 @@ impl From for HolonError { } } +// impl Into for HolonError { +// fn into(self) -> WasmError { +// wasm_error!("HolonError {:?}", self.to_string()) +// } +// } impl Into for HolonError { fn into(self) -> WasmError { - wasm_error!("HolonError {:?}", self.to_string()) + wasm_error!(WasmErrorInner::Guest(self.to_string())) // Correct usage of the `wasm_error!` macro } } diff --git a/crates/coordinator/holons/src/holon_space.rs b/crates/coordinator/holons/src/holon_space.rs index 42dc2bd9..1971c57a 100644 --- a/crates/coordinator/holons/src/holon_space.rs +++ b/crates/coordinator/holons/src/holon_space.rs @@ -1,60 +1,74 @@ -use hdi::map_extern::ExternResult; -use hdi::prelude::Path; -use hdk::hdk::HDK; -use hdk::link::{get_links, GetLinksInputBuilder}; -use hdk::prelude::{GetInput, GetOptions}; -use holochain_integrity_types::Record; -use holons_integrity::LinkTypes; -use shared_types_holon::{HolonId, MapString}; -use crate::context::HolonsContext; +use hdi::prelude::{Deserialize, Serialize}; + +use shared_types_holon::{MapString, PropertyName, PropertyValue}; + use crate::holon::Holon; use crate::holon_error::HolonError; -use crate::holon_reference::HolonReference; -use crate::smart_reference::SmartReference; - +#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)] pub struct HolonSpace(pub Holon); impl HolonSpace { pub fn new(holon: Holon) -> HolonSpace { HolonSpace(holon) } + pub fn get_description(&self) -> Result { + let property_name = PropertyName(MapString("description".to_string())); - pub fn into_holon(self) -> Holon { - self.0 - } - /// get_local_holon_space retrieves the local holon space from the persistent store - pub fn get_local_holon_space(context: &HolonsContext) -> Result { - // For now, it just uses a brute force linear search through all saved holons, searching - // for a holon with key "LocalHolonSpace". If found, it extracts its HolonId and - // A HolonReference to the cached HolonSpace Holon is then returned - // TODO: Scaffold a new `LocalHolonSpace` LinkType and search by path instead of linear search - let all_holons = Holon::get_all_holons()?; - let search_key = MapString("LocalHolonSpace".to_string()); - - for holon in &all_holons { - match holon.get_key()? { - Some(key) if key == search_key => { - let holon_id = HolonId::Local(holon.get_local_id()?); - // use get_rc_holon on the cache_manager to populate the HolonSpace holon in the cache - let holon_space_rc_holon = context - .cache_manager - .borrow_mut() - .get_rc_holon(&holon_id)?; - // build a HolonReference from the holon_space_rc_holon. - // TODO: We should have a helper function that creates a new SmartReference from a Holon. - // This function could populate the smart_property_values from the holon's descriptor - // But for now, we'll just construct the HolonReference from holon_id - - return Ok(HolonReference::Smart(SmartReference::new(holon_id, None))); - } - _ => continue, - } + match self.0.get_property_value(&property_name)? { + PropertyValue::StringValue(name) => Ok(name), + _ => Err(HolonError::InvalidType(format!( + "Expected StringValue for '{}'", property_name.0 + ))), } - - // Return HolonError::NotFound if no matching holon is found - Err(HolonError::HolonNotFound(search_key.to_string())) } + pub fn get_key(&self) -> Result, HolonError> { + self.0.get_key() + } + pub fn get_name(&self) -> Result { + let property_name = PropertyName(MapString("name".to_string())); + match self.0.get_property_value(&property_name)? { + PropertyValue::StringValue(name) => Ok(name), + _ => Err(HolonError::InvalidType(format!( + "Expected StringValue for '{}'", property_name.0 + ))), + } + } + fn holon_mut(&mut self) -> &mut Holon { + &mut self.0 // Return a mutable reference to the inner `Holon` + } + pub fn into_holon(self) -> Holon { + self.0.clone() + } + /// get_local_holon_space retrieves the local holon space from the persistent store + /// This currently does a brute force linear search through all saved holons + /// TODO: Replace this logic with a fetch based on HolonSpace LinkType + pub fn with_description(&mut self, description: &MapString) -> Result<&mut Self, HolonError> { + self + .holon_mut() + .with_property_value( + PropertyName(MapString("description".to_string())), + description.clone().into_base_value(), + )?; + Ok(self) + } + /// Sets the name property for the HolonSpace (and currently the "key" property) + /// + pub fn with_name(&mut self, name: &MapString) -> Result<&mut Self, HolonError> { + self + .holon_mut() + .with_property_value( + PropertyName(MapString("name".to_string())), + name.clone().into_base_value(), + )? + // TODO: drop this once descriptor-based key support is implemented + .with_property_value( + PropertyName(MapString("key".to_string())), + name.clone().into_base_value(), + )?; + Ok(self) + } } + diff --git a/crates/coordinator/holons/src/holon_space_manager.rs b/crates/coordinator/holons/src/holon_space_manager.rs new file mode 100644 index 00000000..170b8bf5 --- /dev/null +++ b/crates/coordinator/holons/src/holon_space_manager.rs @@ -0,0 +1,109 @@ +use hdi::prelude::info; +use shared_types_holon::{HolonId, MapString}; +use crate::commit_manager::CommitManager; + +use crate::context::HolonsContext; +use crate::holon::Holon; +use crate::holon_error::HolonError; +use crate::holon_reference::HolonReference; +use crate::holon_space::HolonSpace; +use crate::smart_reference::SmartReference; + +pub struct HolonSpaceManager<'a> { + context: &'a HolonsContext, // Reference to the context where the HolonSpace will be persisted +} + +impl<'a> HolonSpaceManager<'a> { + // Constructor for the service + pub fn new(context: &'a HolonsContext) -> Self { + HolonSpaceManager { context } + } + /// This function stages and commits a HolonSpace within this DHT + /// It is intended to be called from the init() function with _*exactly-once*_ semantics being + /// enforced by the progenitor pattern. + pub fn create_local_holon_space(&self) -> Result { + info!("Preparing to stage and commit the LocalHolonSpace"); + let mut holon_space = HolonSpace::new(Holon::new()); + let name = MapString("LocalHolonSpace".to_string()); + let description = MapString("Default HolonSpace description. Actual description should be \ + loaded from DNA properties.".to_string()); + + holon_space + .with_name(&name)? + .with_description(&description)? + ; + + // Stage the new holon space and set it in the context + let _staged_holon_space_ref = self.context + .commit_manager + .borrow_mut() + .stage_new_holon(holon_space.into_holon())?; + + // Commit the staged holon space + let commit_response = CommitManager::commit(self.context); + + if commit_response.is_complete() { + let local_id =commit_response.find_local_id_by_key(&name)?; + info!("Created LocalHolonSpace with id {:#?}", local_id.clone()); + return Ok(HolonReference::Smart(SmartReference::new_from_id(local_id.into()))) + // TODO: Tie the newly saved holon to the holon space LinkType anchor + } + return Err(HolonError::CommitFailure("Unable to commit LocalHolonSpace".to_string())) + + } + /// Ensure that a LocalHolonSpace reference is included in the context. The simplest case is + /// that context is already populated with the reference. If not, try to fetch the reference + /// from the persistent store. If that doesn't work, then (for now), try to stage and commit + /// the local HolonSpace. + /// + pub fn ensure_local_holon_space_in_context(&self)-> Result { + return match self.context.get_local_holon_space() { + Some(space_reference) => Ok(space_reference), + None => { + info!("No LocalHolonSpace found in context, fetching it."); + let holon_space_fetch_result = self.fetch_and_set_local_holon_space(); + match holon_space_fetch_result { + Ok(space_reference) => { + self.context.set_local_holon_space(space_reference.clone())?; + Ok(space_reference) + }, + Err(_fetch_error) => { + // Handle the case where we were unable to get the LocalHolonSpace from the + // persistent store. + // NOTE: Once we have moved holon space creation to init(), we should just + // return an error indicating initialization is not complete. + // But for now, use this to trigger creation of the local holon space + let space_reference = self.create_local_holon_space()?; + self.context.set_local_holon_space(space_reference.clone())?; + Ok(space_reference) + }, + } + } + } + } + + /// Search the DHT for its (singleton) LocalHolonSpace and update the context to include + /// a HolonReference to it. Returns a HolonNotFound error if LocalHolonSpace cannot be found. + fn fetch_and_set_local_holon_space(&self) -> Result { + // For now, it just uses a brute force linear search through all saved holons, searching + // for a holon with key "LocalHolonSpace". If found, it extracts its HolonId and + // a HolonReference for that HolonId is returned + // TODO: Scaffold a new `LocalHolonSpace` LinkType and search by path instead of linear search + let all_holons = Holon::get_all_holons()?; + let search_key = MapString("LocalHolonSpace".to_string()); + + for holon in &all_holons { + match holon.get_key()? { + Some(key) if key == search_key => { + let holon_id = HolonId::Local(holon.get_local_id()?); + let holon_space_reference = HolonReference::Smart(SmartReference::new_from_id(holon_id)); + self.context.set_local_holon_space(holon_space_reference.clone())?; + return Ok(holon_space_reference); + } + _ => continue, + } + } + // Return HolonError::NotFound if no matching holon is found + Err(HolonError::HolonNotFound(search_key.to_string())) + } +} \ No newline at end of file diff --git a/crates/coordinator/holons/src/lib.rs b/crates/coordinator/holons/src/lib.rs index c4b7fcb3..f08468c5 100644 --- a/crates/coordinator/holons/src/lib.rs +++ b/crates/coordinator/holons/src/lib.rs @@ -18,6 +18,8 @@ pub mod transient_collection; pub mod json_adapter; pub mod query; pub mod holon_space; +pub mod holon_space_manager; + use hdk::prelude::*; diff --git a/crates/coordinator/holons/src/smart_reference.rs b/crates/coordinator/holons/src/smart_reference.rs index a9cae3c2..8e858639 100644 --- a/crates/coordinator/holons/src/smart_reference.rs +++ b/crates/coordinator/holons/src/smart_reference.rs @@ -23,6 +23,13 @@ pub struct SmartReference { } impl SmartReference { + /// Constructor for SmartReference that takes a HolonId and sets smart_property_values to None + pub fn new_from_id(holon_id: HolonId) -> Self { + SmartReference { + holon_id, + smart_property_values: None, + } + } pub fn clone_reference(&self) -> SmartReference { SmartReference { holon_id: self.holon_id.clone(), diff --git a/crates/coordinator/holons/src/smartlink.rs b/crates/coordinator/holons/src/smartlink.rs index eb7b5de2..5070b1f2 100644 --- a/crates/coordinator/holons/src/smartlink.rs +++ b/crates/coordinator/holons/src/smartlink.rs @@ -1,7 +1,7 @@ use hdk::prelude::*; use holons_integrity::LinkTypes; use holons_integrity::*; -use shared_types_holon::{BaseValue, HolonId, LocalId, MapString, PropertyMap, PropertyName, PropertyValue}; +use shared_types_holon::{BaseValue, HolonId, LocalId, MapString, PropertyMap, PropertyName}; use std::{collections::BTreeMap, str}; use crate::helpers::get_key_from_property_map; @@ -9,10 +9,10 @@ use crate::holon_reference::HolonReference; use crate::smart_reference::SmartReference; use crate::{holon_error::HolonError, relationship::RelationshipName}; -const fn smartlink_tag_header_length() -> usize { - // leaving this nomenclature for now - SMARTLINK_HEADER_BYTES.len() -} +// const fn smartlink_tag_header_length() -> usize { +// // leaving this nomenclature for now +// SMARTLINK_HEADER_BYTES.len() +// } #[derive(Serialize, Deserialize, Debug)] pub struct SmartLink { diff --git a/crates/integrity/holons_integrity/src/holon_node.rs b/crates/integrity/holons_integrity/src/holon_node.rs index 656e23b9..f458096c 100644 --- a/crates/integrity/holons_integrity/src/holon_node.rs +++ b/crates/integrity/holons_integrity/src/holon_node.rs @@ -1,6 +1,6 @@ use hdi::prelude::*; use shared_types_holon::HolonNode; -use shared_validation::ValidationError; +// use shared_validation::ValidationError; /* #[hdk_entry_helper] diff --git a/crates/shared_types/holon/src/value_types.rs b/crates/shared_types/holon/src/value_types.rs index 3800b201..5c6f4ec7 100644 --- a/crates/shared_types/holon/src/value_types.rs +++ b/crates/shared_types/holon/src/value_types.rs @@ -22,6 +22,11 @@ impl fmt::Display for MapString { write!(f, "{}", self.0) } } +impl MapString { + pub fn into_base_value(self) -> BaseValue { + BaseValue::StringValue(self) + } +} #[hdk_entry_helper] #[derive(Clone, PartialEq, Eq)] diff --git a/flake.lock b/flake.lock index 04005e53..e7ffffd2 100644 --- a/flake.lock +++ b/flake.lock @@ -20,33 +20,27 @@ "cargo-rdme": { "flake": false, "locked": { - "lastModified": 1675118998, - "narHash": "sha256-lrYWqu3h88fr8gG3Yo5GbFGYaq5/1Os7UtM+Af0Bg4k=", + "lastModified": 1718044745, + "narHash": "sha256-Oa667BTz/PdxZmhGSP+qfPcUbORlk7nP5OrCJyYqVQg=", "owner": "orium", "repo": "cargo-rdme", - "rev": "f9dbb6bccc078f4869f45ae270a2890ac9a75877", + "rev": "22d756971037ad4c7953db882c5b96a662364f15", "type": "github" }, "original": { "owner": "orium", - "ref": "v1.1.0", + "ref": "v1.4.4", "repo": "cargo-rdme", "type": "github" } }, "crane": { - "inputs": { - "nixpkgs": [ - "holochain-flake", - "nixpkgs" - ] - }, "locked": { - "lastModified": 1721322122, - "narHash": "sha256-a0G1NvyXGzdwgu6e1HQpmK5R5yLsfxeBe07nNDyYd+g=", + "lastModified": 1725125250, + "narHash": "sha256-CB20rDD5eHikF6mMTTJdwPP1qvyoiyyw1RDUzwIaIF8=", "owner": "ipetkov", "repo": "crane", - "rev": "8a68b987c476a33e90f203f0927614a75c3f47ea", + "rev": "96fd12c7100e9e05fa1a0a5bd108525600ce282f", "type": "github" }, "original": { @@ -55,22 +49,6 @@ "type": "github" } }, - "crate2nix": { - "flake": false, - "locked": { - "lastModified": 1719760654, - "narHash": "sha256-L3VIJ9182wsYJqP27xO5qiWwfK+a00x0JHiy8ns3NQE=", - "owner": "kolloch", - "repo": "crate2nix", - "rev": "a6ca1e58132bab26fc08572f22a34bbb86f4d91d", - "type": "github" - }, - "original": { - "owner": "kolloch", - "repo": "crate2nix", - "type": "github" - } - }, "empty": { "flake": false, "locked": { @@ -108,11 +86,11 @@ "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1719994518, - "narHash": "sha256-pQMhCCHyQGRzdfAkdJ4cIWiw+JNuWsTX7f0ZYSyz0VY=", + "lastModified": 1725234343, + "narHash": "sha256-+ebgonl3NbiKD2UD0x4BszCZQ6sTfL4xioaM49o5B3Y=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "9227223f6d922fee3c7b190b2cc238a99527bbb7", + "rev": "567b938d64d4b4112ee253b9274472dc3a346eb6", "type": "github" }, "original": { @@ -142,7 +120,6 @@ "cargo-chef": "cargo-chef", "cargo-rdme": "cargo-rdme", "crane": "crane", - "crate2nix": "crate2nix", "empty": "empty", "flake-compat": "flake-compat", "flake-parts": "flake-parts", @@ -172,11 +149,11 @@ ] }, "locked": { - "lastModified": 1723629000, - "narHash": "sha256-0CdNS+9JcZ8/V+0mvMumnZBceJLDIZBKM9ThGTzWfpw=", + "lastModified": 1727887143, + "narHash": "sha256-DUSLg1zNuuHvZH+dDgFw7J5Gidq/C+wSsLkprWfyFGc=", "owner": "holochain", "repo": "holochain", - "rev": "0cd05ccac515c1a78e889e88198931a98eb1aab3", + "rev": "d7ad1372ed8f9a8081d7dee0308e552b7decd0b6", "type": "github" }, "original": { @@ -236,11 +213,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1723175592, - "narHash": "sha256-M0xJ3FbDUc4fRZ84dPGx5VvgFsOzds77KiBMW/mMTnI=", + "lastModified": 1727348695, + "narHash": "sha256-J+PeFKSDV+pHL7ukkfpVzCOO7mBSrrpJ3svwBFABbhI=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "5e0ca22929f3342b19569b21b2f3462f053e497b", + "rev": "1925c603f17fc89f4c8f6bf6f631a802ad85d784", "type": "github" }, "original": { @@ -251,24 +228,24 @@ }, "nixpkgs-lib": { "locked": { - "lastModified": 1719876945, - "narHash": "sha256-Fm2rDDs86sHy0/1jxTOKB1118Q0O3Uc7EC0iXvXKpbI=", + "lastModified": 1725233747, + "narHash": "sha256-Ss8QWLXdr2JCBPcYChJhz4xJm+h/xjl4G0c0XlP6a74=", "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/5daf0514482af3f97abaefc78a6606365c9108e2.tar.gz" + "url": "https://github.com/NixOS/nixpkgs/archive/356624c12086a18f2ea2825fed34523d60ccc4e3.tar.gz" }, "original": { "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/5daf0514482af3f97abaefc78a6606365c9108e2.tar.gz" + "url": "https://github.com/NixOS/nixpkgs/archive/356624c12086a18f2ea2825fed34523d60ccc4e3.tar.gz" } }, "pre-commit-hooks-nix": { "flake": false, "locked": { - "lastModified": 1721042469, - "narHash": "sha256-6FPUl7HVtvRHCCBQne7Ylp4p+dpP3P/OYuzjztZ4s70=", + "lastModified": 1724857454, + "narHash": "sha256-Qyl9Q4QMTLZnnBb/8OuQ9LSkzWjBU1T5l5zIzTxkkhk=", "owner": "cachix", "repo": "pre-commit-hooks.nix", - "rev": "f451c19376071a90d8c58ab1a953c6e9840527fd", + "rev": "4509ca64f1084e73bc7a721b20c669a8d4c5ebe6", "type": "github" }, "original": { @@ -311,11 +288,11 @@ ] }, "locked": { - "lastModified": 1723343015, - "narHash": "sha256-oS8Qhpo71B/6OOsuVBFJbems7RKD/5e3TN2AdXhwMjg=", + "lastModified": 1727577080, + "narHash": "sha256-2LPT76Acp6ebt7fCt90eq/M8T2+X09s/yTVgfVFrtno=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "ed4fe9af3814694d59c572649e881a6aa6eba533", + "rev": "73a833855442ce8cee710cf4d8d054fea1c81196", "type": "github" }, "original": { @@ -327,11 +304,11 @@ "scaffolding": { "flake": false, "locked": { - "lastModified": 1722862548, - "narHash": "sha256-8FXBPbL2qXiDAhQbbPehRDuauEUb9V3Uc7K4YjC0ev4=", + "lastModified": 1724073530, + "narHash": "sha256-PUM8otA5F5s8ZHxhjupn7R+RZAjh2rueYIFwu3UkK44=", "owner": "holochain", "repo": "scaffolding", - "rev": "fc557aa8164d23c5638faa5fe5ed99d30e8404b7", + "rev": "8a6d1dab0f1668c2781a46d93a5ad638fcf25598", "type": "github" }, "original": { @@ -350,11 +327,11 @@ }, "locked": { "dir": "versions/0_3", - "lastModified": 1723629000, - "narHash": "sha256-0CdNS+9JcZ8/V+0mvMumnZBceJLDIZBKM9ThGTzWfpw=", + "lastModified": 1727887143, + "narHash": "sha256-DUSLg1zNuuHvZH+dDgFw7J5Gidq/C+wSsLkprWfyFGc=", "owner": "holochain", "repo": "holochain", - "rev": "0cd05ccac515c1a78e889e88198931a98eb1aab3", + "rev": "d7ad1372ed8f9a8081d7dee0308e552b7decd0b6", "type": "github" }, "original": { From d6f9096960fe19691294d93ba5d92f486a36b0f9 Mon Sep 17 00:00:00 2001 From: evomimic Date: Tue, 8 Oct 2024 07:50:28 -0600 Subject: [PATCH 7/7] reconciled problems arising from merge -- all tests pass --- crates/coordinator/core_schema/src/loader.rs | 11 +++- .../coordinator/dances/src/dance_response.rs | 2 +- crates/coordinator/dances/src/dancer.rs | 5 +- .../dances/src/holon_dance_adapter.rs | 64 ++++++++----------- .../tests/shared_test/test_delete_holon.rs | 4 +- .../shared_test/test_remove_related_holon.rs | 2 +- crates/coordinator/holons/src/holon_error.rs | 6 +- crates/coordinator/holons/src/smartlink.rs | 2 +- flake.lock | 38 +++++------ 9 files changed, 64 insertions(+), 70 deletions(-) diff --git a/crates/coordinator/core_schema/src/loader.rs b/crates/coordinator/core_schema/src/loader.rs index 9fd81068..c84cd632 100644 --- a/crates/coordinator/core_schema/src/loader.rs +++ b/crates/coordinator/core_schema/src/loader.rs @@ -55,6 +55,11 @@ pub fn load_core_schema(context: &HolonsContext) -> Result Result Vec { ]; - // Let's add all of the CoreSchemaValueTypes to the initial load set + // Let's add all the CoreSchemaValueTypes to the initial load set for variant in CoreStringValueTypeName::iter() { result.push(CoreSchemaTypeName::ValueType(CoreValueTypeName::StringType(variant))); diff --git a/crates/coordinator/dances/src/dance_response.rs b/crates/coordinator/dances/src/dance_response.rs index a32bfd24..5fc76021 100644 --- a/crates/coordinator/dances/src/dance_response.rs +++ b/crates/coordinator/dances/src/dance_response.rs @@ -72,7 +72,7 @@ impl From for ResponseStatusCode { HolonError::MissingStagedCollection(_) => ResponseStatusCode::BadRequest, HolonError::FailedToBorrow(_) => ResponseStatusCode::ServerError, HolonError::UnableToAddHolons(_) => ResponseStatusCode::ServerError, - HolonError::InvalidRelationship(_, _) => ResponseStatusCode::BadRequest, + HolonError::InvalidRelationship(_,_) => ResponseStatusCode::BadRequest, HolonError::CacheError(_) => ResponseStatusCode::ServerError, HolonError::NotAccessible(_, _) => ResponseStatusCode::Conflict, HolonError::ValidationError(_) => ResponseStatusCode::BadRequest, diff --git a/crates/coordinator/dances/src/dancer.rs b/crates/coordinator/dances/src/dancer.rs index 252e2248..118a6f06 100644 --- a/crates/coordinator/dances/src/dancer.rs +++ b/crates/coordinator/dances/src/dancer.rs @@ -203,11 +203,8 @@ fn process_dispatch_result(context: &HolonsContext, dispatch_result: Result { - }; let error_message = extract_error_message(&error); - - // Construct DanceResponse with error details DanceResponse { status_code: ResponseStatusCode::from(error), // Convert HolonError to ResponseStatusCode @@ -227,6 +224,7 @@ fn extract_error_message(error:&HolonError)->String { | HolonError::InvalidParameter(_) | HolonError::HolonNotFound(_) | HolonError::CommitFailure(_) + | HolonError::DeletionNotAllowed(_) | HolonError::WasmError(_) | HolonError::RecordConversion(_) | HolonError::InvalidHolonReference(_) @@ -245,6 +243,7 @@ fn extract_error_message(error:&HolonError)->String { | HolonError::CacheError(_) => error.to_string(), HolonError::ValidationError(validation_error) => validation_error.to_string(), + } } diff --git a/crates/coordinator/dances/src/holon_dance_adapter.rs b/crates/coordinator/dances/src/holon_dance_adapter.rs index 50465273..fb7de4e1 100644 --- a/crates/coordinator/dances/src/holon_dance_adapter.rs +++ b/crates/coordinator/dances/src/holon_dance_adapter.rs @@ -28,11 +28,9 @@ use shared_types_holon::{MapString, PropertyMap}; use crate::dance_request::{DanceRequest, DanceType, RequestBody}; use crate::dance_response::ResponseBody; - use crate::session_state::SessionState; use crate::staging_area::StagingArea; - /// *DanceRequest:* /// - dance_name: "add_related_holons" /// - dance_type: Command(StagedIndex) -- references the staged holon that is the `source` of the relationship being extended @@ -91,40 +89,23 @@ pub fn add_related_holons_dance( )), } } -/// -/// Builds a DanceRequest for adding related holons to a source_holon. -pub fn build_add_related_holons_dance_request( - staging_area: StagingArea, - index: StagedIndex, - relationship_name: RelationshipName, - holons_to_add: Vec, -) -> Result { - let body = RequestBody::new_target_holons(relationship_name, holons_to_add); - Ok(DanceRequest::new( - MapString("add_related_holons".to_string()), - DanceType::CommandMethod(index), - body, - staging_area, - )) -} - /// This dance deletes an existing holon from the persistent store. -/// +/// /// *DanceRequest:* /// - dance_name: "delete_holon" /// - dance_type: DeleteMethod(HolonId) /// - request_body: None -/// +/// /// /// *ResponseBody:* /// None /// // In the absence of descriptors that can specify the DeletionSemantic, -// this enhancement will adopt Allow as a default policy. When we have RelationshipDescriptors, we can use their properties +// this enhancement will adopt Allow as a default policy. When we have RelationshipDescriptors, we can use their properties // to drive a richer range of deletion behaviors. // -// NOTE: This dance implements an immediate delete. We may want to consider staging holons for deletion and postponing the actual deletion until commit. -// This would allow the cascaded effects of the delete to be determined and shared with the agent, leaving them free to cancel the deletion if desired. +// NOTE: This dance implements an immediate delete. We may want to consider staging holons for deletion and postponing the actual deletion until commit. +// This would allow the cascaded effects of the delete to be determined and shared with the agent, leaving them free to cancel the deletion if desired. // A staged deletion process would be more consistent with the staged creation process. pub fn delete_holon_dance( _context: &HolonsContext, @@ -151,7 +132,7 @@ pub fn build_delete_holon_dance_request( MapString("delete_holon".to_string()), DanceType::DeleteMethod(holon_to_delete), body, - session_state, + session_state.clone(), )) } @@ -214,9 +195,12 @@ pub fn remove_related_holons_dance( } } + + + /// Builds a DanceRequest for removing related holons to a source_holon. pub fn build_remove_related_holons_dance_request( - session_state: SessionState, + session_state: &SessionState, index: StagedIndex, relationship_name: RelationshipName, holons_to_remove: Vec, @@ -226,7 +210,7 @@ pub fn build_remove_related_holons_dance_request( MapString("remove_related_holons".to_string()), DanceType::CommandMethod(index), body, - session_state, + session_state.clone(), )) } @@ -248,7 +232,6 @@ pub fn build_add_related_holons_dance_request( )) } - /// *DanceRequest:* /// - dance_name: "query_relationships" /// - dance_type: QueryMethod(NodeCollection) -- specifies the Collection to use as the source of the query @@ -266,17 +249,17 @@ pub fn query_relationships_dance( match request.dance_type { DanceType::QueryMethod(node_collection) => { - let relationship_name = - match request.body { - RequestBody::QueryExpression(expression) => expression.relationship_name, - _ => return Err(HolonError::InvalidParameter( + let relationship_name = match request.body { + RequestBody::QueryExpression(expression) => expression.relationship_name, + _ => { + return Err(HolonError::InvalidParameter( "Invalid RequestBody: expected QueryExpression with relationship name, \ - didn't get one" - .to_string(), - )), - }; + didn't get one".to_string(), + )) + } + }; - let result_collection = evaluate_query(node_collection, context, relationship_name)?; + let result_collection = evaluate_query(node_collection,context,relationship_name)?; Ok(ResponseBody::Collection(result_collection)) } _ => Err(HolonError::InvalidParameter( @@ -285,6 +268,9 @@ pub fn query_relationships_dance( } } + + + // pub fn query_relationships_dance( // context: &HolonsContext, // request: DanceRequest, @@ -519,7 +505,9 @@ pub fn get_all_holons_dance( debug!("Entering get_all_holons dance.."); let query_result = Holon::get_all_holons(); match query_result { - Ok(holons) => Ok(ResponseBody::Holons(holons)), + Ok(holons) => { + Ok(ResponseBody::Holons(holons)) + }, Err(holon_error) => Err(holon_error.into()), } } diff --git a/crates/coordinator/dances/tests/shared_test/test_delete_holon.rs b/crates/coordinator/dances/tests/shared_test/test_delete_holon.rs index d435429f..b1f7e8b4 100644 --- a/crates/coordinator/dances/tests/shared_test/test_delete_holon.rs +++ b/crates/coordinator/dances/tests/shared_test/test_delete_holon.rs @@ -41,7 +41,7 @@ pub async fn execute_delete_holon( let local_id = holon_to_delete.get_local_id().unwrap(); // Build a stage_holon DanceRequest let delete_holon_request = - build_delete_holon_dance_request(test_state.staging_area.clone(), local_id.clone()); + build_delete_holon_dance_request(&test_state.session_state, local_id.clone()); debug!("delete_holon Dance Request: {:#?}", delete_holon_request); match delete_holon_request { @@ -68,7 +68,7 @@ pub async fn execute_delete_holon( Ok(_) => { info!("Success! delete_holon returned OK response, confirming deletion..."); let get_holon_by_id_request = build_get_holon_by_id_dance_request( - test_state.staging_area.clone(), + &test_state.session_state, HolonId::Local(local_id.clone()), ); match get_holon_by_id_request { diff --git a/crates/coordinator/dances/tests/shared_test/test_remove_related_holon.rs b/crates/coordinator/dances/tests/shared_test/test_remove_related_holon.rs index 05144db1..5ce48790 100644 --- a/crates/coordinator/dances/tests/shared_test/test_remove_related_holon.rs +++ b/crates/coordinator/dances/tests/shared_test/test_remove_related_holon.rs @@ -68,7 +68,7 @@ pub async fn execute_remove_related_holons( // Build the DanceRequest let request = build_remove_related_holons_dance_request( - test_state.session_state.clone(), + &test_state.session_state, source_holon_index, relationship_name, holons_to_remove, diff --git a/crates/coordinator/holons/src/holon_error.rs b/crates/coordinator/holons/src/holon_error.rs index 5a6ad9c0..6c3e4e9f 100644 --- a/crates/coordinator/holons/src/holon_error.rs +++ b/crates/coordinator/holons/src/holon_error.rs @@ -27,8 +27,10 @@ pub enum HolonError { InvalidHolonReference(String), #[error("Invalid Type, {0}")] InvalidType(String), - #[error("{0} Not Implemented")] - NotImplemented(String), + #[error("Invalid Parameter: {0}")] + InvalidParameter(String), + #[error("{0} is not a valid relationship for this source holon type {1}")] + InvalidRelationship(String, String), // TODO: move this error to ValidationError #[error("Miscellaneous error: {0}")] Misc(String), #[error("{0} relationship is missing StagedCollection")] diff --git a/crates/coordinator/holons/src/smartlink.rs b/crates/coordinator/holons/src/smartlink.rs index 998a9811..5fe90453 100644 --- a/crates/coordinator/holons/src/smartlink.rs +++ b/crates/coordinator/holons/src/smartlink.rs @@ -2,7 +2,7 @@ use hdi::prelude::*; use hdk::prelude::*; use holons_integrity::LinkTypes; use holons_integrity::*; -use shared_types_holon::{BaseValue, HolonId, LocalId, MapString, PropertyMap, PropertyName}; +use shared_types_holon::{BaseValue, ExternalId, HolonId, HolonSpaceId, LocalId, MapString, PropertyMap, PropertyName}; use std::{collections::BTreeMap, str}; diff --git a/flake.lock b/flake.lock index e7ffffd2..77cff7f7 100644 --- a/flake.lock +++ b/flake.lock @@ -101,16 +101,16 @@ "holochain": { "flake": false, "locked": { - "lastModified": 1722347117, - "narHash": "sha256-Jv4DxaVtdbO+fOD4woFoepCCOtRN/HF94xJSwViz3ck=", + "lastModified": 1728056814, + "narHash": "sha256-OUVNmUCUk4G2ur+O/Q6Ji77iHQeN3PufmiPDz9MS8AY=", "owner": "holochain", "repo": "holochain", - "rev": "97d86050b177829b623461970db5c3b64fbd74c1", + "rev": "63aeec5fd95b3263bc8ebce73c53b9f0e03bbf36", "type": "github" }, "original": { "owner": "holochain", - "ref": "holochain-0.3.2", + "ref": "holochain-0.3.3", "repo": "holochain", "type": "github" } @@ -149,11 +149,11 @@ ] }, "locked": { - "lastModified": 1727887143, - "narHash": "sha256-DUSLg1zNuuHvZH+dDgFw7J5Gidq/C+wSsLkprWfyFGc=", + "lastModified": 1728272048, + "narHash": "sha256-DTUdt8/fOXLqieHXgPz9U5qS6MiCh4XGeZ8aEfZnszA=", "owner": "holochain", "repo": "holochain", - "rev": "d7ad1372ed8f9a8081d7dee0308e552b7decd0b6", + "rev": "7d3c5cfefe6c2cb3b650f69189b6b9e52a01e2c8", "type": "github" }, "original": { @@ -213,11 +213,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1727348695, - "narHash": "sha256-J+PeFKSDV+pHL7ukkfpVzCOO7mBSrrpJ3svwBFABbhI=", + "lastModified": 1728018373, + "narHash": "sha256-NOiTvBbRLIOe5F6RbHaAh6++BNjsb149fGZd1T4+KBg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1925c603f17fc89f4c8f6bf6f631a802ad85d784", + "rev": "bc947f541ae55e999ffdb4013441347d83b00feb", "type": "github" }, "original": { @@ -288,11 +288,11 @@ ] }, "locked": { - "lastModified": 1727577080, - "narHash": "sha256-2LPT76Acp6ebt7fCt90eq/M8T2+X09s/yTVgfVFrtno=", + "lastModified": 1728181869, + "narHash": "sha256-sQXHXsjIcGEoIHkB+RO6BZdrPfB+43V1TEpyoWRI3ww=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "73a833855442ce8cee710cf4d8d054fea1c81196", + "rev": "cd46aa3906c14790ef5cbe278d9e54f2c38f95c0", "type": "github" }, "original": { @@ -304,11 +304,11 @@ "scaffolding": { "flake": false, "locked": { - "lastModified": 1724073530, - "narHash": "sha256-PUM8otA5F5s8ZHxhjupn7R+RZAjh2rueYIFwu3UkK44=", + "lastModified": 1727691892, + "narHash": "sha256-8dMLmpYp19wZhxlR1uiSeR23nGAOhHnyiZ/5CPwOoAg=", "owner": "holochain", "repo": "scaffolding", - "rev": "8a6d1dab0f1668c2781a46d93a5ad638fcf25598", + "rev": "d0290b88ac08e6811d57acb3294a177d107d2528", "type": "github" }, "original": { @@ -327,11 +327,11 @@ }, "locked": { "dir": "versions/0_3", - "lastModified": 1727887143, - "narHash": "sha256-DUSLg1zNuuHvZH+dDgFw7J5Gidq/C+wSsLkprWfyFGc=", + "lastModified": 1728272048, + "narHash": "sha256-DTUdt8/fOXLqieHXgPz9U5qS6MiCh4XGeZ8aEfZnszA=", "owner": "holochain", "repo": "holochain", - "rev": "d7ad1372ed8f9a8081d7dee0308e552b7decd0b6", + "rev": "7d3c5cfefe6c2cb3b650f69189b6b9e52a01e2c8", "type": "github" }, "original": {