Typorithm · medium

Cache identity includes the selected population

pythondjangoindependent-practice
Saved on this device
Full lesson · 4 learning steps Open any exercise for focused practice
1

Step 1 of 4 · intro card

Cache identity includes the selected population

0%

Concept and contract

Use Django’s cache API with an explicit key and expiry while keeping representation scope separate from storage backend.

A cached result is useful only when its identity matches the request that reuses it. A country-specific role list must not share one key with every other country.

This lesson uses Django’s cache API backed by owned local memory, so no Redis service or production cache is contacted. The loader records which fictional country was actually computed, allowing the fixture to distinguish a cache hit from accidental reuse of the wrong population.

Mechanism and worked example

The key includes the selected country and the entry has an explicit thirty-second timeout.

The key includes the selected country and the entry has an explicit thirty-second timeout. A repeated request for the same key reuses its stored representation, while another country invokes the loader separately.

The helper clears only the isolated teaching backend before each scenario. Cache storage and key design remain distinct: changing the backend to Redis would not repair a key that omitted an important request dimension.

Complete worked example

python

from bootstrap_lab import django_setup
django_setup(__name__)

from django.core.cache import cache

def cached_countries(countries):
    cache.clear()
    reads = []
    def load(country):
        reads.append(country)
        return {"country": country}
    results = []
    for country in countries:
        value = cache.get_or_set(f"roles:{country}", lambda: load(country), timeout=30)
        results.append(value["country"])
    return {"countries": results, "reads": reads}
Reasoning
The key includes the selected country and the entry has an explicit thirty-second timeout. A repeated request for the same key reuses its stored representation, while another country invokes the loader separately.

Counterexamples and common mistakes

The counterexample uses a single roles key for all countries.

The counterexample uses a single roles key for all countries. Its second request can return the first country’s data while still appearing fast and successful.

Do not use cache speed as evidence of correct scope. A get_or_set convenience also does not automatically provide a universal distributed single-flight guarantee. Personalized data may need account or permission scope and careful response policy in addition to the public country dimension shown here.

Counterexample: a runnable framework mistake

python

from bootstrap_lab import django_setup
django_setup(__name__)

from django.core.cache import cache

def cached_countries(countries):
    cache.clear()
    reads = []
    def load(country):
        reads.append(country)
        return {"country": country}
    results = []
    for country in countries:
        value = cache.get_or_set("roles", lambda: load(country), timeout=30)
        results.append(value["country"])
    return {"countries": results, "reads": reads}
Reasoning
The counterexample uses a single roles key for all countries. Its second request can return the first country’s data while still appearing fast and successful.

Independent practice: one bounded framework change

Normalize each country by trimming and uppercasing before constructing the key or invoking the loader.

Normalize each country by trimming and uppercasing before constructing the key or invoking the loader. Accept only the declared supported codes.

Begin with two spellings of Ukraine and require one computation, then include another country and reject an unknown code. This small identity change must be applied consistently to the stored value and the key, rather than hiding wrong output behind a display-only normalization.

Step 1: Normalize and validate the country before key construction. Step 2: Keep the key, loaded value and returned scope consistent.

Practice starter: solve before reading the solution

python

from bootstrap_lab import django_setup
django_setup(__name__)

from django.core.cache import cache

def cached_countries(countries):
    # Remove this placeholder, then adapt the retained baseline:
    # Normalize and validate the country before key construction.
    raise NotImplementedError
    cache.clear()
    reads = []
    def load(country):
        reads.append(country)
        return {"country": country}
    results = []
    for country in countries:
        value = cache.get_or_set(f"roles:{country}", lambda: load(country), timeout=30)
        results.append(value["country"])
    return {"countries": results, "reads": reads}
Reasoning
Normalize and validate the country before key construction. Keep the key, loaded value and returned scope consistent.
  • Hint 1: Trim and uppercase once before both cache and loader use.
  • Hint 2: Inspect the loader sequence, not only the final labels.

Solution, tests and trade-offs

The cases compare both observed returned countries and the loader-call sequence.

The cases compare both observed returned countries and the loader-call sequence. They expose a constant key even when the repeated output looks superficially plausible.

Practice checks normalized repeated values and invalid input. The tests do not sleep or infer a production hit rate from this tiny scenario. Expiry, eviction, stampede control and backend failures need separate workload and failure evidence before an operational guarantee is made.

Practice solution and acceptance checks

python

from bootstrap_lab import django_setup
django_setup(__name__)

from django.core.cache import cache

def cached_countries(countries):
    cache.clear()
    reads = []
    def load(country):
        reads.append(country)
        return {"country": country}
    results = []
    for country in countries:
        if not isinstance(country, str) or country.strip().upper() not in {"US", "IL", "UA", "CA"}:
            raise ValueError("supported country required")
        country = country.strip().upper()
        value = cache.get_or_set(f"roles:{country}", lambda: load(country), timeout=30)
        results.append(value["country"])
    return {"countries": results, "reads": reads}
Reasoning
The cases compare both observed returned countries and the loader-call sequence. They expose a constant key even when the repeated output looks superficially plausible.

Interview reasoning and next step

Explain every dimension needed to identify one cached representation, then state its freshness and retention policy.

Explain every dimension needed to identify one cached representation, then state its freshness and retention policy. Authorization scope, query parameters and content versions can matter in a real application.

Cache invalidation after a write should occur at a coherent publication boundary, not before an operation that may roll back. The testing lesson next shows how a weak assertion can miss a changed contract even when requests and responses all appear successful.

Optional stretch — after the core task works: Add account scope to a private fixture and verify that users never share cached private output.

Computer practice: https://applydjinn.com/typorithm/python-frameworks-lab-20261105.zip. Install the pinned dependencies in an isolated environment, run verify.py --track django, then edit the retained exercise baseline and check it with --practice dj-cache. The lab uses owned in-memory databases, local framework clients and tiny CPU tensors. It never reads the working ApplyDjinn database, contacts production feeds or downloads models.

Use Django’s cache API with an explicit key and expiry while keeping representation scope separate from storage backend.