Machine Coding Problem

Inventory Management

maco30maco60macoAllcommercetwo-phase-reservationttl-cleanupobserver-patternthread-safe-inventory-decrements
Commonly Asked By:AmazonWalmartShopify

Functional Scope (In-Scope)

  • Two-Phase Inventory Lock: Implement soft stock reservations (RESERVE) that roll back if checkout fails or expires (TTL).
  • Zero Overselling: Guarantee thread safety during high volume concurrent purchases.
  • Automated TTL Cleanup: Free up expired reservations asynchronously using highly efficient background workers.
  • Stock Shortage Notifications (Observer Pattern): Watch threshold limits and trigger low-stock alerts to observers.

Explicit Boundaries (Out-of-Scope)

  • No Complex Shipping logistics API: Excludes tracking warehouse labels, shipping containers, or coordinate tracking.
  • No Automatic Purchase Order (PO) Builder: System design handles item counts; does not write real-world legal purchase contracts.

Practical reference implementations showing transactional inventory checkouts in Java and Python:

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

interface InventoryObserver {
    void onLowStock(String productId, int availableQty);
}

class RestockAlertSystem implements InventoryObserver {
    @Override
    public void onLowStock(String productId, int availableQty) {
        System.out.println(String.format("[Alert] Product %s is running low on stock! Current: %d", productId, availableQty));
    }
}

class Product {
    private final String id;
    private final String name;
    private int availableQty;
    private int reservedQty;
    private final int lowStockThreshold;
    private final List<InventoryObserver> observers = new CopyOnWriteArrayList<>();
    private final ReentrantLock lock = new ReentrantLock();

    public Product(String id, String name, int initialQty, int threshold) {
        this.id = id;
        this.name = name;
        this.availableQty = initialQty;
        this.reservedQty = 0;
        this.lowStockThreshold = threshold;
    }

    public String getId() { return id; }
    public String getName() { return name; }
    
    public int getAvailableQty() {
        lock.lock();
        try { return availableQty; } finally { lock.unlock(); }
    }

    public void addObserver(InventoryObserver obs) { observers.add(obs); }

    public boolean reserve(int qty) {
        lock.lock();
        try {
            if (availableQty >= qty) {
                availableQty -= qty;
                reservedQty += qty;
                checkThreshold();
                return true;
            }
            return false;
        } finally {
            lock.unlock();
        }
    }

    public void confirm(int qty) {
        lock.lock();
        try {
            reservedQty = Math.max(0, reservedQty - qty);
        } finally {
            lock.unlock();
        }
    }

    public void release(int qty) {
        lock.lock();
        try {
            reservedQty = Math.max(0, reservedQty - qty);
            availableQty += qty;
        } finally {
            lock.unlock();
        }
    }

    public void restock(int qty) {
        lock.lock();
        try {
            availableQty += qty;
        } finally {
            lock.unlock();
        }
    }

    private void checkThreshold() {
        if (availableQty <= lowStockThreshold) {
            for (InventoryObserver obs : observers) {
                obs.onLowStock(id, availableQty);
            }
        }
    }
}

class Reservation {
    private final String id;
    private final String productId;
    private final int quantity;
    private final long expiryTime;

    public Reservation(String id, String productId, int qty, long ttlMs) {
        this.id = id;
        this.productId = productId;
        this.quantity = qty;
        this.expiryTime = System.currentTimeMillis() + ttlMs;
    }

    public String getId() { return id; }
    public String getProductId() { return productId; }
    public int getQuantity() { return quantity; }
    public boolean isExpired() { return System.currentTimeMillis() > expiryTime; }
}

class InventoryService {
    private final Map<String, Product> products = new ConcurrentHashMap<>();
    private final Map<String, Reservation> reservations = new ConcurrentHashMap<>();
    private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();

    public InventoryService() {
        scheduler.scheduleAtFixedRate(this::cleanExpiredReservations, 100, 100, TimeUnit.MILLISECONDS);
    }

    public void addProduct(Product p) { products.put(p.getId(), p); }

    public boolean reserveStock(String reservationId, String productId, int qty, long ttlMs) {
        Product p = products.get(productId);
        if (p != null && p.reserve(qty)) {
            reservations.put(reservationId, new Reservation(reservationId, productId, qty, ttlMs));
            return true;
        }
        return false;
    }

    public boolean confirmPurchase(String reservationId) {
        Reservation res = reservations.remove(reservationId);
        if (res != null && !res.isExpired()) {
            Product p = products.get(res.getProductId());
            if (p != null) {
                p.confirm(res.getQuantity());
                System.out.println("[Service] Purchase confirmed for Reservation: " + reservationId);
                return true;
            }
        }
        return false;
    }

    private void cleanExpiredReservations() {
        for (Reservation res : reservations.values()) {
            if (res.isExpired()) {
                if (reservations.remove(res.getId()) != null) {
                    Product p = products.get(res.getProductId());
                    if (p != null) {
                        p.release(res.getQuantity());
                        System.out.println(String.format("[TTL Cleanup] Released expired Reservation %s (%d units of %s)",
                                res.getId(), res.getQuantity(), p.getName()));
                    }
                }
            }
        }
    }

    public void shutdown() {
        scheduler.shutdown();
    }
}

public class Main {
    public static void main(String[] args) throws InterruptedException {
        System.out.println("=== Inventory Management Simulation ===");
        InventoryService service = new InventoryService();
        RestockAlertSystem alertSystem = new RestockAlertSystem();

        Product laptop = new Product("PROD-01", "MacBook Pro", 6, 2);
        laptop.addObserver(alertSystem);
        service.addProduct(laptop);

        // Reserve Stock - Success
        boolean r1 = service.reserveStock("RES-101", "PROD-01", 3, 200); // 200ms expiry
        System.out.println("Reservation RES-101: " + (r1 ? "SUCCESS" : "FAILED"));

        // Reserve Stock - Triggers Low Stock Alert
        boolean r2 = service.reserveStock("RES-102", "PROD-01", 2, 1000);
        System.out.println("Reservation RES-102: " + (r2 ? "SUCCESS" : "FAILED"));

        // Let RES-101 expire (TTL)
        Thread.sleep(300);

        // Confirm RES-102 Purchase
        service.confirmPurchase("RES-102");

        service.shutdown();
    }
}