puzzleAdvanced Patterns

The core of Happen is built on a radical commitment to simplicity: two primitives, Nodes and Events, form the entire foundation. While you can build powerful systems using only the basic concepts, the true power of this minimalist approach is its composability. Happen's raw primitives are designed to be powerful building blocks, allowing you to construct sophisticated, production-grade solutions for challenges like distributed transactions, fault tolerance, and system resilience—if your application requires it.

This section is not about features built into the framework; it's about what you can build with the framework. The following patterns demonstrate how Happen's simple, causal-by-default model provides the foundation to implement robust architectures, similar to those found in battle-tested systems like Erlang/OTP, without sacrificing the framework's core simplicity. You don't have to build systems this way, but with Happen, you can.

Saga Pattern for Distributed Transactions

The Saga pattern manages distributed transactions through a sequence of local operations, each with compensating actions for failure scenarios. This is particularly valuable for maintaining consistency across distributed components.

// Create a saga coordinator
const orderSaga = createNode("order-saga");

// Start saga for order processing
orderSaga.on("process-order", async (event) => {
  const { orderId } = event.payload;
  const context = { orderId, steps: [] };
  
  try {
    // Step 1: Reserve inventory
    const inventoryResult = await orderSaga.send(inventoryNode, {
      type: "reserve-inventory",
      payload: event.payload
    }).return();
    
    if (!inventoryResult.success) {
      throw new Error(`Inventory reservation failed: ${inventoryResult.reason}`);
    }
    
    context.steps.push("inventory-reserved");
    
    // Step 2: Process payment
    const paymentResult = await orderSaga.send(paymentNode, {
      type: "process-payment",
      payload: event.payload
    }).return();
    
    if (!paymentResult.success) {
      throw new Error(`Payment failed: ${paymentResult.reason}`);
    }
    
    context.steps.push("payment-processed");
    context.paymentId = paymentResult.paymentId;
    
    // Step 3: Create shipment
    const shipmentResult = await orderSaga.send(shipmentNode, {
      type: "create-shipment",
      payload: {
        orderId,
        items: event.payload.items,
        address: event.payload.shippingAddress
      }
    }).return();
    
    if (!shipmentResult.success) {
      throw new Error(`Shipment creation failed: ${shipmentResult.reason}`);
    }
    
    // Complete the saga
    orderSaga.broadcast({
      type: "order-processed",
      payload: {
        orderId,
        status: "processed",
        shipmentId: shipmentResult.shipmentId
      }
    });
    
    return { 
      success: true, 
      orderId,
      shipmentId: shipmentResult.shipmentId
    };
    
  } catch (error) {
    // Execute compensating transactions in reverse order
    if (context.steps.includes("payment-processed")) {
      await orderSaga.send(paymentNode, {
        type: "refund-payment",
        payload: {
          paymentId: context.paymentId
        }
      }).return();
    }
    
    if (context.steps.includes("inventory-reserved")) {
      await orderSaga.send(inventoryNode, {
        type: "release-inventory",
        payload: event.payload
      }).return();
    }
    
    // Saga failed
    orderSaga.broadcast({
      type: "order-processing-failed",
      payload: {
        orderId,
        reason: error.message
      }
    });
    
    return { 
      success: false, 
      reason: error.message
    };
  }
});

This implementation shows how Happen's event-driven model naturally supports complex transactional scenarios that span multiple services.

Retry Pattern with Exponential Backoff

The Retry pattern handles transient failures by automatically retrying operations with increasing delays between attempts.

This pattern demonstrates Happen's function-returning mechanism to create sophisticated retry logic with minimal code.

Circuit Breaker Pattern

The Circuit Breaker pattern prevents cascading failures by stopping operations that are likely to fail.

This pattern shows how Happen can be extended to implement sophisticated resilience patterns that protect systems from cascading failures.

Supervisor Pattern

The Supervisor pattern manages component lifecycles and handles failures through a hierarchical oversight structure.

This pattern demonstrates Happen's ability to implement hierarchical oversight and automated recovery mechanisms using its core primitives.

State Machine Workflow

The State Machine pattern models entities that transition between discrete states according to well-defined rules.

This pattern shows how Happen's state management capabilities can be used to implement formal state machines with controlled transitions.

Reactive Aggregates

The Reactive Aggregates pattern combines event-driven reactivity with consistent state management for domain aggregates.

This pattern demonstrates how Happen can combine reactive event handling with consistent state management in domain-driven designs.

Last updated