Filter Open Restaurants Through Existing Domain APIs
DoorDashSoftware Engineer · Technical ScreenLast updated
Implement an orchestrator service that coordinates calls to a directory API and an operating-hours API with bounded concurrency, short-circuit filtering, resilient error handling, and in-memory caching.
Problem Statement
At DoorDash, presenting an accurate feed of open restaurants requires coordinating multiple downstream microservices. You are tasked with implementing the core orchestration logic for a service that retrieves and filters restaurants for a given city at a specific Unix timestamp.
You are provided with two external domain client interfaces:
-
DirectoryClientget_restaurants_by_city(city: str) -> list[dict]- Returns restaurant summaries:
[{"id": str, "name": str, "city": str, "active": bool}, ...]
-
HoursClientis_open(restaurant_id: str, timestamp_utc: int) -> bool- Returns
Trueif the store is open at the given timestamp,Falseotherwise. This call is network-intensive and may raise exceptions (e.g.,TimeoutErrororConnectionError).
Implement the class OpenRestaurantFinder with the following requirements:
- Pre-filtering & Short-circuiting: Do not call
HoursClientfor restaurants whereactiveisFalseor whosecitydoes not match the requested city (case-insensitive comparison). - Bounded Concurrency: Query the
HoursClientconcurrently for valid candidates using at mostmax_workersparallel workers. - Failure Handling: If
HoursClient.is_openraises an error for any restaurant, treat that restaurant as closed (False) rather than failing the entire request. - Order Preservation: The returned list of open restaurants must maintain the relative ordering provided by the
DirectoryClient. - Safe In-Memory Caching: Cache the boolean result of
(restaurant_id, timestamp_utc)calls in memory so repeated requests with identical parameters do not make duplicate downstream calls toHoursClient.
Class Interface
class OpenRestaurantFinder:
def __init__(self, directory_client, hours_client, max_workers: int = 5):
"""
Initialize with downstream API clients and concurrency limit.
"""
pass
def get_open_restaurants(self, city: str, timestamp_utc: int) -> list[dict]:
"""
Returns only active, open restaurants for the specified city at timestamp_utc,
preserving original ranking order.
"""
pass
Constraints
1 = 01 <= max_workers <= 20- Number of restaurants returned by directory:
0 <= N <= 10,000 - The cache should be thread-safe if your implementation uses multi-threading.
Examples
Example 1
Directory response for city = "San Francisco":
[
{"id": "r1", "name": "Tartine", "city": "San Francisco", "active": True},
{"id": "r2", "name": "Bob's Donuts", "city": "San Francisco", "active": False},
{"id": "r3", "name": "Arsicault", "city": "San Francisco", "active": True},
{"id": "r4", "name": "Che Fico", "city": "Oakland", "active": True}
]
HoursClient.is_open(restaurant_id, 1700000000) results:
"r1":True"r3":False"r2"and"r4"should never be queried because"r2"is inactive and"r4"is in Oakland.
Output:
[
{"id": "r1", "name": "Tartine", "city": "San Francisco", "active": True}
]
Example 2 (Downstream Failure)
Directory response for city = "Seattle":
[
{"id": "s1", "name": "Pike Bagels", "city": "Seattle", "active": True},
{"id": "s2", "name": "Canlis", "city": "Seattle", "active": True}
]
HoursClient.is_open calls:
"s1"raisesTimeoutError"s2"returnsTrue
Output:
[
{"id": "s2", "name": "Canlis", "city": "Seattle", "active": True}
]
Hints
Hint 1
Filter out inactive or out-of-city entries synchronously before dispatching async or threaded workers to minimize network calls.
Hint 2
Map futures back to their original index in the pre-filtered candidate list so you can preserve the original ordering despite out-of-order worker completion.
Hint 3
Protect in-memory cache writes with a mutex lock (or use thread-safe data structures) when running concurrent requests.
Follow-up questions
- How would you implement a Time-To-Live (TTL) eviction policy for the cache to prevent memory bloat in production?
- If the HoursClient is consistently timing out across multiple stores, how would you incorporate a circuit breaker pattern to shed load?
- How would you bucket timestamps (e.g., 5-minute windows) to increase cache hit rates without sacrificing opening/closing accuracy?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.