FAIL3.5
Loading cell…
Loading cell…
Write a TypeScript function named createIdempotencyGuard.
Requirements:
key, ttlMs, and an async handler function.Output format: { "code": "...", "explanation": "...", "complexity": { "time": "...", "space": "..." }, "tests": ["...", "...", "...", "...", "..."] }
{
"code": "interface CacheEntry<T = any> {\n promise?: Promise<T>;\n result?: T;\n expiry?: number;\n}\n\nconst _cache = new Map<string, CacheEntry>();\n\nasync function createIdempotencyGuard<T>(args: {\n key: string;\n ttlMs: number;\n handler: () => Promise<T>;\n}): Promise<T> {\n const { key, ttlMs, handler } = args;\n const now = Date.now();\n const existing = _cache.get(key);\n\n if (existing) {\n // Valid cached result (not expired)\n if (existing.expiry !== undefined && now < existing.expiry) {\n return existing.result as T;\n }\n // In-flight promise (no expiry set yet)\n if (existing.promise) {\n return existing.promise;\n }\n // Expired result with no promise — evict\n _cache.delete(key);\n }\n\n const promise = handler().then(\n (result) => {\n _cache.set(key, { result, expiry: Date.now() + ttlMs });\n return result;\n },\n (error) => {\n _cache.delete(key);\n throw error;\n }\n );\n\n _cache.set(key, { promise });\n return promise;\n}\n\n// Exposed for testing only\nfunction _clearCache(): void {\n _cache.clear();\n}",
"explanation": "The function uses a module-level Map to track both in-flight promises and completed results keyed by the idempotency key. On each call it first checks the cache: if a non-expired result exists it returns it immediately; if an in-flight promise exists it returns that same promise so concurrent callers share one execution; otherwise it invokes the handler. On success the promise is replaced in the cache with the resolved value and an expiry timestamp. On failure the cache entry is deleted so subsequent calls retry. A result is considered cached when its `expiry` field is defined, which correctly handles handlers that legitimately resolve to `undefined`.",
"complexity": {
"time": "O(1) per call for the cache lookup and update, plus O(H) where H is the runtime of the handler itself. Overall: O(1) + O(H).",
"space": "O(N) where N is the
0/2 checks passed