Katkat

Debug a Test-Driven C++ Project

AmazonSoftware Engineer · Online Assessment

Last updated

Tests your ability to design and implement a sliding-window rate limiter with deduplication and state cleanup, reflecting common logic and edge-case errors encountered when debugging test-driven C++ systems.

Problem Statement

You are tasked with building a resilient in-memory order processor component for an e-commerce platform. The system must filter out duplicate requests and enforce per-customer rate limits over a sliding time window.

Implement the OrderRateLimiter class with the following methods:

  • OrderRateLimiter(window_size: int, max_orders_per_customer: int): Initializes the rate limiter with a sliding window duration of window_size seconds and an allowed maximum of max_orders_per_customer successful orders per customer in that window.

  • process_order(order_id: str, customer_id: str, timestamp: int) -> bool: Attempts to process an incoming order at timestamp. An order is accepted (True) if and only if:

    1. The order_id has not already been accepted within the current sliding window [timestamp - window_size + 1, timestamp].
    2. The customer has accepted strictly fewer than max_orders_per_customer orders within the current sliding window [timestamp - window_size + 1, timestamp].

    If either condition fails, the order is rejected and the method returns False. Rejected orders do not consume capacity and should not block future retries if conditions change.

  • get_active_orders_count() -> int: Returns the total number of accepted orders currently within the active window relative to the most recent timestamp observed across all calls to process_order. If no orders have been processed yet, return 0.

Constraints

  • 1 <= window_size <= 10^9
  • 1 <= max_orders_per_customer <= 10^5
  • 1 <= len(order_id), len(customer_id) <= 32 (alphanumeric strings)
  • 0 <= timestamp <= 10^9
  • Calls to process_order are guaranteed to have non-decreasing timestamp values.
  • Up to 2 * 10^5 total calls across all methods.

Examples

Example 1

limiter = OrderRateLimiter(window_size=10, max_orders_per_customer=2)

limiter.process_order("ord_1", "cust_A", 1)   # returns True  (window: [1, 1], cust_A count: 1)
limiter.process_order("ord_2", "cust_A", 5)   # returns True  (window: [1, 5], cust_A count: 2)
limiter.process_order("ord_1", "cust_A", 6)   # returns False (ord_1 already accepted in window [1, 6])
limiter.process_order("ord_3", "cust_A", 7)   # returns False (cust_A limit reached: 2 orders in window [1, 7])
limiter.get_active_orders_count()              # returns 2     ("ord_1" and "ord_2" are active at t=7)

limiter.process_order("ord_4", "cust_A", 11)  # returns True  (window: [2, 11]; "ord_1" at t=1 expired, cust_A count drops to 1, then becomes 2)
limiter.get_active_orders_count()              # returns 2     ("ord_2" and "ord_4" are active at t=11)

Example 2

limiter = OrderRateLimiter(window_size=5, max_orders_per_customer=1)

limiter.process_order("ord_1", "cust_B", 10)  # returns True
limiter.process_order("ord_1", "cust_B", 16)  # returns True ("ord_1" expired at t=15, so re-using the ID is allowed)
limiter.get_active_orders_count()              # returns 1

Edge Cases to Consider

  • Multiple orders occurring at the exact same timestamp.
  • Ensuring expired orders are evicted before checking both deduplication sets and customer order counts.
  • Rejected orders must not leave residual state that incorrectly triggers deduplication or counts against customer quotas.

Hints

Hint 1

Because timestamps arrive in non-decreasing order, a queue (FIFO) can track accepted orders alongside their timestamps to evict expired orders efficiently in amortized O(1) time.

Hint 2

Make sure to clean up state across all tracking structures (the queue, the active ID set, and the per-customer counts) before checking if the current order is valid.

Hint 3

Pay close attention to window inclusion: an order at timestamp `t` expires when the current timestamp satisfies `current_timestamp >= t + window_size`.

Follow-up questions

  • How would you adapt this design if order timestamps could arrive out of order due to network latency?
  • How would you make this class thread-safe in C++ for high-concurrency read and write access without creating a global lock bottleneck?
  • If the window size is very large (e.g., 30 days) and tracking every raw order exceeds memory constraints, what approximate streaming algorithms would you use?