This project puts the module together in the shop's busiest route, GET /products. Earlier lessons made the list ask only for id, name, price and read one keyset page at a time with ?after=. Two things are still missing: clients can't choose the page size, and the list lost its cache when it got pages.
A size with a limit: clients will pick the size with ?size=, but only up to a limit. Without one, a single request for ?size=1000000 reads and sends the whole table, and the pages were for nothing. Give the number a default, and refuse anything out of range with 400, like this route for reviews does:
app.MapGet("/reviews", (int? count) => {
count = count ?? 10;
if (count < 1 || count > 20) {
return Results.Json(new { error = "count must be between 1 and 20" }, statusCode: 400);
}
...
});
One cache entry per page: a single key like "products" would hand out the first cached page for every page. Each page needs its own cache key, built from everything that decides its content: after and size, as in "products:6:3". The routes that change products already call cache.Clear(), which forgets every page at once.
On a fresh shop, these requests, in this order, must get these answers:
GET /products → 200 {"next_after": 3, "products": [{"id": 1, "name": "Mug", "price": 12}, …]}
GET /products?size=5 → 200 {"next_after": 5, "products": [… 5 products, ids 1 to 5 …]}
GET /products?after=6 → 200 {"next_after": null, "products": [{"id": 7, "name": "Stapler", …}, {"id": 8, …}]}
GET /products?after=6 → 200 the same page, from the cache
GET /debug/queries → 200 {"queries": 3}
POST /products {"name": "Cup", "price": 8} → 201 {"id": 9, "name": "Cup", "price": 8}
GET /products?after=6 → 200 {"next_after": 9, "products": [{"id": 7, …}, {"id": 8, …}, {"id": 9, "name": "Cup", "price": 8}]}
GET /products?size=6 → 400 {"error": "size must be between 1 and 5"}
GET /products?size=0 → 400 {"error": "size must be between 1 and 5"}
GET /debug/queries → 200 {"queries": 5}
Your task: add const int MAX_PAGE_SIZE = 5;. Set size to PAGE_SIZE when the URL has none, and answer 400 when it is below 1 or above 5. Keep the answer in a variable and return it, and cache each page under its own key for CACHE_SECONDS.
Assignment
Follow the Coding Tutorial to add a page size limit to GET /products and give each page its own cache entry.
Hint
Build the key from both after and size with +, which turns the numbers into text. Check the size before you make the key, so a refused size never runs a query or fills a cache entry.
Free plan: 30 tutor messages. PRO is unlimited.
