Hone logo
Hone
Problems

Implementing a Time-To-Live (TTL) Cache in JavaScript

Caching is a crucial technique for optimizing performance by storing frequently accessed data and retrieving it quickly. This challenge asks you to implement a simple in-memory cache in JavaScript that supports a Time-To-Live (TTL) for cached items. This is useful for scenarios where data freshness is important and you want to automatically expire old data.

Problem Description

You need to create a Cache class in JavaScript. This class should allow you to store key-value pairs, with each key-value pair having an associated TTL (in milliseconds). The cache should automatically remove entries that have exceeded their TTL. The class should provide the following methods:

  • set(key, value, ttl): Stores a key-value pair in the cache. key is a string, value can be any JavaScript data type, and ttl is the time-to-live in milliseconds.
  • get(key): Retrieves the value associated with a given key. If the key exists and the TTL hasn't expired, return the value. If the key doesn't exist or the TTL has expired, return undefined.
  • delete(key): Removes a key-value pair from the cache.
  • clear(): Removes all entries from the cache.

The cache should internally manage the expiration of entries using setTimeout.

Examples

Example 1:

Input:
cache = new Cache();
cache.set("name", "John Doe", 2000);
console.log(cache.get("name"));
setTimeout(() => { console.log(cache.get("name")); }, 3000);

Output:

John Doe
undefined

Explanation: The name key is set with a TTL of 2 seconds. The first get call retrieves "John Doe" immediately. After 3 seconds (longer than the TTL), the second get call returns undefined because the entry has expired.

Example 2:

Input:
cache = new Cache();
cache.set("data", { value: 10 }, 5000);
cache.delete("data");
console.log(cache.get("data"));

Output:

undefined

Explanation: The data key is set with a TTL of 5 seconds. The delete method removes the entry before it expires, so get returns undefined.

Example 3: (Edge Case - Concurrent Access)

Input:
cache = new Cache();
cache.set("item", "value", 1000);
setTimeout(() => { console.log(cache.get("item")); }, 500); // Access before TTL expires
setTimeout(() => { console.log(cache.get("item")); }, 1500); // Access after TTL expires

Output:

value
undefined

Explanation: Demonstrates that the cache correctly handles access before and after the TTL expires.

Constraints

  • ttl values will always be non-negative integers.
  • Keys will always be strings.
  • The cache should be thread-safe (although JavaScript is single-threaded, consider potential issues if used in a multi-threaded environment - focus on avoiding race conditions within the cache's internal logic).
  • The set method should not block the main thread for extended periods. Use setTimeout appropriately.
  • The cache should not leak memory. Expired timers should be properly cleaned up.

Notes

  • Consider using a Map for efficient key-value storage.
  • The setTimeout function will be crucial for managing TTLs. Make sure to store the timeout ID so you can clear it if the entry is deleted before it expires.
  • Think about how to handle the case where an entry is deleted before its TTL expires. You should cancel the associated timeout.
  • Focus on clarity and maintainability of your code. Good variable names and comments are appreciated.
  • While a production-ready cache would likely involve more sophisticated eviction strategies and concurrency controls, this challenge focuses on the core TTL functionality.
Loading editor...
javascript