pub struct Aim {}Implementations§
Source§impl Aim
impl Aim
Sourcepub fn create(path: Arc<PathBuf>) -> Result<Sheet>
pub fn create(path: Arc<PathBuf>) -> Result<Sheet>
Creates a new AIMX workspace at the specified path with default structure.
§Initializes the foundational directory architecture and system workflow nodes
required for agentic workflow management. Creates both .aim and .jnl files
for persistent storage with MVCC versioning.
§title: Create
Creates a new AIM workspace at the specified path with the default workspace structure.
This function establishes the foundational directory architecture needed for agentic workflow management and initializes the default system workflow nodes required by the AIM ecosystem.
§Arguments
path- An absoluteArc<PathBuf>specifying the directory path where the workspace files will be created
§Returns
Returns a Sheet representing the successfully initialized workspace root structure.
§Errors
Returns an error if:
- The parent directory cannot be created or accessed
- The workspace files cannot be written to disk
- The workspace path has already been initialized (workspace already exists)
§Behavior
Internally, create() performs the following operations:
- Path Initialization: Sets up the workspace base path and ensures parent directories exist
- Default Node Creation: Initializes the core system workflows including context, inference, status, tool, and workflow management nodes
- Persistent Storage: Saves the workspace configuration to disk with MVCC versioning
- Workspace Binding: Binds the global workspace singleton to the newly created structure
§Side Effects
This function creates the following directory structure and files:
workspace.aim # Main workspace configuration file
workspace.jnl # Version journal for MVCC operations
workspace/ # Directory containing workflow files
├── context.aim # Context management workflow
├── context.jnl # Context workflow journal
├── inference.aim # Inference tracking workflow
├── inference.jnl # Inference workflow journal
├── status.aim # System status workflow
├── status.jnl # Status workflow journal
├── tool.aim # Tool integration workflow
├── tool.jnl # Tool workflow journal
├── workflow.aim # Main workflow container
└── workflow.jnl # Workflow journal§MVCC Behavior
When creating a workspace, create() establishes an initial Multi-Version Concurrency Control (MVCC)
context. The first version (epoch 1) is created immediately with all default nodes populated.
- Initial Version: Starts at epoch 1 with minor version 0
- Node Population: Default nodes are created as immutable facts in the initial version
- Concurrent Visibility: Readers see the complete initialized structure immediately after creation
§File Operations
The function creates both the main .aim files and their corresponding .jnl journal files.
These files are essential for:
- Workspace Recovery: Persisting workspace state across application restarts
- MVCC Tracking: Maintaining version history for concurrent access
- Cross-Reference Integrity: Ensuring workflow nodes can locate each other correctly
§Usage Pattern
use aimx::{Aim, Sheet};
use std::{path::PathBuf, sync::Arc};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Specify the workspace location
let workspace_path = Arc::new(PathBuf::from("/path/to/my_workspace"));
// Create the workspace
let sheet = Aim::create(workspace_path.clone())?;
// Use the returned Sheet to inspect workspace metadata
println!("Created workspace at: {}", sheet.path);
println!("Workspace locator: {}", sheet.locator);
println!("Initial version: {}, minor: {}", sheet.version, sheet.minor_version);
// The workspace is now ready for use with other AIM API functions
Ok(())
}§Performance Considerations
- First-Time Setup: Initial workspace creation involves disk I/O and may take longer than subsequent operations
- Memory Usage: The global workspace singleton consumes memory proportional to the number of default nodes
- File System: Creates multiple small files; consider SSD storage for optimal performance
§See Also
Sourcepub fn open(path: &Path) -> Result<Sheet>
pub fn open(path: &Path) -> Result<Sheet>
§Opens an existing AIMX workspace at the specified path.
§title: Open
Opens an existing AIMX workspace at the specified path and returns the workspace metadata as a Sheet.
This function establishes the global workspace singleton and prepares the workspace for subsequent API operations. It should typically be called first when working with an existing AIMX workspace that was previously created with Aim::create.
§Arguments
path- A reference to thePathwhere the workspace file is located. This should point to the main workspace file (typicallyworkspace.aim).
§Returns
Returns a Sheet containing metadata about the workspace structure, including:
- Workflow locator reference
- File system path
- Version information (current, minor, first, latest)
- Creation timestamp
- Inference model and pattern configuration
- Workflow row count
§Errors
Returns an error if:
- The workspace path has already been initialized by another process running in the same address space
- File system operations fail when creating parent directories
- The workspace structure is corrupted or invalid
§Behavior
Internally, open() performs the following operations:
- Initializes the workspace base path for file operations
- Acquires a write lock on the global workspace singleton
- Converts the workspace node to a
SheetusingSheet::convert - Returns the metadata sheet for inspection
The function does not load individual workflow files until they are specifically accessed via other API calls. It only initializes the workspace structure and makes it available for subsequent operations.
§Side Effects
- Initializes the global workspace singleton
- Establishes the base path for subsequent file operations
- Makes the workspace available for all subsequent API calls
- Creates parent directories if they don’t exist
§Usage Pattern
use aimx::{Aim, Sheet};
use std::path::Path;
fn main() -> anyhow::Result<()> {
// Open an existing workspace
let workspace_path = Path::new("/path/to/existing/workspace.aim");
let sheet = Aim::open(workspace_path)?;
// Use the sheet metadata
println!("Workspace version: {}", sheet.version);
println!("Workflow count: {}", sheet.length);
Ok(())
}§See Also
Aim::create- Create a new workspaceAim::save- Save workspace changesAim::root- Get workspace root referenceSheet- Workspace metadata structure
Sourcepub fn save() -> Result<()>
pub fn save() -> Result<()>
§Saves all pending changes to the current workspace.
§title: Save
This function commits all modifications made to the workspace since the last save operation, persisting the changes to disk and making them visible to other processes or future sessions.
The save operation uses Multi-Version Concurrency Control (MVCC) to ensure that concurrent readers can continue accessing previous versions while the save operation completes. Only workspace-level changes are saved; individual workflow instances require Aim::snapshot to persist their changes.
§Returns
Returns Ok(()) if the save operation completes successfully.
§Errors
Returns an error if:
- The workspace has not been initialized via
Aim::createorAim::open - The workspace path is not accessible or writable
- File system permissions prevent writing to the workspace directory
- The workspace workflow is in an invalid state
- I/O errors occur during file writing operations
§Side Effects
- Writes the main workspace file (
workspace.aim) to disk - Creates a new journal entry (
workspace.jnl) for the save transaction - Updates the workspace’s internal version tracking (epoch and partial counters)
- Makes workspace-level changes visible to concurrent readers via MVCC
- Acquires exclusive write locks during the save process
§MVCC Behavior
The save operation creates a new version snapshot using Multi-Version Concurrency Control:
- Read Consistency: Previous versions remain accessible for concurrent readers during the save
- Write Locking: Writers acquire exclusive locks to prevent concurrent modifications
- Version Visibility: The new version becomes the current readable state after successful save
- Reader Isolation: Existing readers continue to see the version they started with until they refresh
§Usage Pattern
use aimx::{Aim, Cell};
use std::sync::Arc;
// Create or open a workspace
let path = Arc::new(std::path::PathBuf::from("workspace.aim"));
let _sheet = Aim::create(path).unwrap();
// Make some workspace-level changes
let foo_ref = Aim::add("foo", "evaluation").unwrap();
let bar_ref = Aim::add("bar", "inference").unwrap();
// Save workspace changes
Aim::save().unwrap();
// Changes are now persistent and visible to other processes§Implementation Details
Internally, save() performs the following operations:
- Acquires a write lock on the global workspace singleton
- Retrieves a mutable copy of the workspace workflow
- Calls the workflow’s
save()method to persist changes:- If changes require a new version, increments the epoch counter
- If changes are partial, increments the partial counter
- Writes version headers and rule data to the AIM file
- Updates the journal file with position information for fast lookup
- Updates the workspace node with the saved workflow
- Releases the write lock, making changes available to other readers
§Important Notes
- Scope: This function only saves workspace-level changes. Individual workflow instances must use
Aim::snapshotto persist their modifications - Atomicity: Save operations are atomic - either the entire save succeeds or fails
- Durability: Once saved, changes are durable and will persist across application restarts
- Concurrency: The function is thread-safe and uses internal locking to handle concurrent access
- Versioning: Each save operation creates a new version entry in the journal file for audit trail and rollback capabilities
§See Also
Aim::save_all- Save all workflows including nested nodesAim::snapshot- Save changes from a specific workflow instanceAim::create- Create and initialize a new workspaceAim::open- Open an existing workspaceAim::acquire- Acquire exclusive write access to a workflowAim::release- Release a workflow context and finalize changes
Sourcepub fn save_all() -> Result<()>
pub fn save_all() -> Result<()>
§Saves all workflows within the workspace hierarchy.
§title: Save All
This function saves all workflows within the workspace hierarchy, ensuring that all pending changes across the entire workspace tree are persisted to disk. Unlike Aim::save which only saves the root workspace workflow, save_all() traverses the entire workspace tree and saves all modified workflows.
The function uses Multi-Version Concurrency Control (MVCC) to ensure that concurrent readers can continue accessing previous versions while save operations complete. All workflow instances that have been modified must be saved using Aim::snapshot before calling save_all() to ensure their changes are included.
§Returns
Returns Ok(()) if all save operations complete successfully.
§Errors
Returns an error if:
- The workspace has not been initialized via
Aim::createorAim::open - Any workflow in the workspace tree has an inaccessible or unwritable path
- File system permissions prevent writing to any workflow directory
- Any workflow is in an invalid state
- I/O errors occur during file writing operations for any workflow
- A workflow instance has unsaved changes that need to be snapshotted first
§Side Effects
- Writes all modified workflow files (.aim) to disk
- Creates new journal entries (.jnl) for each workflow that required saving
- Updates version tracking (epoch and partial counters) for all modified workflows
- Makes all workflow changes visible to concurrent readers via MVCC
- Acquires exclusive write locks for each workflow during its save process
- Traverses the entire workspace directory tree, potentially accessing many files
§MVCC Behavior
The save_all operation creates new version snapshots for all modified workflows using Multi-Version Concurrency Control:
- Read Consistency: Previous versions remain accessible for concurrent readers during each workflow’s save
- Write Locking: Each workflow acquires exclusive locks to prevent concurrent modifications during its individual save
- Version Visibility: New versions become the current readable state after each workflow’s successful save
- Reader Isolation: Existing readers continue to see the versions they started with until they refresh
- Atomic Per-Workflow: Each workflow’s save is atomic, but the overall operation may save workflows incrementally
§Usage Pattern
use aimx::{Aim, Cell, Reference};
use std::sync::Arc;
// Create or open a workspace
let path = Arc::new(std::path::PathBuf::from("workspace.aim"));
let _sheet = Aim::create(path).unwrap();
// Make some changes to various workflows
let foo_ref = Aim::add("foo", "evaluation").unwrap();
let bar_ref = Aim::add("bar", "inference").unwrap();
// Acquire contexts for nested workflows
let foo_instance = Aim::acquire(foo_ref.clone()).unwrap();
let baz_ref = Aim::add_node(foo_ref.clone(), Arc::from("baz"), "search").unwrap();
// Make changes to nested workflows
let cell = Cell::new("result", "Number", "42", "");
Aim::append_or_update_cell(&foo_instance, cell).unwrap();
// Snapshot individual workflow changes
Aim::snapshot(&foo_instance).unwrap();
Aim::release(&foo_instance).unwrap();
// Save all workflows in the workspace hierarchy
Aim::save_all().unwrap();
// All changes are now persistent and visible to other processes§Implementation Details
Internally, save_all() performs the following operations:
- Acquires a read lock on the global workspace singleton
- Retrieves the workspace workflow and saves it using the standard save process
- Traverses all child nodes in the workspace workflow
- For each child node that represents a workflow:
- Loads the workflow if not already in memory
- Checks if the workflow has pending changes (is_touched())
- If changes exist, saves the workflow:
- Acquires exclusive write lock for the workflow
- Calls the workflow’s
save()method to persist changes - Updates the workflow’s version tracking and journal
- Releases the write lock
- Recursively processes nested workflows in subdirectories
- Returns success only after all workflows have been successfully saved
§Important Notes
- Scope: This function saves ALL workflows in the workspace tree, not just the root workspace
- Performance: This operation can be expensive for large workspace hierarchies as it may need to save many workflows
- Atomicity: While each individual workflow save is atomic, the overall operation saves workflows incrementally. If interrupted, some workflows may be saved while others are not
- Concurrency: The function is thread-safe and uses internal locking, but concurrent modifications during the save process may cause some workflows to be saved with stale data
- Instance Requirements: All workflow instances with pending changes must be snapshotted before calling
save_all()to ensure their changes are included - Error Handling: If any workflow fails to save, the operation stops and returns an error. Some workflows may have been saved before the failure occurred
§Comparison with save()
Aim::save(): Saves only the root workspace workflow. Faster, but doesn’t save nested workflowsAim::save_all(): Saves the root workspace workflow AND all nested workflows. Comprehensive but potentially slower
§See Also
Aim::save- Save only the root workspace workflowAim::snapshot- Save changes from a specific workflow instanceAim::create- Create and initialize a new workspaceAim::open- Open an existing workspaceAim::acquire- Acquire exclusive write access to a workflowAim::release- Release a workflow context and finalize changes
Sourcepub fn compact() -> Result<()>
pub fn compact() -> Result<()>
§Prunes open read-only nodes from memory to free resources and optimize memory usage.
§title: Compact
This function prunes open read-only nodes from memory to free resources and optimize memory usage.
The compact operation traverses all loaded workflow nodes and instances in the workspace, identifying those that have not been modified since they were loaded. These unmodified workflows are converted from their loaded state back to an unloaded state, releasing the memory used to hold their content while preserving the ability to reload them on demand.
§Returns
Returns a Result<()> containing:
Ok(())if compaction completed successfullyErr(anyhow::Error)if an error occurred during the compaction process
§Errors
Returns an error if:
- A poisoned lock is encountered during traversal
- An unexpected internal state is found during compaction
§Behavior
Internally, compact() performs the following operations:
- Acquires a read lock on the global workspace
- Traverses all loaded nodes and instances in the workspace workflow
- For each loaded workflow, checks if it has been modified using
is_touched() - If a workflow hasn’t been touched, converts it from
Loadedstate back toUnloadedstate - Releases memory associated with the workflow content while preserving the reference
§Side Effects
- Reduces memory usage by unloading read-only workflows that haven’t been modified
- Converts
NodeState::LoadedtoNodeState::Unloadedfor untouched workflows - No persistent changes to disk - workflows can be reloaded on next access
§Usage Pattern
The compact function is typically called periodically to optimize memory usage, especially after batch operations that may have loaded many workflows:
use aimx::Aim;
// Perform batch operations that load many workflows
// ... (various API operations that access workflows)
// Compact memory usage
match Aim::compact() {
Ok(()) => println!("Memory compaction completed successfully"),
Err(e) => println!("Memory compaction failed: {}", e),
}§See Also
Node::compact()- Individual node compactionInstance::compact()- Individual instance compactionWorkflow::is_touched()- Check if workflow has been modified
Sourcepub fn root() -> Arc<Reference>
pub fn root() -> Arc<Reference>
§Returns the global singleton reference to the workspace root.
§title: Root
Returns the global singleton reference to the workspace root identifier (_).
This function provides access to the shared workspace reference (_),
which serves as the foundation for navigating the entire AIMX workspace
hierarchy. The root reference acts as the entry point for tree traversal
and workflow discovery operations, and is used internally by several API
functions for workspace-level operations.
§Returns
Returns an Arc<Reference> pointing to the workspace root identifier (_).
This reference is shared across all API instances and maintains thread-safe
access to the global workspace context using OnceCell for lazy initialization.
§Behavior
Internally, root() delegates to Reference::workspace(), which performs the following operations:
- Uses a static
OnceCell<Arc<Reference>>to ensure the reference is created only once - Creates a new single-part reference with the identifier
"_" - Returns a clone of the cached reference for thread-safe sharing
This implementation ensures that:
- The workspace root reference is consistent across the entire application
- Multiple calls to
root()return equivalent references - Thread-safe access is maintained through
ArcandOnceCell
§MVCC Considerations
The root reference operates within the Multi-Version Concurrency Control (MVCC) context
for the workspace. Initially this will be the version that opened via Aim::open.
Concurrent changes being made to this workflow by other processes will not be visible
until either Aim::snapshot or Aim::release are called.
§Usage Pattern
The root reference is typically used as the starting point for workspace operations:
use aimx::{Aim, Reference};
use aimx::expressions::ExpressionLike;
// Get the workspace root reference
let root_reference = Aim::root();
// Use it with API functions for workspace operations
let catalog = Aim::catalog(root_reference.clone()).unwrap();
for node in catalog {
println!("Node: {}", node.to_formula());
}
// Get workspace metadata
let sheet = Aim::sheet(root_reference.clone()).unwrap();
println!("Workspace has {} rules", sheet.length);
// List all rules at the workspace level
let rules = Aim::list(root_reference.clone()).unwrap();
for cell in rules {
if cell.is_node() {
if let Some(identifier) = cell.identifier() {
println!("Node: {}", identifier);
}
}
}§Integration with API
The root reference is used internally by several API functions for workspace-level operations:
Aim::catalog- Lists all nodes in the workspace when passed the root referenceAim::sheet- Gets workspace-level metadata when passed the root referenceAim::list- Enumerates rules at the workspace level when passed the root referenceAim::contains- Checks for the existence of nodes at the workspace levelAim::cell- Retrieves specific cells from the workspace workflow
§See Also
Aim::catalog- Browse workspace hierarchy using the root referenceAim::sheet- Get workspace metadata using the root referenceAim::list- List rules at root level using the root reference- [
Reference::child] - Create child references for navigation from the root Reference::workspace- The underlying function that creates the root referenceAim::open- Establish MVCC workspace context that the root reference operates within
Sourcepub fn catalog(locator: Arc<Reference>) -> Result<Vec<Arc<Sheet>>>
pub fn catalog(locator: Arc<Reference>) -> Result<Vec<Arc<Sheet>>>
§Retrieves a catalog of child node references for the specified workflow locator.
§title: Catalog
This function provides hierarchical navigation through the AIMX workspace by listing
all direct child nodes contained within a given workflow. It supports both workspace
root (_) and nested workflow contexts.
§Arguments
locator- AnArc<Reference>pointing to the workflow whose children should be listed. UseAim::root()for workspace-level cataloging, or any valid workflow reference.
§Returns
Returns a Result<Vec<Arc<Sheet>>> containing sheet metadata for all direct child nodes.
Each sheet represents a navigable child workflow with its metadata. If the locator points
to the workspace root (_), returns all top-level nodes in the workspace. If the locator
points to a specific workflow, returns all nodes defined within that workflow.
§Errors
Returns an error if:
- The locator references a non-existent workflow
- The workflow file cannot be read or is corrupted
- The node structure is incompatible with current API version
§Behavior
Internally, catalog() performs the following operations:
-
Special Case Handling: If the locator is
"_"(workspace root), calls [Workspace::list()] to enumerate all top-level nodes in the workspace workflow. -
Node Resolution: For non-root locators, resolves the target node using
Workspace::locate_node(). -
Workflow Access: Retrieves the workflow from the located node using
Node::get_workflow(). -
Rule Iteration: Iterates through all rules in the workflow using
WorkflowLike::iter_rules(). -
Node Filtering: For each rule, checks if it represents a node using
Rule::is_node(). -
Reference Construction: For each node rule found, constructs a child reference using [
Reference::child()] and the rule’s identifier. -
Result Compilation: Collects all child references into a vector and returns it.
§Side Effects
- Reads workflow data from disk if not already cached in memory
- No modifications are made to the workspace or workflow files
- May trigger lazy loading of workflow content into memory
§Usage Pattern
use aimx::{Aim, Reference, expressions::ExpressionLike};
// Catalog workspace root
let root_reference = Aim::root();
let workspace_nodes = Aim::catalog(root_reference).unwrap();
for node_ref in workspace_nodes {
println!("Found node: {}", node_ref.to_formula());
}
// Catalog a specific workflow
let workflow_reference = Reference::parse("parent").unwrap();
let child_nodes = Aim::catalog(workflow_reference).unwrap();
for child_ref in child_nodes {
println!("Found child: {}", child_ref.to_formula());
}§See Also
Aim::root()- Get workspace root reference for catalogingAim::sheet()- Get workflow metadata for discovered nodesAim::list()- List rules within a workflow (different from cataloging nodes)Aim::contains()- Check if specific node exists- [
Reference::child()] - Construct child references for navigation
§File Operations
The function performs read-only access to workflow files. When cataloging a workflow that
is not currently loaded in memory, the system will read the .aim file from disk and
parse its contents. Subsequent catalog operations on the same workflow will use the
cached in-memory representation.
§MVCC Considerations
The catalog reflects the current version of the workflow state in the workspace. Initially this
will be the version that opened via Aim::open. Concurrent changes being made to this workflow
by other processes will not be visible until either Aim::snapshot or Aim::release are
called.
§Performance Considerations
- Workspace root cataloging is typically fast as it only reads the main workspace workflow
- Deeply nested workflow cataloging may require loading multiple workflow files
- Results are not cached between calls, so frequent cataloging of the same workflow should be done judiciously
- The function scales linearly with the number of rules in the target workflow
Sourcepub fn add(identifier: &str, parameters: &str) -> Result<Arc<Reference>>
pub fn add(identifier: &str, parameters: &str) -> Result<Arc<Reference>>
§Adds a new workflow node to the workspace root with the specified inference configuration.
§title: Add
This function creates a new top-level workflow node in the workspace with the specified inference configuration. The node becomes immediately available for navigation and subsequent operations within the workspace hierarchy.
§Arguments
-
identifier- A unique identifier for the new workflow node. Must be a valid AIMX identifier (alphanumeric characters and underscores, starting with a letter). Cannot be empty or “_” (reserved for workspace root). -
parameters- A string specifying the inference configuration for the workflow. Uses AIMX inference syntax to define the orchestration pattern and optional model.
§Returns
Returns an Arc<Reference> pointing to the newly created workflow node.
This reference can be used for subsequent operations on the workflow.
§Errors
Returns an error if:
- The identifier is empty or invalid
- The identifier “_” is used (reserved for workspace root)
- A node with the same identifier already exists
- The workspace has not been initialized (no call to
Aim::create()orAim::open())
§Side Effects
- Creates a new workflow file (
{identifier}.aim) and corresponding journal file ({identifier}.jnl) in the workspace directory - Updates the workspace workflow with the new node reference
- Creates corresponding journal entries for MVCC tracking
- The new workflow node becomes immediately visible to concurrent readers
§Behavior
Internally, add() performs the following operations:
- Validates the identifier using
parse_identifier()to ensure it follows AIMX naming conventions - Parses the parameters string using
Node::parse()to determine the inference configuration - Checks if a node with the same identifier already exists in the workspace
- Creates a new
Nodewith the specified inference characteristics - Adds the node to the workspace workflow using
workspace.add_node() - Saves the workspace changes to disk
§MVCC Considerations
The new node becomes visible to concurrent readers immediately after this function successfully returns. The operation is atomic - either the node is fully created or no changes are made to the workspace.
§Usage Pattern
use aimx::{Aim, Reference};
use std::sync::Arc;
// Create or open a workspace first
let path = Arc::new(std::env::current_dir().unwrap().join("workspace.aim"));
let _sheet = Aim::create(path).unwrap();
// Add a new workflow node with evaluation pattern (default)
let foo_reference = Aim::add("foo", "evaluation").unwrap();
println!("Created node: {}", foo_reference);
// Add another node with inference pattern and thinking model
let bar_reference = Aim::add("bar", "inference thinking").unwrap();
println!("Created node: {}", bar_reference);
// Verify the nodes exist
assert!(Aim::contains(Aim::root(), "foo").unwrap());
assert!(Aim::contains(Aim::root(), "bar").unwrap());
// Add a node with search pattern and extraction model
let search_reference = Aim::add("searcher", "search extract").unwrap();
println!("Created search node: {}", search_reference);§See Also
Aim::add_node- Add nested nodes within existing workflowsAim::copy- Copy existing workflow nodesAim::rename- Rename workflow nodesAim::remove- Remove workflow nodesAim::catalog- Browse workspace hierarchyAim::save- Persist workspace changesReference- Reference parsing and manipulation
Sourcepub fn copy(from: &str, to: &str) -> Result<()>
pub fn copy(from: &str, to: &str) -> Result<()>
§Copies an existing workflow node to create a new node with a different identifier.
§title: Copy
This function creates a deep copy of an existing workflow node, including all its associated files, directory structure, and child nodes. The copy operation preserves the original node’s inference configuration, rules, and internal structure while assigning it a new identifier in the workspace hierarchy.
§Arguments
-
from- The identifier of the source workflow node to copy. Must be a valid AIMX identifier that exists in the workspace. -
to- The identifier for the new workflow node. Must be a valid AIMX identifier that does not already exist in the workspace.
§Returns
Returns Ok(()) if the copy operation completes successfully.
§Errors
Returns an error if:
- The source node (
from) does not exist - The target identifier (
to) already exists - Either identifier is invalid or empty
- File system operations fail during the copy process
- The workspace cannot be written to
§Side Effects
Creates a complete copy of the source node including:
- Main workflow file (
{to}.aim) - Journal file (
{to}.jnl) if it exists - Directory structure for child nodes
- All child workflow files recursively
- Updates the workspace workflow with the new node reference
§MVCC Considerations
The new top level node becomes visible to concurrent readers immediately after this function successfully returns.
§File Operations
The copy operation performs the following file system operations:
workspace/
├── {from}.aim → workspace/{to}.aim (copied)
├── {from}.jnl → workspace/{to}.jnl (copied if exists)
└── {from}/ → workspace/{to}/ (recursively copied)
├── child1.aim → workspace/{to}/child1.aim
└── child2.aim → workspace/{to}/child2.aim§Usage Pattern
use aimx::Aim;
use std::sync::Arc;
// Copy an existing workflow node
let result = Aim::copy("existing_node", "new_node_copy");
match result {
Ok(()) => println!("Successfully copied existing_node to new_node_copy"),
Err(e) => println!("Failed to copy node: {}", e),
}§Example
use aimx::{Aim, expressions::ExpressionLike};
// Copy an existing workflow node to a new identifier
Aim::copy("existing_workflow", "copied_workflow").unwrap();
// Verify the copy was created
let catalog = Aim::catalog(Aim::root()).unwrap();
let node_names: Vec<String> = catalog
.iter()
.map(|reference| reference.to_formula())
.collect();
assert!(node_names.contains(&"existing_workflow".to_string()));
assert!(node_names.contains(&"copied_workflow".to_string()));§Implementation Details
Internally, copy() performs the following operations:
- Validates both source and target identifiers
- Checks that the source node exists and target node doesn’t exist
- Creates a new
Nodewith the same inference configuration as the source - Copies all associated files (.aim, .jnl) using file system operations
- Recursively copies child node directories if they exist
- Adds the new node reference to the workspace workflow
- Updates the workspace structure
§See Also
Aim::add- Create a new workflow nodeAim::rename- Rename an existing workflow nodeAim::remove- Remove a workflow nodeAim::copy_node- Copy nodes within a workflow contextAim::catalog- Browse workspace hierarchyAim::save- Persist workspace changes
Sourcepub fn rename(from: &str, to: &str) -> Result<()>
pub fn rename(from: &str, to: &str) -> Result<()>
§Renames an existing workflow node in the workspace.
§title: Rename
This function changes the identifier of an existing workflow node, updating all associated files and references while preserving the node’s content, structure, and inference configuration. The rename operation is atomic and maintains the integrity of the workspace hierarchy.
§Arguments
-
from- The current identifier of the workflow node to rename. Must be a valid AIMX identifier that exists in the workspace. -
to- The new identifier for the workflow node. Must be a valid AIMX identifier that does not already exist in the workspace.
§Returns
Returns Ok(()) if the rename operation completes successfully.
§Errors
Returns an error if:
- The source node (
from) does not exist - The target identifier (
to) already exists - Either identifier is invalid or empty
- The identifier “_” is used (reserved for workspace root)
- File system operations fail during the rename process
- The workspace cannot be written to
§Side Effects
Performs comprehensive file system operations to rename all associated files:
- Renames the main workflow file (
{from}.aim→{to}.aim) - Renames the journal file (
{from}.jnl→{to}.jnl) if it exists - Renames the directory (
{from}/→{to}/) if it exists (for child nodes) - Updates the workspace workflow with the new node reference
- Creates corresponding journal entries for MVCC tracking
§MVCC Considerations
The new top level node becomes visible to concurrent readers immediately after this function successfully returns.
§File Operations
The rename operation performs the following file system operations:
workspace/
├── {from}.aim → workspace/{to}.aim (renamed)
├── {from}.jnl → workspace/{to}.jnl (renamed if exists)
└── {from}/ → workspace/{to}/ (renamed if exists)
├── child1.aim → workspace/{to}/child1.aim
└── child2.aim → workspace/{to}/child2.aim§Behavior
Internally, rename() performs the following operations:
- Validates both source and target identifiers using
parse_identifier() - Checks that the source node exists in the workspace workflow
- Verifies that the target identifier doesn’t already exist
- Acquires a write lock on the global workspace singleton
- Updates the node reference in the workspace workflow by calling
rename_node()on the rule - Renames all associated files (.aim, .jnl) using file system operations
- Recursively renames child node directories if they exist
- Saves the updated workspace workflow and updates the workspace structure
The operation preserves all content and structure:
- All rules and their values remain unchanged
- Inference configuration is preserved
- Child nodes become accessible via the new reference path
- Existing references within the workspace are automatically updated
§Usage Pattern
use aimx::{Aim, Reference};
use aimx::expressions::ExpressionLike;
use std::sync::Arc;
// Ensure the workspace exists and contains the node to rename
let root_reference = Aim::root();
let catalog = Aim::catalog(root_reference.clone()).unwrap();
let nodes: Vec<String> = catalog
.iter()
.filter_map(|reference| Some(reference.to_formula()))
.collect();
// Verify the source node exists before renaming
assert!(nodes.contains(&"old_name".to_string()));
// Rename the workflow node
match Aim::rename("old_name", "new_name") {
Ok(()) => {
println!("Successfully renamed 'old_name' to 'new_name'");
// Verify the rename was successful
let updated_catalog = Aim::catalog(root_reference).unwrap();
let updated_nodes: Vec<String> = updated_catalog
.iter()
.filter_map(|reference| Some(reference.to_formula()))
.collect();
assert!(updated_nodes.contains(&"new_name".to_string()));
assert!(!updated_nodes.contains(&"old_name".to_string()));
}
Err(e) => {
eprintln!("Failed to rename node: {}", e);
}
}
// The renamed node is immediately available for use
let new_reference = Reference::parse("new_name").unwrap();§Integration with Workflow Operations
After renaming, the node remains fully functional with:
- All rules and content preserved
- Inference configuration unchanged
- Child nodes accessible via the new reference path
- Existing references automatically updated within the workspace
§See Also
Aim::add- Create a new workflow nodeAim::copy- Copy an existing workflow nodeAim::remove- Remove a workflow nodeAim::rename_node- Rename nodes within a workflow contextAim::catalog- Browse workspace hierarchyAim::save- Persist workspace changes
Sourcepub fn remove(identifier: &str) -> Result<()>
pub fn remove(identifier: &str) -> Result<()>
Removes a workflow node from the workspace along with all associated files.
§This function permanently deletes a workflow node and all its associated resources, including the workflow file, journal file, and any child directories or files. The removal operation is irreversible and comprehensive.
§title: Remove
This function permanently deletes a workflow node and all its associated resources, including the workflow file, journal file, and any child directories or files. The removal operation is irreversible and comprehensive, ensuring no orphaned files remain in the workspace.
§Arguments
identifier- The identifier of the workflow node to remove. Must be a valid AIMX identifier that exists in the workspace. Cannot be “_” (reserved for workspace root) or “workflow” (reserved for workspace itself).
§Returns
Returns Ok(()) if the removal operation completes successfully.
§Errors
Returns an error if:
- The specified node does not exist
- The identifier is “_” or “workflow” (reserved identifiers)
- The workspace cannot be modified (e.g., read-only permissions)
- File system operations fail during the removal process
- The workspace is in an invalid state
§Side Effects
Performs comprehensive file system operations to remove all associated files:
- Deletes the main workflow file (
{identifier}.aim) - Deletes the journal file (
{identifier}.jnl) if it exists - Deletes the directory (
{identifier}/) if it exists, including all child workflows recursively - Removes the node reference from the workspace workflow
- Creates corresponding journal entries for MVCC tracking
§Safety Considerations
This operation is irreversible. Once a node is removed, all its data, rules, child workflows, and inference history are permanently deleted. Applications should implement confirmation dialogs or undo mechanisms when calling this function interactively.
§MVCC Considerations
The removed node becomes invisible to concurrent readers immediately after this function successfully returns.
§File Operations
The removal operation performs the following file system operations:
workspace/
├── {identifier}.aim (deleted)
├── {identifier}.jnl (deleted if exists)
└── {identifier}/ (recursively deleted if exists)
├── child1.aim → (deleted)
└── child2.aim → (deleted)§Behavior
Internally, remove() performs the following operations:
- Validates the identifier is not reserved (“_” or “workflow”)
- Checks that the node exists in the workspace
- Acquires a write lock on the global workspace singleton
- Removes the node reference from the workspace workflow
- Deletes all associated files (.aim, .jnl) using file system operations
- Recursively deletes child node directories if they exist
- Updates the workspace structure
§Integration with Context Operations
If the workflow being removed has an active context instance (via Aim::acquire),
the removal operation will still proceed but may leave orphaned context entries.
Consider calling Aim::release on any active handle before removal.
§Usage Pattern
use aimx::{Aim, Reference};
use std::sync::Arc;
// Create or open a workspace first
let path = Arc::new(std::env::current_dir().unwrap().join("workspace.aim"));
let _sheet = Aim::create(path).unwrap();
// Add a workflow node to remove
let test_reference = Aim::add("test_node", "evaluation").unwrap();
assert!(Aim::contains(Aim::root(), "test_node").unwrap());
// Remove the workflow node
Aim::remove("test_node").unwrap();
// Verify the node is gone
assert!(!Aim::contains(Aim::root(), "test_node").unwrap());
// Try to remove a non-existent node (will return error)
let result = Aim::remove("nonexistent");
assert!(result.is_err());§See Also
Aim::add- Create a new workflow nodeAim::copy- Copy an existing workflow nodeAim::rename- Rename an existing workflow nodeAim::remove_node- Remove nodes within a workflow contextAim::catalog- Browse workspace hierarchy before removalAim::save- Persist workspace changes after removal
Sourcepub fn sheet(locator: Arc<Reference>) -> Result<Sheet>
pub fn sheet(locator: Arc<Reference>) -> Result<Sheet>
§Retrieves metadata and structural information about a workflow as a Sheet.
§title: Sheet
Retrieves comprehensive metadata about a workflow, providing structural information, versioning details, inference configuration, and file system characteristics. This function serves as the primary mechanism for inspecting workflow properties without accessing individual rules or cells.
§Arguments
locator- AnArc<Reference>pointing to the workflow to inspect. UseAim::root()for workspace-level metadata, or any valid workflow reference such as"foo","foo.bar", or"foo.bar.baz".
§Returns
Returns a Sheet containing comprehensive metadata about the specified workflow.
The Sheet structure includes:
- locator: The workflow’s unique reference path within the workspace
- path: Absolute file system path to the workflow
.aimfile - date: Creation/modification timestamp (DateTime)
- version: Current major version (epoch) number
- minor_version: Current minor version (partial) number
- first_version: Initial version when workflow was created
- latest_version: Most recent version available in the journal
- model: Inference model configuration (e.g., “thinking”, “standard”, “fast”)
- pattern: Inference pattern (e.g., “evaluation”, “inference”, “search”)
- length: Number of rules/cells currently in the workflow
§Errors
Returns an error if:
- The locator references a non-existent workflow
- The workflow file cannot be read or is corrupted
- The node structure is incompatible with current API version
§Behavior
Internally, sheet() performs the following operations:
- Checks if the locator is the workspace root (
_) - For workspace root: Calls
Workspace::sheet()to get workspace-level metadata - For specific workflows: Locates the node using
Workspace::locate_node() - Converts the node to a
SheetusingSheet::convert() - Returns the populated
Sheetstructure
§MVCC Considerations
The sheet reflects the current version of the workflow state in the workspace:
- Initially shows the version that opened via
Aim::openorAim::create - Concurrent changes being made by other processes will not be visible until
Aim::snapshotorAim::releaseare called - Does not require write locks (read-only operation)
- Safe for concurrent access with other readers
§Usage Examples
§Basic Usage
use aimx::{Aim, Reference};
use std::sync::Arc;
// Get workspace metadata
let root_reference = Aim::root();
let workspace_sheet = Aim::sheet(root_reference).unwrap();
println!("Workspace path: {}", workspace_sheet.path);
println!("Version: {}.{}", workspace_sheet.version, workspace_sheet.minor_version);§Inspect Specific Workflow
use aimx::{Aim, Reference};
use std::sync::Arc;
// Parse a workflow reference
let reference = Reference::parse("foo.bar").unwrap();
// Get sheet information
let sheet = Aim::sheet(reference).unwrap();
println!("Workflow: {}", sheet.locator);
println!("Rules count: {}", sheet.length);
println!("Model: {}", sheet.model);
println!("Pattern: {}", sheet.pattern);§Check Version Information
use aimx::{Aim, Reference};
use std::sync::Arc;
let reference = Reference::parse("project").unwrap();
let sheet = Aim::sheet(reference).unwrap();
println!("Current version: {}.{}", sheet.version, sheet.minor_version);
println!("First version: {}", sheet.first_version);
println!("Latest version: {}", sheet.latest_version);
println!("Last modified: {}", sheet.date);§Integration with Workflow Operations
The returned Sheet is particularly useful for:
- User Interfaces: Displaying workflow properties and metadata
- Debugging: Understanding workflow structure and configuration
- Monitoring: Tracking workflow health, version history, and size
- Management Tools: Integration with workflow orchestration systems
- Audit Trail: Understanding when workflows were created/modified
- Version Control: Tracking major/minor version changes over time
§Performance Considerations
- Fast Operation: Sheet retrieval is read-only and does not load workflow rules
- Lazy Loading: Node metadata is loaded on-demand
- Caching: Workspace nodes maintain cached metadata for efficiency
- No File I/O: Only reads metadata, not full workflow content
§See Also
Aim::root()- Get workspace root reference for sheet operationsAim::catalog()- Browse workflow hierarchy before inspectionAim::list()- List rules within a workflow (more detailed than sheet)Aim::cell()- Access individual rules within a workflowAim::contains()- Check if a workflow contains a specific ruleSheet- Structure containing workflow metadataReference- Workflow locator and reference system
Sourcepub fn list(locator: Arc<Reference>) -> Result<Vec<Cell>>
pub fn list(locator: Arc<Reference>) -> Result<Vec<Cell>>
§Lists all rules within a workflow as Cell objects.
§title: List
Lists all rules within a workflow as Cell objects, providing a complete view of the
workflow’s structure and content. This function converts internal rule representations
to user-facing Cell objects that can be inspected, modified, or used for analysis.
§Arguments
locator- AnArc<Reference>pointing to the workflow whose rules should be listed. UseAim::root()for workspace-level rules, or any valid workflow reference such as"foo","foo.bar", or"foo.bar.baz".
§Returns
Returns a Result<Vec<Cell>> containing all rules within the specified workflow in their
original order. Each Cell represents a different type of workflow element:
- Formula Cells: Standard rules with type definitions, formulas, and values
- Node Cells: References to nested workflow nodes
- Format Cells: Template and formatting instructions
- Branch Cells: Conditional workflow branching logic
- Retry Cells: Retry logic with conditions and limits
- Comment Cells: Documentation and explanatory text
- Error Cells: Rules that failed to parse or evaluate
- Empty Cells: Placeholder or deleted rule positions
§Errors
Returns an error if:
- The locator references a non-existent workflow
- The workflow file cannot be read or is corrupted
- The node structure is incompatible with current API version
§Behavior
Internally, list() performs the following operations:
- Checks if the locator is the workspace root (
_) - For workspace root: Accesses the workspace workflow via
Workspace::get_node("workflow") - For specific workflows: Locates the node using
Workspace::locate_node() - Iterates through all rows using the workflow’s
iter_rows()method - Converts each row to a
CellusingCell::convert_row() - Returns the vector of
Cellobjects in their original order
§MVCC Considerations
The list reflects the current committed version of the workflow state:
- Shows the version that was opened via
Aim::openorAim::create - Changes made in other processes are not visible until they are committed via
Aim::snapshotorAim::release - Safe for concurrent read access with other processes
- Does not require write locks (read-only operation)
§Usage Examples
§Basic Usage
use aimx::{Aim, Reference};
use std::sync::Arc;
// List rules in a specific workflow
let reference = Reference::parse("project.tasks").unwrap();
let cells = Aim::list(reference).unwrap();
for cell in cells {
if let Some(identifier) = cell.identifier() {
println!("Rule: {}", identifier);
}
if cell.is_formula() {
if let Some(formula) = cell.formula() {
println!(" Formula: {}", formula);
}
if let Some(value) = cell.value() {
println!(" Value: {}", value);
}
}
}§Inspect Workspace Structure
use aimx::{Aim, Cell};
use std::sync::Arc;
// List all workspace-level rules
let root_reference = Aim::root();
let cells = Aim::list(root_reference).unwrap();
println!("Workspace contains {} rules:", cells.len());
for cell in cells {
match cell {
Cell::Node { identifier, value } => {
println!(" Node: {} -> {}", identifier, value);
}
Cell::Comment { comment } => {
println!(" Comment: {}", comment);
}
_ => {
if let Some(identifier) = cell.identifier() {
println!(" Rule: {}", identifier);
}
}
}
}§Filter and Analyze Rules
use aimx::{Aim, Cell, Reference};
use std::sync::Arc;
let reference = Reference::parse("analysis").unwrap();
let cells = Aim::list(reference).unwrap();
// Count different types of rules
let mut formula_count = 0;
let mut node_count = 0;
let mut error_count = 0;
for cell in &cells {
match cell {
Cell::Formula { .. } => formula_count += 1,
Cell::Node { .. } => node_count += 1,
Cell::Errata { .. } => error_count += 1,
_ => {}
}
}
println!("Analysis workflow contains:");
println!(" {} formula rules", formula_count);
println!(" {} node references", node_count);
println!(" {} error rules", error_count);
// Find all error details
let errors: Vec<_> = cells.iter()
.filter_map(|cell| match cell {
Cell::Errata { identifier, reason, .. } => Some((identifier, reason)),
_ => None,
})
.collect();
for (id, reason) in errors {
println!("Error in {}: {}", id, reason);
}§Integration with Context Operations
use aimx::{Aim, Cell, Reference};
use std::sync::Arc;
let workflow_ref = Reference::parse("process").unwrap();
// First, examine the current state
let current_cells = Aim::list(workflow_ref.clone()).unwrap();
println!("Current rules: {}", current_cells.len());
// Acquire write context for modifications
let handle = Aim::acquire(workflow_ref.clone()).unwrap();
// Add a new rule
let new_cell = Cell::new("result", "Number", "input * 2", "");
Aim::append_or_update_cell(&handle, new_cell).unwrap();
// The list function will still show the old state
let still_old = Aim::list(workflow_ref.clone()).unwrap();
assert_eq!(still_old.len(), current_cells.len());
// Commit changes to make them visible
Aim::snapshot(&handle).unwrap();
// Now list shows the updated state
let updated_cells = Aim::list(workflow_ref).unwrap();
assert_eq!(updated_cells.len(), current_cells.len() + 1);
Aim::release(&handle).unwrap();§Cell Type Details
Each Cell type provides different information:
- Formula:
identifier,typedef,formula,value - Node:
identifier,value(workflow reference) - Format:
identifier,instruction,template,examples - Branch:
identifier,condition,target - Retry:
identifier,count,condition,target - Comment:
comment - Errata:
identifier,typedef,reason,formula,location - Empty: No content (placeholder)
§Performance Considerations
- Memory Usage: Loads all rules into memory at once
- File I/O: Reads the complete workflow file
- Conversion Overhead: Converts all internal representations to
Cellobjects - For Large Workflows: Consider using
Aim::cell()for individual rule access - Caching: Results are not cached; each call reads from disk
§Integration with Other Functions
- Preceding Operations: Use
Aim::sheet()to get workflow metadata before listing - Navigation: Use
Aim::catalog()to find child workflows to list - Individual Access: Use
Aim::cell()to access specific rules by identifier - Existence Check: Use
Aim::contains()to verify rule existence - Modification: Use context operations (
Aim::acquire(), etc.) to modify rules
§See Also
Aim::sheet()- Get workflow metadata without loading all rulesAim::catalog()- List child workflow nodes (different from rule listing)Aim::cell()- Access individual rules by identifierAim::contains()- Check if a workflow contains a specific ruleAim::acquire()- Acquire write context for rule modificationsCell- Structure containing rule metadata and contentReference- Workflow locator and reference system
pub fn exists(locator: Arc<Reference>) -> Result<bool>
Sourcepub fn contains(locator: Arc<Reference>, identifier: &str) -> Result<bool>
pub fn contains(locator: Arc<Reference>, identifier: &str) -> Result<bool>
§Checks if a workflow contains a rule with the specified identifier.
§title: Contains
This function performs a fast existence check for rules within a workflow or nodes within the workspace. It’s optimized for quick lookups and is particularly useful for validation, duplicate checking, and conditional workflow operations.
§Arguments
-
locator- AnArc<Reference>pointing to the workflow to search. UseAim::root()to check for node existence in the workspace. -
identifier- The identifier to search for within the workflow. Must be a valid AIMX identifier (alphanumeric, starting with letter).
§Returns
Returns Ok(true) if the identifier exists in the specified workflow,
Ok(false) if it does not exist, or an error if the workflow cannot be accessed.
§Errors
Returns an error if:
- The locator references a non-existent workflow
- The workflow file cannot be read or is corrupted
- The workspace is not properly initialized
§MVCC Considerations
The lookup reflects the current version of the workflow state in the workspace. Initially this
will be the version that opened via Aim::open. Concurrent changes being made to this workflow
by other processes will not be visible until either Aim::snapshot or Aim::release are
called.
§Behavior by Locator Type
When locator is the workspace root (_):
- Checks if a node with the identifier exists in the workspace hierarchy
- Uses
Workspace::contains_node()for workspace-level node lookup - Returns
truefor top-level workflow nodes like “foo”, “bar”, etc.
When locator is a specific workflow reference:
- Checks if a rule with the identifier exists within that workflow
- Uses the workflow’s
contains()method for rule lookup - Returns
truefor rules like “baz”, “index”, “identifier” within the workflow
§Usage Pattern
use aimx::{Aim, Reference};
use std::sync::Arc;
// Acquire workflow context
let reference = Reference::parse("foo.bar").unwrap();
let handle = Aim::acquire(reference.clone()).unwrap();
// Check if rule exists before adding
if !Aim::contains(reference.clone(), "new_rule").unwrap() {
// Rule doesn't exist, safe to add
let cell = aimx::Cell::new("new_rule", "Number", "42", "");
Aim::append_or_update_cell(&handle, cell).unwrap();
}
// Make changes visible
Aim::release(&handle).unwrap();§Performance Considerations
- Optimized: Uses efficient lookup mechanisms without loading unnecessary data
- Cached: Leverages workspace caching for repeated lookups
- Lightweight: Minimal overhead compared to full rule loading with
Aim::list
§See Also
Aim::list- Get all rules (more detailed than existence check)Aim::catalog- List child nodes (different from rule existence)Aim::has_cell- Check rule existence within a write contextAim::get_cell- Get rule details if it existsAim::cell- Access individual rules directly
Sourcepub fn import(_locator: Arc<Reference>, _target_path: &Path) -> Result<()>
pub fn import(_locator: Arc<Reference>, _target_path: &Path) -> Result<()>
§Imports workflow data from a CSV file into an existing workflow.
§title: Import
This function imports workflow data from a CSV file into an existing workflow. The import process reads the CSV file and creates or updates cells (rules) in the workflow based on the imported data. This is useful for bulk data entry, migration from spreadsheets, or initializing workflows with existing datasets.
§Arguments
locator- AnArc<Reference>pointing to the target workflow where data will be imported. The reference must point to an existing workflow in the workspace.target_path- APathspecifying the file system path to the CSV file to import. The file must exist and be readable.
§Returns
Returns a Result<()> indicating success or failure of the import operation.
On success, the workflow will contain the imported data. On failure, the workflow
remains unchanged.
§Errors
Returns an error if:
- The workflow locator references a non-existent workflow
- The CSV file does not exist or cannot be read
- The CSV file has invalid format or encoding
- The CSV data contains invalid cell identifiers or formulas
- The workspace is not properly initialized
- Insufficient permissions to read the CSV file
§Behavior
Internally, import() performs the following operations:
- Validation: Verifies the workflow locator points to an existing workflow
- File Access: Opens and validates the CSV file format
- Data Parsing: Parses CSV rows into cell data structures
- Validation: Validates cell identifiers, types, and formulas
- Import: Creates or updates cells in the target workflow
- Commit: Saves changes to make them permanent
§Usage Pattern
use aimx::{Aim, Reference};
use std::{sync::Arc, path::Path};
// Acquire workflow context
let reference = Reference::parse("data.import_target").unwrap();
let handle = Aim::acquire(reference.clone()).unwrap();
// Import CSV data
let csv_path = Path::new("/path/to/data.csv");
match Aim::import(reference.clone(), csv_path) {
Ok(()) => println!("Data imported successfully"),
Err(e) => println!("Import failed: {}", e),
}
// Make changes visible
Aim::release(&handle).unwrap();§CSV Format
The CSV file should follow this format:
identifier,typedef,formula,value
user_count,Number,,1000
user_revenue,Number,"user_count * 50",
growth_rate,Number,"(current_revenue / previous_revenue) - 1",0.15Column Requirements:
identifier: Unique cell identifier (required)typedef: Type definition (Number, Text, Bool, etc.) (required)formula: AIMX expression formula (optional)value: Static value (optional)
§Side Effects
- Creates new cells in the target workflow
- Updates existing cells if identifiers match
- Modifies workflow structure permanently
- Generates new version in the workflow journal
- Triggers evaluation of affected formulas
§File Operations
The import function performs the following file operations:
- Reads the CSV file from the specified path
- Parses CSV content in memory
- Writes changes to the workflow file
- Updates the workflow journal with version information
- No temporary files are created
§MVCC Considerations
The import operation is subject to MVCC (Multi-Version Concurrency Control):
- Isolation: Import runs within an acquired write context
- Atomicity: Changes become visible only after successful completion
- Consistency: Invalid data prevents any changes from being applied
- Conflict Prevention: Workflow must be acquired before import
- Rollback: On error, no changes are applied to the workflow
§Performance Considerations
- Batch Processing: Large CSV files are processed efficiently
- Memory Usage: CSV data is loaded incrementally to manage memory
- Disk I/O: Minimizes file operations through batch writes
- Validation: Comprehensive validation prevents invalid data entry
- Error Handling: Stops on first validation error to prevent partial imports
§See Also
Reference- References a workflow locationAim::export()- Export workflow data to CSVAim::acquire()- Acquire write context for modificationsAim::release()- Release workflow contextCell- Represents a single cell/rule in a workflow
Sourcepub fn export(_locator: Arc<Reference>, _target_path: &Path) -> Result<()>
pub fn export(_locator: Arc<Reference>, _target_path: &Path) -> Result<()>
§Exports workflow data to a CSV file from an existing workflow.
§title: Export
This function exports workflow data to a CSV file from an existing workflow. The export process reads the workflow cells (rules) and writes them to a CSV file in a format that can be imported back into AIMX or used with external spreadsheet applications. This is useful for data backup, migration to spreadsheets, or analysis with external tools.
§Arguments
locator- AnArc<Reference>pointing to the source workflow to export. The reference must point to an existing workflow in the workspace.target_path- APathspecifying the file system path where the CSV file will be created. The file will be created or overwritten if it already exists.
§Returns
Returns a Result<()> indicating success or failure of the export operation.
On success, a CSV file will be created at the specified path containing the
workflow data. On failure, no file is created or modified.
§Errors
Returns an error if:
- The workflow locator references a non-existent workflow
- The target path is invalid or cannot be written to
- The parent directory does not exist and cannot be created
- Insufficient permissions to create or write the file
- The workspace is not properly initialized
- The workflow cannot be read due to concurrent access issues
§Behavior
Internally, export() performs the following operations:
- Validation: Verifies the workflow locator points to an existing workflow
- Workflow Access: Opens the workflow for reading
- Data Collection: Gathers all cells (rules) from the workflow
- CSV Generation: Converts cell data to CSV format
- File Creation: Creates the target CSV file and writes the data
- Completion: Ensures the file is properly written and closed
§Usage Pattern
use aimx::{Aim, Reference};
use std::{sync::Arc, path::Path};
// Acquire workflow context (optional for export)
let reference = Reference::parse("data.export_source").unwrap();
// Export workflow to CSV
let csv_path = Path::new("/path/to/exported_data.csv");
match Aim::export(reference.clone(), csv_path) {
Ok(()) => println!("Data exported successfully"),
Err(e) => println!("Export failed: {}", e),
}§CSV Format
The exported CSV file follows this format:
identifier,typedef,formula,value
user_count,Number,,1000
user_revenue,Number,"user_count * 50",
growth_rate,Number,"(current_revenue / previous_revenue) - 1",0.15
status,Text,,"active"
is_valid,Bool,,trueColumn Structure:
identifier: Cell identifier (unique within workflow)typedef: Type definition (Number, Text, Bool, Date, etc.)formula: AIMX expression formula (empty if static value)value: Current evaluated value (empty if formula-based)
§Side Effects
- Creates or overwrites a CSV file at the target path
- No modifications are made to the source workflow
- Generates file system I/O operations
- No changes to workflow versioning or journaling
- No impact on concurrent readers or writers
§File Operations
The export function performs the following file operations:
- Creates the target CSV file (overwrites if exists)
- Writes CSV header row with column names
- Writes one row per workflow cell
- Uses comma-separated values with proper escaping
- Handles text values with quotes when necessary
- No temporary files are created
§MVCC Considerations
The export operation respects MVCC (Multi-Version Concurrency Control):
- Read-Only: Export operates on the current committed state of the workflow
- Consistency: Sees a consistent snapshot of the workflow at export time
- No Locking: Does not acquire write locks or block other operations
- Visibility: Exports data that is visible to all concurrent readers
- Non-Blocking: Does not interfere with ongoing write operations
- Snapshot Isolation: Exports the latest committed version, not pending changes
§Performance Considerations
- Memory Usage: Loads workflow data incrementally for large workflows
- Disk I/O: Single sequential write operation for the CSV file
- Encoding: Uses UTF-8 encoding for text data
- Escaping: Properly escapes CSV special characters (commas, quotes, newlines)
- Batch Processing: Efficiently handles workflows with many cells
- Minimal Overhead: No additional validation or transformation overhead
§Compatibility
The exported CSV format is compatible with:
- AIMX import functionality (
Aim::import()) - Microsoft Excel and other spreadsheet applications
- Database import tools
- Data analysis software (Python pandas, R, etc.)
- Custom data processing scripts
§See Also
Reference- References a workflow locationAim::import()- Import workflow data from CSVAim::print()- Print workflow to markdown stringCell- Represents a single cell/rule in a workflowAim::list()- List all cells in a workflowAim::sheet()- Get workflow metadata and structure
Sourcepub fn print(_locator: Arc<Reference>) -> Result<Arc<str>>
pub fn print(_locator: Arc<Reference>) -> Result<Arc<str>>
§Print workflow to md string
§title: Print
This function generates a markdown string representation of a workflow for display, documentation, or debugging purposes. The print operation reads the workflow structure and content, formatting it as human-readable markdown that can be displayed in applications, included in documentation, or used for debugging workflow structure and content.
§Arguments
locator- AnArc<Reference>pointing to the workflow to print. The reference must point to an existing workflow in the workspace.
§Returns
Returns a Result<Arc<str>> containing a markdown string representation of the
workflow. On success, the string contains structured markdown with workflow
metadata, cell listings, and formatting suitable for display in markdown viewers
or documentation systems. On failure, returns an error describing what went wrong.
§Errors
Returns an error if:
- The workflow locator references a non-existent workflow
- The workspace is not properly initialized
- The workflow cannot be read due to concurrent access issues
- Insufficient permissions to access the workflow
§Behavior
Internally, print() performs the following operations:
- Validation: Verifies the workflow locator points to an existing workflow
- Workflow Access: Opens the workflow for reading
- Metadata Collection: Gathers workflow metadata (sheet information)
- Cell Collection: Retrieves all cells (rules) from the workflow
- Markdown Generation: Formats the data into structured markdown
- String Construction: Creates an efficient string representation
§Usage Pattern
use aimx::{Aim, Reference};
use std::sync::Arc;
// Get a reference to the workflow to print
let reference = Reference::parse("project.workplan").unwrap();
// Generate markdown representation
match Aim::print(reference.clone()) {
Ok(markdown) => {
println!("Workflow documentation:");
println!("{}", markdown);
// Could also save to file for documentation
std::fs::write("workplan.md", &*markdown).unwrap();
},
Err(e) => println!("Print failed: {}", e),
}§Markdown Format
The generated markdown follows this structured format:
# Project Workplan
## Workflow Metadata
- **Path**: workspace/project/workplan.aim
- **Model**: evaluation
- **Pattern**: standard
- **Version**: 3 (latest: 3, first: 1)
- **Cells**: 12 total
## Workflow Cells
### Formula Cells
**task_count**: Number = 5
**completed_tasks**: Number = "task_count - pending_tasks" $5
**progress**: Number = "completed_tasks / task_count * 100" $100
### Node Cells
**subproject**: Node = "subproject_details"
### Branch Cells
**decision_point**: Branch = "task_count > 10" -> "complex_workflow"
### Format Cells
**report_template**: Format = "Generate weekly report" <report.md> "weekly", "summary"
### Comment Cells
> This workflow manages project task tracking and reporting
### Error Cells
**invalid_rule**: Error = "division_by_zero" # Cannot divide by zero (at line 12)Section Structure:
- Title: Workflow name based on reference
- Metadata: Sheet information (path, model, version, cell count)
- Cell Categories: Organized by cell type (Formula, Node, Branch, etc.)
- Cell Details: Identifier, type, formula, and current value
- Comments: Workflow documentation and notes
- Errors: Any evaluation or parsing errors
§Side Effects
- No modifications are made to the source workflow
- No file system changes are made
- Generates minimal memory usage for large workflows
- No changes to workflow versioning or journaling
- No impact on concurrent readers or writers
- Pure read operation with no state changes
§Performance Considerations
- Memory Usage: Efficiently builds string representation without intermediate copies
- Lazy Evaluation: Only loads workflow data needed for display
- String Optimization: Uses
Arc<str>for efficient string sharing - Incremental Processing: Handles large workflows without excessive memory usage
- No Caching: Each call reads fresh data from the workflow
- Minimal Overhead: Direct formatting without intermediate data structures
§Display Integration
The markdown output is designed for integration with various display systems:
- Documentation Tools: Compatible with markdown processors (GitHub, GitLab, etc.)
- IDE Integration: Can be displayed in IDE markdown preview panels
- Web Applications: Suitable for rendering in web-based markdown viewers
- CLI Tools: Can be printed to terminals with markdown support
- Documentation Generation: Integrates with static site generators
§Comparison with Other Functions
Compared to related functions:
- vs
export():print()generates markdown for display,export()creates CSV for data exchange - vs
list():print()formats for human consumption,list()returns structuredCellobjects - vs
sheet():print()includes cell content,sheet()returns only metadata
§See Also
Reference- References a workflow locationAim::export()- Export workflow data to CSVAim::list()- List all cells in a workflowAim::sheet()- Get workflow metadata and structureCell- Represents a single cell/rule in a workflowSheet- Contains workflow metadata and structure information
Sourcepub fn cell(locator: Arc<Reference>, identifier: Arc<str>) -> Result<Cell>
pub fn cell(locator: Arc<Reference>, identifier: Arc<str>) -> Result<Cell>
§Retrieves a specific cell (rule) from a workflow by its identifier.
§title: Cell
This function retrieves a specific cell (rule) from a workflow by its identifier, providing
direct access to the current state of that rule. It supports reading cells from any
workflow in the workspace hierarchy and converts internal rule representations into
high-level Cell objects that can be easily consumed by applications.
§Arguments
locator- AnArc<Reference>pointing to the workflow containing the cell. This can reference any workflow in the workspace hierarchy using dot notation (e.g.,"foo","foo.bar","foo.bar.baz").identifier- AnArc<str>specifying the unique identifier of the cell to retrieve. Must exactly match the rule’s identifier in the workflow.
§Returns
Returns a Result<Cell> containing:
Cell::Empty- If no cell with the specified identifier exists in the workflowCell::Comment- For comment cells containing documentation textCell::Errata- For error cells with detailed error information including reason, formula, and locationCell::Node- For workflow node references with their configuration valuesCell::Format- For formatting instruction cells with instruction, template, and examplesCell::Branch- For conditional branch cells with condition and target workflowCell::Retry- For retryable operation cells with count, condition, and targetCell::Formula- For formula-based rule cells with type definition, formula, and current valueCell::Result- For inference result cells (when used withAim::results)
§Errors
Returns an error if:
- The locator references a non-existent workflow node
- The reference path contains invalid syntax
- File system access fails when reading workflow files
§Behavior
Internally, cell() performs the following operations:
- Reference Construction: Creates a child reference by appending the identifier
to the locator using
locator.child(identifier) - Rule Resolution: Uses
Workspace::locate_rule()to find the rule at the specified reference path - Cell Conversion: If a rule is found, converts it to a
CellusingCell::convert_rule()which handles all rule types and error states - Empty Handling: If no rule is found, returns
Cell::Emptyrather than an error for graceful handling of missing cells
§MVCC Visibility
This function provides read-only access to the current MVCC version of the workflow:
- Initially reflects the version loaded when the workspace was opened
- Changes made by other processes become visible after
Aim::snapshotorAim::releaseare called - Concurrent modifications within the same process are only visible after being committed to the workflow
§Usage Pattern
use aimx::{Aim, Reference, Cell};
use std::sync::Arc;
// Open an existing workspace
let workspace_path = std::path::Path::new("workspace.aim");
let _sheet = Aim::open(workspace_path).unwrap();
// Get a reference to a specific workflow
let workflow_ref = Reference::parse("my_workflow").unwrap();
// Retrieve a specific cell from the workflow
let cell = Aim::cell(workflow_ref, Arc::from("my_rule")).unwrap();
// Check the cell type and extract information
match cell {
Cell::Formula { identifier, typedef, formula, value } => {
println!("Formula cell: {} : {} = {}", identifier, typedef, formula);
println!("Current value: {}", value);
}
Cell::Node { identifier, value } => {
println!("Node cell: {} = {}", identifier, value);
}
Cell::Empty => {
println!("No cell found with that identifier");
}
_ => {
println!("Other cell type: {:?}", cell);
}
}§Side Effects
- Read-only: This function does not modify any workflow state
- File Access: May trigger lazy loading of workflow files from disk
- Caching: Leverages workspace caching for improved performance on repeated access
§Performance Considerations
- Efficient Lookup: Uses direct reference-based lookup without loading unnecessary data
- Lazy Loading: Workflow files are only loaded when first accessed
- Cached Access: Subsequent calls to the same workflow benefit from in-memory caching
- Reference Resolution: Minimal overhead for constructing and resolving references
§Differences from Context-Based Operations
This function provides read-only MVCC access to committed workflow state:
- Use
Aim::get_cellfor reading cells within an active write context - Use
Aim::has_cellfor checking cell existence without retrieving content - Use
Aim::listfor retrieving all cells in a workflow at once - Use
Aim::acquireto begin a write context for modifications
§Error Handling
The function gracefully handles missing cells by returning Cell::Empty rather
than an error. This allows applications to check for cell existence without
exception handling:
use aimx::{Aim, Reference, Cell};
use std::sync::Arc;
let workflow_ref = Reference::parse("my_workflow").unwrap();
let cell = Aim::cell(workflow_ref, Arc::from("optional_rule")).unwrap();
if !cell.is_empty() {
// Process the cell
if let Some(identifier) = cell.identifier() {
println!("Found cell: {}", identifier);
}
}§See Also
Aim::list- Retrieve all cells in a workflowAim::contains- Check if a cell exists without retrieving itAim::get_cell- Read cells within an active write contextAim::sheet- Get workflow metadata and structural informationAim::acquire- Acquire write context for workflow modificationsCell- Complete documentation for cell types and methodsReference- Documentation for reference construction and parsing
Sourcepub fn acquire(locator: Arc<Reference>) -> Result<Arc<str>>
pub fn acquire(locator: Arc<Reference>) -> Result<Arc<str>>
§Acquires exclusive write access to a workflow for modifications.
§title: Acquire
Acquires exclusive write access to a workflow for modifications.
This function establishes a write context for a workflow, enabling modifications to its rules, structure, and inference configuration. It implements Multi-Version Concurrency Control (MVCC) by creating a mutable copy of the workflow that can be modified independently of concurrent readers.
§Arguments
locator- AnArc<Reference>pointing to the workflow to acquire for writing. The reference must point to an existing workflow in the workspace.
§Returns
Returns an Arc<str> containing a unique instance handle that identifies the
active write context. This handle must be used for all subsequent write operations
and must be released with Aim::release() to free the workflow for other writers.
§Errors
Returns an error if:
- The workflow locator references a non-existent workflow
- The workflow is already acquired by another process (concurrent write conflict)
- The context workflow cannot be accessed or modified
- The workspace is not properly initialized
§Behavior
Internally, acquire() performs the following operations:
- Context Workflow Access: Locates the global context workflow (
context.aim) - Handle Generation: Converts the reference to a handle string using underscore separators
- Conflict Check: Verifies the workflow is not already in use by checking if the handle exists
- Write Lock Acquisition: Acquires exclusive access to the context workflow
- Instance Registration: Adds the instance handle to the context workflow as an instance mapping
§Side Effects
- Creates or modifies the global
context.aimworkflow to track active instances - Acquires an exclusive write lock on the context workflow
- Registers the workflow instance for MVCC isolation
- Makes the workflow unavailable for concurrent writers
§Usage Pattern
Always use acquire() in conjunction with release() to prevent resource leaks:
use aimx::{Aim, Reference, Cell};
use std::sync::Arc;
// Acquire workflow context
let reference = Reference::parse("foo.bar").unwrap();
let handle = Aim::acquire(reference.clone()).unwrap();
// Make changes to the workflow
let cell = Cell::new("meaning_of_life", "Number", "", "42");
Aim::append_or_update_cell(&handle, cell).unwrap();
// Make changes visible
Aim::snapshot(&handle).unwrap();
// Release the workflow
Aim::release(&handle).unwrap();§See Also
Reference- References a workflow locationAim::snapshot()- Create intermediate checkpointsAim::release()- Release a workflow context
§MVCC Considerations
The acquire function implements Multi-Version Concurrency Control:
- Isolation: Writers work on a private copy of the workflow
- Consistency: Readers continue to see the previous version
- Atomicity: Changes become visible only after
Aim::snapshot()orAim::release() - Conflict Prevention: Only one writer can acquire a workflow at a time
- Conflict Detection: Attempting to acquire an already-acquired workflow returns an error
§MVCC Visibility Timeline
Time | Writer Operations | Reader Operations
-------------|------------------------------|------------------------
T0 | acquire() | cell(), list(), contains()
T1 | append_or_update_cell() | (changes not visible yet)
T2 | snapshot() | (changes now visible)
T3 | update_cell() | (additional changes not visible yet)
T4 | release() | (final state permanent)§Performance Considerations
- Low Overhead: Handle acquisition is lightweight
- File System: Minimal I/O operations during acquisition
- Memory Usage: Creates a copy of workflow data in memory
- Lock Duration: Keep acquisition periods short for better concurrency
- Handle Format: Generated handles use underscore-separated format for uniqueness
Sourcepub fn snapshot(handle: &str) -> Result<()>
pub fn snapshot(handle: &str) -> Result<()>
§Saves the current state of a workflow instance to disk, making changes permanently visible.
§title: Snapshot
This function creates a durable snapshot of all pending changes made within a workflow context,
persisting them to the workflow’s .aim file and updating the MVCC version history. Unlike
Aim::save() which operates at the workspace level, snapshot() focuses on instance-specific
changes and is typically called after completing a set of related modifications.
§Arguments
handle- The unique instance handle obtained fromAim::acquire()that identifies the active workflow context to snapshot.
§Returns
Returns Ok(()) if the snapshot operation completes successfully.
§Errors
Returns an error if:
- The instance handle is invalid or expired
- The workflow file cannot be written (permissions, disk full)
- The workflow is in an invalid state (corrupted structure)
- Concurrent modifications conflict with the snapshot operation
§MVCC Behavior
The snapshot operation operates within the Multi-Version Concurrency Control system:
- Creates a new version entry in the workflow’s journal file (
.jnl) - Marks the snapshot version as the new readable state for concurrent readers
- Previous versions remain accessible for existing readers
- Writers acquire exclusive locks during the snapshot process
§Side Effects
- Writes the workflow file (
{identifier}.aim) with all current changes - Creates a journal entry in the workflow’s journal file (
{identifier}.jnl) - Updates the workflow’s version metadata (
version,latest_version) - Makes all context changes visible through the
Aim::cell()andAim::list()APIs
§MVCC Visibility Timeline
Time | Context Operations | MVCC Read Operations
-------------|------------------------------|------------------------
T0 | acquire() | cell(), list(), contains()
T1 | append_or_update_cell() | (changes not visible yet)
T2 | snapshot() | (changes now visible)
T3 | update_cell() | (additional changes not visible yet)
T4 | release() | (final state permanent)§Usage Pattern
snapshot() should be called after completing a logical group of changes:
use aimx::{Aim, Cell, Reference};
use std::sync::Arc;
// Acquire workflow context
let reference = Reference::parse("foo.bar").unwrap();
let handle = Aim::acquire(reference.clone()).unwrap();
// Make related changes
let input_cell = Cell::new("input_data", "Text", r#""processed""#, "");
Aim::append_or_update_cell(&handle, input_cell).unwrap();
let result_cell = Cell::new("analysed", "Bool", "true", "");
Aim::append_or_update_cell(&handle, result_cell).unwrap();
// Snapshot the logical unit of work
Aim::snapshot(&handle).unwrap();
// Changes are now visible to other processes
assert!(Aim::contains(reference.clone(), "input_data").unwrap());
assert!(Aim::contains(reference.clone(), "analysed").unwrap());
Aim::release(&handle).unwrap();§Performance Considerations
- Atomicity: The snapshot operation is atomic - either all changes are saved or none are
- Efficiency: Consider batching related changes before calling
snapshot() - Frequency: Balance between frequent snapshots (safety) vs. performance overhead
§Implementation Details
Internally, snapshot() performs:
- Locates the instance context using the provided handle
- Acquires a write lock on the instance
- Calls the instance’s
save()method to persist changes - Updates the workflow’s version tracking
- Releases the write lock
§Error Handling Strategy
In case of failure:
- The workflow remains in its previous consistent state
- The instance handle remains valid for retry attempts
- Detailed error information is available for debugging
§See Also
Aim::acquire()- Acquire a workflow context for modificationsAim::release()- Release a workflow context and finalize changesAim::save()- Save workspace-level changesAim::save_all()- Batch save multiple workflowsAim::cell()- Read cells through MVCC after snapshotAim::list()- List workflow rules through MVCC after snapshot
Sourcepub fn release(handle: &str) -> Result<()>
pub fn release(handle: &str) -> Result<()>
§Releases a workflow context handle and finalizes all pending changes.
§title: Release
This function releases a workflow context handle and finalizes all pending changes. It performs the final cleanup of a workflow modification session by saving any remaining changes and removing the instance from the global context workflow.
§Arguments
handle- A string slice containing the unique instance handle obtained fromAim::acquire()that identifies the active workflow context to release.
§Returns
Returns Result<()> which is:
Ok(())if the release operation completes successfullyErr(anyhow::Error)if any step fails
§Errors
Returns an error if:
- The instance handle is invalid or cannot be located
- The instance cannot be locked for writing (e.g., concurrent access)
- The workflow save operation fails (e.g., file system errors)
- The context workflow cannot be located or accessed
- The instance entry cannot be found in the context workflow
- The context workflow operations fail (e.g., save errors)
§Behavior
Internally, release() performs a two-phase cleanup operation:
Phase 1: Final Save
- Locates the instance context using the provided handle via
Instance::locate() - Acquires a write lock on the instance context
- Calls
save()on the instance to persist any remaining changes - Releases the instance write lock
Phase 2: Context Cleanup
- Locates the global
contextworkflow usingReference::context() - Acquires a write lock on the context workflow via
LockManager - Searches for the instance handle in the context workflow using the workflow’s
get_indexmethod - Removes the instance row from the context workflow via the workflow’s
remove_rowmethod - Saves the updated context workflow via the workflow’s
savemethod - Updates the context node with the modified workflow
- Releases the context workflow write lock
§Side Effects
- Final Persistence: Saves any unsaved changes to the target workflow
- Context Cleanup: Removes the instance entry from the global context workflow
- Lock Release: Releases write locks on both the instance and context workflow
- Resource Cleanup: Makes the workflow available for future
Aim::acquire()calls - MVCC Update: Finalizes the version state for concurrent readers
§Usage Pattern
use aimx::{Aim, Reference};
use std::sync::Arc;
// Acquire workflow context
let reference = Reference::parse("foo.bar").unwrap();
let handle = Aim::acquire(reference.clone()).unwrap();
// Make changes to the workflow using the handle
// ... workflow modifications ...
// Make changes visible and release
Aim::release(&handle).unwrap();§Error Handling
The function uses a strict error handling approach:
- If the instance cannot be located or saved, the function returns an error
- If the context cleanup fails, the function returns an error indicating that the instance may still be locked and require manual cleanup
- If the instance is not found in the context workflow, returns a specific error message indicating a missing instance
§MVCC Considerations
The release operation finalizes the Multi-Version Concurrency Control cycle:
- Creates a final version of all accumulated changes
- Makes the final state permanently visible to concurrent readers
- Removes the exclusive write lock, allowing other processes to acquire the workflow
- Updates the workflow’s version tracking in the journal
§Differences from Aim::snapshot()
| Function | Timing | Lock Behavior | Context State | Purpose |
|---|---|---|---|---|
snapshot() | During session | Keeps context active | Context remains acquired | Intermediate checkpoint |
release() | End of session | Releases all locks | Context is released | Final cleanup and persistence |
Use snapshot() for intermediate saves during long-running operations, and
release() when the modification session is complete and the context should
be cleaned up.
§See Also
Aim::acquire()- Acquire a workflow context for modificationsAim::snapshot()- Create intermediate checkpoints during modificationsAim::save()- Save workspace-level changesInstance::locate()- Locate an instance by handle- Context lifecycle management best practices
Sourcepub fn add_node(
locator: Arc<Reference>,
identifier: Arc<str>,
parameters: &str,
) -> Result<Arc<Reference>>
pub fn add_node( locator: Arc<Reference>, identifier: Arc<str>, parameters: &str, ) -> Result<Arc<Reference>>
§Adds a new child workflow node within an existing workflow using an active write context.
§title: Add node
This function creates a nested workflow node within a parent workflow that has an active
write context (Aim::acquire()). This enables hierarchical workflow structures where
workflows can contain sub-workflows, supporting complex agentic workflow compositions.
§Arguments
-
handle- The unique instance handle obtained fromAim::acquire()that identifies the active write context for the parent workflow. -
identifier- AnArc<str>specifying the unique identifier for the new child node. Must be a valid AIMX identifier (alphanumeric, starting with letter, no underscores). The identifier should be unique within the parent workflow. -
parameters- A string specifying the inference configuration for the child workflow. Uses the same AIMX inference syntax asAim::add():- Patterns: “evaluation”, “inference”, “search”, “summarize”, “compose”, “debate”
- Models: “fast”, “standard”, “thinking”, “extract”, “instruct”, “coder” Examples: “evaluation”, “inference thinking”, “search extract”
§Returns
Returns an Arc<Reference> pointing to the newly created child workflow node.
The reference path will be {parent_workflow}.{identifier} (e.g., foo.baz).
§Errors
Returns an error if:
- The instance handle is invalid or expired
- The identifier is empty, contains invalid characters, or is “_”
- A node with the same identifier already exists within the parent workflow
- The parameters string contains invalid inference syntax
- The parent workflow file cannot be written to
- The workspace is in an invalid state
§Behavior
Internally, add_node() performs the following operations:
- Locates the active instance context using the provided handle
- Acquires a write lock on the workflow instance
- Parses the inference parameters into a
Nodestructure - Calls the workflow’s
add_node()method to create the child workflow - Creates the child workflow file with default structure
- Returns a reference to the newly created child node
§File Operations
This function creates the following file system structure:
workspace/
├── {parent}.aim # Parent workflow file (updated with node rule)
└── {parent}/ # Parent workflow directory (created if needed)
└── {identifier}.aim # New child workflow file with default headerThe child workflow is initialized as an unloaded node and will be created on first access.
§Usage Pattern
Basic usage with hierarchical workflows:
use aimx::{Aim, Reference};
use std::sync::Arc;
// Create top-level workflow
let foo_ref = Aim::add("foo", "evaluation").unwrap();
// Acquire write context for the parent workflow
let handle = Aim::acquire(foo_ref.clone()).unwrap();
// Add child workflow optimized for complex reasoning
let child_ref = Aim::add_node(foo_ref.clone(), Arc::from("analysis"), "inference thinking").unwrap();
println!("Created child workflow: {}", child_ref);
// Make changes visible to other readers
Aim::snapshot(&handle).unwrap();
// Child workflow is now accessible via MVCC
let child_sheet = Aim::sheet(child_ref).unwrap();
println!("Child workflow model: {}", child_sheet.model);
// Release the write context
Aim::release(&handle).unwrap();§MVCC Considerations
The new child node becomes visible to concurrent readers only after calling
Aim::snapshot() or Aim::release(). Within the write context, the node
is immediately available for subsequent operations. The child workflow file
is created lazily when first accessed.
§Performance Considerations
- Atomicity: The node creation is atomic within the write transaction
- File System: Creates node rule in parent workflow (child file created on demand)
- Caching: Leverages workspace caching for subsequent operations
- Context Efficiency: Batch multiple node creations before calling
Aim::snapshot
§See Also
Aim::add()- Add top-level workflow nodes to workspaceAim::copy_node()- Copy existing workflow nodesAim::rename_node()- Rename workflow nodesAim::remove_node()- Remove workflow nodesAim::catalog()- Browse workflow hierarchyAim::snapshot()- Persist changes made in write contextAim::acquire()- Acquire write context for modificationsAim::sheet()- Get metadata about a workflow
Sourcepub fn copy_node(
locator: Arc<Reference>,
from: Arc<Reference>,
to: Arc<str>,
) -> Result<()>
pub fn copy_node( locator: Arc<Reference>, from: Arc<Reference>, to: Arc<str>, ) -> Result<()>
§Copies an existing workflow node within a parent workflow to create a replica with a different identifier.
§title: Copy Node
This function copies an existing workflow node within a parent workflow to create a replica with a different identifier. The copy operation includes all associated files (.aim, .jnl) and recursively copies any child directory structure and contents.
§Arguments
handle- A&strrepresenting the workflow instance handle obtained fromAim::acquire(). This handle provides exclusive write access to the workflow context where the node will be copied.from- AnArc<Reference>pointing to the existing node that should be copied. This reference identifies the source node within the workspace hierarchy.to- AnArc<str>containing the new identifier for the copied node. This must be a valid, unique identifier within the target workflow.
§Returns
Returns a Result<()> which is:
Ok(())if the node was successfully copiedErr(anyhow::Error)if the operation failed
§Errors
Returns an error if:
- The
handleis invalid or doesn’t correspond to an active workflow instance - The
fromreference points to a non-existent node - The
toidentifier already exists in the target workflow - The
toidentifier is invalid (empty, contains invalid characters, or is the reserved_identifier) - File system operations fail (copying files, creating directories, etc.)
- The target workflow cannot be modified due to access restrictions
§Behavior
Internally, copy_node() performs the following operations:
- Validation: Verifies that the
fromnode exists and thetoidentifier is unique and valid - File System Copy: Recursively copies all associated files and directories:
- Copies the
.aimworkflow file from source to target - Copies the
.jnljournal file if it exists - Recursively copies the entire child directory structure if it exists
- Copies the
- Node Creation: Creates a new
Nodewith the same inference configuration as the source - Workflow Update: Adds the new node to the target workflow using
Aim::add_node()
§Side Effects
- Creates a new workflow node file at the target location
- Creates or updates journal files for version tracking
- Creates directory structures for nested nodes
- Modifies the target workflow to include the new node reference
- File system changes are immediately visible and persistent
§Usage Pattern
use aimx::{Aim, Reference};
use std::sync::Arc;
// Acquire workflow context
let parent_reference = Reference::parse("parent").unwrap();
let handle = Aim::acquire(parent_reference.clone()).unwrap();
// Copy an existing node to a new identifier
let source_reference = Reference::parse("existing.child").unwrap();
let new_identifier = Arc::from("copied_child");
Aim::copy_node(parent_reference.clone(), source_reference, new_identifier).unwrap();
// Make changes visible
Aim::release(&handle).unwrap();§See Also
Aim::add_node()- Adds a new node to a workflowAim::rename_node()- Renames an existing nodeAim::remove_node()- Removes a node from a workflowAim::acquire()- Acquires write access to a workflowReference- Hierarchical node references
§File Operations
The copy operation performs the following file system operations:
- Copies
source.aimtotarget.aim - Copies
source.jnltotarget.jnl(if exists) - Recursively copies
source/directory totarget/(if exists) - Creates parent directories as needed
- All file operations use standard OS file copying mechanisms
§MVCC Considerations
- The copy operation is performed within an active write context
- Changes are only visible within the workflow instance until
Aim::release()is called - The operation maintains version consistency through the journaling system
- Concurrent read access to the original node remains available during the copy operation
§Performance Considerations
- File copying performance depends on the size of the workflow files and directory structure
- Large workflows with extensive journal history may take longer to copy
- The operation is atomic at the workflow level - either the entire copy succeeds or fails
- Consider using
Aim::snapshot()if you need to make the copy visible before releasing the handle
Sourcepub fn rename_node(
locator: Arc<Reference>,
from: &str,
to: Arc<str>,
) -> Result<()>
pub fn rename_node( locator: Arc<Reference>, from: &str, to: Arc<str>, ) -> Result<()>
§Renames a workflow node within a parent workflow using an active write context.
§title: Rename Node
This function renames an existing workflow node within a parent workflow that has an active write context. The rename operation preserves the node’s inference configuration, rules, and internal structure while updating its identifier within the parent workflow hierarchy.
§Arguments
-
handle- The unique instance handle obtained fromAim::acquire()that identifies the active write context for the parent workflow. -
from- The current identifier of the workflow node to rename. Must be a valid AIMX identifier that exists within the parent workflow. -
to- AnArc<str>specifying the new identifier for the workflow node. Must be a valid AIMX identifier that does not already exist within the parent workflow.
§Returns
Returns Ok(()) if the rename operation completes successfully.
§Errors
Returns an error if:
- The instance handle is invalid or expired
- The source node identifier (
from) does not exist within the parent workflow - The target identifier (
to) already exists within the parent workflow - Either identifier is invalid (contains invalid characters or is empty)
- File system operations fail during the rename process
- The parent workflow cannot be written to
§Behavior
Internally, rename_node() performs the following operations:
- Locates the active instance context using the provided handle
- Acquires a write lock on the workflow instance
- Validates that the target identifier is unique within the parent workflow
- Retrieves the source node rule and its associated node
- Renames the node rule within the parent workflow
- Performs comprehensive file system operations to rename associated files:
- Renames the
.aimworkflow file - Renames the
.jnljournal file (if it exists) - Renames the associated directory structure (if it exists)
- Renames the
§Side Effects
- File System Changes: Renames all associated files and directories
- Workflow Modification: Updates the parent workflow with the new node reference
- MVCC Visibility: Changes become visible only after
Aim::snapshot()orAim::release()
§File Operations
The rename operation performs comprehensive file system operations:
workspace/
└── {parent}/ # Parent workflow directory
├── {from}.aim # Source workflow file (renamed)
├── {from}.jnl # Source journal file (renamed if exists)
└── {from}/ # Source directory structure (renamed)
↓ renamed to ↓
├── {to}.aim # Target workflow file
├── {to}.jnl # Target journal file (if source had one)
└── {to}/ # Target directory structure§Usage Pattern
use aimx::{Aim, Reference};
use std::sync::Arc;
// Acquire workflow context
let parent_reference = Reference::parse("foo").unwrap();
let handle = Aim::acquire(parent_reference.clone()).unwrap();
// Rename a node within the workflow
let result = Aim::rename_node(parent_reference.clone(), "old_name", Arc::from("new_name"));
assert!(result.is_ok());
// Make changes visible
Aim::release(&handle).unwrap();§Differences from Aim::rename()
| Aspect | Aim::rename() | Aim::rename_node() |
|---|---|---|
| Scope | Workspace level | Within existing workflow context |
| Context | Direct workspace access | Requires active write context |
| Reference | Top-level (e.g., “foo” → “bar”) | Nested (e.g., “foo.baz” → “foo.qux”) |
| File Location | workspace/foo.aim → workspace/bar.aim | workspace/foo/baz.aim → workspace/foo/qux.aim |
§MVCC Considerations
The renamed node becomes visible to concurrent readers only after calling Aim::snapshot() or Aim::release(). Within the write context, the renamed node is immediately available for subsequent operations using the new identifier.
§Performance Considerations
- Recursive Rename: Renames entire directory structure recursively
- File Operations: Performs multiple file system operations for each file
- Atomicity: The operation is atomic - either all files are renamed or none are
- Error Recovery: If renaming fails partway, created files are rolled back
§Safety Considerations
The rename operation is atomic and reversible until the context is released:
- If the operation fails, the workflow remains in its original state
- Until
Aim::snapshot()orAim::release()are called, the original node remains accessible via its old identifier - Applications can implement undo mechanisms by calling
rename_node()again with the reversed identifiers before committing changes
§See Also
Aim::rename()- Rename workflow nodes at workspace levelAim::add_node()- Create new workflow nodes within contextAim::copy_node()- Copy workflow nodes within contextAim::remove_node()- Remove workflow nodes within contextAim::snapshot()- Persist changes made in write contextAim::catalog()- Browse workflow hierarchy after renaming
Sourcepub fn remove_node(locator: Arc<Reference>, identifier: &str) -> Result<()>
pub fn remove_node(locator: Arc<Reference>, identifier: &str) -> Result<()>
§Removes a workflow node from within a parent workflow using an active write context.
§title: Remove node
This function permanently deletes a child workflow node and all its associated resources (including child workflows, files, and journal entries) from within a parent workflow that has an active write context. The removal operation is comprehensive and irreversible, ensuring no orphaned files remain in the workspace.
§Arguments
-
handle- The unique instance handle obtained fromAim::acquire()that identifies the active write context for the parent workflow. -
identifier- The identifier of the child workflow node to remove. Must be a valid AIMX identifier that exists within the parent workflow. Cannot be empty or “_” (reserved for workspace root).
§Returns
Returns Ok(()) if the removal operation completes successfully.
§Errors
Returns an error if:
- The instance handle is invalid or expired
- The specified child node does not exist within the parent workflow
- The identifier is empty or invalid (contains invalid characters)
- File system operations fail during the removal process
- The parent workflow cannot be written to
§Side Effects
Performs comprehensive file system operations to remove all associated files:
- Deletes the child workflow file (
{parent}/{identifier}.aim) - Deletes the child journal file (
{parent}/{identifier}.jnl) if it exists - Deletes the child directory (
{parent}/{identifier}/) if it exists, including all nested child workflows recursively - Removes the node reference from the parent workflow
- Creates corresponding journal entries for MVCC tracking
§Safety Considerations
This operation is irreversible. Once a child node is removed, all its data, rules, nested workflows, and inference history are permanently deleted. Applications should implement confirmation dialogs or undo mechanisms when calling this function interactively.
§MVCC Considerations
The removed child node becomes invisible to concurrent readers only after calling
Aim::snapshot() or Aim::release(). Within the write context, the removal
is immediately effective for subsequent operations.
§File Operations
The removal operation performs the following file system operations:
workspace/
└── {parent}/ # Parent workflow directory
├── {identifier}.aim # Child workflow file (deleted)
├── {identifier}.jnl # Child journal file (deleted if exists)
└── {identifier}/ # Child directory structure (recursively deleted)
├── nested1.aim → (deleted)
└── nested2.aim → (deleted)§Behavior
Internally, remove_node() performs the following operations:
- Locates the active instance context using the provided handle
- Acquires a write lock on the workflow instance
- Calls the workflow’s
delete_node()method to perform the actual removal - Executes file system operations to delete all associated files
- Updates the parent workflow by removing the node reference
§Performance Considerations
- Recursive Deletion: Deletes entire directory structure recursively
- File Operations: Performs multiple file system operations for each file
- Atomicity: The operation is atomic - either all files are deleted or none are
- Error Recovery: If deletion fails partway, created files are rolled back
§Differences from Aim::remove()
| Aspect | Aim::remove() | Aim::remove_node() |
|---|---|---|
| Scope | Workspace level | Within existing workflow context |
| Context | Direct workspace access | Requires active write context |
| Reference | Top-level (e.g., “foo”) | Nested (e.g., “foo.baz”) |
| File Location | workspace/foo.aim | workspace/foo/baz.aim |
§Usage Pattern
use aimx::{Aim, Reference};
use std::sync::Arc;
// Create top-level workflow and child node
let parent_ref = Aim::add("parent", "evaluation").unwrap();
let handle = Aim::acquire(parent_ref.clone()).unwrap();
let child_ref = Aim::add_node(parent_ref.clone(), Arc::from("child"), "inference").unwrap();
// Verify child exists
let child_sheets = Aim::catalog(parent_ref.clone()).unwrap();
assert!(child_sheets.iter().any(|sheet| sheet.path().contains("child")));
// Remove the child node
Aim::remove_node(parent_ref.clone(), "child").unwrap();
// Make removal visible to other readers
Aim::snapshot(&handle).unwrap();
// Verify child is gone
let remaining_children = Aim::catalog(parent_ref).unwrap();
assert!(!remaining_children.iter().any(|sheet| sheet.path().contains("child")));
// Release the write context
Aim::release(&handle).unwrap();§Integration with Context Operations
If the child workflow being removed has an active context instance (via Aim::acquire),
the removal operation will still proceed but may leave orphaned context entries.
Consider calling Aim::release on any active child workflow handles before removal.
§See Also
Aim::remove()- Remove workflow nodes at workspace levelAim::add_node()- Create new workflow nodes within contextAim::copy_node()- Copy workflow nodes within contextAim::rename_node()- Rename workflow nodes within contextAim::catalog()- Browse workflow hierarchy before removalAim::snapshot()- Persist changes made in write contextAim::acquire()- Acquire write context for modifications
Sourcepub fn get_index(handle: &str, identifier: &str) -> Result<Option<usize>>
pub fn get_index(handle: &str, identifier: &str) -> Result<Option<usize>>
§Retrieves the index position of a cell within a workflow using an active write context.
§title: Get Index
This function retrieves the zero-based row index position of a rule within a workflow using an active write context. It provides fast lookup of rule positions for operations that need to work with rules by their index rather than their identifier.
§Arguments
handle- A string slice containing the context handle that was returned byAim::acquire(). This provides exclusive write access to the workflow.identifier- A string slice containing the rule identifier to find the index for.
§Returns
Returns a Result<Option<usize>> where:
Ok(Some(usize))- The zero-based index position of the rule if it existsOk(None)- If no rule with the given identifier exists in the workflowErr(anyhow::Error)- If the context handle is invalid or the workflow cannot be accessed
§Errors
Returns an error if:
- The provided
handleis not a valid context handle - The workflow associated with the handle cannot be accessed
- The instance context has been corrupted or is no longer valid
§Behavior
Internally, get_index() performs the following operations:
- Locates the instance context using the provided handle
- Acquires a write lock on the context to ensure thread-safe access
- Calls the underlying workflow’s
get_index()method which performs a hash map lookup - Returns the index position if the rule exists, or
Noneif it doesn’t
The function uses the workflow’s internal lookup table (a HashMap<Arc<str>, usize>) to provide O(1) average-case lookup performance for rule positions.
§Side Effects
- Acquires a write lock on the instance context (but doesn’t modify the workflow)
- No persistent changes are made to the workflow or its files
§Usage Pattern
use aimx::{Aim, Cell};
use std::sync::Arc;
// Acquire workflow context
let reference = aimx::Reference::parse("example.workflow").unwrap();
let handle = Aim::acquire(reference).unwrap();
// Add some cells to the workflow
let cell1 = Cell::new("rule1", "Number", "42", "");
let cell2 = Cell::new("rule2", "Text", "\"hello\"", "");
let cell3 = Cell::new("rule3", "Bool", "true", "");
Aim::append_or_update_cell(&handle, cell1).unwrap();
Aim::append_or_update_cell(&handle, cell2).unwrap();
Aim::append_or_update_cell(&handle, cell3).unwrap();
// Get index positions of rules
if let Some(index) = Aim::get_index(&handle, "rule2").unwrap() {
println!("rule2 is at index: {}", index);
// index will be 1 (zero-based)
}
// Check for non-existent rule
let none_index = Aim::get_index(&handle, "nonexistent").unwrap();
assert!(none_index.is_none());
// Make changes visible
Aim::release(&handle).unwrap();§See Also
Aim::acquire()- Acquires exclusive write access to a workflowAim::get_row()- Retrieves a rule by its index positionAim::has_cell()- Checks if a rule exists by identifierAim::get_cell()- Retrieves a rule by its identifier
Sourcepub fn get_row(handle: &str, index: usize) -> Result<Cell>
pub fn get_row(handle: &str, index: usize) -> Result<Cell>
§Retrieves a specific cell (rule) from a workflow by its zero-based index position within an active write context.
§title: Get Row
This function retrieves a specific rule from a workflow by its zero-based index position within an active write context, returning a Cell representation of the rule’s content.
§Arguments
handle- A string slice that references the unique instance handle obtained fromAim::acquire(). This handle identifies the active write context for the workflow where the rule should be retrieved.index- The zero-based index position of the rule to retrieve. Must be a valid index within the current bounds of the workflow rule collection.
§Returns
Returns a Cell enum variant representing the rule’s current state at the specified index position. The cell type depends on the rule’s content:
Cell::Formula- For standard formula-based rules with expression and valueCell::Node- For workflow node references that point to child workflowsCell::Branch- For conditional branch logic with condition and targetCell::Format- For formatting instructions with templates and examplesCell::Retry- For retryable operations with count, condition, and targetCell::Errata- For error states containing error informationCell::Comment- For comment rows in the workflowCell::Empty- For cleared or non-existent rules at the specified index
§Errors
Returns an error if:
- The instance handle is invalid, expired, or cannot be located
- The workflow context operations fail due to concurrent access issues
- The instance has been released or is no longer active
The function performs bounds checking internally and returns Cell::Empty for out-of-bounds indices rather than failing.
§Behavior
Internally, get_row() performs the following operations:
- Context Resolution: Locates the active instance context using the provided handle via
Instance::locate() - Lock Acquisition: Acquires a write lock on the workflow instance to ensure thread safety
- Row Retrieval: Calls the workflow’s internal
get_row()method to retrieve the rule data at the specified index - Conversion: Converts the internal
Rowrepresentation to aCellusingCell::convert_row() - Bounds Handling: Returns
Row::Emptyfor out-of-bounds access, which converts toCell::Empty
§Side Effects
- Read Operation: This is a read-only operation that does not modify the workflow
- Lock Acquisition: Temporarily acquires a write lock for thread safety, but does not modify the workflow content
- No Persistence: Changes to the returned cell do not affect the workflow until explicitly saved using
Aim::snapshot()orAim::release()
§Usage Pattern
use aimx::{Aim, Cell};
// Acquire workflow context for modifications
let locator = aimx::Reference::parse("workflow.subworkflow").unwrap();
let handle = Aim::acquire(locator).unwrap();
// Add some rules to the workflow
let cell1 = Cell::new("rule1", "Number", "10 + 5", "");
let cell2 = Cell::new("rule2", "Text", "\"hello world\"", "");
let cell3 = Cell::new("rule3", "Bool", "true", "");
Aim::append_or_update_cell(&handle, cell1).unwrap();
Aim::append_or_update_cell(&handle, cell2).unwrap();
Aim::append_or_update_cell(&handle, cell3).unwrap();
Aim::snapshot(&handle).unwrap();
// Retrieve rules by index
let first_rule = Aim::get_row(&handle, 0).unwrap();
let second_rule = Aim::get_row(&handle, 1).unwrap();
let third_rule = Aim::get_row(&handle, 2).unwrap();
println!("First rule: {}", first_rule.identifier().unwrap_or_default());
println!("Second rule: {}", second_rule.identifier().unwrap_or_default());
println!("Third rule: {}", third_rule.identifier().unwrap_or_default());
// Handle out-of-bounds access (returns Empty)
let empty_rule = Aim::get_row(&handle, 99).unwrap();
assert!(empty_rule.is_empty());
// Clean up
Aim::release(&handle).unwrap();§Integration with Other Index-Based Operations
The retrieved cell can be used in conjunction with other positional operations:
Aim::set_row()- Replace the cell content at this indexAim::insert_row()- Insert new cell after this indexAim::reposition_row()- Move cell to different index positionAim::clear_row()- Clear cell content while maintaining positionAim::remove_row()- Remove cell entirely with index adjustment
§Comparison with Identifier-Based Access
| Aspect | Index-Based (get_row) | Identifier-Based (get_cell) |
|---|---|---|
| Lookup Method | Array index position | Hash-based identifier lookup |
| Use Case | Position-aware operations, bulk processing | Direct rule content access, rule updates |
| Performance | O(1) direct array access | O(1) hash lookup |
| Stability | May change during reordering operations | Stable across workflow modifications |
| API Family | get_row, set_row, insert_row, reposition_row | get_cell, update_cell, delete_cell |
| Bounds Handling | Returns Cell::Empty for out-of-bounds | Returns None for missing identifiers |
§MVCC Considerations
The cell reflects the current state of the workflow within the write context, including any uncommitted changes. Changes made through index-based operations are not visible to concurrent readers until Aim::snapshot() or Aim::release() are called to commit the changes.
§Performance Characteristics
- Direct Access: O(1) array-based lookup for efficient positional access
- Context Required: Requires active write context handle for thread safety
- Index Stability: Indices remain stable within atomic operations but may change during batch modifications
- Memory Efficient: Minimal overhead compared to loading entire workflow
§Related Operations
For comprehensive workflow management, consider these related functions:
Aim::get_index()- Convert identifier to index position for index-based operationsAim::has_cell()- Check if rule exists (identifier-based)Aim::append_or_update_cell()- Add or update rules in workflowAim::list()- Bulk access to all workflow cells with their positionsAim::snapshot()- Commit changes to make them globally visibleAim::acquire()- Acquire write context for modifications
§See Also
Aim::get_index()- Convert identifier to index positionAim::set_row()- Update cell content by indexAim::insert_row()- Insert new cell at specified indexAim::reposition_row()- Move cell to different index positionAim::clear_row()- Clear cell content while preserving indexAim::remove_row()- Remove cell from specified indexAim::get_cell()- Identifier-based cell accessAim::list()- Bulk access to all workflow cellsAim::acquire()- Acquire write context for modifications
Sourcepub fn set_row(handle: &str, index: usize, cell: Cell) -> Result<()>
pub fn set_row(handle: &str, index: usize, cell: Cell) -> Result<()>
§Updates a specific row within a workflow using an active write context.
§title: Set row
This function updates a specific row within a workflow using an active write context. It replaces the content at the specified zero-based index with a new cell, or creates the row if it doesn’t exist.
§Arguments
handle- A&strreference to an active workflow context handle obtained fromAim::acquire()index- Ausizerepresenting the zero-based row index where the cell should be placedcell- ACellcontaining the new cell data to set at the specified index
§Returns
Returns Ok(()) if the operation succeeds, or an error if the handle is invalid or the operation fails.
§Errors
Returns an error if:
- The
handledoes not correspond to an active workflow context - The
cellcontains an identifier that conflicts with an existing rule at a different index - The
cellcontains an invalid identifier format
§Behavior
Internally, set_row() performs the following operations:
- Locates the workflow instance using the provided handle
- Acquires a write lock on the workflow
- Converts the
Cellto aRowusingRow::convert() - Calls the workflow’s
set_row()method to update the specified index - The workflow performs validation and updates its internal state
The workflow’s set_row() method:
- Validates the cell identifier format
- Checks for identifier conflicts with existing rules
- Expands the workflow’s row vector if the index is beyond current bounds
- Updates the rule lookup index to maintain identifier-to-index mapping
- Marks the workflow as having changes that need to be saved
§Side Effects
- Modifies the workflow’s internal row structure
- Updates the rule lookup index for fast identifier-based access
- Marks the workflow as having pending changes (requires
Aim::snapshot()orAim::release()to persist) - May expand the workflow’s row vector to accommodate the specified index
§Usage Pattern
use aimx::{Aim, Cell, Reference};
use std::sync::Arc;
// Acquire workflow context
let reference = Reference::parse("foo.bar").unwrap();
let handle = Aim::acquire(reference.clone()).unwrap();
// Create a new cell
let cell = Cell::new("updated_rule", "Number", "42", "");
// Update the row at index 0
Aim::set_row(&handle, 0, cell).unwrap();
// Make changes visible
Aim::snapshot(&handle).unwrap();
Aim::release(&handle).unwrap();§See Also
Aim::acquire()- Acquires exclusive write access to a workflowAim::get_row()- Retrieves a specific row from a workflowAim::insert_row()- Inserts a new row at a specified indexAim::snapshot()- Saves the current state to make changes visibleAim::release()- Releases a workflow context and finalizes changesCell- Cell data structure for workflow rulesRow- Internal row representation in workflows
§MVCC Considerations
This function operates on a private workspace context that is not visible to other readers until Aim::snapshot() or Aim::release() is called. Multiple writers can operate on different workflow contexts simultaneously without interference.
§Performance Considerations
- Row index lookup is O(1) for existing rows
- Identifier validation occurs on each call
- Large index values may cause vector expansion with O(n) memory allocation
- The workflow maintains an internal hash map for O(1) identifier-to-index lookups
Sourcepub fn insert_row(handle: &str, index: usize, cell: Cell) -> Result<()>
pub fn insert_row(handle: &str, index: usize, cell: Cell) -> Result<()>
Inserts a new row at the specified index within a workflow using an active write context. This function inserts a new row at a specified index within a workflow using an active write context. It shifts existing rows to higher indices and maintains workflow integrity through identifier uniqueness checks.
§Arguments
-
handle- The unique instance handle obtained fromAim::acquire()that identifies the active write context for the workflow being modified. -
index- The zero-based row index where the new cell should be inserted. If the index exceeds the current workflow size, the workflow will be expanded with empty rows to accommodate the position before insertion. -
cell- ACellobject containing the new rule definition to insert. The cell must contain a valid rule with a unique identifier within the workflow.
§Returns
Returns Ok(()) on successful insertion, indicating the row was placed correctly.
§Errors
Returns an error if:
- The instance handle is invalid or expired
- The cell contains an invalid rule identifier
- A rule with the same identifier already exists in the workflow
- The workflow file cannot be written to
- The workspace is in an invalid state
§Behavior
Internally, insert_row() performs the following operations:
- Locates the active instance context using the provided handle
- Acquires a write lock on the workflow instance
- Converts the
Cellto aRowusingRow::convert() - Validates the rule identifier for uniqueness across the entire workflow
- Inserts the row at the specified index, shifting existing rows
- Rebuilds the internal identifier-to-index lookup mapping
- Triggers version-level change tracking (always requires version change)
§MVCC Considerations
The row insertion becomes visible to concurrent readers only after calling
Aim::snapshot() or Aim::release(). Within the write context, the inserted
row is immediately available for subsequent operations.
§Index Behavior
The function handles various index scenarios:
- Valid Index: Inserts at position, shifting existing rows to higher indices
- Index Equals Size: Appends to end of workflow (equivalent to append)
- Index Beyond Size: Expands workflow with empty rows, then inserts at position
- Empty Workflow: Creates workflow with single row at index 0
§Identifier Uniqueness
Unlike Aim::set_row(), this function enforces strict identifier uniqueness:
- New Identifier: Must not exist anywhere in the workflow
- Duplicate Detection: Checks entire workflow before insertion
- Error Prevention: Fails early if identifier conflict detected
§Performance Characteristics
- Insertion Complexity: O(n) due to row shifting and reindexing
- Lookup Updates: Internal identifier-to-index mapping is rebuilt
- Version Tracking: Always triggers version-level change tracking
- Memory Usage: Workflow size increases by one row
§Differences from Related Functions
| Function | Purpose | Index Behavior | Identifier Handling | Change Level |
|---|---|---|---|---|
insert_row() | Insert at index | Shifts existing rows | Must be new identifier | Version |
set_row() | Update specific index | Expands if needed | Enforces uniqueness | Partial/Version |
append_or_update_cell() | Add/update by identifier | Appends to end | Updates if exists | Partial |
§Usage Pattern
use aimx::{Aim, Cell, Reference};
use std::sync::Arc;
// Acquire workflow context
let reference = Reference::parse("foo.bar").unwrap();
let handle = Aim::acquire(reference.clone()).unwrap();
// Create a new cell to insert
let new_cell = Cell::new("new_rule", "Number", "42", "");
// Insert at index 1 (shifting existing rows)
Aim::insert_row(&handle, 1, new_cell).unwrap();
// Make changes visible
Aim::snapshot(&handle).unwrap();
// Clean up
Aim::release(&handle).unwrap();§See Also
Aim::get_row()- Retrieve row content by indexAim::set_row()- Update row content at specific positionAim::append_or_update_cell()- Add or update rule by identifierAim::reposition_row()- Move existing row to different positionAim::acquire()- Acquire write context for modificationsAim::snapshot()- Make changes visible to readersAim::release()- Finalize write context
Sourcepub fn reposition_row(handle: &str, from: usize, to: usize) -> Result<()>
pub fn reposition_row(handle: &str, from: usize, to: usize) -> Result<()>
§Moves a rule from one row position to another within a workflow.
§title: Reposition Row
Moves a rule from one row position to another within a workflow, reordering the workflow structure.
This function repositions a rule within a workflow by moving it from its current zero-based index position to a new target position. The operation shifts other rules as needed to accommodate the move and maintains the workflow’s internal indexing for efficient rule lookups.
§Arguments
-
handle- An active write context handle obtained fromAim::acquire. Must be a valid handle pointing to a workflow that has been acquired for writing. -
from- The current zero-based row index of the rule to move. If the index exceeds the current workflow size, the workflow will be expanded with empty rows as needed. -
to- The target zero-based row index where the rule should be placed. Can be any valid index, including positions beyond the current workflow size. The workflow will be expanded with empty rows if necessary.
§Returns
Returns Ok(()) if the reposition operation was successful.
§Errors
Returns an error if:
- The
handleis invalid or points to a non-existent workflow context - The underlying workflow operation fails
§Side Effects
- Changes the order of rules within the workflow
- Expands the workflow’s row vector if
fromortoindices exceed current bounds - Triggers a partial change flag on the workflow (requires
Aim::snapshotto persist) - Rebuilds the internal identifier-to-index lookup mapping
- The repositioning is immediately visible within the active write context
§Behavior
Internally, reposition_row() performs the following operations:
- Early Return: If
fromequalsto, the function returns immediately as no operation is needed - Vector Expansion: Expands the workflow’s rows vector if either
fromortoexceeds current bounds - Change Tracking: Marks the workflow with a partial change flag
- Empty Row Optimization: If both source and destination are empty, returns early
- Row Movement: Removes the row from the
fromindex and inserts it at thetoindex - Index Rebuilding: Rebuilds the internal lookup table that maps rule identifiers to row indices
§MVCC Considerations
The reposition operation is performed within the active write context and is not
visible to concurrent readers until Aim::snapshot is called to persist the changes.
The operation only sets a partial change flag, making it efficient for frequent reordering operations.
§Performance Characteristics
- Time Complexity: O(n) where n is the number of rules in the workflow
- Space Complexity: O(1) additional space, but may expand the row vector
- Index Rebuilding: Requires rebuilding the identifier-to-index lookup table in O(n) time
§Usage Pattern
use aimx::{Aim, Cell, Reference};
use std::sync::Arc;
// Acquire workflow context
let locator = Reference::parse("example.workflow").unwrap();
let handle = Aim::acquire(locator).unwrap();
// Add some initial rules
let cell1 = Cell::new("first", "Number", "1", "");
let cell2 = Cell::new("second", "Text", "\"hello\"", "");
let cell3 = Cell::new("third", "Bool", "true", "");
Aim::append_or_update_cell(&handle, cell1).unwrap();
Aim::append_or_update_cell(&handle, cell2).unwrap();
Aim::append_or_update_cell(&handle, cell3).unwrap();
// Reposition: move rule from index 0 to index 2
Aim::reposition_row(&handle, 0, 2).unwrap();
// The rule originally at index 0 is now at index 2
let moved_cell = Aim::get_row(&handle, 2).unwrap();
assert_eq!(moved_cell.identifier(), Some(Arc::from("first")));
// Make changes visible
Aim::snapshot(&handle).unwrap();
Aim::release(&handle).unwrap();§Integration with Other Operations
The repositioned rule maintains its identifier and all associated metadata. Other operations that rely on row indices will see the new ordering:
Aim::get_row- Retrieves rules by their new positionsAim::set_row- Updates rules at their new positionsAim::insert_row- Inserts rules relative to the new orderingAim::clear_row- Clears rules at their new positionsAim::remove_row- Removes rules from their new positions
§See Also
Aim::acquire- Acquire a write context handleAim::snapshot- Persist workflow changesAim::release- Release a write contextAim::get_index- Get the index of a rule by identifierAim::get_row- Get a rule by its row indexAim::set_row- Set a rule at a specific indexAim::insert_row- Insert a rule at a specific indexAim::clear_row- Clear a rule at a specific indexAim::remove_row- Remove a rule at a specific index
Sourcepub fn clear_row(handle: &str, index: usize) -> Result<Cell>
pub fn clear_row(handle: &str, index: usize) -> Result<Cell>
§Clears the content of a cell at the specified index while preserving its position.
§title: Clear Row
Clears the content of a cell at the specified index while preserving its position within the workflow. This operation removes the rule from the specified index but maintains the row structure, allowing the position to be reused later.
§Arguments
handle- A reference to the instance handle obtained fromAim::acquire()that identifies the active write context for the workflow.index- The zero-based index position of the row to clear.
§Returns
Returns a Cell containing the rule that was cleared from the specified index. If the index was out of bounds or the row was already empty, returns Cell::Empty.
§Errors
This function does not return errors for invalid operations. Instead:
- If the
handleis invalid, it returns an error when trying to locate the instance - If the
indexis out of bounds, it returnsCell::Empty - If the row at the specified index is already empty, it returns
Cell::Empty
§Behavior
Internally, clear_row() performs the following operations:
- Locates the active instance context using the provided handle
- Acquires a write lock on the workflow instance to ensure thread safety
- Calls the workflow’s internal
clear_row()method - Converts the cleared row to a
CellusingCell::convert_row() - Returns the cell containing the cleared rule (or
Cell::Emptyif no rule was present)
The underlying workflow implementation ensures that:
- The row at the specified index becomes empty
- The row count remains unchanged
- The rule is removed from the internal lookup table
- The operation is marked as a version change
§Side Effects
- Removes the rule from the workflow’s internal identifier lookup table
- Marks the workflow as having version changes (requiring a save)
- Decreases the rule count by one (if a rule was present)
- Preserves the total row count
§Usage Pattern
use aimx::{Aim, Cell, Reference};
use std::sync::Arc;
// Acquire workflow context
let reference = Reference::parse("foo.bar").unwrap();
let handle = Aim::acquire(reference.clone()).unwrap();
// Clear a row at index 2 and capture the cleared content
let cleared_cell = Aim::clear_row(&handle, 2).unwrap();
// Check what was cleared
match cleared_cell {
Cell::Empty => println!("Row was already empty"),
cell => if let Some(identifier) = cell.identifier() {
println!("Cleared rule: {}", identifier)
},
}
// Make changes visible
Aim::snapshot(&handle).unwrap();
Aim::release(&handle).unwrap();§Clear vs Remove Semantics
clear_row() maintains the workflow structure by keeping the row position:
| Operation | Row Count | Index Preservation | Content Recovery |
|---|---|---|---|
| Clear | Unchanged | ✅ Preserved | ✅ Return value |
| Remove | Decremented | ❌ Shifts down | ✅ Return value |
Use clear_row() when:
- You want to temporarily disable a rule without affecting other row positions
- You need to preserve the exact workflow structure for later operations
- You want to capture the cleared rule for potential restoration
Use remove_row() when:
- You want to permanently delete a rule and compact the workflow
- Other rows should shift to fill the gap
- You don’t need to preserve the exact row structure
§MVCC Considerations
The cleared row state is managed within the write context and becomes visible to concurrent readers only after calling Aim::snapshot() or Aim::release(). The cleared row will appear as Cell::Empty when retrieved using Aim::get_row().
§Performance Characteristics
- Index Access: O(1) array-based operation for row access
- Lookup Update: O(1) hash table removal for identifier lookup
- Memory Impact: Minimal - the cleared row slot remains allocated
- Thread Safety: Requires active write context and internal locking
§See Also
Aim::get_row()- Retrieve cell content by indexAim::set_row()- Replace cell content at indexAim::remove_row()- Remove cell entirely with index adjustmentAim::insert_row()- Insert new cell at specified indexAim::reposition_row()- Move cell from one index to anotherAim::delete_cell()- Delete cell by identifier
Sourcepub fn remove_row(handle: &str, index: usize) -> Result<Cell>
pub fn remove_row(handle: &str, index: usize) -> Result<Cell>
§Removes a specific row from a workflow permanently and returns the removed content.
§title: Remove Row
This function permanently removes a row from a workflow at the specified zero-based index and returns the removed content as a cell.
§Arguments
handle- An active write context handle obtained fromAim::acquire. The workflow must be acquired for writing before calling this function.index- Zero-based index specifying which row to remove. Must be within the bounds of the workflow.
§Returns
Returns a Cell containing the removed row’s data. The cell type depends on what was removed:
Cell::Emptyif the index was out of boundsCell::Formulaif a formula rule was removedCell::Commentif a comment was removedCell::Nodeif a node rule was removedCell::Branchif a branch rule was removedCell::Retryif a retry rule was removedCell::Formatif a format rule was removedCell::Errataif an error state was removed
§Errors
This function does not return errors for invalid operations. Instead:
- If the handle is invalid or refers to a released context, the function will panic
- If the index is out of bounds, it returns
Cell::Empty
§Behavior
Internally, remove_row() performs the following operations:
- Locates the instance using the provided handle
- Acquires a write lock on the workflow
- Calls
target().remove_row(index)on the underlying workflow - Converts the removed row to a
CellusingCell::convert_row() - Returns the cell result
The underlying workflow method handles the actual removal and reindexing operations.
§Side Effects
- Version Change: Flags the workflow for a version change since this is a structural modification
- Row Removal: Removes the row entirely from the workflow, shrinking the row vector
- Index Shifting: Subsequent rows are shifted to lower indices to fill the gap
- Lookup Update: Rebuilds the internal identifier-to-index mapping via
reindex() - Change Tracking: Marks the workflow as having pending changes
§Usage Pattern
use aimx::{Aim, Cell, Reference};
use std::sync::Arc;
// Acquire workflow context
let reference = Reference::parse("foo.bar").unwrap();
let handle = Aim::acquire(reference.clone()).unwrap();
// Remove a row by index
let removed_cell: Cell = Aim::remove_row(&handle, 0).unwrap();
// Make changes visible
Aim::snapshot(&handle).unwrap();
// Release the handle
Aim::release(&handle).unwrap();§See Also
clear_row- Clears row content without removing the rowinsert_row- Inserts a new row at a specific indexget_row- Retrieves a row at a specific indexset_row- Sets/replaces a row at a specific indexreposition_row- Moves a row to a different positiondelete_cell- Removes a rule by identifier instead of index
Sourcepub fn has_cell(handle: &str, identifier: &str) -> Result<bool>
pub fn has_cell(handle: &str, identifier: &str) -> Result<bool>
§Checks if a specific cell exists within a workflow using an active write context.
§title: Has Cell
Checks if a specific cell (rule) exists within a workflow using an active write context.
This function provides write-context-aware existence checking during workflow modifications, allowing you to conditionally add or update cells based on their current presence in the in-memory workflow state.
§Arguments
handle- A string handle representing an active write context acquired viaAim::acquire.identifier- The unique identifier of the cell (rule) to check for existence.
§Returns
Returns a Result containing:
Ok(true)if the cell exists within the workflow under the active write contextOk(false)if the cell does not exist in the workflowErrif the handle is invalid or the workflow cannot be accessed
§Errors
Returns an error if:
- The
handledoes not correspond to an active write context (instance not found) - The workflow context cannot be accessed due to internal errors
- The underlying storage system encounters an error
§Behavior
Internally, has_cell() performs the following operations:
- Context Lookup: Uses
Instance::locate()to find the active write context associated with the handle - Lock Acquisition: Acquires a write lock on the workflow context to ensure thread-safe access
- Identifier Check: Calls the workflow’s
contains()method to check if the identifier exists - Result Return: Returns the boolean result wrapped in a
Resulttype
§Context-Aware Semantics
Unlike Aim::contains, which provides a read-only MVCC view of the last committed state,
has_cell() operates within a write context and reflects the current in-memory state:
§MVCC vs Context-Aware Differences
| Aspect | Aim::contains | has_cell() |
|---|---|---|
| Context Required | No | Yes (via Aim::acquire |
| State Viewed | Last committed (disk) | Current in-memory modifications |
| Concurrency | Read-only, safe for concurrent access | Write context, exclusive access |
| Unsaved Changes | Not visible | Visible and included |
§Use Cases
has_cell() is essential for:
- Conditional Logic: Checking if a cell exists before adding or updating it
- Workflow Validation: Ensuring required cells are present before proceeding
- Modification Workflows: Building complex modification sequences that depend on cell existence
- Error Prevention: Avoiding duplicate cell creation or updating non-existent cells
§Side Effects
- None: This function only reads the current state and does not modify the workflow
- Thread Safety: Acquires internal locks but releases them before returning
- Performance: Efficient O(1) lookup using the workflow’s internal hash map
§Usage Pattern
use aimx::{Aim, Cell};
use std::sync::Arc;
// Acquire workflow context
let reference = aimx::Reference::parse("my_workflow").unwrap();
let handle = Aim::acquire(reference).unwrap();
// Check if cell exists before adding
if !Aim::has_cell(&handle, "important_metric").unwrap() {
let cell = Cell::new("important_metric", "Number", "42", "");
Aim::append_or_update_cell(&handle, cell).unwrap();
}
// Make changes visible
Aim::release(&handle).unwrap();§Integration with Other Functions
has_cell() works closely with several other API functions:
- Precondition Check: Often used before
Aim::append_or_update_cell,Aim::update_cell, orAim::delete_cell - Workflow Building: Part of sequences with
Aim::get_cellandAim::set_rowfor complex modifications - Validation: Used with
Aim::get_indexto validate cell positions before operations
§Performance Considerations
- Efficient Lookup: Uses the underlying workflow’s hash map for O(1) identifier lookup
- In-Memory Operation: No disk I/O required since the workflow is loaded in the context
- Lock Overhead: Minimal lock acquisition time due to fine-grained locking
- Context Bound: Performance depends on workflow size but is generally very fast
§See Also
Aim::contains- Read-only existence check without write contextAim::get_cell- Retrieve cell details within write contextAim::append_or_update_cell- Add or modify cells with conditional logicAim::delete_cell- Remove cells within write contextAim::acquire- Obtain write context for modification operationsAim::snapshot- Persist context modifications to diskAim::release- Finalize and clean up write context
Sourcepub fn get_cell(handle: &str, identifier: &str) -> Result<Option<Cell>>
pub fn get_cell(handle: &str, identifier: &str) -> Result<Option<Cell>>
§Retrieves a specific cell (rule) from a workflow using an active write context by its identifier.
§title: Get Cell
This function retrieves a specific cell (rule) from a workflow using an active write context by its identifier. It returns Some(Cell) if the cell exists, or None if no cell with the given identifier is found.
Unlike Aim::cell() which reads from the globally visible MVCC state, get_cell() reads from the write context’s current state, which may include uncommitted changes that haven’t been made globally visible yet.
§Arguments
handle- A&strcontext handle obtained fromAim::acquire()that provides exclusive write access to the workflowidentifier- A&strunique identifier of the cell (rule) to retrieve within the workflow
§Returns
Returns a Result<Option<Cell>> containing:
Some(Cell)if a cell with the specified identifier exists in the workflowNoneif no cell with the specified identifier existsErr(anyhow::Error)if there’s an error locating the context or accessing the workflow
§Errors
Returns an error if:
- The context handle is invalid or cannot be located in the workspace
- There’s an issue accessing the workflow data structure
- The workspace context is corrupted or unavailable
§Behavior
Internally, get_cell() performs the following operations:
- Locates the
Instanceusing the provided handle viaInstance::locate() - Acquires a write lock on the instance to ensure thread-safe access
- Calls
WorkflowLike::get_rule()to retrieve the rule by identifier - Converts the rule to a
Cellrepresentation usingCell::convert_rule() - Returns
Some(Cell)if found, orNoneif the rule doesn’t exist
§Side Effects
- None. This function only reads data and does not modify the workflow state
§Usage Pattern
use aimx::{Aim, Reference};
use std::sync::Arc;
// Acquire workflow context for modification
let reference = Reference::parse("my_workflow").unwrap();
let handle = Aim::acquire(reference.clone()).unwrap();
// Retrieve a cell by identifier
if let Some(cell) = Aim::get_cell(&handle, "my_cell").unwrap() {
// Use the cell data
if let Some(identifier) = cell.identifier() {
println!("Cell identifier: {}", identifier);
}
if let Some(typedef) = cell.typedef() {
println!("Cell type: {}", typedef);
}
if let Some(value) = cell.value() {
println!("Cell value: {}", value);
}
}
// Release the workflow context
Aim::release(&handle).unwrap();§See Also
Aim::cell()- Retrieves a cell from the globally visible MVCC stateAim::has_cell()- Checks if a cell exists without retrieving itAim::get_row()- Retrieves a cell by index position instead of identifierAim::acquire()- Acquires exclusive write access to a workflowAim::snapshot()- Makes changes visible globallyCell- The cell data structure and its methods
§MVCC Considerations
This function operates on the write context’s current state, which includes:
- All previously committed changes from snapshots
- All uncommitted changes made in this write context
- Changes are isolated from other concurrent write contexts until
snapshot()is called
For reading from the globally visible state (after snapshots), use Aim::cell() instead.
§Performance Considerations
- Time complexity: O(log n) for rule lookup in the workflow’s internal data structure
- Memory overhead: Minimal - only the cell data is returned
- Lock contention: Uses a write lock internally, but only for read access, so it doesn’t block other readers
- For frequent identifier lookups, consider caching the result or using batch operations
Sourcepub fn append_or_update_cell(handle: &str, cell: Cell) -> Result<()>
pub fn append_or_update_cell(handle: &str, cell: Cell) -> Result<()>
§Appends a new rule to or updates an existing rule within a workflow using an active write context.
§title: Append or Update Cell
This function appends a new cell (rule) to a workflow or updates an existing cell with the same identifier using an active write context.
§Arguments
handle- A string slice referencing an active workflow context handle obtained fromAim::acquire()cell- ACellcontaining the rule data to append or update
§Returns
Returns Ok(()) on success, or an error if the operation fails.
§Errors
Returns an error if:
- The handle is not a valid active workflow context
- The cell identifier is invalid (empty or contains reserved characters)
- The workflow is not accessible for writing
§Behavior
Internally, append_or_update_cell() performs the following operations:
- Locates the instance context using the provided handle
- Converts the
Cellto aRowusingRow::convert() - Calls the workflow’s append_or_update method on the target workflow:
- If a rule with the same identifier already exists, it updates the existing rule
- If no rule with that identifier exists, it appends the new rule to the end of the workflow
- Marks the workflow as having pending changes for eventual saving
§Side Effects
- Creates or updates a rule in the specified workflow
- Marks the workflow as having pending changes that will be saved on the next snapshot or release
- If updating an existing rule, preserves the rule’s position in the workflow
§Usage Pattern
use aimx::{Aim, Cell, Reference};
use std::sync::Arc;
// Acquire workflow context
let reference = Reference::parse("foo.bar").unwrap();
let handle = Aim::acquire(reference.clone()).unwrap();
// Create and append/update a cell
let cell = Cell::new("my_rule", "Number", "42", "");
Aim::append_or_update_cell(&handle, cell).unwrap();
// Make changes visible
Aim::snapshot(&handle).unwrap();
// Release the context
Aim::release(&handle).unwrap();§See Also
Aim::acquire()- Acquires exclusive write access to a workflowAim::snapshot()- Saves the current state to make changes visibleAim::release()- Releases a workflow context and finalizes changesCell::new()- Creates a new cell with specified propertiesCell::convert_rule()- Converts a rule to a cell representation
Sourcepub fn update_cell(
handle: &str,
identifier: Arc<str>,
typedef: Arc<str>,
formula: Arc<str>,
value: Arc<str>,
) -> Result<()>
pub fn update_cell( handle: &str, identifier: Arc<str>, typedef: Arc<str>, formula: Arc<str>, value: Arc<str>, ) -> Result<()>
§Updates a specific cell (rule) within a workflow using an active write context.
§title: Update Cell
Updates an existing cell (rule) within a workflow using an active write context, replacing all aspects of the rule including identifier, type definition, formula, and value.
Unlike Aim::append_or_update_cell(), this function only updates existing cells and will fail if the cell does not exist.
§Arguments
handle- An active write context handle obtained fromAim::acquire(). This handle provides exclusive write access to the workflow.identifier- The new identifier for the cell. This can be the same as the current identifier or a different one for renaming. Must be unique within the workflow.typedef- The type definition for the cell (e.g.,"Number","Text","Bool","Node","Format"). This determines how the cell’s value is interpreted and validated.formula- The AIMX expression formula that computes the cell’s value. Can be empty""for static cells or cells that derive their value from other sources.value- The current value of the cell. For computed cells, this is typically empty""and will be populated when the formula is evaluated.
§Returns
Returns Ok(()) on successful update, or an anyhow::Result error if the operation fails.
§Errors
Returns an error if:
- The workflow handle is invalid or expired
- The target cell does not exist in the workflow
- The new identifier conflicts with an existing cell (when renaming)
- The type definition is invalid or unsupported
- The formula contains syntax errors (parsing failures)
- Insufficient permissions or I/O errors occur during the update
§Behavior
The update_cell function performs a complete replacement of an existing cell’s properties:
- Validation: Validates that the target cell exists and the new identifier won’t cause conflicts
- Rule Construction: Creates a new
Rulefrom the provided parameters, performing static evaluation of constant expressions - Atomic Update: Replaces the entire rule atomically - either all changes succeed or none are applied
- Immediate Effect: Changes are visible immediately within the current write context
- MVCC Protection: Changes remain private to the write context until
Aim::snapshot()is called
§Side Effects
- Workflow Modification: Updates the specified rule in the workflow’s internal rule table
- Change Tracking: Marks the workflow as changed for subsequent saving
- MVCC State: Creates a private version of the workflow visible only to the current write context
- Identifier Updates: If the identifier changes, updates internal lookup tables for efficient rule access
§Usage Pattern
Update an existing cell’s formula and type while optionally renaming it:
use aimx::{Aim, Reference, Cell};
use std::sync::Arc;
// Acquire workflow context
let reference = Reference::parse("project.budget").unwrap();
let handle = Aim::acquire(reference.clone()).unwrap();
// First, check if the cell exists and get its current state
if Aim::has_cell(&handle, "total_cost").unwrap() {
// Update the cell's formula and type
Aim::update_cell(
&handle,
Arc::from("total_cost"), // Keep same identifier
Arc::from("Number"), // Change to Number type
Arc::from("materials + labor + overhead"), // New formula
Arc::from("") // Empty value (computed)
).unwrap();
// Make changes visible to other contexts
Aim::snapshot(&handle).unwrap();
} else {
println!("Cell 'total_cost' does not exist");
}
// Clean up and persist changes
Aim::release(&handle).unwrap();Rename a cell while updating its content:
use aimx::{Aim, Reference};
use std::sync::Arc;
let reference = Reference::parse("project.schedule").unwrap();
let handle = Aim::acquire(reference).unwrap();
// Rename 'old_deadline' to 'project_deadline' and update its value
Aim::update_cell(
&handle,
Arc::from("project_deadline"), // New identifier
Arc::from("Date"), // Type
Arc::from(""), // No formula (static value)
Arc::from("\"2024-12-31\"") // New value
).unwrap();
Aim::snapshot(&handle).unwrap();
Aim::release(&handle).unwrap();§MVCC Considerations
- Private Updates: Changes are only visible within the write context that made them
- Reader Isolation: Other read contexts continue to see the previous version of the workflow
- Snapshot Requirement: Call
Aim::snapshot()to make changes globally visible to new readers - Conflict Prevention: Update operations are atomic and isolated within each write context
§Performance Considerations
- Formula Parsing: Formulas are parsed immediately during the update operation
- Static Evaluation: Constant expressions are evaluated at update time for performance
- Validation: Type and syntax validation occurs synchronously during the update
- Memory Usage: Only the modified cell is updated in memory; the entire workflow is not copied
- Lookup Efficiency: Cell identifier changes update internal hash tables for O(1) access
§Common Use Cases
- Formula Correction: Fix syntax errors or logic issues in existing formulas
- Type Migration: Change data types as requirements evolve (e.g., Text to Number)
- Identifier Refactoring: Rename cells for better organization and clarity
- Value Updates: Update static values (though
Aim::update_cell_value()is more efficient for this) - Rule Enhancement: Add error handling, validation, or optimization to formulas
- Data Model Evolution: Modify the structure of workflow data as business rules change
§Error Handling
When update_cell fails, the error typically indicates one of these issues:
use aimx::{Aim, Reference};
use std::sync::Arc;
let reference = Reference::parse("project.data").unwrap();
let handle = Aim::acquire(reference).unwrap();
match Aim::update_cell(
&handle,
Arc::from("nonexistent_cell"), // This will fail
Arc::from("Number"),
Arc::from("1 + 1"),
Arc::from("")
) {
Ok(()) => println!("Cell updated successfully"),
Err(e) => {
if e.to_string().contains("does not exist") {
println!("Cell not found - use append_or_update_cell for new cells");
} else {
println!("Update failed: {}", e);
}
}
}
Aim::release(&handle).unwrap();§Integration with Other APIs
- Use
Aim::get_cell()to retrieve current values before updating - Use
Aim::has_cell()to check if a cell exists before callingupdate_cell - Use
Aim::append_or_update_cell()for operations that should create the cell if it doesn’t exist - Use
Aim::update_cell_value()for updating only the value when the formula should remain unchanged - Use
Aim::delete_cell()to remove a cell entirely - Use
Aim::snapshot()to make changes visible to other contexts - Use
Aim::release()to finalize changes and clean up the write context
§See Also
Aim::append_or_update_cell()- Create or update a cell (safer for unknown cells)Aim::update_cell_value()- Update only the value of an existing cellAim::get_cell()- Retrieve the current state of a cellAim::has_cell()- Check if a cell exists in the workflowAim::delete_cell()- Remove a cell from the workflowAim::acquire()- Obtain an exclusive write context handleAim::snapshot()- Make pending changes visible to readersAim::release()- Finalize and persist changes, cleaning up the write context
§Related Types
Cell- The API representation of a workflow cellRule- The internal representation of a workflow ruleReference- Identifies a specific workflow in the workspaceValue- Runtime value representation with type informationcrate::expressions::ExpressionLike- Parsed AIMX expression for formula evaluation
Sourcepub fn update_cell_value(
handle: &str,
identifier: Arc<str>,
value: Arc<str>,
) -> Result<()>
pub fn update_cell_value( handle: &str, identifier: Arc<str>, value: Arc<str>, ) -> Result<()>
§Updates only the value of an existing cell within a workflow using an active write context.
§title: Update Cell Value
This function updates only the value of an existing cell (rule) within a workflow using an active write context. Unlike update_cell(), this function only modifies the cell’s value while preserving its type definition and formula.
§Arguments
handle- A&strrepresenting the workflow instance handle obtained fromAim::acquire(). This provides exclusive write access to the workflow.identifier- AnArc<str>containing the unique identifier of the cell to update. The cell must already exist in the workflow.value- AnArc<str>containing the new value to set. This will be converted to an appropriateValuetype internally.
§Returns
Returns a Result<()> indicating success or failure. The operation succeeds if the cell exists and the value is successfully updated.
§Errors
Returns an error if:
- The workflow instance handle is invalid
- The cell with the specified identifier does not exist in the workflow
- The workflow cannot be accessed for writing (e.g., not properly acquired)
§Behavior
Internally, update_cell_value() performs the following operations:
- Locates the workflow instance using the provided handle
- Acquires a write lock on the workflow
- Finds the existing rule by its identifier
- Updates only the rule’s value field with the new value
- Marks the workflow as having partial changes for persistence
This function only updates the value portion of a cell, leaving the type definition and formula unchanged. If you need to modify the type or formula as well, use Aim::update_cell() instead.
§Side Effects
- Updates the value of an existing rule in the workflow
- Marks the workflow as having pending changes that need to be saved
- Changes are only visible within the current write context until
Aim::snapshot()orAim::release()is called
§Usage Pattern
use aimx::{Aim, Cell, Reference};
use std::sync::Arc;
// Acquire workflow context
let reference = Reference::parse("my_workflow").unwrap();
let handle = Aim::acquire(reference).unwrap();
// Update a cell's value
Aim::update_cell_value(&handle, Arc::from("my_cell"), Arc::from("new_value")).unwrap();
// Make changes visible
Aim::snapshot(&handle).unwrap();
// Release the workflow
Aim::release(&handle).unwrap();§See Also
Aim::acquire()- Acquire exclusive write access to a workflowAim::update_cell()- Update an entire cell including type and formulaAim::snapshot()- Save changes to make them globally visibleAim::release()- Release workflow write accessAim::get_cell()- Retrieve a cell’s current stateCell- Container for cell data including identifier, type, formula, and value
Sourcepub fn delete_cell(handle: &str, identifier: Arc<str>) -> Result<Cell>
pub fn delete_cell(handle: &str, identifier: Arc<str>) -> Result<Cell>
§Permanently removes a cell (rule) from a workflow by its identifier and returns the removed cell.
§title: Delete Cell
This function permanently removes a cell (rule) from a workflow by its identifier and returns the removed cell.
§Arguments
handle- A&strreference to an active write context handle obtained fromAim::acquire. The workflow must be acquired for writing before calling this function.identifier- AnArc<str>containing the identifier of the rule to delete. Must exactly match an existing rule identifier in the workflow.
§Returns
Returns a Result<Cell> containing:
- Success: Returns
Ok(Cell)with the removed rule’s data - Non-existent Rule: Returns
Ok(Cell::Empty)if the identifier does not exist (no error thrown) - Execution Error: Returns
Err(anyhow::Error)if the handle is invalid or refers to a released context
§Errors
Returns an error if:
- The handle is invalid or refers to a released context
- The workflow cannot be modified
§Behavior
Internally, delete_cell() performs the following operations:
- Locates the instance using the provided handle
- Acquires a write lock on the workflow context
- Calls
target().delete_rule(&identifier)on the underlying workflow - Converts the deleted row to a
CellusingCell::convert_row() - Returns the cell (or
Cell::Emptyif the rule didn’t exist)
The underlying delete_rule method:
- Removes the rule from the workflow’s internal storage
- Updates the identifier-to-index mapping by removing the entry
- Sets the change status to
Versionto indicate structural changes - Leaves an empty row at the original position to maintain index stability
§Side Effects
- Removes the rule from the workflow’s internal storage
- Updates the identifier-to-index mapping by removing the entry for the deleted rule
- Flags the workflow for a version change on next save
- Maintains row structure by leaving an empty row at the deleted position
- May affect subsequent rule lookups and index-based operations
§Usage Pattern
use aimx::{Aim, Cell};
use std::sync::Arc;
// Acquire workflow context
let reference = aimx::Reference::parse("foo.bar").unwrap();
let handle = Aim::acquire(reference.clone()).unwrap();
// Delete a specific cell
let deleted_cell = Aim::delete_cell(&handle, Arc::from("target_rule")).unwrap();
if !deleted_cell.is_empty() {
if let Some(identifier) = deleted_cell.identifier() {
println!("Deleted cell: {}", identifier);
}
}
// Make changes visible
Aim::snapshot(&handle).unwrap();
Aim::release(&handle).unwrap();§See Also
remove_row: Remove a row by index positionclear_row: Clear row content without deleting the ruleupdate_cell: Replace rule contenthas_cell: Check if a rule exists before deletionget_cell: Retrieve rule metadata before deletion
§MVCC Considerations
The deleted rule becomes invisible to concurrent readers immediately after Aim::snapshot is called, following the workspace’s MVCC model. Until then, the deletion is only visible within the current write context.
§Performance Considerations
- Identifier lookups are O(1) due to internal hash map storage
- Row structure is preserved to maintain index stability for existing operations
- Change tracking automatically flags the workflow for version-based persistence
- No file system operations are performed until the next save operation
Sourcepub fn start(
_source: Arc<Reference>,
_target: Option<Arc<Reference>>,
) -> Result<Arc<str>>
pub fn start( _source: Arc<Reference>, _target: Option<Arc<Reference>>, ) -> Result<Arc<str>>
§Starts a new workflow inference instance by creating a context instance that binds a source workflow template to an inference target.
§title: Start
This function initiates a new workflow inference instance by creating a context instance that binds a source workflow template to an inference target. It generates a unique handle identifier and sets up the necessary infrastructure for running agentic workflows with inference capabilities.
§Arguments
source- AnArc<Reference>pointing to the source workflow that serves as the template for inference. This workflow contains the rules and structure that will be executed during inference.target- An optionalOption<Arc<Reference>>pointing to the target workflow where inference results will be stored. IfNone, a new target workflow is automatically created.
§Returns
Returns a Result<Arc<str>> containing a unique handle identifier that can be used to:
- Reference the inference instance in subsequent API calls
- Access the inference context for evaluation
- Monitor and control the inference workflow execution
§Errors
Returns an error if:
- The source workflow cannot be located or accessed
- The target workflow cannot be created or accessed (if specified)
- There are insufficient permissions to create inference instances
- The workspace is in an invalid state
§Behavior
Internally, start() performs the following operations:
- Generate identifiers: Creates a unique date-stamped identifier for tracking and a random handle identifier for API access
- Create inference node: Adds a new node to the
inferenceworkflow to track this inference instance - Create context instance: Adds a new context instance to the
contextworkflow that binds the source and target workflows - Bind workflows: Establishes the relationship between the source template and target workflow for inference execution
- Return handle: Provides the unique handle for subsequent API interactions
§Side Effects
- Creates or modifies the
inferenceworkflow to track the new inference instance - Creates or modifies the
contextworkflow to establish the source-target binding - Allocates resources for the inference instance that must be cleaned up with
Aim::cancel()or completion - May create a new target workflow if none is specified
§Usage Pattern
use aimx::{Aim, Reference};
use std::sync::Arc;
// Parse the source workflow reference
let source_reference = Reference::parse("my_workflow").unwrap();
// Start a new inference instance
let handle = Aim::start(source_reference.clone(), None).unwrap();
println!("Started inference with handle: {}", handle);
/* Run inference steps using the handle */
// When done, cancel the inference to clean up resources
Aim::cancel(&handle).unwrap();§See Also
Aim::next()- Execute the next step in the workflowAim::cancel()- Cancel and clean up an inference instanceAim::results()- Retrieve inference results from a workflowAim::acquire()- Acquire exclusive write access for modificationsReference- Workflow reference handling
§MVCC Considerations
The start() function operates on the inference and context workflows which are part of the workspace’s MVCC system. The created instances are visible to concurrent readers once committed, but the actual inference execution maintains isolation through the context system.
§Performance Considerations
- Instance creation involves file I/O operations to update the
inferenceandcontextworkflows - Each active inference instance consumes memory for its context and maintains file locks
- Consider cleaning up completed or cancelled instances to free resources
- The function uses workspace-level locks during instance creation, which may block other operations
Sourcepub fn next(_handle: &str) -> Result<()>
pub fn next(_handle: &str) -> Result<()>
§Executes the next step in a workflow inference instance.
§title: Next
This function executes the next step in a workflow inference instance. It advances the workflow evaluation by one step, processing the current rule and potentially branching to the next rule based on the evaluation result. This enables step-by-step execution of agentic workflows for fine-grained control and debugging.
§Arguments
handle- A string slice referencing the workflow inference instance handle obtained fromAim::start(). This handle uniquely identifies the active inference session and provides access to the workflow context.
§Returns
Returns a Result<()> indicating the success or failure of the step execution:
Ok(())- The step executed successfully, which may include:- Normal rule evaluation completion
- Successful branching to another rule
- Workflow completion
Err(anyhow::Error)- The step failed to execute due to:- Invalid or expired handle
- Workflow evaluation errors
- Resource constraints
- State corruption
§Errors
Returns an error if:
- The provided handle does not correspond to an active inference instance
- The inference instance context cannot be accessed or loaded
- The workflow evaluation encounters a critical error
- The step exceeds the maximum evaluation limit (10,000 steps)
- The workflow contains invalid rule references or syntax errors
§Behavior
Internally, next() performs the following operations:
- Instance Resolution: Locates the inference instance using the provided handle
- Context Loading: Acquires the evaluation context for the workflow
- Rule Evaluation: Executes the current rule in the workflow using the context
- Control Flow Processing: Handles branching logic from
Value::Branchresults - State Advancement: Moves the evaluation pointer to the next rule or target
- Error Handling: Captures and reports any evaluation failures
The function implements a step-wise interpreter that:
- Evaluates rules by row index in order
- Respects control-flow constructs like
BranchandRetryexpressions - Prevents infinite loops with a maximum step limit
- Maintains workflow state between calls
- Supports resumption from suspended states
§Side Effects
- Advances the internal evaluation state of the workflow instance
- May modify rule values through
Context::set_value() - Can trigger branching to different rule paths
- May cause inference calls to nested workflows
- Updates the workflow’s change tracking status
- Persists changes to disk when evaluation completes or fails
§Usage Pattern
use aimx::{Aim, Reference};
use std::sync::Arc;
// Start a new inference instance
let source_reference = Reference::parse("my_workflow").unwrap();
let handle = Aim::start(source_reference.clone(), None).unwrap();
// Execute workflow step by step
loop {
match Aim::next(&handle) {
Ok(()) => {
// Check if workflow completed or continue
// Additional logic here...
}
Err(e) => {
println!("Workflow step failed: {}", e);
break;
}
}
}
// Clean up when done
Aim::cancel(&handle).unwrap();§See Also
Aim::start()- Initialize a new workflow inference instanceAim::cancel()- Terminate and clean up an inference instanceAim::results()- Retrieve results from a completed workflowAim::acquire()- Acquire exclusive write access for modificationscrate::aim::ContextLike::run_evaluation()- The underlying evaluation enginecrate::aim::WorkflowStatus- Status enum for workflow execution states
§MVCC Considerations
The next() function operates on workflow instances that participate in the MVCC system:
- Each step may create new version entries in the workflow journal
- Concurrent readers see consistent snapshots of the workflow state
- Write locks are acquired during inference calls to nested workflows
- Changes become visible to other readers only after successful completion
- Failed steps may leave the workflow in an inconsistent state requiring cleanup
§Performance Considerations
- Each call involves context lookup and lock acquisition overhead
- Complex rule expressions or inference calls may take significant time
- Branching operations require additional rule lookups
- Memory usage grows with workflow complexity and nesting depth
- Consider using batch evaluation for simple workflows without branching
- The 10,000 step limit prevents runaway evaluations but may impact very large workflows
§Error Recovery
When next() returns an error:
- The workflow instance remains in its current state
- Use
Aim::results()to examine the current rule values - Consider calling
Aim::cancel()to clean up the instance - Restart with a new instance if the workflow needs to be re-executed
- Check the error details to understand the root cause
§Workflow Control Flow
The function supports AIMX’s control flow constructs:
- Branch expressions:
(condition) -> target_rule- jumps to target on true - Retry expressions:
count, condition -> target_rule- decrements counter and branches - Conditional evaluation: Rules are skipped when previous branches redirect flow
- Error propagation: Critical errors halt evaluation and return failure status
Sourcepub fn undo(_handle: &str) -> Result<()>
pub fn undo(_handle: &str) -> Result<()>
§Moves the workflow instance to the previous version in its journal history.
§title: Undo
Moves the workflow instance to the previous version in its journal history.
This function implements version rollback by navigating to the previous version stored in the workflow’s journal file. It allows reverting workflow changes by moving the active instance context to an earlier point in time.
§Arguments
handle- A string slice containing the unique instance handle obtained fromAim::acquire()that identifies the active workflow context to undo.
§Returns
Returns Result<()> which is:
Ok(())if the undo operation completes successfullyErr(anyhow::Error)if any step fails
§Errors
Returns an error if:
- The instance handle is invalid or cannot be located
- The workflow has no previous versions in its journal (already at first version)
- The previous version cannot be loaded (e.g., corrupted journal or missing data)
- The workflow save operation fails after loading the previous version
- The journal file is missing or cannot be parsed
- The target version is not found in the journal
§Behavior
Internally, undo() performs the following operations:
- Instance Validation: Locates the instance context using the provided handle via
Instance::locate() - Write Lock Acquisition: Acquires a write lock on the instance context
- Journal Check: Verifies that a previous version exists in the workflow’s journal
- Version Navigation: Identifies the previous version number from the journal entries
- Previous Version Loading: Loads the identified previous version using the workflow’s
load_version()method - State Update: Updates the workflow instance to reflect the previous version’s state
- Persistence: Saves the instance state to make the rollback permanent
§Side Effects
- Version Rollback: Changes the workflow’s active version to the previous one
- Data Reversion: Restores all rules and values to their state in the previous version
- Version Tracking: Updates the workflow’s version metadata to reflect the rollback
- Journal Preservation: Maintains the journal history (does not delete versions)
- Instance State: Updates the instance context to work with the rolled-back workflow
§Usage Pattern
use aimx::{Aim, Reference};
use std::sync::Arc;
// Acquire workflow context
let reference = Reference::parse("foo.bar").unwrap();
let handle = Aim::acquire(reference.clone()).unwrap();
// Make some changes
// ... workflow modifications ...
// Save the changes
Aim::snapshot(&handle).unwrap();
// Make more changes
// ... additional modifications ...
// Save again
Aim::snapshot(&handle).unwrap();
// Undo to previous version
match Aim::undo(&handle) {
Ok(()) => println!("Successfully rolled back to previous version"),
Err(e) => println!("Failed to undo: {}", e),
}
// Release the workflow
Aim::release(&handle).unwrap();§Version History Navigation
The undo() function enables time-travel through workflow versions:
Version Timeline:
[1] Initial version
[2] First modification ← undo() from here
[3] Second modification ← current active version
After undo():
[1] Initial version
[2] First modification ← current active version
[3] Second modification ← still exists in journal§MVCC Considerations
The undo operation works within the Multi-Version Concurrency Control framework:
- Isolation: Only affects the current write context, not other concurrent readers
- Atomicity: Either completely rolls back to the previous version or fails entirely
- Consistency: Maintains workflow integrity by loading complete previous states
- Durability: Changes are persisted to disk after successful rollback
§Relationship to Other Version Functions
| Function | Direction | Target | Purpose |
|---|---|---|---|
undo() | Backward | Previous version | Rollback recent changes |
redo() | Forward | Next version | Re-apply undone changes |
proceed() | Forward | Next version | Move to newer version |
snapshot() | Current | Current version | Save current state |
§Error Recovery
If undo() fails, the workflow instance remains in its current state:
- No partial rollbacks occur
- The original version remains active
- Subsequent operations can retry the undo or take alternative actions
- Journal integrity is preserved regardless of operation success
§See Also
Aim::redo()- Re-apply changes that were undoneAim::proceed()- Move to the next version in the journalAim::snapshot()- Save the current state to create a new versioncrate::aim::Workflow::load_version()- Internal method for loading specific versionscrate::aim::Journal- Version tracking and navigation system- Context lifecycle management best practices
§Performance Considerations
- I/O Operations: Requires reading the target version from disk
- Memory Usage: Loads the entire previous version into memory
- Lock Duration: Holds write locks during the entire operation
- Journal Size: Performance may degrade with very large journal files
- Version Distance: Time complexity is generally constant regardless of version distance
§Implementation Notes
The function is currently implemented as a TODO placeholder. When implemented, it should:
- Integrate with the existing journal system in
crate::aim::journal - Use the workflow’s
load_version()method for version navigation - Follow the same error handling patterns as other API functions
- Maintain consistency with the MVCC architecture
- Include comprehensive tests for edge cases and error conditions
Sourcepub fn proceed(_handle: &str) -> Result<()>
pub fn proceed(_handle: &str) -> Result<()>
§Makes a previous version (currently loaded by undo) the current workflow instance.
§title: Proceed
This function advances a workflow inference instance to the next version in its journal history, effectively moving forward through the workflow’s version timeline after a reverse operation like undo().
When called on an inference instance handle, proceed() locates the associated workflow, reads its journal to find the next available version, loads that version, and makes it the current active version for the inference instance. This function is typically used in conjunction with undo() to provide forward navigation through workflow state history.
§Arguments
handle- A string reference to the workflow inference instance handle obtained fromAim::start()or other inference management functions. The handle uniquely identifies the active inference instance within the workspace context.
§Returns
Returns a Result<()> containing:
Ok(())if the workflow was successfully advanced to the next versionErr(anyhow::Error)if the operation failed due to invalid handle, missing journal entries, or file system errors
§Errors
Returns an error if:
- The provided handle does not correspond to an active inference instance
- The workflow associated with the handle has no journal entries
- The workflow is already at the latest version (no forward versions available)
- The journal file cannot be read or parsed
- The target version cannot be loaded from the workflow file
- File system access is denied or the workflow file is corrupted
§Behavior
Internally, proceed() performs the following operations:
- Instance Resolution: Locates the inference instance using the provided handle
- Workflow Access: Acquires read access to the workflow associated with the instance
- Journal Analysis: Reads the workflow’s journal file to determine available versions
- Version Validation: Checks if there is a next version available to proceed to
- Version Loading: Loads the target version from the workflow file
- State Update: Updates the workflow instance to use the new version as current
- MVCC Coordination: Ensures the version change is properly coordinated with the MVCC system
§Side Effects
- Updates the current version of the specified workflow inference instance
- May load different rule sets and workflow state from the target version
- Changes the evaluation context for subsequent
Aim::next()calls on the same instance - Maintains audit trail through the journal system for version transitions
§Usage Pattern
use aimx::{Aim, Reference};
use std::sync::Arc;
// Start a workflow inference instance
let source: Arc<Reference> = Arc::from(Reference::parse("my_workflow").unwrap());
let handle = Aim::start(source, None).unwrap();
// Perform some inference steps
Aim::next(&handle).unwrap();
// Undo to a previous version
Aim::undo(&handle).unwrap();
// Proceed forward to the next version (undo the undo)
Aim::proceed(&handle).unwrap();
// Continue with inference
Aim::next(&handle).unwrap();
// Clean up
Aim::cancel(&handle).unwrap();§See Also
Aim::start()- Creates new workflow inference instancesAim::next()- Executes the next step in workflow inferenceAim::undo()- Moves workflow to previous version in journalAim::redo()- Alternative name for proceeding forward in version historyAim::cancel()- Terminates and removes workflow inference instancesInstance- Internal type managing workflow inference stateWorkflowLike- Trait providing version and journal accesscrate::aim::Journal- Version history management system
§MVCC Considerations
The proceed() function operates within the MVCC (Multi-Version Concurrency Control) framework:
- Version transitions are atomic operations that maintain consistency
- Multiple inference instances can exist simultaneously with different versions
- The journal provides immutable version history for rollback/forward operations
- Workflow locks are acquired during version transitions to prevent conflicts
§Performance Considerations
- Journal reading is cached and efficient for subsequent operations
- Version loading involves parsing workflow content, which has O(n) complexity where n is the number of rules
- Frequent version switching may impact performance; consider caching frequently accessed versions
- Large workflow files with extensive journal history may require more memory for version management
Sourcepub fn redo(_handle: &str) -> Result<()>
pub fn redo(_handle: &str) -> Result<()>
§Re-applies changes that were previously undone using Aim::undo(), effectively moving forward through the workflow’s version history to restore previously rolled-back changes.
§title: Redo
Re-applies changes that were previously undone using Aim::undo(), effectively moving forward through the workflow’s version history to restore previously rolled-back changes.
This function implements forward navigation in the workflow version timeline, allowing users to re-apply changes that were undone. It is particularly useful when an undo operation was performed in error or when exploring different versions of a workflow during development.
§Arguments
handle- A string slice containing the unique instance handle obtained fromAim::acquire()that identifies the active workflow context to redo.
§Returns
Returns Result<()> which is:
Ok(())if the redo operation completes successfullyErr(anyhow::Error)if any step fails
§Errors
Returns an error if:
- The instance handle is invalid or cannot be located
- No previous undo operation has been performed (no changes to redo)
- The next version in the redo sequence cannot be loaded (e.g., corrupted journal or missing data)
- The workflow save operation fails after loading the target version
- The journal file is missing or cannot be parsed
- The target version is not found in the journal
- The workflow has reached the latest version (no forward versions available for redo)
§Behavior
Internally, redo() performs the following operations:
- Instance Validation: Locates the instance context using the provided handle via
Instance::locate() - Write Lock Acquisition: Acquires a write lock on the instance context
- Undo History Check: Verifies that a previous undo operation has been performed and identifies the target version to redo
- Version Validation: Ensures the target version exists and is accessible
- Version Loading: Loads the identified version using the workflow’s
load_version()method - State Restoration: Updates the workflow instance to reflect the target version’s state
- Persistence: Saves the instance state to make the redo permanent
- Undo History Update: Advances the undo/redo position pointer for future operations
§Side Effects
- Change Restoration: Re-applies workflow changes that were previously undone
- Version Navigation: Moves the workflow’s active version forward in the version timeline
- State Update: Restores all rules and values to their state in the target version
- Version Tracking: Updates the workflow’s version metadata to reflect the redo operation
- Undo History Management: Advances the position in the undo/redo history chain
- Instance State: Updates the instance context to work with the restored workflow
§Usage Pattern
use aimx::{Aim, Reference};
use std::sync::Arc;
// Acquire workflow context
let reference = Reference::parse("foo.bar").unwrap();
let handle = Aim::acquire(reference.clone()).unwrap();
// Make some changes and save
// ... workflow modifications ...
Aim::snapshot(&handle).unwrap();
// Undo the changes
match Aim::undo(&handle) {
Ok(()) => println!("Successfully undid changes"),
Err(e) => println!("Failed to undo: {}", e),
}
// Redo to restore the changes
match Aim::redo(&handle) {
Ok(()) => println!("Successfully redid changes"),
Err(e) => println!("Failed to redo: {}", e),
}
// Release the workflow
Aim::release(&handle).unwrap();§Version History Navigation
The redo() function enables forward navigation through workflow versions:
Version Timeline:
[1] Initial version
[2] First modification ← undo() was performed from here to version 1
[3] Second modification ← current active version after redo()
After undo():
[1] Initial version ← active version
[2] First modification
[3] Second modification
After redo():
[1] Initial version
[2] First modification ← restored to this version
[3] Second modification §Relationship to Other Version Functions
| Function | Direction | Target | Purpose |
|---|---|---|---|
undo() | Backward | Previous version | Rollback recent changes |
redo() | Forward | Next undone version | Re-apply previously undone changes |
proceed() | Forward | Next version | Move to newer version regardless of undo state |
snapshot() | Current | Current version | Save current state to create a new version |
Key differences:
redo()specifically re-applies changes that were undone viaundo()proceed()moves forward to any next version, regardless of undo historyredo()maintains undo/redo history state, whileproceed()does not
§MVCC Considerations
The redo operation works within the Multi-Version Concurrency Control framework:
- Isolation: Only affects the current write context, not other concurrent readers
- Atomicity: Either completely restores the target version or fails entirely
- Consistency: Maintains workflow integrity by loading complete target states
- Durability: Changes are persisted to disk after successful restoration
- Undo/Redo Chain: Maintains the undo/redo history for potential future operations
§Error Recovery
If redo() fails, the workflow instance remains in its current state:
- No partial restorations occur
- The original version remains active
- Subsequent operations can retry the redo or take alternative actions
- Undo/redo history is preserved regardless of operation success
- The workflow can still use other version navigation functions
§See Also
Aim::undo()- Undoes recent changes to enable redo operationsAim::proceed()- Alternative forward version navigationAim::snapshot()- Creates new versions for undo/redo operationsAim::acquire()- Obtains workflow context for version operationsAim::release()- Finalizes changes and releases workflow contextcrate::aim::Workflow::load_version()- Internal method for loading specific versionscrate::aim::Journal- Version tracking and navigation system
§Performance Considerations
- I/O Operations: Requires reading the target version from disk
- Memory Usage: Loads the entire target version into memory
- Lock Duration: Holds write locks during the entire operation
- Journal Size: Performance may degrade with very large journal files
- Undo History: Maintains additional metadata for undo/redo chain management
- Version Distance: Time complexity is generally constant regardless of version distance
§Implementation Notes
The function is currently implemented as a TODO placeholder. When implemented, it should:
- Integrate with the existing journal system in
crate::aim::journal - Track undo/redo position state to determine the correct target version
- Use the workflow’s
load_version()method for version navigation - Follow the same error handling patterns as other API functions
- Maintain consistency with the MVCC architecture
- Include comprehensive tests for edge cases and error conditions
- Ensure undo/redo operations are inverses of each other
- Handle cases where versions have been pruned or journal entries are missing
§Typical Workflow Patterns
use aimx::{Aim, Reference};
use std::sync::Arc;
let reference = Reference::parse("my_workflow").unwrap();
let handle = Aim::acquire(reference).unwrap();
// Pattern 1: Save, undo, then redo
Aim::snapshot(&handle).unwrap();
Aim::undo(&handle).unwrap();
Aim::redo(&handle).unwrap();
// Pattern 2: Multiple undo/redo cycles
Aim::snapshot(&handle).unwrap();
Aim::snapshot(&handle).unwrap();
Aim::undo(&handle).unwrap(); // Back to snapshot 1
Aim::undo(&handle).unwrap(); // Back to initial version
Aim::redo(&handle).unwrap(); // Forward to snapshot 1
Aim::redo(&handle).unwrap(); // Forward to snapshot 2
// Pattern 3: Error handling
match Aim::redo(&handle) {
Ok(()) => println!("Redo successful"),
Err(e) => {
println!("Redo failed: {}", e);
// Handle the error appropriately
}
}
Aim::release(&handle).unwrap();Sourcepub fn cancel(_handle: &str) -> Result<()>
pub fn cancel(_handle: &str) -> Result<()>
§Terminates and cleans up a workflow inference instance, removing all associated resources without saving changes.
§title: Cancel
This function terminates and cleans up a workflow inference instance, removing all
associated resources and releasing any locks. Unlike Aim::release() which saves
changes before cleanup, cancel() discards any unsaved changes and performs a
clean termination of the inference session.
§Arguments
handle- A string slice containing the unique instance handle obtained fromAim::start()that identifies the active workflow inference instance to cancel.
§Returns
Returns Result<()> which is:
Ok(())if the cancellation operation completes successfullyErr(anyhow::Error)if any step fails
§Errors
Returns an error if:
- The instance handle is invalid or cannot be located
- The instance cannot be locked for writing (e.g., concurrent access)
- The context workflow cannot be located or accessed
- The context workflow operations fail (e.g., save errors)
- The instance entry cannot be found in the context workflow
§Behavior
Internally, cancel() performs a clean termination operation that removes the
inference instance without preserving any changes:
Phase 1: Instance Cleanup
- Locates the instance context using the provided handle via
Instance::locate() - Acquires a write lock on the instance context
- Discards any unsaved changes - unlike
release(), no save operation is performed - Releases the instance write lock
Phase 2: Context Cleanup
- Locates the global
contextworkflow usingReference::context() - Acquires a write lock on the context workflow via
LockManager - Searches for the instance handle in the context workflow using the workflow’s
get_indexmethod - Removes the instance row from the context workflow via the workflow’s
remove_rowmethod - Saves the updated context workflow via the workflow’s
savemethod - Updates the context node with the modified workflow
- Releases the context workflow write lock
§Side Effects
- No Persistence: Does not save any unsaved changes to the target workflow
- Context Cleanup: Removes the instance entry from the global context workflow
- Lock Release: Releases write locks on both the instance and context workflow
- Resource Cleanup: Makes the workflow available for future access
- Instance Termination: Permanently terminates the inference session
§Usage Pattern
use aimx::{Aim, Reference};
use std::sync::Arc;
// Start a workflow inference
let source_reference = Reference::parse("foo.bar").unwrap();
let handle = Aim::start(source_reference.clone(), None).unwrap();
// Run some inference steps
// ... inference operations ...
// Cancel the inference if needed (e.g., on error or user request)
Aim::cancel(&handle).unwrap();§Error Handling
The function uses a strict error handling approach:
- If the instance cannot be located, the function returns an error
- If the context cleanup fails, the function returns an error indicating that the instance may still be locked and require manual cleanup
- If the instance is not found in the context workflow, returns a specific error message indicating a missing instance
§When to Use cancel() vs release()
| Function | Use Case | Persistence | Resource Cleanup |
|---|---|---|---|
cancel() | Error conditions, user abort, cleanup without saving | No - discards changes | Yes - removes instance |
release() | Normal completion of modifications | Yes - saves all changes | Yes - removes instance |
§Workflow Inference Lifecycle
The cancel() function is part of the workflow inference lifecycle:
- Start:
Aim::start()creates a new inference instance - Execute:
Aim::next()runs inference steps - Cancel:
Aim::cancel()terminates without saving (this function) - Release:
Aim::release()terminates with saving (for modifications)
§Error Recovery
When using cancel() for error recovery:
- Call
cancel()to clean up the failed inference instance - The original workflow state is preserved (no changes from the failed inference)
- Start a new inference instance if needed
- Consider using
Aim::results()to examine the current workflow state
§MVCC Considerations
The cancellation operation affects Multi-Version Concurrency Control:
- No new version is created for the target workflow (changes are discarded)
- The source workflow remains unchanged and available for concurrent readers
- The context workflow is updated to remove the instance, making it available for new instances
- Released locks allow other processes to access the workflow immediately
§See Also
Aim::start()- Initialize a new workflow inference instanceAim::next()- Execute the next step in workflow inferenceAim::release()- Release and save changes from a workflow modification sessionAim::acquire()- Acquire exclusive write access for direct modificationsInstance::locate()- Locate an instance by handle- Workflow inference error handling best practices
Sourcepub fn results(locator: Arc<Reference>) -> Result<Vec<Cell>>
pub fn results(locator: Arc<Reference>) -> Result<Vec<Cell>>
§Retrieves all inference results from a workflow as result cells optimized for output display.
§title: Results
Retrieves all inference results from a workflow as result cells optimized for output display.
This function provides access to the evaluated results of a workflow, converting each row into a Cell::Result representation that shows the final computed values rather than the source formulas. It’s designed for reading workflow output after inference execution.
§Arguments
locator- AnArc<Reference>that identifies the workflow to retrieve results from
§Returns
Returns a Result<Vec<Cell>> containing:
- A vector of
Cellobjects representing workflow results - Each cell is converted using
Cell::convert_result()for result-oriented display - Cells may be
Cell::Empty,Cell::Comment,Cell::Errata, orCell::Result
§Errors
Returns an error if:
- The locator references a non-existent workflow node
- The workflow file cannot be read or parsed
- The workspace is in an invalid state
§Behavior
Internally, results() performs the following operations:
- Node Location: Uses
Workspace::locate_node()to find the workflow node - Workflow Access: Retrieves the workflow from the located node
- Row Iteration: Iterates through all rows in the workflow using
workflow.iter_rows() - Result Conversion: Converts each row to a result cell using
Cell::convert_result() - Collection: Returns all converted cells as a vector
§Key Differences from list()
| Feature | list() | results() |
|---|---|---|
| Purpose | Source template viewing/editing | Inference output display |
| Cell Type | Formula cells with source | Result cells with values |
| Error Display | Shows formula errors | Shows evaluation errors |
| Value Content | May show computed values | Always shows final values |
§Usage Pattern
use aimx::{Aim, Reference, Cell};
use std::sync::Arc;
// Create or acquire a workflow reference
let locator = Reference::parse("my_workflow").unwrap();
// Retrieve results (typically after inference execution)
let results = Aim::results(locator).unwrap();
// Process results
for cell in results {
match cell {
Cell::Result { identifier, typedef, value } => {
println!("{}: {} = {}", identifier, typedef, value);
},
Cell::Errata { identifier, reason, .. } => {
println!("Error in {}: {}", identifier, reason);
},
Cell::Comment { comment } => {
println!("Comment: {}", comment);
},
_ => {
// Handle other cell types (Node, Format, Branch, Retry, Formula, Empty)
}
}
}§Integration with Inference Workflow
This function is typically used in the following inference scenarios:
- After inference execution: Retrieve results from completed inference steps
- Batch processing: Get all results from a workflow that has been fully evaluated
- Result monitoring: Monitor inference progress by checking result values
- Error tracking: Identify which rules produced errors during inference
§Example: Basic Results Retrieval
use aimx::{Aim, Reference, Cell};
use std::sync::Arc;
// Create or acquire a workflow reference
let locator = Reference::parse("my_workflow").unwrap();
// Retrieve results (after inference has been executed)
let results = Aim::results(locator).unwrap();
// Process and display results
for cell in results {
match cell {
Cell::Result { identifier, typedef, value } => {
println!("Result: {} ({}): {}", identifier, typedef, value);
},
Cell::Errata { identifier, reason, .. } => {
println!("Error in {}: {}", identifier, reason);
},
Cell::Comment { comment } => {
println!("Comment: {}", comment);
},
_ => {
// Handle other cell types (Node, Format, Branch, Retry, Formula, Empty)
}
}
}§Performance Considerations
- Memory Usage: Loads entire workflow into memory for row iteration
- Conversion Overhead: Each row undergoes result conversion which may involve value formatting
- Error Processing: Error state checking adds minimal overhead per row
- Best Practice: Use for result retrieval rather than frequent polling during inference
§Error Handling Strategy
The function follows AIMX’s error propagation model:
- Node location errors are propagated as workspace errors
- Workflow parsing errors are returned as IO errors
- Individual rule errors are captured in
Cell::Errataresults - This allows comprehensive error tracking from source to final results
§See Also
Aim::list() - Retrieves source template cells for editing
Aim::start() - Starts a new inference instance
Aim::next() - Executes next inference step
Cell::convert_result() - Converts rows to result cells
Reference - Workflow locator reference type
Workspace::locate_node() - Node location function
pub fn check_identifier(input: &str) -> Result<()>
Sourcepub fn function_categories() -> Result<Vec<Arc<str>>>
pub fn function_categories() -> Result<Vec<Arc<str>>>
Get all available function categories.
Returns a list of all function categories in the standard library. Categories include: text, math, business, date, collection, statistical, functional, set, task, and utility.
Sourcepub fn function_list(category: &str) -> Result<Vec<Arc<str>>>
pub fn function_list(category: &str) -> Result<Vec<Arc<str>>>
Get all functions in a specific category.
Returns a list of function identifiers for the specified category. Returns an empty list if the category doesn’t exist.
Sourcepub fn function_card(identifier: &str) -> Result<FunctionCard>
pub fn function_card(identifier: &str) -> Result<FunctionCard>
Get complete documentation for a specific function.
Returns a FunctionCard containing the function’s signature, description, examples, and other documentation. Returns an error if the function is not found.