Kikobeats/cacheable-response

Caching until the data has changed

kachkaev opened this issue · 7 comments

Hi @Kikobeats 👋

I came across your PR in Next.js that replaces LRU cache with the library and decided to drop a line. Curious if cacheable-response could potentially offer a solution to my problem.

Imagine a Next.js app that's sitting in front of a GraphQL server, which serves a more or less static dataset. This can be a list of products, which normally changes once in a while, but this can happen at any time. Alternatively, the website can focus on showing weather forecasts, which update a few times a day.

What we need for these conditionally static websites is to avoid rendering React trees on every request. At the same time, we want to have an option to flush or miss the cache before any for the requests after running some async checker. On a product website this could be a light GraphGL query to the backend asking the modification time and on the weather website we can just check the current time. In both of these cases, I would like to cache pages forever until the condition has changed, but at the same time I would never want to send the x-cache-expired-at header to the clients, because any page refresh at any time can unexpectedly result the new data.

Implementing these tricks seems somewhat possible by adding additional express logic around your module, but I'm wondering if it's possible to add some native support. WDYT?

Thanks for your work!

Feeling like right now you can achieve that with:

  • Setup an Infinity ttl cache. Content will never expired.
  • When you need to refresh the cache copies, create a request with forceas a query param. It can be done internally, doing ping to your own API, then the user never face with the problem.

That’s what I’m about to do, yes. Except that there’ll be my dataset timestsmp instead of force as a param. What I’d like to avoid doing is removing the headers that your module sets. Can there be added an option that does not set response headers?

note that x-cache-expired-atis just for debugging purposes; why remove that since users are not going to see it and you know what the value represent?

But does not x-cache-* get picked by a reverse proxy and turned into a real cache header? That's what I thought but I might be wrong. If that's the case, an option to not set these headers would be useful.

Also, a method to reset the whole cache could be beneficial in the use cases described above. Calling it after quickly checking the dataset modification date feels easier than injecting custom get requests to artificially miss the cache. What I mean is something like lruCache.reset(). Changing request parameters instead of resetting cache causes higher RAM usage over time. WDYT?

I don't think so. Prefixed header with x- are not standard and in this case the value is written in a human readable format intentionally

Even if there's no chance that headers can be picked up by reverse proxies, what is the benefit from making them compulsory in production? Regardless of them, cache-control that's being set at all times does not enable the use cases described above. Well, at least if all these headers are not manually removed from the Express response (which is laborious).

WDYT re the reset method? Would it be worth discussing it in a separate issue?

As I said, it is added for debugging purposes.

If you are saying that the value is not representing the correct expiration date even after a for force refresh, that's a bug and we need to open a new issue 🙂