A fintech payments gateway processes millions of charge requests per day. To prevent double-charging when clients retry (due to timeouts or flaky mobile networks), the gateway uses an idempotency key: multiple concurrent requests with the same key must share the same result.
You are implementing an in-memory, thread-safe “idempotency ledger” for a single process.
Implement:
process_request_threadsafe(key: str, expensive_work: Callable[[], int]) -> int
Requirements:
process_request_threadsafe with the same key at the same time, exactly one thread may run expensive_work(). All other threads must wait and then return the same computed value.expensive_work() runs. (It’s fine to use a global lock for short state transitions.)expensive_work() raises an exception, the key must not be marked as completed. Waiting callers should be released, and a later call for the same key should be allowed to retry (and may run expensive_work() again).Example 1
key = "x", two concurrent callers, expensive_work() -> 77, and expensive_work executes once.Example 2
["a","b","c"] concurrently, each expensive_work returns 1,2,3[1,2,3], each key computed once; work for different keys can overlap.