evomimic / map-holons

3 stars 1 forks source link

Complete Implementation of get_related_holons dance #107

Closed evomimic closed 2 days ago

evomimic commented 1 month ago

Summary

This enhancement completes the work begun under issue #84 and delivers the "_get_related_holons_" dance to the Uniform API. This dance is a QueryMethod that retrieves references to existing or staged holons that are related to the source holon via a specified relationship_name (if such a name is supplied) or via ANY relationship if a relationship_name is not supplied. If the source holon is an existing (vs. a staged) holon, then a side-effect of this dance may be to retrieve SmartLinks from the persistent store in order to update the RelationshipTarget(s) within the source holon's RelationshipMap.

Current State of Native Functionality:

Dependencies

Proposal

Enhance Native Functionality

Define and Implement get_related_holons method to the HolonGettable Trait

fn get_related_holons(
        &self,
        context: &HolonsContext,
        relationship_name: Option<RelationshipName>,
    ) -> Result<RelationshipMap, HolonError>;

In this method,

This method populates the cached source holon's RelationshipTarget for the specified relationship if one is provided. If relationship_name is None, the source holon's RelationshipTargets are populated for all relationships that have related holons.

In the holon.rs file

_In the holonreference.rs file

_In the stagedreference.rs file

_In the smartreference.rs file

Dance Enhancements

Implementation Initial Query Layer Data Objects

This issue provides the opportunity to introduce the Query Layer of the guest-side architecture: image

The basic concept is a graph data structure consisting of nodes, relationships, and collections . Nodes, their relationships, and the collections referenced from those relationships are returned as results of query dances and those nodes or collections can be used as inputs to subsequent query dances.

pub struct Collection { members: Vec, query_spec: Option }

pub struct QueryPathMap (pub BTreeMap<RelationshipName, Collection>)

pub struct QueryExpression { relationship_name: Option }


Note that none of these objects actually contain Holon's themselves, only references to holons. Holon state is only maintained in the _Shared Objects Layer_. Specifically, each staged Holon exists exactly once in the _StagingArea_ and each previously persisted holon exists at most once in the _HolonsCache_.

**_In the dance_request.rs file:_**

- [x] Change the DanceType::QueryMethod variant definition to: `QueryMethod(Collection),`
- [x] Add a `RequestBody` variant of `QueryExpression(QueryExpression)`

**_In the dance_response.rs file:_**

- [x] Add a `ResponseBody` variant of `Collection(Collection)`

_**In the holon_dance_adapter.rs file:**_

/// DanceRequest: /// - dance_name: "query_relationships" /// - dance_type: QueryMethod(Collection) -- specifies the Collection to use as the source of the query /// - request_body: QueryExpression(QueryExpression) /// /// /// ResponseBody: /// - Collection -- a collection containing the same source nodes passed in the request, but with their relationships /// updated to include entries that satisfy the criteria set by the QueryExpression supplied in the request ///


- [x] Add a new `build_query_relationships_dance_request` function
- [x] Implement a new `query_relationships_dance` dance function  
This function iterates through the supplied Collection and invokes the `get_related_holons` method on the node's `holon_reference` and transforms the resulting RelationshipMap as follows:
- create a Node whose `source_holon` matches the HolonReference if the input node and whose relationships are populated from the query result as follows:
    - For each entry in the RelationshipMap returned by the native function, add an entry in the Node's `relationships` map. The `RelationshipName` key can be cloned directly from the RelationshipMap. To create the `Collection`, iterate through the _HolonCollection_, create a `Node` for each `HolonReference` and add that node to `members`.

_**In the dancer.rs file:**_

- [x] Add "query_relationships" dance to the Dancer's dispatch table

## Testing Enhancements

_**implement a new test_query_relationships.rs file:**_

- [x] Implement "execute_query_relationships" test step executor

_**In the test_data_types.rs file:**_

- [x] Add a QueryRelationships(Collection, QueryExpression,  ResponseStatusCode) variant in the `DanceTestStep` enum definition
- [x] add its fmt::Display implementation
- [x] implement the `add_query_relationships_test_step` function that takes a Collection, a QueryExpression, and expected ResponseStatusCode

_**In the dance_fixture.rs file:**_
- [x] Edit the existing `simple_add_related_holons_fixture` 
- [x] Add a `query_relationships` step to the test_case after the commit step. Expect OK and check that the previously related holons are returned

_**In the dance_tests.rs file:**_
- [x] Add a match for the  `DanceTestStep::QueryRelationships` step that passes `node_collection`, `query_expression`and `expected_response` to the `execute_query_relationships` function

### Carryover from #79 

- [x] Enhance the _abandon_staged_changes_ test case to use get_related_holons to ensure:
    - [x] relationships that are expected to have been populated on commit ARE populated and relationships that are NOT expected to have been populated have NOT been populated.
    - [x] attempts to get_related_holons for an abandoned holon fail

## Definition of Done:
- [x] After adding `query_relationships_test_step` to the `simple_add_related_holons_fixture`, test case **passes** 
- [x] After adding  `query_relationships_test_step` to the `abandon_staged_changes` test case, test case **passes**
dauphin3 commented 3 weeks ago

@evomimic if there are not relationships for the given name, should get_related_holons just return an empty RelationshipMap, or should it be an Option or HolonError ?

evomimic commented 3 weeks ago

@evomimic if there are not relationships for the given name, should get_related_holons just return an empty RelationshipMap, or should it be an Option or HolonError ?

Empty RelationshipMap

evomimic commented 3 weeks ago

Comments on this morning's push:

Proposal

_In smartreference.rs:

The get_property_map and get_relationship_map methods should just be deleted, but this has ripple effects to other files, so I've pushed those changes off to a separate issue #118.

There are also several issues in the holon.rs file: <I'll fill these in shortly>

evomimic commented 3 weeks ago

Some additional comments on the previous push:

My review also revealed a problem with the load_relationship_map implementation. One of the central tenets of the Shared Objects Layer is at-most-once semantics. Specifically:

  1. a holon_node should be retrieved at-most-once from the persistence tier and then cached and
  2. the links for a holon_node should be retrieved at-most-once from the persistence tier.

In the current implementation, (1) is enforced by HolonCache, but (2) should be enforced by load_relationship_map, but it isn't.

Proposal

_In smartreference.rs:

The get_property_map and get_relationship_map methods should just be deleted, but this has ripple effects to other files, so I've pushed those changes off to a separate issue #118.

There are also several issues in the holon.rs file:

evomimic commented 2 weeks ago

Steps for completing the carryover from Issue #79 . These steps are being deferred to a later issue.

In the holon.rs file:

In the dance_fixtures.rs file for the abandon_staged_changes test chase: