Advanced 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