"""
Pattern 190: Compensation Pattern
Purpose: Undo actions when transaction fails
"""
from typing import Dict, Any, List, Optional, Callable
from dataclasses import dataclass, field
from datetime import datetime
from enum import Enum
class TransactionStatus(Enum):
"""Transaction status."""
PENDING = "pending"
COMMITTED = "committed"
COMPENSATING = "compensating"
COMPENSATED = "compensated"
FAILED = "failed"
@dataclass
class Action:
"""Action with compensation."""
name: str
execute: Callable
compensate: Callable
executed: bool = False
compensated: bool = False
@dataclass
class Transaction:
"""Transaction record."""
id: str
actions: List[Action]
status: TransactionStatus = TransactionStatus.PENDING
timestamp: datetime = field(default_factory=datetime.now)
error: Optional[str] = None
class CompensationPattern:
"""
Compensation Pattern - Undo actions when transaction fails.
Features:
- Transaction management
- Automatic compensation
- Rollback on failure
- Compensation history
- Saga pattern support
"""
def __init__(self):
self.transactions: Dict[str, Transaction] = {}
self.stats = {
"total_transactions": 0,
"committed": 0,
"compensated": 0,
"failed": 0
}
def execute_transaction(self, transaction: Transaction) -> bool:
"""Execute transaction with compensation on failure."""
self.stats["total_transactions"] += 1
transaction.status = TransactionStatus.PENDING
executed_actions = []
try:
# Execute all actions
for action in transaction.actions:
print(f" Executing: {action.name}")
action.execute()
action.executed = True
executed_actions.append(action)
# All succeeded - commit
transaction.status = TransactionStatus.COMMITTED
self.stats["committed"] += 1
self.transactions[transaction.id] = transaction
print(f"✅ Transaction {transaction.id} committed")
return True
except Exception as e:
# Failure - compensate executed actions in reverse
print(f"❌ Transaction {transaction.id} failed: {e}")
transaction.error = str(e)
transaction.status = TransactionStatus.COMPENSATING
print(f"⚠️ Compensating {len(executed_actions)} actions...")
for action in reversed(executed_actions):
try:
print(f" Compensating: {action.name}")
action.compensate()
action.compensated = True
except Exception as comp_error:
print(f" ⚠️ Compensation failed for {action.name}: {comp_error}")
transaction.status = TransactionStatus.COMPENSATED
self.stats["compensated"] += 1
self.transactions[transaction.id] = transaction
return False
def get_stats(self) -> Dict[str, Any]:
"""Get transaction statistics."""
success_rate = (
self.stats["committed"] / self.stats["total_transactions"] * 100
if self.stats["total_transactions"] > 0 else 0
)
return {
**self.stats,
"success_rate": f"{success_rate:.1f}%"
}
if __name__ == "__main__":
print("=== Compensation Pattern Demo ===\n")
pattern = CompensationPattern()
# Define actions with compensation
db_data = {"balance": 1000}
def debit_account():
print(f" Debiting account (balance: {db_data['balance']})")
db_data['balance'] -= 100
def compensate_debit():
print(f" Reversing debit (balance: {db_data['balance']})")
db_data['balance'] += 100
def send_payment():
print(f" Sending payment")
# Simulate payment
pass
def compensate_payment():
print(f" Reversing payment")
pass
def send_notification():
print(f" Sending notification")
raise Exception("Notification service unavailable") # Simulate failure
def compensate_notification():
print(f" No notification to reverse")
pass
# Create transaction
transaction = Transaction(
id="TXN-001",
actions=[
Action("debit_account", debit_account, compensate_debit),
Action("send_payment", send_payment, compensate_payment),
Action("send_notification", send_notification, compensate_notification)
]
)
print("1. Executing transaction with compensation:\n")
print(f"Initial balance: ${db_data['balance']}")
success = pattern.execute_transaction(transaction)
print(f"\nFinal balance: ${db_data['balance']}")
print(f"Success: {success}\n")
# Successful transaction
print("\n2. Successful transaction:\n")
db_data['balance'] = 1000
transaction2 = Transaction(
id="TXN-002",
actions=[
Action("debit_account", debit_account, compensate_debit),
Action("send_payment", send_payment, compensate_payment)
]
)
print(f"Initial balance: ${db_data['balance']}")
success = pattern.execute_transaction(transaction2)
print(f"\nFinal balance: ${db_data['balance']}")
print(f"Success: {success}\n")
print("\n=== Statistics ===")
stats = pattern.get_stats()
print(f"Total transactions: {stats['total_transactions']}")
print(f"Committed: {stats['committed']}")
print(f"Compensated: {stats['compensated']}")
print(f"Success rate: {stats['success_rate']}")
Agentic Architecture Pattern: Compensation
Pattern 190: 190 Compensation – Line-by-Line Explanation
Overview
Pattern 190: Compensation Pattern Purpose: Undo actions when transaction fails
Code Structure Analysis
File Information
- Pattern Number: 190
- Pattern Name: 190 Compensation
- File Path:
patterns\error_handling\190_compensation.py - Total Lines: 188
Detailed Code Explanation
Module Docstring
"""
Pattern 190: Compensation Pattern
Purpose: Undo actions when transaction fails
"""
Explanation: This module docstring describes the purpose and key features of the 190 Compensation pattern.
Imports Section
from typing import Dict, Any, List, Optional, Callable
from dataclasses import dataclass, field
from datetime import datetime
from enum import Enum # First 20 imports shown
Explanation: The module imports necessary dependencies:
– from typing import Dict, Any, List, Optional, Callable: Type hints for better code documentation
– from dataclasses import dataclass, field: Data class decorators for clean data structures
– from datetime import datetime: Date and time utilities
– from enum import Enum: Enumeration support for fixed sets of values
Enumerations
TransactionStatus (Line 12)
class TransactionStatus(Enum):
PENDING
COMMITTED
COMPENSATING
COMPENSATED
FAILED
Purpose: Transaction status.
Values:
– PENDING: Initial state, not yet processed
– COMMITTED: Represents committed
– COMPENSATING: Represents compensating
– COMPENSATED: Represents compensated
– FAILED: Execution failed
Classes
TransactionStatus (Line 12)
Description: Transaction status.
Action (Line 22)
Description: Action with compensation.
Transaction (Line 32)
Description: Transaction record.
CompensationPattern (Line 41)
Description: Compensation Pattern – Undo actions when transaction fails.
Features: – Transaction management – Automatic compensation – Rollback on failure – Compensation history – Saga pattern support
Methods:
__init__ (Line 53)
def __init__(self):
"""No method docstring."""
Purpose: No method docstring.
Parameters:
– self: Instance reference
execute_transaction (Line 62)
def execute_transaction(self, transaction):
"""Execute transaction with compensation on failure."""
Purpose: Execute transaction with compensation on failure.
Parameters:
– self: Instance reference
– transaction: Parameter for transaction
get_stats (Line 103)
def get_stats(self):
"""Get transaction statistics."""
Purpose: Get transaction statistics.
Parameters:
– self: Instance reference
Design Patterns Used
- Strategy Pattern: Different execution strategies for various scenarios
- State Pattern: Managing different states in the workflow
- Chain of Responsibility: Sequential processing through workflow nodes
- Observer Pattern: Tracking and monitoring pattern execution
- Factory Pattern: Creating instances with proper configuration
Usage Example
# Initialize the pattern
pattern = TransactionStatus(name="example", model_name="gpt-4")
# Configure and execute
result = pattern.execute(data={"key": "value"})
# Check results
print(result)
Key Concepts
- LLM Integration: Uses LangChain/OpenAI for intelligent decision-making
- Workflow Orchestration: LangGraph manages execution flow through nodes
- State Management: TypedDict defines workflow state structure
- Error Handling: Comprehensive error handling and fallback mechanisms
- Extensibility: Designed for easy customization and extension
Extension Points
This pattern can be extended by: 1. Adding custom workflow nodes 2. Implementing additional validation logic 3. Integrating with external services 4. Customizing LLM prompts and responses 5. Adding monitoring and logging capabilities
Leave a Reply