boxState Management

State management in Happen provides powerful capabilities through minimal abstractions. This guide explores patterns and approaches for effectively managing state across your Happen applications.

Core Principles

Happen's approach to state management follows these foundational principles:

  1. Clear Ownership: Each node owns and is responsible for its specific state

  2. Functional Transformations: State changes occur through pure functional transformations

  3. Event-Driven Updates: State typically changes in response to events

  4. Decentralized Intelligence: Nodes make autonomous decisions based on their local state

  5. Composition Over Complexity: Complex state management emerges from composing simple patterns

Under the hood, Happen uses NATS JetStream's Key-Value store to provide durable, distributed state storage with high consistency guarantees.

Basic State Operations

Accessing State

Happen provides a clean, functional approach to accessing state:

// Access the complete state
const orderState = orderNode.state.get();

// Access with transformation (focused state access)
const activeOrders = orderNode.state.get(state =>
  (state.orders || {}).filter(order => order.status === "active")
);

Transforming State

State transformations use a functional approach:

Composing Transformations

You can compose transformations for cleaner code:

View System

Views provide a window into other nodes' state, enabling coordinated operations across node boundaries.

Basic View Usage

Enhanced Collection

For more efficient collection of state from multiple nodes, use the collect pattern:

This approach:

  • Traverses the node graph only once

  • Collects specific slices of state from each relevant node

  • Transforms the state during collection

  • Returns a unified object with all the collected data

Scaling Patterns

As your application grows, these patterns help manage increasing state complexity.

Selective State Access

Access only what you need to minimize memory footprint:

Domain Partitioning

Partition state across multiple domain-specific nodes:

Each node maintains state for its specific domain, communicating via events when necessary.

Event-Driven State Synchronization

Use events to communicate state changes between nodes:

Chunked Processing

For large state objects, process in manageable chunks:

Advanced Patterns

State Versioning

Track state versions for debugging and auditing:

Computed State

Define computed values based on raw state:

State-Based Event Generation

Generate events based on state conditions:

NATS JetStream Key-Value Store Integration

Under the hood, Happen uses NATS JetStream's Key-Value store capability to provide durable, distributed state storage. The framework handles all the details of storing and retrieving state, ensuring:

  1. Persistence: State is preserved even if nodes or processes restart

  2. Distributed Access: State can be accessed across different processes and machines

  3. Consistency: State updates maintain causal ordering

  4. Performance: High-performance storage with minimal overhead

This integration happens transparently - your code uses the same state API regardless of where nodes are running or how state is stored.

Best Practices

Keep State Focused

Each node should maintain state relevant to its domain:

Use Immutable Patterns

Always update state immutably to maintain predictability:

Prefer Event Communication

Use events to communicate state changes between nodes:

Let Event Flow Drive State Changes

Instead of directly modifying state in response to external conditions, let events drive state changes:

By focusing on clear ownership, functional transformations, and event-driven communication, you can create systems that are both powerful and maintainable. The integration with NATS JetStream's Key-Value store provides a robust foundation for distributed state management without adding complexity to your application code.

Last updated