Support stale-while-revalidate and stale-if-error
Hi @kornelski, thanks for your work on this library, it looks fantastic.
For my use case, I would need the library to support these two Cache-Control directives. From MDN:
-
stale-while-revalidate=<seconds>: Indicates that the client is willing to accept a stale response while asynchronously checking in the background for a fresh one. The seconds value indicates for how long the client is willing to accept a stale response. -
stale-if-error=<seconds>: Indicates that the client is willing to accept a stale response if the check for a fresh one fails.
I think it could be implemented in the following way:
-
satisfiesWithoutRevalidation()would check thestale-if-errordirective and returntrueif the response is a 5XX and the stale response can be used. - A new method
satisfiesWithRevalidation()would check thestale-while-revalidatedirective and returntrueif the stale response can be used while revalidating in the background. The caller would be expected to make the request while also using the cached response.
If you're open to these enhancements, I'd be happy to work on them.
It would be great to support these features. stale-if-error seems like a straighforward improvement of the current implementation.
stale-while-revalidate is the more interesting feature, but it doesn't fit the existing API. satisfiesWithRevalidation is not a good solution, since a cache would have to run both functions, so it's adding whole another evaluation just for taking one option into account.
Perhaps there could be a new method like whatDoIDoWithThis (needs a better name) that returns one of "use it", "use it, but revalidate", "don't use it, go to server", etc. (needs better names).
I'll work on stale-if-error first since it doesn't require a change to the API.
Maybe the new method could look like this:
const { use, revalidate } = policy.check(newRequest)
Yeah, that looks good.
I started implementing this and realized that my proposal for stale-if-error doesn't work. satisfiesWithoutRevalidation looks at the new request before revalidation, whereas stale-if-error only applies if a validation attempt fails due to an error.
So I think this has to be done with a new method satisfiesIfError(newRequest), which would need to be called if satisfiedWithoutRevalidation(newRequest) returns false and the revalidation responses is a 50X.
Ah, right. So together with stale-while-revalidate this requires rethinking how this interacts with caches.
I think stale-if-error should:
- change the time to live of a policy
- have no impact on
satisfiesWithoutRevalidation - change the behaviour of
revalidatedPolicy. On error we automatically get a modified=false, and the policy is not updated
What do you think? I am happy to help with the implementation
If you're implementing it in parallel with an actual HTTP client I'm confident it'll make sense.
The implementation is ready here: https://github.com/kornelski/http-cache-semantics/pull/30