Start learning free

LESSON 125 OF 173 · BACKEND: SPEED

Expire the Cache

Practice

Clearing the cache works for changes made through the shop's own routes. But other programs change the database too, like a stock import or an admin tool, and nobody clears your cache for them. The safety net is a TTL (time to live): every cached answer gets an expiry, and after it the answer is thrown away and worked out again.

To know an answer's age, remember when you stored it, next to the value. Its age is the current time minus the stored time. Here is the idea on another value, a remembered weather report that may be used for 10 minutes:

String weather = "sunny";
double weatherTime = now();

if (now() - weatherTime < 600) {
    System.out.println("still fresh: " + weather);
}

Ask the time through a small clock method, now(), instead of calling System.currentTimeMillis() everywhere: a method is one place a test can replace. The check swaps your now() for a fake clock that it sets with each request, so it can jump a minute ahead without waiting. With a TTL of 60 seconds, your code must give these answers, in this order:

GET /products  (clock at 1000)  →  200  [{"category": "kitchen", "id": 1, "name": "Mug", …}, … 8 products]
GET /products  (clock at 1059)  →  200  [the same 8 products]
GET /debug/queries  →  200  {"queries": 1}
GET /products  (clock at 1060)  →  200  [the same 8 products]
GET /debug/queries  →  200  {"queries": 2}
GET /products  (clock at 1119)  →  200  [the same 8 products]
GET /debug/queries  →  200  {"queries": 2}

At 1059 the list is 59 seconds old, so it comes from the cache. At 1060 it is 60 seconds old, which is not less than 60: the query runs, and the fresh list is stored with the time 1060. At 1119 that list is 59 seconds old again. A shorter TTL gives fresher answers and more queries; a longer one, fewer queries and older answers.

Your task: add a constant CACHE_SECONDS set to 60 and a method now() that returns System.currentTimeMillis() / 1000.0, the time in seconds. Add a map cacheTimes, and in getProducts store now() in it under "products" when you cache the list. Answer from the cache only if cache has "products" and its age is less than CACHE_SECONDS.


Assignment
Follow the Coding Tutorial to give the cached product list a time to live of 60 seconds.


Hint
The age is now() minus cacheTimes.get("products"). Put cache.containsKey("products") first in the if: thanks to &&, the stored time is only read when the key is there.


STEP 1 OF 7
    Ctrl + Enter to check