Caches lie eventually. When the underlying data changes, a stale cached entry must be dropped so the next read goes back to the source. Add an invalidate method that evicts a single key.
After invalidating a key, the next fetch for it is a cache miss again, the proxy rebuilds nothing, but it does call the real service once more, so the call counter climbs.
Invalidating a key that is not in the cache must be harmless, no error.
class RealService:
def __init__(self, backend):
self.backend = dict(backend)
self.calls = 0
def fetch(self, key):
self.calls += 1
return self.backend.get(key)
class Proxy:
def __init__(self, backend, allowed=None):
self._backend = dict(backend)
self._real = None
self._cache = {}
self._allowed = allowed
def _ensure_real(self):
if self._real is None:
self._real = RealService(self._backend)
def _is_allowed(self, key):
return self._allowed is None or key in self._allowed
def fetch(self, key):
if not self._is_allowed(key):
return None
if key in self._cache:
return self._cache[key]
self._ensure_real()
value = self._real.fetch(key)
self._cache[key] = value
return value
def invalidate(self, key):
"""Drop key from the cache so the next fetch re-hits the service."""
# TODO: self._cache.pop(key, None)
pass
The editor and the test runner need a wide screen. Open this page on a desktop browser and your progress will be waiting.
Caches lie eventually. When the underlying data changes, a stale cached entry must be dropped so the next read goes back to the source. Add an invalidate method that evicts a single key.
After invalidating a key, the next fetch for it is a cache miss again, the proxy rebuilds nothing, but it does call the real service once more, so the call counter climbs.
Invalidating a key that is not in the cache must be harmless, no error.
Press Run Tests or ββ© to check your solution.