pub struct Node { /* private fields */ }Expand description
A clonable, concurrency-aware handle to a single workflow
Node provides lazy loading semantics where workflows are only loaded from disk
when first accessed. It implements efficient cloning through Arc sharing,
making it suitable for concurrent access patterns.
§Concurrency Model
Node is designed for concurrent access:
- Read access: Multiple threads can concurrently read the workflow using
get_workflow()orget_workflow_like() - Write access: Mutation requires external coordination through the lock manager
and should be done through
get_workflow_mut() - Lazy loading: Thread-safe transitions from unloaded to loaded state using double-checked locking pattern
§Lifecycle
Nodes begin in the Unloaded state and transition to
Loaded on first access:
Node::new() ──▶ Unloaded ──get_workflow()──▶ Loaded ──set_workflow()──▶ Loaded§Examples
Basic usage:
let reference = Reference::new("example");
let node = Node::new(reference);
// Node is created in unloaded state
// Workflow loading happens lazily on first accessCloning for concurrent access:
let node1 = Node::new(reference);
let node2 = node1.clone();
// Both nodes share the same internal state
assert_eq!(node1, node2);The Clone implementation is cheap, as it only increments the reference
count of the internal Arc.
Implementations§
Source§impl Node
impl Node
Sourcepub fn new(reference: Reference) -> Self
pub fn new(reference: Reference) -> Self
Creates a new Node in an Unloaded state
The workflow will remain unloaded until the first access through
get_workflow() or get_workflow_mut().
§Arguments
reference- The reference pointing to the workflow file location
§Examples
use aimx::Reference;
use aimx::values::Node;
let reference = Reference::new("main");
let node = Node::new(reference);Sourcepub fn get_workflow(&self) -> Arc<Workflow>
pub fn get_workflow(&self) -> Arc<Workflow>
Gets the workflow for read-only access, loading it from disk if necessary
This method employs a double-checked locking pattern to ensure thread safety:
- Acquires read lock to check if workflow is already loaded
- If unloaded, releases read lock and acquires write lock
- Re-checks state (protected by write lock) and loads workflow if still needed
This ensures that:
- Concurrent readers never block each other when workflow is loaded
- Only one thread loads the workflow when transitioning from unloaded to loaded
- No race conditions during state transition
§Returns
An Arc<Workflow> containing a shared, immutable reference to the workflow
§Panics
This method will panic if the thread is unable to acquire the necessary locks, which typically indicates a deadlock scenario.
Sourcepub fn get_workflow_like(&self) -> Arc<dyn WorkflowLike>
pub fn get_workflow_like(&self) -> Arc<dyn WorkflowLike>
Gets the workflow as a trait object implementing WorkflowLike
This provides dynamic dispatch capabilities for workflow operations. The workflow is loaded from disk if not already in memory.
This method is equivalent to calling get_workflow() and
casting the result to Arc<dyn WorkflowLike>. It’s provided as a convenience
for cases where you need to work with the workflow through its trait interface.
§Returns
An Arc<dyn WorkflowLike> trait object for dynamic workflow operations
§Panics
This method will panic if the thread is unable to acquire the necessary locks, which typically indicates a deadlock scenario.
Sourcepub fn get_workflow_mut(&self) -> Workflow
pub fn get_workflow_mut(&self) -> Workflow
Gets the workflow for mutable access, loading it from disk if necessary
§Important Safety Requirement
The caller must already have write permission from the lock manager before calling this method. This method does not acquire external locks.
This method follows the same double-checked locking pattern as
get_workflow() but returns a cloned Workflow
suitable for mutation rather than a shared reference.
Unlike get_workflow() which returns a shared reference,
this method returns an owned Workflow that can be modified. The internal
state still remains loaded, but modifications to the returned workflow won’t
affect the node’s state until set_workflow() is called.
§Returns
A cloned Workflow instance that can be modified
§Panics
This method will panic if the thread is unable to acquire the necessary locks, which typically indicates a deadlock scenario.
Sourcepub fn set_workflow(&self, workflow: Workflow)
pub fn set_workflow(&self, workflow: Workflow)
Atomically replaces the workflow of the node with a concrete Workflow
This method atomically updates the node’s state to contain the provided workflow. The previous state (loaded or unloaded) is replaced entirely.
This is typically used after modifying a workflow obtained through
get_workflow_mut() to commit the changes back to the node.
§Arguments
workflow- The new workflow to store in the node
§Panics
This method will panic if the thread is unable to acquire the necessary write lock, which typically indicates a deadlock scenario.
Trait Implementations§
Source§impl PartialEq for Node
impl PartialEq for Node
Source§fn eq(&self, other: &Self) -> bool
fn eq(&self, other: &Self) -> bool
Compares two Node instances for equality based on shared identity
Two Node instances are considered equal if they reference the exact
same internal Arc<RwLock<NodeState>>. This means they are clones of
each other or reference the same underlying workflow state.
This is not a deep comparison of workflow contents. Two nodes with
different Arc instances but identical workflow contents will be considered
different, while two cloned nodes sharing the same Arc will be equal.
§Returns
true if both nodes share the same internal state pointer, false otherwise
§Examples
let reference = Reference::new("example");
let node1 = Node::new(reference);
let node2 = node1.clone();
// Cloned nodes are equal because they share the same internal state
assert_eq!(node1, node2);