Implement a Key-Value Cache with Fixed TTL, Renewal and a Live-Entry Count
OracleSoftware Engineer · OnsiteLast updated
Implement an in-memory key-value cache whose entries expire a fixed time-to-live after their last write, with put, get, renew and a count of live entries, and write your own tests for it. It tests expiry boundary semantics, renewal rules, efficient cleanup of expired entries and test design.
Implement an in-memory key-value cache in which every entry expires a fixed time-to-live (TTL) after it was last written. The exercise follows the pattern of a common token-expiry design problem: the TTL is set once when the cache is created, the current time is passed into every operation, a live entry can be renewed, and the cache can report how many entries are still live. You are expected to write your own test cases.
A reasonable interface:
class TTLCache:
def __init__(self, ttl: int) -> None: ...
def put(self, key: str, value: object, now: int) -> None: ...
def get(self, key: str, now: int) -> object | None: ...
def renew(self, key: str, now: int) -> bool: ...
def count_live(self, now: int) -> int: ...
putinserts a new entry or overwrites an existing one; the entry expires atnow + ttl.getreturns the value of a live entry, orNoneif the key is missing or has expired.renewmoves the expiry of a live entry tonow + ttland reports whether it did so. An expired entry is not revived.count_livereturns how many entries are live at timenow.
Constraints and Clarifications
- The TTL is a positive integer, fixed for the lifetime of the cache.
- Time values are integers in the same unit as the TTL.
- The tests are part of the answer: you are expected to design them, not only the class.
Clarifying Questions
- Is an entry that expires exactly at time
nowstill live atnow? - Are the
nowvalues passed across calls guaranteed never to decrease? - Does
getextend an entry's lifetime, or onlyputandrenew? - Does
puton a key whose entry has already expired behave like a fresh insert? - Is there a capacity limit, and if so, what happens when the cache is full?
- Can a stored value be
None, which would make aNoneresult fromgetambiguous?
Hints
Hint 1
Make the boundary testable: Your tests have to land exactly on the moment an entry expires, and on either side of it. Keep time an explicit input, and decide in writing what happens at that exact moment.
Hint 2
Look for an order you get for free: `count_live` may be called far more often than entries change. With one TTL shared by every entry, think about which entries must expire first.
Follow-up questions
- How would the design change if each entry could have its own TTL?
- How would you add a maximum capacity with least-recently-used eviction on top of expiry?
- How would you make the cache safe for concurrent callers, and would lazy cleanup still be enough?
- If time came from a system clock instead of a parameter, how would you keep the tests deterministic?
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.