Skip to content

WiP restructure of Space_Managers and responsibility of cache,stage and commit #171

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
213 changes: 213 additions & 0 deletions crates/coordinator/holons/src/commit_service.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
use hdk::prelude::*;
use std::cell::{Ref, RefCell, RefMut};
use std::rc::Rc;

//use crate::context::HolonsContext;
use crate::holon::{Holon, HolonState};
use crate::holon_error::HolonError;
use shared_types_holon::{LocalId, MapInteger, MapString};

#[derive(Debug, Eq, PartialEq, Clone)]
pub struct CommitResponse {
pub status: CommitRequestStatus,
pub commits_attempted: MapInteger,
// could the order of these Vecs cause challenges with identifying Holons in relation to their staged_index?
pub saved_holons: Vec<Holon>, // should this be index? where else used?
pub abandoned_holons: Vec<Holon>, // 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<LocalId, HolonError> {
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
///
/// *Incomplete* means one or more of the staged_holons could not be committed.
/// For details, iterate through the staged_holons vector.
/// Holon's with a `Saved` status have been committed,
/// Holon's with a `New` or `Changed` state had error(s), see the Holon's errors vector for details
pub enum CommitRequestStatus {
Complete,
Incomplete,
}


/// This function attempts to persist the state of all staged_holons AND their relationships.
///
/// The commit is performed in two passes: (1) staged_holons, (2) their relationships.
///
/// In the first pass,
/// * if a staged_holon commit succeeds,
/// * change holon's state to `Saved`
/// * populate holon's saved_node
/// * add the holon to the saved_nodes vector in the CommitResponse
/// * if a staged_holon commit fails,
/// * leave holon's state unchanged
/// * leave holon's saved_node unpopulated
/// * push the error into the holon's errors vector
/// * do NOT add the holon to the saved_nodes vector in the CommitResponse
///
/// If ANY staged_holon commit fails:
/// * The 2nd pass (to commit the staged_holon's relationships) is SKIPPED
/// * the overall return status in the CommitResponse is set to `Incomplete`
/// * the function returns.
///
/// Otherwise, the 2nd pass is performed.
/// * If ANY attempt to add a relationship generates an Error, the error is pushed into the
/// source holon's `errors` vector and processing continues
///
///
/// If relationship commits succeed for ALL staged_holons,
/// * The commit_manager's staged_holons are cleared
/// * The Commit Response returns a `Complete` status
///
/// NOTE: The CommitResponse returns clones of any successfully
/// committed holons, even if the response status is `Incomplete`.
///


pub fn commit_holon(holon:&mut Holon) -> CommitResponse{
// Initialize the request_status to Complete, assuming all commits will succeed
// If any commit errors are encountered, reset request_status to `Incomplete`
let mut response = CommitResponse {
status: CommitRequestStatus::Complete,
commits_attempted: MapInteger(1 as i64),
saved_holons: Vec::new(),
abandoned_holons: Vec::new(),
};

// FIRST PASS: Commit Staged Holons
{
info!("\n\nStarting FIRST PASS... commit staged_holons...");
//let commit_manager = context.commit_manager.borrow();
//for rc_holon in rc_holons.clone() {
// trace!(" In commit_manager... getting ready to call commit()");
let outcome = holon.commit(); //rc_holon.borrow_mut().commit();
match outcome {
Ok(holon) => match holon.state {
HolonState::Abandoned => {
// should these be index?
//if !response.abandoned_holons.contains(&holon) {
response.abandoned_holons.push(holon);
//}
}
HolonState::Saved => {
response.saved_holons.push(holon);
}
_ => {}
},
Err(error) => {
response.status = CommitRequestStatus::Incomplete;
warn!("Attempt to commit holon returned error: {:?}", error.to_string());
}
}
//}
}
response
// if response.status == CommitRequestStatus::Incomplete {//
// return response;
// }

/* // SECOND PASS: Commit relationships
{
info!("\n\nStarting 2ND PASS... commit relationships for the saved staged_holons...");
let commit_manager = context.commit_manager.borrow();
for rc_holon in commit_manager.staged_holons.clone() {
let outcome = rc_holon.borrow_mut().commit_relationships(context);
if let Err(error) = outcome {
rc_holon.borrow_mut().errors.push(error.clone());
response.status = CommitRequestStatus::Incomplete;
warn!("Attempt to commit relationship returned error: {:?}", error.to_string());
}
}
}*/

}

pub fn commit_rc_holons(rc_holons: &Vec<Rc<RefCell<Holon>>>) -> CommitResponse {
debug!("Entering commit...");

// Initialize the request_status to Complete, assuming all commits will succeed
// If any commit errors are encountered, reset request_status to `Incomplete`
let mut response = CommitResponse {
status: CommitRequestStatus::Complete,
commits_attempted: MapInteger(rc_holons.len() as i64),
saved_holons: Vec::new(),
abandoned_holons: Vec::new(),
};

// FIRST PASS: Commit Staged Holons
{
info!("\n\nStarting FIRST PASS... commit staged_holons...");
//let commit_manager = context.commit_manager.borrow();
for rc_holon in rc_holons{//.clone() {
trace!(" In commit_manager... getting ready to call commit()");
let outcome = rc_holon.borrow_mut().commit(); //rc_holon.borrow_mut().commit();
match outcome {
Ok(holon) => match holon.state {
HolonState::Abandoned => {
// should these be index?
//if !response.abandoned_holons.contains(&holon) {
response.abandoned_holons.push(holon);
//}
}
HolonState::Saved => {
response.saved_holons.push(holon);
}
_ => {}
},
Err(error) => {
response.status = CommitRequestStatus::Incomplete;
warn!("Attempt to commit holon returned error: {:?}", error.to_string());
}
}
}
}

if response.status == CommitRequestStatus::Incomplete {
return response;
}

// SECOND PASS: Commit relationships
//TODO: do we need to pass through the context?
/*
{
info!("\n\nStarting 2ND PASS... commit relationships for the saved staged_holons...");
//let commit_manager = context.commit_manager.borrow();
for rc_holon in rc_holons.clone(){//commit_manager.staged_holons.clone() {
let outcome = rc_holon.borrow_mut().commit_relationships(context);
if let Err(error) = outcome {
rc_holon.borrow_mut().errors.push(error.clone());
response.status = CommitRequestStatus::Incomplete;
warn!("Attempt to commit relationship returned error: {:?}", error.to_string());
}
}
}*/

info!("\n\n VVVVVVVVVVV SAVED HOLONS AFTER COMMIT VVVVVVVVV\n");
response

}
13 changes: 13 additions & 0 deletions crates/coordinator/holons/src/holon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,19 @@ impl Holon {
})
}

/// gets a specific HolonNode from the local persistent store based on its ActionHash, it then
/// "inflates" the HolonNode into a Holon and returns it
pub fn get_holon_by_local_id(local_id: &LocalId) -> Result<Holon, HolonError> {
let holon_node_record = get(local_id.0.clone(), GetOptions::default())?;
if let Some(node) = holon_node_record {
let holon = Holon::try_from_node(node)?;
return Ok(holon);
} else {
// no holon_node fetched for specified holon_id
Err(HolonError::HolonNotFound(local_id.0.to_string()))
}
}

pub fn get_all_holons() -> Result<Vec<Holon>, HolonError> {
let records = get_all_holon_nodes(());
match records {
Expand Down
Loading