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:

const weather = { time: now(), value: "sunny" };

if (now() - weather.time < 600) {
  console.log("still fresh:", weather.value);
}

Ask the time through a small clock function, now(), instead of calling Date.now() everywhere: Date.now() counts milliseconds, and with now() the whole shop reads the time in one place, in seconds, the same unit as CACHE_SECONDS. A clock is also easy to fake in a test: the check puts its own clock behind Date.now() and sets it 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 clock function now() that returns Date.now() / 1000. In the route for GET /products, store the list together with the time it was stored, as an object with the properties time and value, and answer from the cache only if cache.products is not undefined 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 the stored time. Put the undefined test first in the if: thanks to &&, the stored time is only read when the list is there.


STEP 1 OF 6
    Ctrl + Enter to check