Machine Coding Problem

Order Manager

macoAllcommercestate-machineevent-driven
Commonly Asked By:AmazonWalmartShopifyTarget

Requirements & System Scope

Functional Specifications (In-Scope)

  • Strict Finite State Machine: Defines valid transitions between states and throws errors on illegal moves.
  • Compensating Saga Transactions: Restores physical stock balances and triggers payment refunds if order flow fails.
  • Audit log & Event Stream: Records transitions to build structural tracking logs and emit domain events.
  • Idempotency Guarantees: Avoids executing repeat actions for identical status inputs.

Out-of-Scope Boundaries

  • Payment Gateway Handshakes: Excludes live Stripe/PayPal API endpoints, utilizing mock decorators.
  • Warehousing Carrier Routing: Excludes actual dynamic logistics matching or warehouse pickup slips.

Class Diagram & Entity Relationships

Structural blueprint mapping out state controls and Saga callbacks:

Loading...
  • OrderStateMachine: Core config mapping out valid transition routes.
  • CompensationService: Restores external entities if transaction errors occur.
  • AuditService: Read-only ledger tracking all status changes.

Design Patterns & SOLID Principles

  • State Design Pattern: Encapsulates state-specific validation rules inside an order state machine.
  • Saga Pattern (Choreography / Orchestration): Executes local transaction steps and dispatches compensating actions if steps are cancelled or rejected.
  • Open/Closed Principle (OCP): New order states or custom events can be added without modifying the core orchestrator.

Core Execution Workflows

Order Lifecycle State Machine Transition Workflow

  1. Receive Event: Invoke transitionTo(orderId, targetStatus).
  2. Verify Path:
    1. Load active order entity.
    2. Compare target state with allowed target states under current state (e.g. PLACED -> CONFIRMED | CANCELLED).
    3. If invalid, throw InvalidTransitionException.
  3. Execute Status Commit: Update order status.
  4. Audit & Dispatch:
    1. Write detailed audit log (actor, timestamp, delta).
    2. Emit reactive Kafka/RabbitMQ domain event.
  5. Execute Compensations: If target is CANCELLED or REFUNDED, dispatch parallel Saga rollbacks.

Concurrency & Thread Safety Strategy

Ensuring state machine updates are atomic and free of race conditions:

  • Optimistic Concurrency Control (OCC): Employs version numbers on database entity tables to reject out-of-order state mutations.
  • Distributed Locking: Employs Redis locks on orderId to block duplicate concurrent webhooks.

Complete Clean Code Blueprint

Production reference implementations demonstrating order state validation, audit log capture, and Saga compensations:

// ─── JAVA BLUEPRINT ──────────────────────────────────────────────────────────
import java.util.*;
import java.util.concurrent.*;

enum OrderStatus {
    PLACED,
    CONFIRMED,
    PACKED,
    SHIPPED,
    DELIVERED,
    CANCELLED,
    REFUNDED
}

class OrderItem {
    private final String productId;
    private final int quantity;
    private final double unitPrice;

    public OrderItem(String productId, int quantity, double unitPrice) {
        this.productId = productId;
        this.quantity = quantity;
        this.unitPrice = unitPrice;
    }

    public String getProductId() { return productId; }
    public int getQuantity() { return quantity; }
    public double getUnitPrice() { return unitPrice; }
}

class Order {
    private final String orderId;
    private final List<OrderItem> items;
    private OrderStatus status;
    private final double totalAmount;

    public Order(String orderId, List<OrderItem> items) {
        this.orderId = orderId;
        this.items = items;
        this.status = OrderStatus.PLACED;
        this.totalAmount = items.stream().mapToDouble(i -> i.getQuantity() * i.getUnitPrice()).sum();
    }

    public String getOrderId() { return orderId; }
    public List<OrderItem> getItems() { return items; }
    public OrderStatus getStatus() { return status; }
    public double getTotalAmount() { return totalAmount; }

    public void setStatus(OrderStatus status) {
        this.status = status;
    }
}

class InvalidTransitionException extends RuntimeException {
    public InvalidTransitionException(String message) {
        super(message);
    }
}

class OrderEvent {
    private final String eventId;
    private final String orderId;
    private final OrderStatus fromStatus;
    private final OrderStatus toStatus;
    private final long timestamp;

    public OrderEvent(String orderId, OrderStatus fromStatus, OrderStatus toStatus) {
        this.eventId = UUID.randomUUID().toString();
        this.orderId = orderId;
        this.fromStatus = fromStatus;
        this.toStatus = toStatus;
        this.timestamp = System.currentTimeMillis();
    }

    public String getEventId() { return eventId; }
    public String getOrderId() { return orderId; }
    public OrderStatus getFromStatus() { return fromStatus; }
    public OrderStatus getToStatus() { return toStatus; }
    public long getTimestamp() { return timestamp; }
}

interface OrderEventPublisher {
    void publish(OrderEvent event);
}

class AuditLogEntry {
    private final String orderId;
    private final OrderStatus fromStatus;
    private final OrderStatus toStatus;
    private final String actor;
    private final long timestamp;

    public AuditLogEntry(String orderId, OrderStatus fromStatus, OrderStatus toStatus, String actor) {
        this.orderId = orderId;
        this.fromStatus = fromStatus;
        this.toStatus = toStatus;
        this.actor = actor;
        this.timestamp = System.currentTimeMillis();
    }

    public String getOrderId() { return orderId; }
    public OrderStatus getFromStatus() { return fromStatus; }
    public OrderStatus getToStatus() { return toStatus; }
    public String getActor() { return actor; }
    public long getTimestamp() { return timestamp; }
}

class AuditService {
    private final List<AuditLogEntry> logs = new CopyOnWriteArrayList<>();

    public void logTransition(String orderId, OrderStatus from, OrderStatus to, String actor) {
        logs.add(new AuditLogEntry(orderId, from, to, actor));
    }

    public List<AuditLogEntry> getLogsForOrder(String orderId) {
        List<AuditLogEntry> result = new ArrayList<>();
        for (AuditLogEntry entry : logs) {
            if (entry.getOrderId().equals(orderId)) {
                result.add(entry);
            }
        }
        return result;
    }
}

class CompensationService {
    public boolean triggerPaymentRefund(String orderId, double amount) {
        System.out.println("SAGA COMPENSATOR: Refunding $" + amount + " to customer card for Order ID: " + orderId);
        return true;
    }

    public boolean triggerInventoryRestoration(String orderId, List<OrderItem> items) {
        for (OrderItem item : items) {
            System.out.println("SAGA COMPENSATOR: Restoring Qty " + item.getQuantity() + " for Product ID: " + item.getProductId());
        }
        return true;
    }
}

class OrderStateMachine {
    private final Map<OrderStatus, Set<OrderStatus>> validTransitions = new ConcurrentHashMap<>();

    public OrderStateMachine() {
        validTransitions.put(OrderStatus.PLACED, Set.of(OrderStatus.CONFIRMED, OrderStatus.CANCELLED));
        validTransitions.put(OrderStatus.CONFIRMED, Set.of(OrderStatus.PACKED, OrderStatus.CANCELLED));
        validTransitions.put(OrderStatus.PACKED, Set.of(OrderStatus.SHIPPED, OrderStatus.CANCELLED));
        validTransitions.put(OrderStatus.SHIPPED, Set.of(OrderStatus.DELIVERED, OrderStatus.CANCELLED));
        validTransitions.put(OrderStatus.DELIVERED, Set.of(OrderStatus.REFUNDED));
        validTransitions.put(OrderStatus.CANCELLED, Set.of());
        validTransitions.put(OrderStatus.REFUNDED, Set.of());
    }

    public boolean isValidTransition(OrderStatus from, OrderStatus to) {
        Set<OrderStatus> allowed = validTransitions.get(from);
        return allowed != null && allowed.contains(to);
    }
}

class OrderManager {
    private final Map<String, Order> orderRepository = new ConcurrentHashMap<>();
    private final OrderStateMachine stateMachine;
    private final OrderEventPublisher eventPublisher;
    private final AuditService auditService;
    private final CompensationService compensationService;

    public OrderManager(
        OrderStateMachine stateMachine,
        OrderEventPublisher eventPublisher,
        AuditService auditService,
        CompensationService compensationService
    ) {
        this.stateMachine = stateMachine;
        this.eventPublisher = eventPublisher;
        this.auditService = auditService;
        this.compensationService = compensationService;
    }

    public void registerOrder(Order order) {
        orderRepository.put(order.getOrderId(), order);
        auditService.logTransition(order.getOrderId(), null, OrderStatus.PLACED, "Customer");
    }

    public synchronized void transitionTo(String orderId, OrderStatus nextStatus, String actor) {
        Order order = orderRepository.get(orderId);
        if (order == null) {
            throw new IllegalArgumentException("Order not found: " + orderId);
        }

        OrderStatus currentStatus = order.getStatus();
        if (currentStatus == nextStatus) {
            return;
        }

        if (!stateMachine.isValidTransition(currentStatus, nextStatus)) {
            throw new InvalidTransitionException("Illegal state transition from " + currentStatus + " to " + nextStatus);
        }

        order.setStatus(nextStatus);
        auditService.logTransition(orderId, currentStatus, nextStatus, actor);

        OrderEvent event = new OrderEvent(orderId, currentStatus, nextStatus);
        eventPublisher.publish(event);

        if (nextStatus == OrderStatus.CANCELLED || nextStatus == OrderStatus.REFUNDED) {
            compensationService.triggerPaymentRefund(orderId, order.getTotalAmount());
            compensationService.triggerInventoryRestoration(orderId, order.getItems());
        }
    }

    }
}

public class Main {
    public static void main(String[] args) {
        System.out.println("=== JAVA ORDER MANAGEMENT SYSTEM SIMULATION ===");
        OrderStateMachine stateMachine = new OrderStateMachine();
        AuditService auditService = new AuditService();
        CompensationService compensationService = new CompensationService();
        
        OrderEventPublisher publisher = event -> {
            System.out.println("🔊 EVENT EMITTED: Order ID " + event.getOrderId() + 
                               " transitioned from " + event.getFromStatus() + 
                               " to " + event.getToStatus());
        };

        OrderManager manager = new OrderManager(stateMachine, publisher, auditService, compensationService);

        List<OrderItem> items = new ArrayList<>();
        items.add(new OrderItem("laptop", 1, 1200.0));
        items.add(new OrderItem("mouse", 2, 50.0));

        Order order = new Order("ORD-12345", items);
        manager.registerOrder(order);

        System.out.println("Initial Order Status: " + order.getStatus());
        System.out.println("Total Amount: $" + order.getTotalAmount());

        // Confirmed order
        manager.transitionTo("ORD-12345", OrderStatus.CONFIRMED, "Operator");
        System.out.println("Current Order Status: " + order.getStatus());

        // Attempt invalid transition
        try {
            System.out.println("\nAttempting illegal transition from CONFIRMED to DELIVERED...");
            manager.transitionTo("ORD-12345", OrderStatus.DELIVERED, "Operator");
        } catch (InvalidTransitionException e) {
            System.out.println("Caught Expected Error: " + e.getMessage());
        }

        // Cancel order to trigger compensating Saga transactions
        System.out.println("\nCancelling order to test compensating transaction...");
        manager.transitionTo("ORD-12345", OrderStatus.CANCELLED, "Customer");
        System.out.println("Final Order Status: " + order.getStatus());

        System.out.println("\nAudit Log History:");
        for (AuditLogEntry log : auditService.getLogsForOrder("ORD-12345")) {
            System.out.println(" - Status changed from " + log.getFromStatus() + 
                               " to " + log.getToStatus() + " by " + log.getActor());
        }

        System.out.println("=== END OF JAVA SIMULATION ===");
    }
}

Interactive Simulator

❖Order Lifecycle & State Machine Simulator

State transition controls, illegal path blockades, saga compensators, and event sourced audit logs.

📍 Order State Machine Visualization

PLACED
➔
CONFIRMED
➔
PACKED
➔
SHIPPED
➔
DELIVERED

⚡ Trigger Transitions

Disable Transition GatewaysSimulates raw database modification bugs.

🔄 Saga Compensations Service

Compensating actions will display here on Order Failures.

📜 State Transition Audit Log

PLACEDbyCustomer
5:37:34 AM

📡 Emitted Domain Events Stream

No event dispatches captured.

💬Review

Help Us Improve

How helpful was this walkthrough?

Click a star to rate. We actively use this feedback to refine and update our system design content.

Placeholder
Optional but highly appreciated!

Discussion

Share your thoughts, ask questions, or help others.

Loading comments...